XNA 3D. Questions.

  • (2 Pages)
  • +
  • 1
  • 2

17 Replies - 2427 Views - Last Post: 08 June 2015 - 06:25 AM

#1 dreaminxna  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 71
  • Joined: 10-June 13

XNA 3D. Questions.

Posted 17 May 2015 - 03:53 AM

So uh, ive been studying XNA 3D now, I want to combine it with 2D to achieve the 2.5D effect but first I have to learn 3D.

I am learning XNA 3D on this site

My first question is the view matrix
private Matrix view = Matrix.CreateLookAt(new Vector3(0, 0, 15), new Vector3(0, 5, 0), Vector3.UnitY);


messing with the code.

  • Is the point of origin of 3D is on the center screen? Cause I am use to 2D. I know 3D in unity is on center screen, does XNA too?
  • I also dont know the unit of measurement of XNA. when I put new Vector3(0,50,0) I thought it is using pixel but then the jump is a higher so it must be that the unit is not on pixel.
  • and this Unit how many pixels does it compose? say 1 unit = ? pixel?


I realize the the camera position of lets say
new Vector3(0,0,20)
is like the near clipping plane. I cant think of any other reason of whats the point of putting a near plan in project matrix if the view matrix already has it. I dont get it

This post has been edited by dreaminxna: 17 May 2015 - 04:05 AM


Is This A Good Question/Topic? 0
  • +

Replies To: XNA 3D. Questions.

#2 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: XNA 3D. Questions.

Posted 17 May 2015 - 05:26 AM

Well, I haven't done a lot of 2D especially after high school. (I started programming text based games when I was 12). And I've never tried to do 2.5D or anything like that. But I have done a lot of 3D including a pretty in depth exploration of matrices and how they are used in game programming specifically.

I believe you are thinking too much in terms of how things are done with sprites in 2D. 3D is a whole new game pretty much. Although, there is no such thing as 2D in DirectX 11. So, if you want to do even basic sprite stuff in DX11 in C++ you have to do it in 3D. So there is certainly a relationship between 2D and 3D.

However, you probably need to forget a lot of what you already know for awhile.

RB is a great teacher by the way. I highly endorse his site and his C# book which I think is one of the best programming books I've ever read. You can tell just from his website that he's a good teacher.

Quote

Is the point of origin of 3D is on the center screen? Cause I am use to 2D. I know 3D in unity is on center screen, does XNA too?


The point of the origin in 3D doesn't really exist. It's a mathematical place in an imaginary 3D world. Stated more plainly, it has no relationship with the screen other than what you assign it. Can you put it at the center of the screen? Certainly! How would you do that? Well, you would place the "camera" (aka the view matrix) directly above that position and point it straight down. How do you do that?

private Matrix view = Matrix.CreateLookAt(new Vector3(0, 0, -10), new Vector3(0, 0, 0), Vector3.UnitY);



I never can remember if Z is into the screen or out of the screen partially because it changes for other things outside of XNA and you can even set it either way in DX11 for example. So it may be positive 10. But assuming that negative comes out of your "computer monitor" and that positive Z is "forward" this should place the camera 10 units back from they XY plane and aligned perpendicular to it because of the first vector. The second parameter tells it to face the origin and I think you can use Vector3.Zero for that if the camera is never going to move. The third parameter is a cheat that only works if your camera is never going to rotate. But it works as long as the camera doesn't rotate. It is a vector pointing in the direction "above" the camera.

So, in this example, we're using the XY plane for our 2D plane which you would normally think of as vertical. In 3D, we would normally think of Y as up and X as left and right with Z being forward and backwards. But this is an imaginary mathematical world; you can assign it anything you like but what gets drawn on the 2D computer monitor is all that matters.

So, you are treating this "vertical" plane as if it is horizontal so that you can use X and Y as if you were still in 2D. But you could use the XZ plane instead which would feel a little weird if your used to 2D but would work just as well and keep to the "normal" idea of what is horizontal in 3D. Or, you could get really crazy and use the YZ plane. It's up to you.

Likewise, if you change the third parameter to the LookAt method, the up vector can make the camera spin so that +X, -X, +Y, -Y, or anything in between is at the top of the screen assuming we're looking at the XY plane and spinning on the Z axis which is only true if you place the camera there.

Quote

I also dont know the unit of measurement of XNA. when I put new Vector3(0,50,0) I thought it is using pixel but then the jump is a higher so it must be that the unit is not on pixel.


Nope. You're thinking of 2D. The unit is 1. The unit only has whatever meaning you assign to it. It's an integer. Well, the unit is but it's really a floating point value with a continuum of infinitesimal positions between each unit. Think of it as a "grid" where each square is one unit wide. How big is a unit and thus a square? One unit. How big is that? However big you want it to be. Normally we assign it to mean one meter in game programming. That just seems to work out as nice as anything. By imagining it to be 1 meter, we can scale everything in the game to have proper size relationships between them.

How big is that in pixels? Well it mostly depends on how close the camera is. You can move the camera closer or further away. I've never tried to get it to match 1 for 1. Then again, you also probably want to use an orthographic projection matrix for this if you want more of a 2D look and I almost never use the orthographic projection matrix and always use perspective. But without the perspective things are drawn in their actual dimensions rather than smaller or larger because of perspective. I think you can still back the camera away to make them appear smaller.

Quote

and this Unit how many pixels does it compose? say 1 unit = ? pixel?


Again, it just depends on the distance between the camera and the model and the screen it is being projected on. I wouldn't think of it in terms of pixels; that is 2D thinking. You're in 3D now. A unit is a meter. That meter could be any number of pixels depending on a number of factors. The camera is positioned any number of meters away from the object or the plane it is looking at. And the number of meters width shown on the screen is dependent on the distance of the camera away from it. The whole object might not fit on the screen, or it might be so far away that it is only a single pixel. In fact, it might be so far away that the big object is less than a single pixel and with over sampling and what not the color of the pixel might actually be determined by blending all of the objects colors with the background's colors and not even be determined solely by the object. (Time for mip mapping.)

Quote

I realize the the camera position of lets say view sourceprint?
1 new Vector3(0,0,20)
is like the near clipping plane. I cant think of any other reason of whats the point of putting a near plan in project matrix if the view matrix already has it. I dont get it


I'm not following you here. If you place the camera at 0,0,20 and point it towards the origin what does that have to do with the clipping plane? Nothing. The clipping plane is unrelated to the view matrix in any way that I can think of off the top of my head.

You can't skip the projection matrix. I mean, mathematically before it's all over, the world, view, and projection matrices are all going to be combined into a single matrix. You still can't skip their steps though unless you want the "default" results. And then the projection matrix is the only one necessary. The others can be dropped if you're willing to live with the results. The projection matrix is absolutely mandatory because it is what converts the 3D data into 2D so that it can be drawn on the 2D computer screen. Without it nothing can be drawn correctly ever under any circumstance. I can't even imagine what it would look like. Well, it wouldn't. I mean there's just no way to draw a 2D image with 3D data. It would look like a blank screen.

Anyway, the view matrix does not have any clipping planes. Something could be behind the camera, but the only reason that doesn't get drawn is because of the projection matrix's near clipping plane. Otherwise, it would still be drawn. In fact, I've never tried it largely because I don't do 2D, but I believe you can actually set the near clipping plane to be behind the camera. I think for 2D they set the far clipping plane to 1 and the near clipping plane to -1.

How you then get the view matrix to work with that, I'm not sure. And the example I'm thinking of was actually in OpenGL I think. My lack of having done any significant work in 2D using 3D is showing here. In XNA, we use sprites for 2D and even the 2D stuff I've done in 3D, such as fonts, was pretty straight forward. I had to look at some example code to even remember. I used "DrawString" from SpriteBatch and drew it as sprites.

Since you have to do 2D in 3D in DX11, there has to be a way to get sprites to match 1 for 1 with the screen resolution. There you draw quads (rectangles) and put a texture on the quad as a sprite. You would probably want each texel of the image to match the size of a pixel on the screen. And you would use an orthographic projection matrix to make them look 2D with the camera pointed to the plane they are on. The image plane would probably have a depth of something like zero to one or possibly negative one to positive one but that would only serve to layer the "sprites" in specific layers irrespective of the order they are drawn in which would normally determine which is drawn on top. I've never really tried to do that as I am not really big on 2D and I've only really been doing DX11 for about a year and a half and have focused strictly on normal 3D.

I need to learn how to do 2D in DX11 though for things like drawing text and user interface in 3D.

This post has been edited by BBeck: 17 May 2015 - 05:39 AM

Was This Post Helpful? 1
  • +
  • -

#3 dreaminxna  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 71
  • Joined: 10-June 13

Re: XNA 3D. Questions.

Posted 17 May 2015 - 08:18 AM

Quote

Well, I haven't done a lot of 2D especially after high school. (I started programming text based games when I was 12). And I've never tried to do 2.5D or anything like that. But I have done a lot of 3D including a pretty in depth exploration of matrices and how they are used in game programming specifically.

Thats my initial plan but then i realize there so much more to learn.


Quote

However, you probably need to forget a lot of what you already know for awhile.

Its hard to do that but i guest i have no choice :D/>

Quote

RB is a great teacher by the way. I highly endorse his site and his C# book which I think is one of the best programming books I've ever read. You can tell just from his website that he's a good teacher.


Yeah I actually bought his book. I learn a lot from that book.



Quote

The third parameter is a cheat that only works if your camera is never going to rotate. But it works as long as the camera doesn't rotate. It is a vector pointing in the direction "above" the camera.

Likewise, if you change the third parameter to the LookAt method, the up vector can make the camera spin so that +X, -X, +Y, -Y, or anything in between is at the top of the screen assuming we're looking at the XY plane and spinning on the Z axis which is only true if you place the camera there.


Ive also do some research on this Up vector. Is it safe to say that this is how u tilt your head or the rotation from z axis? like this on image
Posted Image

Quote

Nope. You're thinking of 2D. The unit is 1. The unit only has whatever meaning you assign to it. It's an integer. Well, the unit is but it's really a floating point value with a continuum of infinitesimal positions between each unit. Think of it as a "grid" where each square is one unit wide. How big is a unit and thus a square? One unit. How big is that? However big you want it to be. Normally we assign it to mean one meter in game programming. That just seems to work out as nice as anything. By imagining it to be 1 meter, we can scale everything in the game to have proper size relationships between them.


Uhm can you site a code of actually converting it to 1 meter? like just a one line code?





Quote

I'm not following you here. If you place the camera at 0,0,20 and point it towards the origin what does that have to do with the clipping plane? Nothing. The clipping plane is unrelated to the view matrix in any way that I can think of off the top of my head.
You can't skip the projection matrix. I mean, mathematically before it's all over, the world, view, and projection matrices are all going to be combined into a single matrix. You still can't skip their steps though unless you want the "default" results. And then the projection matrix is the only one necessary. The others can be dropped if you're willing to live with the results. The projection matrix is absolutely mandatory because it is what converts the 3D data into 2D so that it can be drawn on the 2D computer screen. Without it nothing can be drawn correctly ever under any circumstance. I can't even imagine what it would look like. Well, it wouldn't. I mean there's just no way to draw a 2D image with 3D data. It would look like a blank screen.

Anyway, the view matrix does not have any clipping planes. Something could be behind the camera, but the only reason that doesn't get drawn is because of the projection matrix's near clipping plane. Otherwise, it would still be drawn. In fact, I've never tried it largely because I don't do 2D, but I believe you can actually set the near clipping plane to be behind the camera. I think for 2D they set the far clipping plane to 1 and the near clipping plane to -1.


Yeah i think I got confused on projection and camera matrix here. :D/>
this code of view matrix
private Matrix view = Matrix.CreateLookAt(new Vector3(0, 0, 5), new Vector3(-3, 0, 0), new Vector3(0,-1,0));

and this code of projection matrix
private Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 2f, 1f, 100f);

If you change the near plane to 5f in projection matrix it wont draw anything cause the camera position (0,0,5) is limiting it to 5 units z position. Thats why i got confuse that this camera can/may be as well the near clipping plane.

Anyway, Im still a little bit confuse about this clipping planes. Base on googling could you think of this clipping planes as a boundary where you can draw anything inside of it?


Quote

image plane and texel

Did some googling to this stuff as I am new to this. :D/>

This post has been edited by dreaminxna: 17 May 2015 - 08:19 AM

Was This Post Helpful? 0
  • +
  • -

#4 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: XNA 3D. Questions.

Posted 18 May 2015 - 06:21 AM

So the "up" vector of the LookAt method took me over a year to figure out. LOL

Actually, it was when I went to code my own LookAt method for learning purposes that I really figured it out because everyone usually cheats with it in almost every example you will find.

I've been considering doing a video on how 3D graphics fundamentally works but have not gotten around to it yet. But basically everything is done by using vertices to define 3D triangles. You can think of a vertex as the corner of a triangle at it takes 3 to draw a triangle. A vertex is actually a data structure that holds information about that corner. At a minimum it has to have the position of the vertex. It can also include color, texture mapping coordinates, and vector normal to indicate which direction the corner "faces".

All that happens, whether you are building your own vertex buffer or using XNA's model class is that all the vertices of your model are fed into the vertex shader along with any additional processing data especially the world, view, and projection matrices.

The first thing the vertex shader does is to apply these matrices to each vertex of the model which has the effect of applying all three matrices to the entire model.

Usually it is too cumbersome to define an object or model using individual vertices. So, we use modeling programs like Maya, 3D Studio Max, or Blender. The model is passed as a file to our program with whatever vertex positions are in the file. Whatever position it was in in the file is what position it is in when you load it.

Obviously we want to move it around our scene. That's where the world matrix comes in. Every model has at least one world matrix and possibly more if you need to animate the object. You generally have only one view and projection matrix per game but you have a world matrix for each model.

The world matrix contains all the combined math to place the object into the scene. This is kind of working backwards, or rather this is forwards and the process actually works kind of backwards. What I mean is that the projection matrix is more fundamental. I'm probably just confusing this.

Anyway, the world matrix places the object in the 3D world. The view matrix places the camera in the 3D world. And the Projection matrix projects what's in front of the camera onto a 2D plane where it can be drawn.

So, going in the other direction, but applying the Projection matrix to our model, or rather its vertices, we basically take a box and project everything in it to one side of the box. We flatten it out to be 2D. That's pretty much how an orthographic projection matrix actually works. You can't really draw "everything" in the 3d world simultaneously because you need to project it on a limited sized computer screen and you generally don't want to see things "behind" the camera.

So, the near clipping plane is the closest distance that will be drawn. And the far clipping plane is the furthest distance to be drawn. The box height and width match the screen height and width. And those dimensions give you a 3D box. All the vertices of the model currently being drawn (because you draw models one at a time)are smushed down to a 2D plane where they can then be drawn on the 2D screen. You're basically throwing away the Z dimension.

Mathematically, you have to have the box aligned to an axis to make this work. If the camera is looking down the Z axis, then you can just throw away the Z data (or use it to determine which model is drawn on top in 2D because of it's distance in 3D) and you have 2D coordinates ready to draw on a 2D screen.

This data is then sent to the rasterizer 3 vertices at a time and the rasterizer "shades" in the triangle between the 3 2D points.

However, the rasterizer uses the pixel shader to do this. It basically passes the pixel data to the pixel shader for the pixel it is shading in along with other data you can specify such as texture coordinates. So, you can modify the pixel color using the pixel shader. The output of the pixel shader is always only the color of the pixel being currently shaded in. Every pixel of the triangle is passed in and you can substitute the color from a photograph/texture using texture coordinates passed in, for example.

Then that pixel is displayed on your computer monitor.

The problem is that our projection matrix does not have "perspective", which we may or may not want, but mostly that it's mathematically permanently stuck on one axis of the 3D world always looking straight down that axis.

The projection matrix is, of course, a matrix. It's just a bunch of math that projects the vertex positions of the model onto a 2D rectangle because you can't draw actual 3D because your computer monitor is a 2D screen. The perspective projection matrix has different math than the orthographic projection matrix, but it basically works the same way. Instead of a box, imagine taking that far clipping plane side of the box and expanding that rectangle in all 2D directions along it's plane. What you would have is sort of a 4 sided pyramid on it's side with the "tip" being the near clipping plane. That's basically the shape of the projection matrix "capture box" and it captures everything inside that box and projects the vertex positions onto a 2D rectangle to be drawn. It's basically the same as the orthographic projection except it does perspective to make things actually look 3D when they are drawn in 2D.

But either way, both projection matrices are stuck looking straight down the Z axis with the near clipping plane basically at the origin. Or at least that's where the rectangle you are projecting to is.

So, you can't move the "camera". And you can't place your objects in the scene. You would have to create them in your modeling program to be permanently in front of the camera in a fixed position in order to even get them to be drawn because otherwise they would be outside of the projection box and ignored.

So, the world matrix allows you to place the object in the 3D scene. It contains all the math for position, orientation, and scale of the model in order to put in where you want it in the 3D world.

Now you can at least have it placed differently than the way it was originally created.

The view matrix is the solution for being able to move the camera through the scene. There is no way to "move the camera" because there is no "camera". There is just flattening out the Z coordinates to smush them down to a 2D plane to be drawn. So, somebody got smart and realized that if you can't move the camera, what the world matrix has taught us is that you can move the objects in the 3D world. And that's exactly what the view matrix does.

It's basically the same thing as a world matrix except it gets applied equally to everything in the 3D world (one per game rather than one per model) and it is backwards. Basically, the view matrix moves everything the opposite of how you want your "camera" to move. If you want the camera to move backwards, the view matrix moves everything in the 3D universe that far forward. If you want the camera to look up, it rotates everything in the 3D world down. If you want to move right, it moves left that far. Everything is reversed.

This gives the "illusion" of the camera moving through the scene. But in reality, the scene is moving around the camera because the camera is our projection matrix that doesn't know how to do anything except look straight down the Z axis. The projection matrix is basically just a box where everything inside of it gets smushed down to a 2D image but because of the way it works it has to be always looking straight down the Z axis. The view matrix moves everything in our 3D universe uniformly so that we can have different parts of the 3D world inside our projection box which cannot move.

It's a little bit bizarre to think about the first time maybe.

But the first thing the vertex shader does is apply these three matrices to each vertex of the model so that it can be drawn on the 2D screen and passes those 2D coordinates to the rasterizer.

The rasterizer then passes each pixel of the triangle currently being shaded, one pixel at a time, to the pixel shader to determine the color of that pixel.

Then the pixel is drawn to a buffer in memory called the "back buffer" which matches 1 for 1 with the pixels of your computer screen and is specific to the size of your display resolution (and in fact has to be rebuilt if you change resolutions). There is another buffer exactly like it called the "front buffer" which the computer monitor uses to determine the color of every pixel drawn on your computer screen. You don't want to write directly to the front buffer for various reasons that boil down to the fact that it looks bad.

Then XNA will present the back buffer. That means that the back buffer and front buffer swap and the back buffer is now the front buffer and used to light up your computer monitor while the front buffer moves to the back for you to draw to.

That's pretty much the whole process in a nut shell.

So I kind of went off on a tangent to explain the Up vector. LOL I guess I do that a lot. But it should make the purpose of the view matrix more clear.

So, we know the purpose of the view matrix is to simulate a camera by moving the 3D world opposite of the way we want the camera to move. It's basically the same thing as a world matrix and stores position, orientation or direction to look in, and possibly scale but I've never seen anyone mess with that but you definitely want to control camera position and camera direction.

I have a video explaining the basics of how these matrices work mathematically. (Although, if you are not pretty "solid" with vectors you probably want to watch the vector video before the matrix video since it builds on the information in the vector video. Although, if you think my posts are long winded, just wait till you see my videos. LOL) I also have stuff written on my website. My "Matrices in Motion" "tutorial" demonstrates using matrices in XNA even for animation. After the first tutorial I did, I decided to just skip the "tutorials" and write code examples as downloadable projects. So, you can download that XNA project and see a working example. I tried to comment the code extensively so that if you just read through the code you'll see exactly what's going on.

Again, I'm going off on tangents.

The LookAt method and the up vector, right.

Somewhere, I have code where I actually coded the LookAt method from scratch. I substituted it for XNA's built in LookAt method to verify it was doing the exact same thing. So, here's how the LookAt method works.

Hopefully you understand vectors because there are a lot of vectors here. XNA let's you get away with not knowing vectors very well starting out, but all of these matrices are using vectors internally. I've got a video on vectors too. Excuse my voice on that one; it's a bit scratchy since I was going hoarse after talking several hours straight.

Anyway, a vector is just an arrow, a 3D arrow in this case. It has a length and a direction.

So the first thing the LookAt method does is build a vector/arrow that points from the position you pass in to the look at point. Those are the first two parameters you pass in.

But just an arrow by itself doesn't really describe an orientation. You could rotate the arrow around it's shaft and not know what's up or down. The matrices actually hold three vectors that must always be "mutually perpendicular". It's basically 3 arrows that represent a "private" X, Y, and Z axis. By rotating this private axis you can describe how different it's facing and orientation are from the axis of the 3D world. This is how the matrix stores orientation.

So, we have the first axis of our private axis from the lookat method. The third parameter, or up vector, is used to fake another axis. However, it is not necessarily ever going to be perpendicular from the first vector/arrow we built. But we rely on the programmer to use this to tell us what direction is above the camera in order to form a 2D plane in the 3D world between the vector we created and the up vector passed in. Both vectors together define a 2D plane because there is only one 2D plane that both can reside on. Then you use a vector trick to get our second permanent vector of our private axis. The trick is that you can use the vector cross product (I always get the cross product and the dot product confused) to point perfectly in the direction "out" of the 2D plane defined by two vectors.

So, now we've used the data passed into the LookAt method to define two perpendicular vectors/arrows with one pointing forward and one pointing right. That's our private Z axis and our private X axis. Since our "up" vector isn't reliably pointing "up" but somewhere vaguely "up" we instead use the same cross product trick with the Z and X axis vectors we've already formed to create a perfectly mutually perpendicular vector pointing out of their plane. And that's what gets stored in the matrix.

You can use the LookAt method for the world matrix or the view matrix. You may want to look at my Gimbal Lock video to see how using pitch, yaw, and roll are bad and how you should store your orientation entirely in the world or view matrix depending on whether we're talking about the object or the camera. Pitch, Yaw, and Roll are easier to understand at first than matrices, but they cause severe problems as demonstrated in the Gimbal Lock video.

When possible, it is most efficient to always store your position and orientation data in matrices like this because that's what you are going to have to submit to the shader anyway. So, if you don't then you still have to convert the data to matrices at the last minute before sending it to the shader, which may or may not work depending on you coded it (possibly creating Gimbal Lock for example).

If you assign a world matrix to an object in your 3D world, it can store the current position and orientation of the object (you can decompose the matrix to get this info back out too although XNA has some built in methods that really help out here). If you want to change the object's position. You load up a matrix with a translation (position change) using XNA's translation matrix methods. Then you "apply" that change by multiplying the world matrix times the change matrix. Multiplying matrices always combines their data. The result is the new position and orientation that you can store back in the object's world matrix and now the object has been moved. Or, to spin it you can use a rotation matrix in place of the translation matrix. Just be aware that all rotations occur around the origin. So, the only way to rotate an object is move it to the origin, rotate it, and move it back. Otherwise it will orbit the origin rather than rotating.

But this way, the world matrix can always contain the current position and orientation of the object.

You can do the same with the view matrix but because it's backwards you have to invert it using the inverse function. Or you can just recreate it with the LookAt method every frame which is what I've mostly done. But after years of doing it that way, I'm realizing it's more efficient to build the view matrix once and move it and rotate it rather than rebuilding it from scratch every frame. But I've never noticed a performance problem because of it.

Anyway, all of that to say that the way you tilt your head (or the camera) is to change the position being looked towards which is the second parameter. The up vector you specify should always be perpendicular to that, but as I've pointed out, it will "sort of" correct it if it's wrong. However, if you are rotating the camera in every direction, like in a flight simulator you will discover not getting the "up" vector right is a major problem. If you only tilt up and down about 80 degrees in either direction, this should not be an issue.

So, really, you should change the position looked towards to tilt up and down and calculate the up vector to point above the camera. This is also where it helps to not recreate it every frame. If you start the view matrix aligned with the axes, then you can use Vector3.Up to specify it. And then you use the rotation methods to rotate the camera just like you would a world matrix in order to tilt up and down and you don't have to figure out what direction is up because you are not using the LookAt method any more. Also, be aware that the view matrix has to be inversed in order to make it's changes "opposite" of what you are asking.

I think the "Matrices in Motion" tutorial has some good examples of using matrices for movement. I have kind of a 3rd person camera going there, I believe it was, where it basically chases the object.

My first tutorial and my terrain tutorials actually use more of a first person camera to see that in action. In my room builder example (which is fairly complicated compared to some of the tutorials) uses an XNA game component that I created for the camera. I think I may have used the exact same thing in the terrain examples because once you've built a camera class you like, you tend to stick with it. As you can see in the code example below, I store tilt as an angle in radians. I basically use the vector cross product trick to get a vector that points to the right of the camera (I think XNA has a built in method to extract this vector from a view matrix). Then I do a rotation around that created axis by the number or radians in the pitch variable in order to look up and down.

Today I don't know that I would do a camera exactly the same way as this code was written years ago. But it's one way of doing it. And I stored pitch separately partially to avoid looking up or down too far and doing a summersault. Actually, I think I coded this before I understood Gimbal Lock and how the up vector actually works and coded it this way partially to avoid the effects of a bad up vector. It was the Skybox tutorial where I finally figured out how the LookAt method works and what the up vector actually is. In fact, that does the Up vector correctly because I couldn't get the space ship to rotate properly because I didn't understand how the Up vector worked and that forced me to actually learn how it works in order to finish that tutorial. I learned a lot on that one.

Also, I might point out that I generally clean up my tutorial code and comment it to the point of ridiculous. The "examples" on my website are under the examples section partially because they never got cleaned up or commented.

Also, I did this camera as an XNA game component. That's something you may not have gotten into yet with XNA just starting out. They're not that hard once you understand them. It's basically the same thing as making your own class except the Update and Draw methods are called automatically by XNA every frame just like the Game1.cs.

Anyway, hope that overly long explanation helps. :-)

 public abstract class Camera : Microsoft.Xna.Framework.GameComponent
    {
        protected Matrix View;            //ViewMatrix
        protected Matrix Projection;      //Projection Matrix
        protected Vector3 Handle;         //Used to control the camera's "position".
        protected Vector3 HandleFacing;   //Direction Handle of camera faces.
        protected float Velocity;       //Speed that the camera is moving at.
        protected float Yaw;                //Rotational velocity of the camera.


        public Matrix ViewMatrix
        {
            get { return View; }
        }


        public Matrix ProjectionMatrix
        {
            get {return Projection;}

        }


        public Vector3 LensPosition
        {
            get { return Handle; }
        }


        public Vector3 Facing
        {
            get { return HandleFacing; }
            set 
            { 
                HandleFacing = value;
                HandleFacing.Normalize();
            }
        }
         

        public virtual float VelocityPerFrame
        {
            get { return Velocity; }
            set { Velocity = value; }
        }


        public float YawPerFrame
        {
            get { return Yaw; }
            set { Yaw = value; }
        }


        public Camera(Game game)
            : base(game)
        {
            Handle = new Vector3(0f, 0f, 0f);
            HandleFacing = new Vector3(0f, 0f, 1f);
            Velocity = 0f;
            Yaw = 0f;
        }


        public abstract void StrafeLeft();


        public abstract void StrafeRight();


        public abstract void RollToPort();


        public abstract void RollToStarboard();


        public abstract void LookUp();


        public abstract void LookDown();


        public abstract void MoveTo(Vector3 NewPostion);


        public abstract void MoveTo(Vector2 NewPostion);


        //public abstract void FaceTowards(Vector3 LookAt);


        public override void Initialize()
        {
            base.Initialize();
        }


        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
        }
    }



    public class HumanCamera : Camera
    {
        private float EyeLevel = 1.75f;
        private float Pitch = 0f;   //Used to pitch the view up and down.


        public HumanCamera(Game game) : base(game)
        {
        }


        //public Vector2 Position
        //{
        //    get 
        //    {
        //        Vector2 ReturnValue;

        //        ReturnValue.X = Handle.X;
        //        ReturnValue.Y = Handle.Z;
        //        return ReturnValue; 
        //    }
        //    set
        //    {
        //        Handle.X = value.X;
        //        Handle.Y = EyeLevel;
        //        Handle.Z = value.Y;
        //    }

        //}


        public override void Initialize()
        {
            Handle = new Vector3(0f, EyeLevel, 0f);
            HandleFacing = new Vector3(0f, 0F, 1f);
            View = Matrix.CreateLookAt(Handle, Handle+HandleFacing, Vector3.Up);
            Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Game.GraphicsDevice.Viewport.AspectRatio, 0.1f, 2000f);

            base.Initialize();
        }


        public override void MoveTo(Vector2 NewPostion)
        {
            Handle.X = NewPostion.X;
            Handle.Y = EyeLevel;
            Handle.Z = NewPostion.Y;
        }


        public override void MoveTo(Vector3 NewPostion)
        {
            Handle = NewPostion;
        }


        //public override void FaceTowards(Vector3 LookAt)
        //{
        //    HandleFacing = LookAt;
        //}


        public override void StrafeLeft()
        {

        }


        public override void StrafeRight()
        {

        }


        public override void RollToPort()
        {

        }


        public override void RollToStarboard()
        {

        }


        public override void LookUp()
        //===================================================================================
        // LookUp()
        //
        // Purpose: Turns the character's head upwards.
        // Parameters:
        // DependsOn: 
        // Returns: void
        //
        // Notes: 
        //===================================================================================
        {
            Pitch += 0.01f;
            if (Pitch > MathHelper.PiOver4)
            {
                Pitch = MathHelper.PiOver4;
            }
        }
        //===================================================================================


        public override void LookDown()
        //===================================================================================
        // LookDown()
        //
        // Purpose: Turns the character's head downwards.
        // Parameters:  
        // DependsOn: 
        // Returns: void
        //
        // Notes: 
        //===================================================================================
        {
            Pitch -= 0.01f;
            if (Pitch < -MathHelper.PiOver4)
            {
                Pitch = -MathHelper.PiOver4;
            }
        }
        //===================================================================================


        public override void Update(GameTime gameTime)
        {
            Matrix YRotation = Matrix.Identity;
            Matrix PitchRotation = Matrix.Identity;
            Vector3 RightFacing;
            Vector3 LookAt;


            YRotation = Matrix.CreateRotationY(Yaw);
            Handle += HandleFacing * Velocity;
            HandleFacing = Vector3.Transform(HandleFacing, YRotation);
            RightFacing = Vector3.Cross(HandleFacing, Vector3.Up);
            PitchRotation = Matrix.CreateFromAxisAngle(RightFacing, Pitch);    //Now we can pitch with the right vector.
            LookAt = HandleFacing;
            LookAt = Vector3.Transform(LookAt, PitchRotation);  //Apply Pitch rotation.
            View = Matrix.CreateLookAt(Handle, Handle + LookAt, Vector3.Up);
                        
            base.Update(gameTime);
        }
    }




This post has been edited by BBeck: 18 May 2015 - 11:39 AM

Was This Post Helpful? 1
  • +
  • -

#5 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: XNA 3D. Questions.

Posted 18 May 2015 - 06:47 AM

I was looking for a code example that is more straight forward on how I use the LookAt method. My Holodeck tutorial was my very first tutorial. So, I've learned a lot since then and might code it differently now. But it works and has a different approach to the camera. For one thing, I made the user a class.

The program basically creates a square room and lets you walk around in it as the camera. I did not create a camera class but rather put the camera functionality in the Character class representing the user. And I used vectors like there was no tomorrow. Someone told me back then I had gone a bit vector crazy. Looking back on it, maybe they're right. There's probably a more simple way to code this. But on my website that Holodeck tutorial walks you through every step of that code painstakingly with volumes of explanation. You can jump to the end and download the final code. The tutorial actually walks you through creating the code one step at a time and so it's broken up into several code samples as you build up the code. That tutorial was made with the absolute beginner in mind.

After that one took me the better part of a year just to make one tutorial, I decided to cut with the exegesis and commentary and to just make code examples and comment them really well. I have so many things I want to teach and not enough time to write tutorials for half of it.

Looks like by the time I got to my Glowing Grid example I had simplified this camera quite a bit. Here is the project code for that and it's a pretty sweet simple little program using HLSL instead of BasicEffect to make the grid "glow". It needs some work, but it was a pretty cool little example program if I don't say so myself.

On the website it is the "Sample of HLSL" code. But if you don't want to download it, here's the relevant code:

This code is still maybe a little vector crazy but a lot more straight forward. It's well commented which makes it very difficult to read here because of the word wrap and lack of color coding you would get in Visual Studio. However, if you go to the top of the code box and click on the "view source" button it will open it in note pad which will not word wrap it and makes it easier to read. It's still not color coded, so that's tough but just not word wrapping helps.

        Matrix ProjectionMatrix;    //Camera's conversion formula to project onto a 2D screen (your computer monitor).
        Matrix ViewMatrix;  //The camera. Passed to all drawable game components so that they can draw with the same camera.
        Vector2 CameraPosition; //2D position of the camera on the 2D X,Z plane. (Converted to 3D using terrain altitude.)
        Vector2 CameraFacing;   //2D arrow representing the direction the camera is facing on the X,Z plane.
        float CameraPitch;  //Used to look up or down.
        TexturedGridComponent TheGrid;  //The terrain grid object.
        CameraMatricesInterface[] CameraUpdateArray;    //Array used to call all drawable game components.
        const float CameraRotationSpeed = 0.01f;    //Radians per frame that the camera will rotate.
        const float CameraMoveSpeed = 0.11f;     //Units/meters per frame that the camera will travel at.
        const float MaxCameraPitchAngleInRadians = MathHelper.PiOver4;  //Amount that the camera can look up. (Also, amount it can look down.)


            float HeightOfTerrain;  //Used to set the 3D camera's Y axis position.
            bool FootStepsShouldPlay = false;   //Turns the footstep sound on and off.
            Vector3 Camera3DPosition;   //Used to convert the camera's 2D position to 3D.
            Vector3 CameraLooksTowards; //Used to convert the camera's 2D facing direction to 3D.



 //Camera controls.
            if (KB.IsKeyDown(Keys.E))   //Look up.
            {
                CameraPitch += CameraRotationSpeed;
                if (CameraPitch > MaxCameraPitchAngleInRadians) CameraPitch = MaxCameraPitchAngleInRadians;
            }
            if (KB.IsKeyDown(Keys.Q))   //Look down.
            {
                CameraPitch -= CameraRotationSpeed;
                if (CameraPitch < -MaxCameraPitchAngleInRadians) CameraPitch = -MaxCameraPitchAngleInRadians;
            }
            if (KB.IsKeyDown(Keys.W))   //Forward.
            {
                CameraPosition += CameraFacing * CameraMoveSpeed;
                FootStepsShouldPlay = true;
            }
            if (KB.IsKeyDown(Keys.S))   //Backwards.
            {
                CameraPosition += CameraFacing * -CameraMoveSpeed;
                FootStepsShouldPlay = true;
            }
            if (KB.IsKeyDown(Keys.D)) CameraFacing = Vector2.Transform(CameraFacing, Matrix.CreateRotationZ(CameraRotationSpeed));
            if (KB.IsKeyDown(Keys.A)) CameraFacing = Vector2.Transform(CameraFacing, Matrix.CreateRotationZ(-CameraRotationSpeed));
            if (KB.IsKeyDown(Keys.C))
            {
                CameraPosition += new Vector2(-CameraFacing.Y, CameraFacing.X) * CameraMoveSpeed;    //Vector "trick". With vectors, when you switch X and Y, and negate Y, you get a vector 90 degrees clockwise to the first. 
                FootStepsShouldPlay = true;
            }
            if (KB.IsKeyDown(Keys.Z))
            {
                CameraPosition += new Vector2(CameraFacing.Y, -CameraFacing.X) * CameraMoveSpeed;    //Vector "trick". With vectors, When you switch X and Y, and negate X, you get a vector 90 degrees counter clockwise to the first. 
                FootStepsShouldPlay = true;
            }





 CameraFacing.Normalize();   //CameraFacing is "supposed" to ONLY represent a direction and therefore should be normalized. Otherwise, you could have a bug here.
            HeightOfTerrain = TheGrid.TerrainHeightBelowPoint(CameraPosition);  //Get the height of the terrain below the camera.
            Camera3DPosition = new Vector3(CameraPosition.X, HeightOfTerrain + 1.65f, CameraPosition.Y);    //Convert the 2D camera position to 3D since it's really in a 3D world.
            CameraLooksTowards = new Vector3(CameraFacing.X, 0f, CameraFacing.Y);   //The camera's facing is also maintained in 2D and must be converted to 3D to actually use.
            CameraLooksTowards = Camera3DPosition + CameraLooksTowards; //CreateLookAt's "LookAt" parameter is a point in 3D space. We instead want it to be a point relative to Camera3DPosition. In other words, "look from the camera to this point". Try it without this line and you'll see; it will look from the feet rather than from the eyes without this.
            ViewMatrix = Matrix.CreateLookAt(Camera3DPosition, CameraLooksTowards, Vector3.Up);     //Set the camera. Up is "kinda" a cheat.
            ViewMatrix = ViewMatrix * Matrix.Invert(Matrix.CreateRotationX(CameraPitch));   //Do a rotation to simulate the camera, or user's head, looking up or down.



This post has been edited by BBeck: 18 May 2015 - 08:36 AM

Was This Post Helpful? 1
  • +
  • -

#6 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: XNA 3D. Questions.

Posted 18 May 2015 - 10:48 AM

So here are the "critical lines of code" to answer your question of how to tilt the view up and down. I create the ViewMatrix with the CreateLookAt method passing in the camera's 3D position as a Vector3 and the spot that the camera looks at also as a Vector3 which is an arrow pointing straight "in front" of the camera whichever direction the camera now needs to face. Since this is a first person camera that doesn't need to do anything but walk across the terrain and look up or down only so far, I can use Vector3.Up as a cheat rather than calculating an actual up vector that points above the camera. Besides, in this initial position I'm making the camera horizontal and not looking up or down yet and so it's correct for now anyways before you look up or down. By recreating the View Matrix from scratch every frame I can do this. There are advantages and disadvantages to creating it every frame that you have to weigh. It might be a bit harder to keep it from over rotating if I maintained pitch by carrying the same view matrix from frame to frame. By rebuilding it every time I just have to keep track of a pitch angle and keep it from becoming too large positive or negative.

Then I modify the View Matrix to tilt it by the angle in radians stored in CameraPitch. I do that by creating a rotation matrix rotating around the local X axis rather than the game world's X axis by making this the second operand in the equation; rotation * ViewMatrix would rotate around the world's axis which is not what we want. I invert the rotation matrix because it is being used with a view matrix and everything must be backwards to use with the view matrix. Then I combine them by multiplying the ViewMatrix times the inverted rotation.

           ViewMatrix = Matrix.CreateLookAt(Camera3DPosition, CameraLooksTowards, Vector3.Up);     //Set the camera. Up is "kinda" a cheat.
           ViewMatrix = ViewMatrix * Matrix.Invert(Matrix.CreateRotationX(CameraPitch));   //Do a rotation to simulate the camera, or user's head, looking up or down.



I looked for a more simple example but it appears that some of my old code has been deleted, specifically the code where I created my own LookAt method. I want to post that but it looks like it may be gone forever. That's part of the reason I teach and post stuff on my website because it gives me a backup copy if it gets deleted off my computers. Because I know eventually I'll have to come back and reference my own code to see how I did something.

The "Matrices in Motion" tutorial may be one of the best ones I have showing how to use matrices at the moment, but unfortunately it uses kind of a complex chase camera rather than a first person shooter type camera. The camera is on a "boom" attached to an object and you can rotate the camera or rotate the object that it is attached to. But it still may be worth taking a look at although I meant it not so much for a beginner as someone with maybe 6 months experience or so. It's really mostly about animating things. But it displays how simple all of this stuff can be when you use matrices properly.

A lot of the movements tend to be one line of code rotating a matrix or something.

This post has been edited by BBeck: 18 May 2015 - 11:48 AM

Was This Post Helpful? 2
  • +
  • -

#7 dreaminxna  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 71
  • Joined: 10-June 13

Re: XNA 3D. Questions.

Posted 23 May 2015 - 12:44 AM

I see.. I understand the near and far plane now. and these world, view, and projection matrix. Thank you. Although reading your whole post makes me feel that I have more to know about vectors. And uh you explain things in a way beginners could understand I suggest make a book about you know game programming. Right now I am watching your vector video. although it maybe out of topic, why didnt you make your video shorter like chapter by chapter? :D cause uh, most people in youtube are kind of impatient and just want to learn on what they think is relevant and the people who only knows that importance of vector and how many hours they have to spend just understand something works if they dont know vectors, that will go through the end of your video :D Just saying.

Again THANK YOU..
Was This Post Helpful? 0
  • +
  • -

#8 modi123_1  Icon User is online

  • Suitor #2
  • member icon



Reputation: 14033
  • View blog
  • Posts: 56,134
  • Joined: 12-June 08

Re: XNA 3D. Questions.

Posted 23 May 2015 - 07:55 AM

Quote

why didnt you make your video shorter like chapter by chapter? :D cause uh, most people in youtube are kind of impatient and just want to learn on what they think is relevant

Just because people act foolish and impulsive doesn't mean folks need to cater to it. ;)
Was This Post Helpful? 0
  • +
  • -

#9 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: XNA 3D. Questions.

Posted 23 May 2015 - 07:38 PM

Thanks for the complements.

I've thought about writing a book, but the problem is that I don't think there are that many people left on the planet doing this hardcore game programming stuff. Maybe I could write a generic book on terrains not specific to any one platform and just go through all the terrain technology or something. I have a book on terrains that is severely outdated. It's about 15 years old. I think I could do a book like that.

Really, I've just been trying to give away the knowledge for free. The community is so small that I'm not sure there's a lot of profit to be made in teaching. I just want to see the community grow. So, I try to give away everything I know for free.

Originally I did the website focused on XNA. Then when XNA stopped being supported by Microsoft, I eventually decided to switch to DirectX and maybe one day OpenGL. XNA really helped me get ready for DirectX like nothing else I've come across, especially with 3D.

Now I've decided to try and do a YouTube channel with the website as support and a place where I can post code examples for the videos.

I've gotten quite a bit of feed back telling me I need to break the videos up into chapters. That's just my inexperience. These are my first videos and I'm still learning what works and what doesn't.

I'm definitely taking into consideration the chapter thing for future videos. I don't know how to easily break up those videos already posted without re-recording them. And I don't want to go backwards; I've got a lot of new stuff I want to do videos on.

I've been thinking about doing a video on how 3D graphics works. And I think I need to do a video on Blinn-Phong shading and how that actually works. XNA's BasicEffect is pretty much a Blinn-Phong shader. Blinn-Phong is your basic 3D shader and one of the first shaders you will do when you start doing HLSL either in XNA or DirectX. (Or OpenGL's GLSL for that matter or pretty much any platform that you write shaders for.) Oh, and in the Vector video I explain a little of how vector normal are used to do lighting, that's the basic theory behind Blinn-Phong and it's how direct lighting with XNA's BasicEffect works.

My current project is what one might call a core DirectX 11 game engine, for lack of a better word. To call it an engine is really to exaggerate it a bit. It's certainly not an engine like Unity.

But I'm basically trying to create something similar to XNA where you have the Game1 class and you build your DX program by modifying the Initialize(), LoadContent(), Update(), and Draw() methods of the class. I want it to be something where XNA programmers immediately feel right at home.

It's going pretty well. I've been working on making my own model class very similar to XNA's model class. It's been quite an undertaking and I think I've been working on it for like a year. But it's coming along quite nicely.

For the last couple of months, I've been making several prototypes. First I learned Python to program my own custom model exporter from Blender to a human readable model file. Over the past several months, I first built a prototype in XNA to read the file and display a 3D model using my own custom model class (ignoring XNA's built in model class). Then I built the same thing in DirectX 11 and added functionality to save the model to an optimized custom format file that is binary. (It's basically my custom model class serialized and pretty much loads straight into the graphics card from the file.)

Today, I worked on a C# program that reads the binary file and displays its contents in a way that you can understand what the file contains. If you just open the file it's a stream of almost meaningless bytes of data. The C# program interprets the data and tells you what it means. I pretty much finished that today.

Tomorrow I'm probably going to get started on my mostly final model class in DX that will load the model from the binary file. I'll probably make a console app soon that will compile the human readable file from Blender directly to the binary file ready to load into the model class.

Then the "engine" will have all the functionality to handle keyboard input, the Xbox 360 controller input, display a skybox, and load as well as animate any textured rigid models you can create in Blender.

Then maybe it will be time to do a video explaining the code for it.

Anyway, glad to hear you are getting some use out of my videos and writings. I put a lot of time into it in hopes that someone will. A lot of times it feels like no one is using them and it's easy to wonder why bother if no one is using it. But if even a few people are getting some use out of it, it makes it all worth while.

And feel free to ask any questions! I'm always glad to answer them!

Here is a video of he current DX project ("game engine") I've been working on:

Video

This post has been edited by BBeck: 24 May 2015 - 06:05 AM

Was This Post Helpful? 0
  • +
  • -

#10 dreaminxna  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 71
  • Joined: 10-June 13

Re: XNA 3D. Questions.

Posted 24 May 2015 - 05:05 PM

Quote

Really, I've just been trying to give away the knowledge for free. The community is so small that I'm not sure there's a lot of profit to be made in teaching. I just want to see the community grow. So, I try to give away everything I know for free.


This is true. Every time you ask something on different forums other's will just say, "Why dont you use unity". Not that its a bad thing. Its just that most people got caught in the idea of "make games not engine".



Quote

Now I've decided to try and do a YouTube channel with the website as support and a place where I can post code examples for the videos.

I've gotten quite a bit of feed back telling me I need to break the videos up into chapters. That's just my inexperience. These are my first videos and I'm still learning what works and what doesn't.

I suggest watching thenewboston channel. The instructor there is pretty good at breaking stuff into smaller chapters.

Quote

I'm definitely taking into consideration the chapter thing for future videos. I don't know how to easily break up those videos already posted without re-recording them. And I don't want to go backwards; I've got a lot of new stuff I want to do videos on.

I've been thinking about doing a video on how 3D graphics works. And I think I need to do a video on Blinn-Phong shading and how that actually works. XNA's BasicEffect is pretty much a Blinn-Phong shader. Blinn-Phong is your basic 3D shader and one of the first shaders you will do when you start doing HLSL either in XNA or DirectX. (Or OpenGL's GLSL for that matter or pretty much any platform that you write shaders for.) Oh, and in the Vector video I explain a little of how vector normal are used to do lighting, that's the basic theory behind Blinn-Phong and it's how direct lighting with XNA's BasicEffect works.

This!.. I want this :D/> Do you have any timeline on when to release the next video? :D/>

Quote

My current project is what one might call a core DirectX 11 game engine, for lack of a better word. To call it an engine is really to exaggerate it a bit. It's certainly not an engine like Unity.

But I'm basically trying to create something similar to XNA where you have the Game1 class and you build your DX program by modifying the Initialize(), LoadContent(), Update(), and Draw() methods of the class. I want it to be something where XNA programmers immediately feel right at home.

Isn't that what monogame do?


Quote

It's going pretty well. I've been working on making my own model class very similar to XNA's model class. It's been quite an undertaking and I think I've been working on it for like a year. But it's coming along quite nicely.

For the last couple of months, I've been making several prototypes. First I learned Python to program my own custom model exporter from Blender to a human readable model file. Over the past several months, I first built a prototype in XNA to read the file and display a 3D model using my own custom model class (ignoring XNA's built in model class). Then I built the same thing in DirectX 11 and added functionality to save the model to an optimized custom format file that is binary. (It's basically my custom model class serialized and pretty much loads straight into the graphics card from the file.)

Today, I worked on a C# program that reads the binary file and displays its contents in a way that you can understand what the file contains. If you just open the file it's a stream of almost meaningless bytes of data. The C# program interprets the data and tells you what it means. I pretty much finished that today.

Tomorrow I'm probably going to get started on my mostly final model class in DX that will load the model from the binary file. I'll probably make a console app soon that will compile the human readable file from Blender directly to the binary file ready to load into the model class.

Then the "engine" will have all the functionality to handle keyboard input, the Xbox 360 controller input, display a skybox, and load as well as animate any textured rigid models you can create in Blender.


This is the kind of stuff I always ask my self if will ever be able to do if I became a game programmer. For now, seems really impossible for me




Quote


Looks cool. Make it open source :D/>

This post has been edited by dreaminxna: 24 May 2015 - 05:10 PM

Was This Post Helpful? 0
  • +
  • -

#11 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: XNA 3D. Questions.

Posted 25 May 2015 - 06:44 AM

View Postdreaminxna, on 24 May 2015 - 07:05 PM, said:

This is true. Every time you ask something on different forums other's will just say, "Why dont you use unity". Not that its a bad thing. Its just that most people got caught in the idea of "make games not engine".

Yes. I have somewhat mixed feelings about Unity. It's awesome and wonderful and terrible at the same time.

I worry that Unity makes things a bit "too" easy. It think a lot of people may be putting the cart before the horse with Unity; they go in with no programming skills and think they can go far without programming skills. But at the end of the day, you need some pretty serious programming skills even to do Unity. Or at least "someone" does. Another problem with Unity is that you can go buy the scripts you need a lot of times, which is awesome because it saves time on projects where there are not a lot of people working on it. But then what have you learned if you copy or buy a script to do things?

Then worse, it seems to me that you sooner, rather than later, realize that a lot of the art assets and scripts you need or want are not available at any price and that you are going to have to create them yourself. And then suddenly you really need those skills that you managed to avoid learning when you bought all that stuff.

I'm still a fan of Unity although I myself spent about 6 months in it and then decided I missed DirectX and decided to do that instead. I found I actually enjoy the low level stuff and learning how all this works at the deepest level and I just wasn't getting that in Unity, especially when I was buying things rather than building them myself.

I still think XNA is one of the best ways to get into 3D game programming. And MonoGame continues it. The XNA 3.1 books were especially good and gave me the foundation to really start understanding. Unfortunately, with XNA 4.0 they decided to completely overhaul how it draws, which is kind of critical. So, there are some significant code changes between 3.1 and 4.0 that they made on the excuse that it was setting them up for the future of XNA and that biting the bullet "now" would make the transition easier in the long run. Except, we know now there is no long run and that was the final version of XNA. So, then it doesn't make much sense to completely overhaul that, but hindsight's 20/20.

The biggest problem with that is that a lot of the great 3.1 books never got re-written for 4.0 which was needed because they are so different. But by the time the authors were getting ready to re-write those books I think Microsoft had already started talking about abandoning XNA.

XNA really gives you a chance to build your C# skills. My OOP programming and C# got a lot better working in XNA. Everything is so focused on code that you can't help but become a better programmer if you're doing it, unlike Unity where most of it is not even code and when you are coding a lot of people are copying and pasting someone else's script.

And XNA does things a lot closer to the way DirectX does them. You get to play with things like vertex buffers and matrices in XNA. You need to pretty much master that before going into DirectX because DX is going to do the exact same thing in a much more complex environment. Really learning to do 3D in XNA, gives you the foundation for DX. Because without that foundation, you have to learn all that same stuff in DX where you have even more complicated stuff to learn in addition to all that game programming stuff. You could completely master game programming in XNA and DX would still be a little bit of a learning curve. Yet, almost everything you learn in XNA will be used in DX.

I really hate that Microsoft decided to drop it.

Quote

I suggest watching thenewboston channel. The instructor there is pretty good at breaking stuff into smaller chapters.


I just checked it out. Interesting.

Quote

This!.. I want this :D/> Do you have any timeline on when to release the next video? :D/>


No. It's on the "to do" list and it's the next video I had been thinking about doing. I can't decide if I want to do another Power Point Presentation (which I'm not super crazy about) or if I want to do a draw on the board lecture like a classroom or Kahn Academy. The Kahn Academy thing was what I wanted to do originally, but I'm not sure exactly how to do the electronic chalk board.

Anyway, knowing that someone would like to see it motivates me to get to work on it quicker.

I have a lot of projects to write code that have been higher on the agenda, but I'll see what I can do.

Quote

Isn't that what monogame do?


No. MonoGame really is XNA. It's the effort to keep XNA alive and it hopefully will eventually become XNA 5.0. It's in C# and you can just almost copy and paste all of your code directly from XNA to MonoGame. I've done it a few times where I write the whole project in XNA and then just copy and paste to MonoGame and it actually works. There are some differences, but they are minor and they usually involve more complex things like doing video for cut scenes or something.

My project is decidedly C++ and DirectX. XNA sets up a game loop in a way that makes a lot of sense. And it has kind of a component design theory behind it I think that it lends itself to.

While I want this to really make the XNA programmer feel at home, I'm not really trying to recreate XNA or duplicate the MonoGame effort. First, I don't intend to implement every little feature of XNA. But also, all the code for the entire thing is exposed in C++ and DX. With XNA, you've got a model class that does a tremendous amount of work for you that you could have done with pure XNA code, but it's already provided there for your use. But you can't pop open the hood and take a look inside that model class to see how it works. In my project, the model class is right there for you to pop open and trace through line by line if you like.

You can not only open it up and examine it, but you can modify it and make your own model class out of it if you don't like the way it works or want to add a new feature. It's just another class.

So, I'm basically trying to create a game programming class library that is not only open source, but well documented, and then do video tutorials explaining every single line of code. I could place all of these classes in a library and then just expose the interface to the library and it would be similar to XNA where you just call the classes and their methods to get the work done. But in this case, the library comes with full source code for you to modify and make your own. And chances are pretty good that you will want to.

It's mostly there to learn from so that you can then go off and make your own class library for game programming or modify mine to your own use. It should also give a platform where you can immediately jump in and start working on a project. There is a tremendous amount of code involved in starting up a DX project before anything even gets drawn to the screen. Throw in all the code to handle things you'll want to handle in almost every project like models and such and it really does turn into a lot of code to do even the most simple projects.

All that is provided for you in XNA and so it's easy not to appreciate how much code is there. But when you go into DX, none of that is provided for you. DX is like writing a device driver. You are basically manipulating the hardware directly. And that doesn't necessarily have anything to do with game programming. You might be doing 3D graphics for engineering work or medical work or something. You might be building AutoCAD. Whatever it is you're doing in DX your telling the graphics card how to do it's job at a very fundamental level.

So, my point there is that to do 3D game programming, you can just jump straight in with XNA and start working on the game; with DX you have to figure out things like how to build your own model class before you can even start on a project. And so I want to provide sample code for people to say "Here's how I built my own model class and how you might build your own and if you don't like the way it works you can change it so that it works the way you want it to".

Now Microsoft unofficially provides the DirectX ToolKit. And that has some things like sprites and models and stuff so that you can get directly to work in DX. But I left Unity because I wanted to do things myself in order to learn how to do them. So, I refuse to use the TK. It's only half heartily supported by Microsoft and it might get deprecated out in future versions of DX. Most of that stuff was built into DirectX until they went to DX11. And I think they did that because pretty much all professional game designers ignore that stuff like the built in model class and make their own anyway.

It seems to me that your model class can be somewhat personal. The more I get into it, the more I can see where you may or may not want specific features. Like how many texture layers does your model class support? Can it handle normal maps and specular maps? I don't think the XNA model class can. I doubt the one in the TK can. But either way, you may want to implement or not implement a lot of that stuff in a way that is specific to your own project. So, I think that's why professionals make their own model class and Microsoft dropped the model class out of DX after DX 10.

Oh. You can also use the DX 10 model class in DX 11. It's deprecated and not recommended and you've got backwards compatibility issues, but people do it. The more accepted solution is to use the TK. But I learn a lot building my own.

And my project is mostly about sharing what I'm learning. It's really more of an educational project than it is a code project. And the goal is to make videos explaining every line of code in it and to keep expanding on it. And also to use it as a platform to teach stuff that is more game programming rather than engine like how to make a terrain and such.

In XNA, I can jump straight in and show you how to make a terrain. In DX, there is this enormous amount of code before you can even draw a triangle to the screen. So, having that in a constant library where the code is explained, but it's packed away where you don't see it unless you want to, makes it possible to jump in and explain game programming topics rather than "engine" type stuff like how to read keyboard input or setup a game loop.

Quote

This is the kind of stuff I always ask my self if will ever be able to do if I became a game programmer. For now, seems really impossible for me


It takes time and mostly a lot of practice. It also helps if you have people to show you the way.

I've spent over a decade at this. At first, I seemed to be getting nowhere for the first several years. I didn't have anyone to really show me the way and tried just about every direction imaginable. The benefit was that I picked up some skills that a lot of game programmers might not have such as modeling, texturing, animation and stuff on the art side. I'm not great at the art stuff, but at least I know how to do things like texture hair for a human model. I understand the process the artists need to go through to produce the art. I'm familiar with Max and Blender and Photoshop. Also, I've rigged, skinned, and animated 3D models. And there's also things like, "How do you make doors open and close?" or "How do you create a lake in your 3D world that you can swim in and it looks like you're in the water?" Stuff like that I picked up before learning any actual game programming working with engines and such.

But anyway, I spent a lot of time going off on different tangents not knowing how to learn what I wanted to learn which had some advantages. But the disadvantage was that I wasn't really learning how to write 3D games. XNA was what really changed all that for me.

It takes time, but if you learn something new every day, or at least every week, that will add up over time and you'll eventually realize you know how to do a whole lot. It's mostly about learning something new every week and practicing it by coding all the time.

Quote

Looks cool. Make it open source :D/>


I basically am. ;-)

The source code for pretty much that entire thing you see in the video is on my website already. The links on the website are to the entire VS2014 (Community Edition) project that produced that video (I just did a screen capture using Camtasia). So, it's not only the source code, but the art assets and everything else ready to either run or to modify and recompile.

The goal is to not only provide the source code, but to comment the source code to make it extremely easy to read through and then to do YouTube videos explaining the source code even further. At this point it's pretty much all "engine" in that there is a skybox class to produce the skybox and I have a SceneObject class that puts the ground, triangle, and yellow cube in the scene (which I'm thinking about removing from the library as it's somewhat redundant with the model class although far more manual and easier to understand from a learning perspective). And then a model class that puts the toy car in the scene. Maybe I should have animated the wheels on the car. It's setup to do that. It would have been like another 10 to 20 lines of code. But I'm trying not to do too much at once and to make each project a tutorial for other people that they learn how to do a few things with each new project.

Like the first project on the website is core code that you have to have just to put a blank window on the screen which I've extensively commented the code on.

And the XNA portion of my website also has links to the project files where you can read through the source code to see how I did it.

Maybe I should release the library code with an open source license, but I'm pretty cool with anyone using it however they like short of copying and pasting it for tutorials and pretending like they wrote it without giving me any credit for having built the thing. Even that wouldn't be the end of the world as the main reason I put it out there is to help those who are getting started to get started. I figure people can either use it as a learning tool or as a foundation to write their own games. Once you learn how it's done, you may want to rewrite a lot of it anyway.

This post has been edited by BBeck: 25 May 2015 - 06:48 AM

Was This Post Helpful? 0
  • +
  • -

#12 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: XNA 3D. Questions.

Posted 25 May 2015 - 07:02 AM

Oh. I thought I might show you the Game.cpp file from the project that is in the video. I think if you glance over it, you will see some similarities to the Game1.cs file from XNA which you extend to make your game. This works basically the same way. With experience in XNA, most all the methods of the Game class should be familiar. There are some differences because it's DX and C++, but it should still be somewhat familiar. Also realize this produced the scene in the video so most of the code here is optional.

#include "Game.h"


Game::Game(void)
{
}


Game::~Game(void)
{
}


//=====================================================================================================================
//  Game::Initialize()
//
//	Purpose: 
//		To allow any code you want to run once at startup not associated with art assets.
//
//	Input:
//		None.
//
//	Output:
//		bool - The program will close if it returns false assuming a catastrophic error has occured.
//
//  Notes:
//		
//
//=====================================================================================================================
bool Game::Initialize()
{
	bool GameObjectInitializedProperly = false;		//Must be set to true to keep the program from closing.
	D3D11_VIEWPORT DXViewPort;						//Used to query the screen aspect ratio for the Projection matrix.
	UINT NumberOfViewPorts = 1;						//Required by RSGetViewports.


	GraphicsDeviceContext->RSGetViewports(&NumberOfViewPorts, &DXViewPort);		//Get a pointer to the viewport so we can ask it what it's aspect ratio is.
	Projection = XMMatrixPerspectiveFovRH(XM_PIDIV4, DXViewPort.Width/DXViewPort.Height, 0.1f, 5000.0f); //Create a RH Perspective Projection matrix.

	GameObjectInitializedProperly = Shader.Initialize(GraphicsDevice, GraphicsDeviceContext);	//Do any initialization required for the Shader class and fail if it fails.
		
	InFullScreenMode = false;	//Running in windowed mode makes debugging easier.

	CameraHeight = 1.68f;		//Roughly the average eye height in meters of an average man. Our camera will stay at this level to make it feel like we are in the scene.
	CameraFacingNormal = XMVectorSet(0.0f, -1.0f, 0.0f, 0.0f);	//Probably needs a rewrite but this is actually used as a 2D vector.
	CameraPosition = XMVectorSet(0.0f, 10.0f, 0.0f, 0.0f);		//Looking into the scene and positioned to the side.
	CameraTilt = 0.0f;

	DiffuseLightDirection = XMFLOAT3(0.0f, -1.0f, -1.0f);	//3D Normal pointing in the direction the global scene light is shining in.
	XMStoreFloat3(&DiffuseLightDirection, XMVector3Normalize(XMLoadFloat3(&DiffuseLightDirection)));	//Normalize just incase the programmer forgets to. Set the length of the vector to 1.

	DiffuseLightColor = XMFLOAT4(0.55f, 0.5f, 0.9f, 1.0f);	//Set the color of the scene light.
	AmbientLightColor = XMFLOAT4(0.07f, 0.07f, 0.4f, 1.0f);	//Light added to everything in the scene including shadow areas.

	return GameObjectInitializedProperly;
}
//=====================================================================================================================


//=====================================================================================================================
//  Game::LoadContent()
//
//	Purpose: 
//		To allow any code you want to run once at startup associated with art assets.
//
//	Input:
//		None.
//
//	Output:
//		bool - The program will close if it returns false assuming a catastrophic error has occured.
//
//  Notes:
//		Here we are creating all the objects in the scene. The switch statement makes it easy to manage this and add more
//	objects of your own. You merely define all the objects vertices it will need to be drawn and then list the index order
//	of every vertex to specify what order it will be drawn in. These examples merely count the number of vertices for the
//	index which is largely pointless. However, the design means you "could" reuse vertices or specify them out of order and
//	use the index buffer to specify what order to draw them in.
//
//		You'll quickly notice that the number of vertices you have to specify for even the most simple of objects is nearly
//	unacceptable. There are better ways, but we're learning the most straight forward way here which we will build on later.
//
//		Textures were created with Paint.Net by saving as .DDS files with mip maps.
//
//=====================================================================================================================
bool Game::LoadContent()
{
   	bool NoCatastrophicFailuresOccured = false;	//Close the program if even one mesh fails to initialize correctly.
	int x = 0;		//Which object.
	bool AllMeshesDefined = false;	//Flag to close the program if something goes wrong.

	bool TextureLoaded = GrassTexture.Load("./GameTextures/grass.dds", GraphicsDevice);

	//NoCatastrophicFailuresOccured = ModelBuilder.Build(Model, "./Models/RoboGuyRigid.txt", GraphicsDevice, GraphicsDeviceContext);
	NoCatastrophicFailuresOccured = ModelBuilder.Build(Model, "./Models/SmallCar.txt", GraphicsDevice, GraphicsDeviceContext);
	//NoCatastrophicFailuresOccured = ModelBuilder.Build(Model, "./Models/BlenderMonkey.txt", GraphicsDevice, GraphicsDeviceContext);
	//Model.Root.World *= DirectX::XMMatrixTranslation(0.f, 1.5f, 0.f);
	
	
	SkyBox.Define(GraphicsDevice, 2000.0f, "./GameTextures/NightSky_front5.dds", "./GameTextures/NightSky_back6.dds", 
		"./GameTextures/NightSky_top3.dds", "./GameTextures/NightSky_bottom4.dds", "./GameTextures/NightSky_left2.dds", "./GameTextures/NightSky_right1.dds");

	//Define vertices and attempt to initialize mesh for each object. 
	do
	{
		x++;
		switch (x)
		{
		case 1:
			{
				float ScaleFactor = 200.0f;
				float TerrainSize = 500.0f;
				SCENEOBJECTVERTEX GroundVertexList[6] =
				{
					{ XMFLOAT3(-TerrainSize, 0.0, TerrainSize), XMFLOAT2(0.0f, ScaleFactor), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-TerrainSize, 0.0f, -TerrainSize), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(TerrainSize, 0.0f, -TerrainSize), XMFLOAT2(ScaleFactor, 0.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },

					{ XMFLOAT3(TerrainSize, 0.0f, -TerrainSize), XMFLOAT2(ScaleFactor, 0.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(TerrainSize, 0.0f, TerrainSize), XMFLOAT2(ScaleFactor, ScaleFactor), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-TerrainSize, 0.0, TerrainSize), XMFLOAT2(0.0f, ScaleFactor), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) }
				};
				unsigned int GroundIndexList[6] = {0, 1, 2, 3, 4, 5};

				NoCatastrophicFailuresOccured = Ground.DefineMesh(GraphicsDevice, GraphicsDeviceContext, 6, GroundVertexList, 6, GroundIndexList, &GrassTexture);
				break;
			}
		case 2:
			{
				SCENEOBJECTVERTEX TriangleVertexList[3] =
				{
					{XMFLOAT3(0.0f, 0.5f, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f)},
					{XMFLOAT3(0.45f, -0.5, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f)}, 
					{XMFLOAT3(-0.45f, -0.5f, 0.0f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f)}
				};
				unsigned int TriangleIndexList[3] = {0, 1, 2};
				NoCatastrophicFailuresOccured = Triangle.DefineMesh(GraphicsDevice, GraphicsDeviceContext, 3, TriangleVertexList, 3, TriangleIndexList, NULL);
				Triangle.Transform(XMMatrixTranslation(1.0f, 2.0f, 1.0f));	//Position this object in the scene.
				break;
			}
		case 3:
			{
	
				SCENEOBJECTVERTEX CubeVertexList[VERTICESINCUBE] =
				{
					//Front Quad. 
					{ XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },

					{ XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
										
					//Right Quad.
					{ XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },

					{ XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(0.5f, 0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					
					//Bottom Quad. 
					{ XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					
					{ XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, -1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					
					//Back Quad. 
					{ XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					
					{ XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(0.5f, 0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, -1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					
					//Left Quad.
					{ XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					
					{ XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					
					//Top Quad. 
					{ XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },

					{ XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(0.5f, 0.5f, -0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					{ XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f), XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
					
				};
				unsigned int CubeIndexList[VERTICESINCUBE] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 };

			
				NoCatastrophicFailuresOccured = YellowCube.DefineMesh(GraphicsDevice, GraphicsDeviceContext, VERTICESINCUBE, CubeVertexList, VERTICESINCUBE, CubeIndexList, NULL);
				//YellowCube.Transform(XMMatrixScaling(2.0f, 2.0f, 2.0f));	//Make it twice as large.
				YellowCube.Transform(XMMatrixTranslation(-4.0f, 2.5f, 6.0f));	//Reposition it. Play with this value. Start out by adding or subtracting 2 from each number.
				break;
			}
		default:
			{
				AllMeshesDefined = true;
				break;
			}
		}
	} while(NoCatastrophicFailuresOccured && !AllMeshesDefined);


	return NoCatastrophicFailuresOccured;
}
//=====================================================================================================================


//=====================================================================================================================
//  Game::UnloadContent()
//
//	Purpose: 
//		To allow any code you want to run as the program closes in order to cleanup.
//
//	Input:
//		None.
//
//	Output:
//		None.
//
//  Notes:
//		All the game objects you create need their Shutdown() methods called to release the associate vertex and index buffers.
//	Since Shaders are owned by this class, it is also responsible for calling the Shutdown() method of any shaders created.
//
//=====================================================================================================================
void Game::UnloadContent()
{
	Model.Shutdown();
	GrassTexture.ShutDown();
	SkyBox.ShutDown();
	YellowCube.Shutdown();
	Triangle.Shutdown();
	Ground.Shutdown();
	Shader.Shutdown();	//Do any cleanup the Shader requires.
}
//=====================================================================================================================


//=====================================================================================================================
//  Game::Update()
//
//	Purpose: 
//		To do everything that needs to be done in one frame except draw stuff to the screen.
//
//	Input:
//		float TimeDelta - Amount of time that has passed since the last frame occured in milliseconds.
//
//	Output:
//		None.
//
//  Notes:
//		This is where most of your game code will be. It gets called every frame to change anything that needs to be changed
//	or done during that frame. It runs in a loop that needs to be called at least 30 times per second but there's nothing
//	to control how often it gets called. Things would move at unpredictable rates if we did not use TimeDelta to take in to
//	account the amount of time that has passed since the last frame.
//
//		We start out by processing the keyboard and game controller input to change the camera's position and direction. You
//	can also toggle full screen on and off.
//
//		The camera movement this frame is stored as a 3D vector that we treat more like a 2D vector. The facing normal should 
//	point in the direction we want the camera to face. And as a normal should have a length of 1. Any movement during the 
//	frame is cumulative from the various controls. When you move it uses either the CameraFacingNormal or a normal rotated 90
//	degrees away from the camera facing. It's basic vector addition to add the movement to the camera position.
//
//		XMMatrixLookAtRH is used to create a view matrix to simulate the camera every frame. Generally, I would say it is a 
//	good idea to not continuously recreate the view matrix but it's easier then maintaining a view matrix between frames and
//	this is really early in this tutorial series.
//
//		Finally some very simple rigid animation is thrown in to show you not only how to do it, but that it can be done and how
//	easy it is to do. Experiment by turning the rotations off and on and changing their directions and speed. 
//
//		The scene is lit with a simple Blinn-Phong shader that has "directional" lighting as opposed to point lights or
//	spot lights. Directional lighting is nothing more than a direction that the light shines in. It is a normalized vector
//	describing a direction and it has a color. That's all it is. Look at the shader for more detail. By rotating that direction
//	the light source seems to orbit the scene similar to a day and night cycle except the light shines through solid objects.
//
//=====================================================================================================================
void Game::Update(float TimeDelta)
{
	XMVECTOR LookAtVector;										//Position for camera to look at.
	XMVECTOR CameraLocation;									//Where the camera is positioned.
	XMVECTOR CameraMovement = XMVectorZero();					//The change in position this frame as a 3D vector.
	DWORD Controller1StateResult = XInputGetState(0, &Controller1State);	//XBox 360 controller state.
	float ThumbLHorizontal;										//Controller Left Thumb Horizontal value;
	float ThumbLVertical;										//Controller Left Thumb Vertical value;
	float ThumbRHorizontal;										//Controller Right Thumb Horizontal value;
	float ThumbRVertical;										//Controller Right Thumb Vertical value;


	if (!Keyboard.Update()) PostQuitMessage(0);	//If DirectInput has crashed, go ahead and shutdown the app. Otherwise, get the current keyboard state.

	if (Controller1StateResult == ERROR_SUCCESS)	//If there is an XBox360 controller plugged in...
	{
		if(Controller1State.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) PostQuitMessage(0);		//Close the program if the Back button on the controller is pressed.

		ThumbLHorizontal = (float) Controller1State.Gamepad.sThumbLX/32768.0f;	//Get Controller's current Left Thumb horizontal value.
		ThumbLVertical = (float) Controller1State.Gamepad.sThumbLY/32768.0f;	//Get Controller's current Left Thumb vertical value.
		ThumbRHorizontal = (float) Controller1State.Gamepad.sThumbRX/32768.0f;	//Get Controller's current Left Thumb horizontal value.
		ThumbRVertical = (float) Controller1State.Gamepad.sThumbRY/32768.0f;	//Get Controller's current Left Thumb vertical value.

		if (ThumbLVertical > 0.2f || ThumbLVertical < -0.2f) 
			CameraMovement = CameraFacingNormal * ThumbLVertical;		//Left thumb vert moves forward and back. CameraFacing is a vector and multiplying increases its length which is the speed here.
		if (ThumbLHorizontal > 0.2f || ThumbLHorizontal < -0.2f) 
			CameraMovement += XMVector4Transform(CameraFacingNormal, XMMatrixRotationZ(XM_PIDIV2)) * ThumbLHorizontal;	//Move camera left or right. Pi over 2 is a quarter circle. So, this says that in addition to any other movement this frame, move in a direction 90 degrees away from the direction being faced by an amount of whatever the Horizontal Left thumb value is.
		if (ThumbRVertical > 0.2f || ThumbRVertical < -0.2f)
			CameraTilt += (ThumbRVertical * -0.001f * TimeDelta);
		if (ThumbRHorizontal > 0.3f || ThumbRHorizontal < -0.3f) 
			 CameraFacingNormal = XMVector4Transform(CameraFacingNormal, XMMatrixRotationZ(ThumbRHorizontal * 0.0010f * TimeDelta));	//Rotate camera.
	}

	
	if (Keyboard.KeyPressed(DIK_LSHIFT))	//If these keys are pressed while the left shift key is pressed...
	{
		if (Keyboard.KeyPressed(DIK_D)) CameraMovement += XMVector4Transform(CameraFacingNormal,XMMatrixRotationZ(XM_PIDIV2));	//Move right. Pi over 2 is 90 degrees.
		if (Keyboard.KeyPressed(DIK_A)) CameraMovement += XMVector4Transform(CameraFacingNormal,XMMatrixRotationZ(-XM_PIDIV2));	//Move left.
	} 
	else
	{
		if (Keyboard.KeyPressed(DIK_ESCAPE)) PostQuitMessage(0);	//Stop program if escape is pressed.
		if (Keyboard.KeyPressed(DIK_W)) CameraMovement = CameraFacingNormal;		//Move forward.
		if (Keyboard.KeyPressed(DIK_S)) CameraMovement = -CameraFacingNormal;		//Move backward.
		if (Keyboard.KeyPressed(DIK_D))
		{
			CameraFacingNormal = XMVector4Transform(CameraFacingNormal, XMMatrixRotationZ(0.0010f * TimeDelta));	//Spin right.
		}
		if (Keyboard.KeyPressed(DIK_A)) CameraFacingNormal = XMVector4Transform(CameraFacingNormal,XMMatrixRotationZ(-0.0010f * TimeDelta));//Spin left.
		if (Keyboard.KeyPressed(DIK_E)) CameraTilt += (-0.001f * TimeDelta);	//Look up.
		if (Keyboard.KeyPressed(DIK_Q)) CameraTilt += (0.001f * TimeDelta);		//Look down.
		if (Keyboard.KeyPressed(DIK_I)) YellowCube.Transform(XMMatrixTranslation(0.0f, 0.0f, 0.01f));		//Move the Yellow Cube forward down the Z axis.
		if (Keyboard.KeyPressed(DIK_K)) YellowCube.Transform(XMMatrixTranslation(0.0f, 0.0f, -0.01f));		//Move the Yellow Cube backward down the Z axis.
	}
	
	if (Keyboard.KeyPressed(DIK_RALT))		//If the right Alt key is pressed...
	{
		if(Keyboard.KeyPressed(DIK_RETURN) )	//If return is pressed...
		{
			//Toggle between full screen and windowed mode.
			if(InFullScreenMode)
			{
				SwapChain->SetFullscreenState(false, NULL);
				InFullScreenMode = false;
			}
			else
			{
				SwapChain->SetFullscreenState(true, NULL);
				InFullScreenMode = true;
			}
		}
	}

	CameraPosition += CameraMovement * TimeDelta * 0.002f;	//Add the camera movement this frame scaled up or down by the amount of time that has passed since the last frame and a scale number you can change to the current camera position to give a new position.

	CameraLocation = XMVectorSet(XMVectorGetX(CameraPosition), CameraHeight, XMVectorGetY(CameraPosition), 1.0f);	//Throw away the height value of the CameraPosition and use the CameraHeight for the Y value.
	LookAtVector = CameraLocation + XMVectorSet(XMVectorGetX(CameraFacingNormal), 0.0f, XMVectorGetY(CameraFacingNormal), 1.0f);	//Camera should look at a spot that is in the direction of CameraFacingNormal (ignoring any Y value) and the distance in front of the camera position that is the length of CameraFacingNormal.
	
	View = XMMatrixLookAtRH(CameraLocation, LookAtVector, XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f));	//Create a right handed LookAt matrix for our view matrix putting the camera at CameraLocation looking towards the LookAt point and using the cheat for the Up direction.
	if (CameraTilt > XM_PIDIV2) CameraTilt = XM_PIDIV2;		//Don't allow the camera to tilt beyond 90 degrees upward.
	if (CameraTilt < -XM_PIDIV2) CameraTilt = -XM_PIDIV2;	//Don't allow the camera to tilt beyond 90 degrees downward.
	View = View * XMMatrixRotationX(CameraTilt);			//Apply camera tilt.

	Triangle.TransformAtOrigin(XMMatrixRotationY(0.001f * TimeDelta));	//Make the triangle spin by a constant rate regardless of frame rate.
	YellowCube.TransformAtOrigin(XMMatrixRotationY(-0.001f * TimeDelta));	//Make the yellow cube spin.
	//Move the model just for the fun of it.
	DirectX::XMMATRIX ModelRootMatrix = DirectX::XMLoadFloat4x4(&Model.Root.World);
	ModelRootMatrix *= XMMatrixTranslation(0.f, 0.f, -0.001f);	
	DirectX::XMStoreFloat4x4(&Model.Root.World, ModelRootMatrix);
	
}
//=====================================================================================================================


//=====================================================================================================================
//  Game::Draw()
//
//	Purpose: 
//		To do draw a single frame on the computer screen.
//
//	Input:
//		float TimeDelta - Amount of time that has passed since the last frame occured in milliseconds.
//
//	Output:
//		None.
//
//  Notes:
//		Since all the drawing code is tucked away neatly elsewhere, this method ends up being very short and sweet. There's
//	basically nothing to it. The first two lines clear the backbuffer in corn flower blue which is a constant. And then
//	it clears the depth stencil. You can clear the screen in any color you like.
//
//		Then each game object's Draw() method needs to be called to tell it to draw it self to the back buffer. The parameters
//	for the shader have to be sent here.
//
//		Finaly, the swapchain is told to make the backbuffer the frontbuffer and draw it to the screen by presenting it and
//	the image appears on the computer monitor. 
//
//=====================================================================================================================
void Game::Draw(float TimeDelta)
{
	GraphicsDeviceContext->ClearRenderTargetView(BackBuffer, RGBACornFlowerBlue);
	GraphicsDeviceContext->ClearDepthStencilView(DepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);

	SkyBox.Draw(GraphicsDeviceContext, View, Projection, Shader);
	Model.Draw(GraphicsDeviceContext, View, Projection, Shader, DiffuseLightDirection, AmbientLightColor, DiffuseLightColor);
	YellowCube.Draw(GraphicsDeviceContext, View, Projection, Shader, DiffuseLightDirection, AmbientLightColor, DiffuseLightColor);
	Triangle.Draw(GraphicsDeviceContext, View, Projection, Shader, DiffuseLightDirection, AmbientLightColor, DiffuseLightColor);
	Ground.Draw(GraphicsDeviceContext, View, Projection, Shader, DiffuseLightDirection, AmbientLightColor, DiffuseLightColor);
	

	SwapChain->Present(0,0);
}
//=====================================================================================================================





The essential code is much more simple:

#include "Game.h"


Game::Game(void)
{
}


Game::~Game(void)
{
}


bool Game::Initialize()
{
	bool GameObjectInitializedProperly = false;		//Must be set to true to keep the program from closing.
	D3D11_VIEWPORT DXViewPort;						//Used to query the screen aspect ratio for the Projection matrix.
	UINT NumberOfViewPorts = 1;						//Required by RSGetViewports.


	GraphicsDeviceContext->RSGetViewports(&NumberOfViewPorts, &DXViewPort);		//Get a pointer to the viewport so we can ask it what it's aspect ratio is.
	Projection = XMMatrixPerspectiveFovRH(XM_PIDIV4, DXViewPort.Width/DXViewPort.Height, 0.1f, 5000.0f); //Create a RH Perspective Projection matrix.

	GameObjectInitializedProperly = Shader.Initialize(GraphicsDevice, GraphicsDeviceContext);	//Do any initialization required for the Shader class and fail if it fails.

	return GameObjectInitializedProperly;
}


bool Game::LoadContent()
{
   	bool NoCatastrophicFailuresOccured = false;	//Close the program if even one mesh fails to initialize correctly.


	return NoCatastrophicFailuresOccured;
}


void Game::UnloadContent()
{
	Shader.Shutdown();	//Do any cleanup the Shader requires.
}


void Game::Update(float TimeDelta)
{
	XMVECTOR LookAtVector;										//Position for camera to look at.
	XMVECTOR CameraLocation;									//Where the camera is positioned.
	XMVECTOR CameraMovement = XMVectorZero();					//The change in position this frame as a 3D vector.
	DWORD Controller1StateResult = XInputGetState(0, &Controller1State);	//XBox 360 controller state.


	if (!Keyboard.Update()) PostQuitMessage(0);	//If DirectInput has crashed, go ahead and shutdown the app. Otherwise, get the current keyboard state.


	
		if (Keyboard.KeyPressed(DIK_ESCAPE)) PostQuitMessage(0);	//Stop program if escape is pressed.
	
	View = XMMatrixLookAtRH(CameraLocation, LookAtVector, XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f));	//Create a right handed LookAt matrix for our view matrix putting the camera at CameraLocation looking towards the LookAt point and using the cheat for the Up direction.
	
}


void Game::Draw(float TimeDelta)
{
	GraphicsDeviceContext->ClearRenderTargetView(BackBuffer, RGBACornFlowerBlue);
	GraphicsDeviceContext->ClearDepthStencilView(DepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);


	SwapChain->Present(0,0);
}



I comment a lot and use long variable names, so it tends to word wrap on the screen. If you use the view source button on the code window it expands it and makes it easier to read. But that second version should definitely remind you of XNA.

Basically that second version is what you would have for a blank project pretty much. Then you just add code to it like you do in XNA to make a project.

This post has been edited by BBeck: 25 May 2015 - 07:22 AM

Was This Post Helpful? 0
  • +
  • -

#13 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: XNA 3D. Questions.

Posted 25 May 2015 - 11:59 AM

So, I figured out how to do annotations on YouTube to make "chapters". It's not quite the same as dividing the chapters up into separate videos, but it at least allows someone to skip 20 minutes of my describing what vectors are and how they are used and get straight to the math if that's all that someone cares about.

I think modi123_1's sentiment is right in that rushing to the "easy way out" is a recipe for failure. Game programming is a field where you have to be willing to do what it takes and not give up. You have to be very independent and able to go get your own answers most of the time. And you have to learn to wade through large amounts of boring information that you probably already half know on a regular basis, or you'll never figure it out. Also, I recorded what I did for a reason and I would not have bothered making a two hour video if I didn't think what was being said was important.

On the other hand, if you've already watched it once, or if I'm covering ground you are already very familiar with and you just want to get some info on Vector Multiplication for example, then an index or table of contents, at the least, should be helpful.

And then there's the fact that I ramble and go on tangents that in my mind are important and related, but are maybe difficult to follow for someone trying to get to the core subject.

And also, when you find a new source whether it's a book or a tutorial video, most of the time it's going to waste your time and at best only contain a few useful pieces of information that you have to spend hours of digging to get that one piece of info wanted. If you just want to figure out vector multiplication and already otherwise are very familiar with vectors you might want to skip directly to that chapter. And if you're just evaluating the source, you probably want to kind of skim through the table of contents to find out what's covered, how good the presentation is, and whether what you're looking for is even covered at all.

So, I finally added some annotations as two tables of contents. Being video format it's hard to get a lot on one screen and so I broke it up into an intro section and a math section with a table of contents for each.


Was This Post Helpful? 1
  • +
  • -

#14 dreaminxna  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 71
  • Joined: 10-June 13

Re: XNA 3D. Questions.

Posted 26 May 2015 - 01:42 AM

Downloaded the project.. Its full of comment. Thats really nice. But im not that good at c++. Infact Im still afraid of it. Although I already read the c++ primer book.

Tried to run it but needs dx11 :D/> but yeah currently downloading it.

The video is so much better now. The only one left is adding the subject to your description. but thats just a minor detail. Anyway I think it will get more views :D


Edit: weird I do have a directx11 installed on my computer.

Im not really good at c++ debuging. but this the error.

Severity Code Description Project File Line
Error LNK2019 unresolved external symbol _vsnprintf referenced in function "long __cdecl StringVPrintfWorkerA(char *,unsigned __int64,unsigned __int64 *,char const *,char *)" ([email protected]@[email protected]) SceneObject

:D

This post has been edited by dreaminxna: 26 May 2015 - 02:55 AM

Was This Post Helpful? 0
  • +
  • -

#15 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: XNA 3D. Questions.

Posted 26 May 2015 - 03:13 PM

I was afraid of C++ for far too long. It's not that much different than any other programming language by itself. By itself, probably the only thing that makes it more difficult than C# is pointers and memory management. The fact that it is native (unmanaged) code certainly makes it a bit more difficult because most people have a lot of trouble with understanding pointers.

Then on top of that, you have the fact that that by itself only allows you to write console apps that are all text based and less impressive than 1980's DOS apps.

To get something like Windows Forms without going to .NET (CLI) and managed code - which begs the question "Why are you not using C# if you are going to do .Net and managed code?", you have to use a library like MFC. MFC is it's own learning curve on top of C++ and it's a pretty big one. Honestly, I've been trying to learn MFC here lately.

Another problem with MFC is I think it's already deprecated; I think they don't use it anymore in Window 8 let alone Windows 10. So learning it means you're learning an outdated technology. But I found it to be not that well documented and it's all just a wrapper for WIN32.

Real Windows programming is WIN32 programming (at least it was until Windows 8). WIN32 is not object oriented and was designed somewhere around the Windows 3.1 days. It's old and in and of itself not easy to learn as it also is pretty poorly documented, although I've learned to program in it to one extent or another over many years. MFC just turns WIN32 into a class library to make it object oriented. So, to learn MFC you pretty much need to learn WIN32 which is just as hard to learn as MFC and probably harder to learn than C++.

The good news for DX programmers is that you only have to use about 100 lines of WIN32 code to use DX and you can pretty much copy and paste the code every single time without exception. The only WIN32 I can think of you might use is if you want to handles some Windows Events and tap into the Windows Event Loop. You may want to process keyboard commands this way although I chose to use DirectInput from DX8 (yes, that's right DX8) rather than using the Windows Event Loop. So then, all you need to know of WIN32 is how to get it to give you a Windows Process to run under and an actual window to run in (even if you run in full screen mode). That's pretty much it. You really don't have to get very deep in WIN32 to do DX, and you don't have to even know what MFC is let alone how to program for it.

The bad news is that without at least a solid knowledge of WIN32, if not MFC, you are only going to be able to write console apps to build your tools with that are not DirectX apps. At the moment I've been using C#.Net for writing tools, but that's part of the reason I've been trying to put in some time to learn MFC. (I'm also working on MFC because I was reading Ivor Horton's C++ book in order to brush up on my C++ and learn C++ 11 as well as C++ 14. If I'm going to put code samples and tutorials on the Internet, I figured I didn't want to be writing them in outdated versions of C++. And I made it to the chapters on MFC.)

Then on top of this, DirectX is a COM object, or a series of COM objects. You don't have to know a lot about COM to use it other than COM objects pretty much manage their own memory and you don't have to de-allocate their memory. However, it is extremely important that you release them when no longer used because that's how they know it's no longer needed and can be de-allocated. COM objects have a counter and when you release them it decrements the counter. It won't release it from memory unless the counter hits zero. I think that's mostly all you need to know about COM for DX.

But there is another issue that arises and that is that DX, partially because it's a COM object, really likes pointers and so you are kind of forced to use pointers pretty regularly.

Combine that with the fact that you are going to want to pass a lot of these big memory hogs by reference to avoid duplicating them in memory and you're going to have to be really comfortable with pointers really quick at a level that causes most students to drop out of C++ class.

I'm starting to get comfortable with pointers. There are some books out there on the subject, but I think a lot of it is understanding the fundamentals of pointers and then just practicing and working through solving some pointer problems.

So, there is some valid reason to fear C++, but not so much the language (unless you mean pointers and memory management) but more all the libraries you have to use with it to get it to do things like DX and MFC. I let it intimidate me for many years before taking a C class in college that showed me my fears were over exaggerated just from everyone telling me how
"hard" it was. It's really not, and the other stuff is learn-able although it takes a lot of effort to learn it.

I started trying to write a guide on installing DX11, but it's complicated and I'm no expert. Probably the thing I dread most about C++ programming is linker errors. Everything in the actual code compiles great without a single problem and then I get linker errors and there's no hint what the actual problem is. I have really solid debugging skills when it comes to stepping through code with a debugger, but if I can't get it to link that's of no use at all. And I don't think I've ever seen a single linker error that ever made any sense to me. It just spouts some useless babble and then I blindly go off trying to find what the problem is. I compile often to get any linker errors as soon as possible because then I'll know which section of new code caused the linker error. I wish I had better skills at debugging linker problems.

Anyway, there are several things that could be keeping it from linking. Obviously, any linking error likely means it can't find part of the code it's looking for which begs the question of whether it's being told to look in the right places for it. There's also the question of what code it is looking for. I've never heard of "_vsnprintf" and this an error coming out of my code! That's why I hate linker errors; they mean absolutely nothing to me and I never know how to fix them although I always get them fixed in the end.

The first thing you should be aware of is that the "I probably shouldn't have" version of the code with the model class in it that I posted has a known bug in 32 bit. Try compiling in 64 bit. I don't think I introduced the bug until I brought in the model class, and so earlier examples will likely compile in 32 bit with no problem. It all compiles fine in 64 bit which is why I did not notice the issue until after I put it on the website. Normally, I compile in 32 bit then compile in 64 bit, but apparently I forgot to attempt to compile in 32 bit on that example.

There was an issue where SIMD instructions require you to do specific memory alignment when using Matrices (which you use all the time in DX). The memory alignment is not an issue in 64 bit and so it compiles just fine. But it blows up like an H-Bomb in 32 bit.

I fixed the bug by using a somewhat older method of coding that I had not wanted to use but I noticed all the book authors like Frank Luna were doing it the older way and figured out that this is why. It was easier just to avoid the issue rather than fixing it.

That brings up the next issue, which is that I use a fair amount of deprecated code in my examples. I wanted to use all the latest and greatest techniques and really made it a point to try and do so. But I soon found out DX is kind of in a state of disarray where Microsoft is kind of trying to force everyone to go to Windows 8 and Windows 10 but we don't want to go. Their answer to a lot of the problems is "Use Windows 8 or Windows 10". Maybe I'll go to Windows 10 this fall, I'll make the decision later this year. But for now I'm not leaving Windows 7. I bought Windows 7 specifically to avoid Windows 8 and would still be using Windows Vista if it were not for the fact that it is ending its support life and spending hundreds of dollars to go to Windows 7 rather than the much cheaper Windows 8 bought me more support life. I'm never going to Windows 8. We'll see about Windows 10 later. For now, I'm only coding for Windows 7.

And DX is kind of stuck in the middle of this. Nothing higher than DX11.0 will run in Vista and you had better have the latest Service Packs. DX11.1 I guess is what all my stuff is and won't run unless you have at least Windows 7 SP1 installed. DX11.2 requires at least Windows 8 but I don't see the point since you about 12 people on the planet are using Windows 8. ;-) If you are writing Win8 software, you aren't going to have many users to sell it to.

But there are some very significant differences between each version there. My stuff is very much DX11.1 for Windows 7 and anything outside of that is likely to have some issues that require at least small code changes. That means you also have to have a graphics card installed that supports DX11.1 which is probably going to be a more recent one purchased in the last few years.

In theory you can get DX11 to run in DX9 mode, but in practice I've found it not to be easy. My work computer is running Windows 7 SP1. Of course it doesn't really have a graphics card and I doubt it supports DX11. I tried to get it to run some of my DX11 code in DX9 mode but never did get it to run.

DirectX is extremely hardware dependent as well as very OS dependent. I don't have a lot of different systems I can test on, so I haven't faced most of these compatibility issues or tried to get code that runs on older machines or even on newer Win8 or Win10 machines. I'm not sure what all kinds of issues you could run into if not running Windows 7 SP1 with a DX11.1 compatible graphics card. But most of that should be a runtime problem instead of a linker problem.

With the linker, I would expect either some code is missing or it doesn't know how to find it.

One issue is that, partially because it's Windows 7 and partially just because they decided not to include a lot of stuff in DX11, I use a fair amount of deprecated code. I tried to use the latest and greatest where possible. But in the end I ended up using a lot of deprecated stuff just like all the authors of the DX11 books (discovering there's a reason they do this). A big example is that I use DirectInput from DX8 to handle the keyboard. DX11, at least with Win7, does not give you any "good" way to handle keyboard input. They stopped supporting the keyboard with DX9. You can use the WIN32 event loop to handle keyboard and I think I coded it to handle the Escape key to exit. But I think DirectInput gives you more direct access to the keyboard instead of waiting and hoping the Windows Event Loop tells your app about the keyboard events going on. This is largely a matter of choice but some of the DX books I have recommend using DX8's DirectInput.

But that along with several other things I use are deprecated from DX11. They are not in the newest version of DX11 which is included in the Windows SDK.

"Supposedly" if you have Windows 7 SP1 installed along with the latest updates from Microsoft you already have the latest version of DX11.1 on your machine. I've found this version does NOT include even DX11 functionality that is considered deprecated let alone anything from older version of DirectX. In order to get that older functionality to work (specifically I'm using some older DX11 stuff that requires it when compiling shaders) you have to install DX11 separately by installing it manually. So, you basically have to have DX11 installed twice, once as part of the Windows SDK and then also as a manual DX11 installation. The manual DX installation is only required if you use the deprecated functionality, but I've found that you need to be in Windows 8 or higher to have any real hope of not using deprecated functionality. I try to use anything deprecated as least as possible, but unfortunately it's very hard to avoid because MS doesn't give you good current ways of getting it done in Windows 7.

One problem I encounter was D3DX11CompileFromFile. It says DX11 right in the name! But it's deprecated. Go figure! That's an excellent example of what I'm talking about. They expect you to use newer Win8 functions, but I'm not in Win8, I'm in Win7! So, I can't really use Win8 functionality and the Win7 functionality I need is "deprecated" which means they didn't bother to include this DirectX 11 code in the Windows SDK with all the other DX11 code. So, now, I have no other choice but to install the second manual installation of DX11!

It seems no matter what you do, it's a nasty install especially if you aren't willing to cave and just go buy Windows 8 and forget about developing for any earlier version.

Here is a link to Microsoft's downloads:
https://support.micr...en-us/kb/179113

Now I would think that loading the project file "should" have copied the VC++ Directories as part of the project. But it may have lost those. I've found that to be the source of a lot of linker errors. In the project's properties there is "Configuration Properties" and "VC++ Directories" is under that. I use the following setting which I had to enter manually with every new project:

EDIT:Corrected these to match what I have in production where the code is working. Notice it uses both the Windows SDK and the DX SDK. I'm not 100% certain this is correct or the best way to do it, but it works on my machine. Again note that this is for 32 bit and you need x64 for 64 bit.

Executable Directories: $(WindowsSDK_ExecutablePath);$(ExecutablePath);$(DXSDK_DIR)Utilities\Bin\x86

Include Directories: $(WindowsSDK_IncludePath);$(IncludePath);$(DXSDK_DIR)Include

Library Directories: $(DXSDK_DIR)Lib\x86;$(WindowsSDK_LibraryPath);$(LibraryPath)

This helps the compiler and linker to find the Windows SDK and then the manual install of DirectX 11. It has to use the latest from the SDK when ever possible or it gets really confused, but then when it's something missing from the Windows SDK, like DirectInput for the keyboards or D3DX11CompileFromFile, it needs to then look in the manual DX11 installation for it.

That doesn't look right. I'll try and see what I have on my main computer since I'm copying this from the laptop where the code doesn't run. I'll change that to correct it later tonight when I can pull it off a computer where the code is actually running. Also note that any place where it says _x86 that is for 32 bit code and a 32 bit compile. Under the settings for the 64 bit compile all those need to be changed to _x64.

But this is why I tend to steer absolute beginners away from DX. Just getting the thing installed in the first place is a real chore. It just gets harder after that.

XNA really allows you to focus on game programming stuff and not even have to deal with this low level OS stuff that doesn't really even have anything to do with game programming but is absolutely necessary to get DX even running let alone doing something. Making a skybox or a terrain is pretty much the same in any environment you are in and so you can learn that stuff somewhere like XNA without having to worry about non-game programming stuff getting in the way. The problem with Unity is that it is so high level that it pretty much obfuscates this stuff completely away from you. You have no idea how a skybox is implemented under the hood because Unity handles all of that stuff and more for you with a few simple commands. In XNA you actually have to code that stuff yourself from scratch. In DX11 you not only have to code that stuff from scratch but you've got 100 additional things to worry about just to get a simple example of it running such as whether your matrices data storage is 16 bit memory aligned for the 32 bit compile of your code and what to do about it if not and you're using DirectXMath. Matrices just "work" in XNA, you don't have to worry about how they are allocated or deallocated on the heap or learn about SIMD instruction sets. DirectX with C++ is a whole new ball game.

This post has been edited by BBeck: 27 May 2015 - 03:26 AM

Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2