# FAQ: Graphics Math

Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last
• 09-22-2004
crepincdotcom
FAQ: Graphics Math
Hey guys,

this is more of a meth question and less of c, but after searching google for a long time I wasn't getting aynwhere.

Basically, I would like to render a 3d wireframe on the screen, WITHOUT LIBRARIES. I want to hack a few functions to draw lines, then use those, along with math, to make, for instance, a grid-plane that I can 'rotate' around, and have the lines stay in perspective.

so really there are two questions here:

1) (main) How can I use "transformation matrices" to move around this grid and keep the lines correct?

2) (insignificant) How can I stick a single pixel on the screen?

I'm not really looking for straight answers, but perhaps some article people might have seen over the years.

Thanks again,
• 09-22-2004
Salem
Well this is a nice long read
http://thorkildsen.no/faqsys/
• 09-22-2004
MrWizard
Start here, it's a 4 part series...

http://www.devmaster.net/articles/so...ring/part1.php
• 09-22-2004
crepincdotcom
Quote:

Originally Posted by Salem
Well this is a nice long read
http://thorkildsen.no/faqsys/

Seems to be the opening page... didn't have a lot of time now, but tomorrow whould I read the whole site? Or is there just a good long peice....

Thanks guys...

And a func to turn on a pixel in c?
• 09-22-2004
crepincdotcom
After reading the devmaster article..... I understand the math but fail to see how to take an x,y,z point and, using perspective, make it on the screen. (other than by dropping z, and having the camera dead-center)

I will read it again though, perhaps I missed something.....
• 09-22-2004
VirtualAce
You divide by Z - or in the case of modern graphics you divide by W. This is the perspective projection.

Before matrices were widely used this was the formula used for dividing by Z.

Screen.x=(View.x*Dist_To_Plane)/(View.z+CenterScreen.x);
Screen.y=(View.y*Dist_To_Plane)/(View.z+CenterScreen.y);

But with matrices this can be done quite easily and it can also then be added into the graphics pipeline that already uses matrices quite heavily. The advantage is you don't have to change your projection function significantly to perspective project your vertices into screen space.

You really need to buy a book on the mathematics of 3D graphics in order to understand how it all works.

Translation is really just this:

x+=distance_x;
y+=distance_y;
z+=distance_z;

But because of the way we multiply or concatenate matrices a 4x4 homogneous matrix works very well for this:

[1,0,0,0]
[0,1,0,0]
[0,0,1,0]
[distance_x,distance_y,distance_z,1]

A simple concatenation function (and not by any means the fastest) for a 4x4 matrix. Matrix is assumed to be a 4x4 array - again not the best way.

Code:

```void MatMultiply(float mat1[4][4],float mat2[4][4],float result[4][4]) {   for (int i=0;i<4;i++)   {         for (int j=0;j<4;j++)         {           result[i][j]=0.0f;           for (int k=0;k<4;k++)           {                 result[i][j]+=mat1[i][k]*mat2[k][j];           }         }   } }```

And a simple world transform function.

Code:

```void WorldTransform(vertex *vtxs,int numvtxs,float wm[4][4]) {   for (int i=0;i<numvtxs;i++)   {         float lx=vtxs[i].model.x;         float ly=vtxs[i].model.y;         float lz=vtsx[i].model.z;           float wx,wy,wz=0.0f;           wx=lx*wm[0][0]+ly*wm[1][0]+lz*wm[2][0]+wm[3][0];         wy=ly*wm[0][1]+ly*wm[1][1]+lz*wm[2][1]+wm[3][1];         wz=lz*wm[0][2]+ly*wm[1][2]+lz*wm[2][2]+wm[3][2];         vtxs[i].world.x=wx;         vtxs[i].world.y=wy;         vtxs[i].world.z=wz;   } }```
But thankfully in DirectX you don't need to worry about all of this because it is done for you. No more tracking of model, world, view, and screen vertexes/coordinates. But the above code is from a software 3D engine I wrote quite some time ago.
• 09-23-2004
Salem
> Seems to be the opening page
Yeah, click the mathematics link for actual tutorials
• 09-24-2004
crepincdotcom
Salem, that site will keep me busy for the next 11 hours.... ;)

OK bubba, I did your example. I finally saw that it works, and how, however it was in the article you previously sent me as x=D*X'/z... and D was a constant they showed how to get: 1/tan(theta). I figured theta was the angle to look at... but actually, as you posted, it's the distance from the plane.

That's cool.... but I was hoping to figure out how to make an x,y,z point become and x,y, but showing the peices behind the front at an angle, for instance up and to the right maybe, not just expanding sideways in the back. Do I do this with the rotation peice you showed me? Or am I paddling up the wrong creek?

Thanks guys,
• 09-24-2004
Perspective
You need to first perform all the rotations and translations in 3D, then project the resulting vertices on to the projection plane.
• 09-24-2004
crepincdotcom
so... say I have 8 points that make a box. I rotate the box sideways, then when I use the formula from about to get the 2-D points, it works?

I'l hack that up real quick and see if i can get it to work.

Thanks
• 09-29-2004
crepincdotcom
Ok, i'm having a hard time conceptualtizing this. I'mm trying to just make a wireframe box rotate. So I can draw one box... but getting the next point by a 2-degree rotation is hard.

So, I was wondering, does anyone know of any tutorials with example code that show how to do this? If I could just see someone else's code, I could figure it out. I've just never seen how these things are done in the "real world" (ie, not some little dude like me trying to do a big math thing.)

Thanks again you guys,
• 09-29-2004
VirtualAce
You are confused as to what is happening.

First all graphics in 3D are centered around 0,0,0. Every object is centered around 0,0,0 in model space or at least should be or weird things begin to happen. Since you want to always see your 2D wireframe box set the z coordinates to something greater than or equal to 1.0f, but greater than 1.0f is your best bet.

So imagine a universe. A universe is made of planets. The sun is just another very bright planet. All planets have their center at 0,0,0 in their model space. But you want to transform them to world space. So if you want your model to rotate in model space you must rotate first and then translate. If you translate first and then rotate your rotation will be in world space or will make the planet orbit the sun.

All models start in model space. They are then transformed to world space. Then to camera/view space, then to clip space, then to screen space.

It truly is impossible for me to explain 3D mathematics, matrix concatenation, and matrix transformation in one post. I would suggest purchasing a book about 3D to start you on your way. I could write a huge post here with all kinds of code, but it would only confuse the heck out of you. Get a book.
• 09-30-2004
crepincdotcom
OK, I will get a book. But, about centering 0,0,0: I first tryed that a while ago, and what came out was sorts of strange. But probably my fault. So, can you have negative values in the 3d-2d conversion? Ie, is 5,5,5 the same as 5,5,-5? It shouldn't be, I had trouble with that. So, basically, if I just make a box like 5,5,5 5,-5,5 -5,-5,5, etc for all 8 points, that should work?

Thanks agian,
• 10-04-2004
VirtualAce
This depends on your coordinate system. For all of my systems thus far I use this:

-X is left.
+X is right.
-Y is up.
+Y is down.
-Z is toward the camera.
+Z is away from the camera.

So a 2D 20x20 unit box that lies 1.0 z unit from the camera has the following vertexes wound in counterclockwise rotation. I say unit because these values must be appropriate for the system of measurement you are using. For now let's say that all units are pixels.

Vertex 0.......-20,-20,1
Vertex 1........20,-20,1
Vertex 2........-20,20,1
Vertex 3........20,20,1

Okay that is the front face. Now a 3D cube is just a front and a back face connected by 4 lines - which then create 4 more faces. So create the backface. Let's say it is 21 units away from the camera, thus giving our cube a width of 20, height of 20, and depth of 20.

Vertex 4.....-20,-20,21
Vertex 5.....20,-20,21
Vertex 6.....-20,20,21
Vertex 7.....20,20,21

Okay you now have all the vertexes needed for a 6 sided 3D cube. The only thing left to do is create the indices or indexes for the cube. Indexes allow you to specify vertex numbers that make up triangles. So each triangle will have 3 indexes. For instance let's triangulate the front face in a counter-clockwise fashion.

Triangle 1
Vertex 0
Vertex 1
Vertex 2

So the indices for triangle 1 are 0,1,2

Triangle 2

Vertex 1
Vertex 3
Vertex 2

Indices: 1,3,2

So your first 2 sets of indexes for the front face are:

0,1,2
1,3,2

Notice that you can specify these vertexes in any order as long as they proceed counterclockwise around the triangle when viewed from the front if your culling mode is counter-clockwise culling else you must specify vertices in clockwise order.

As you will notice indexing into the vertex data is much more efficient. In this picture alone you can see that these triangles share vertices 1 and 2 but we only declare them once. This means that you index array will be larger than your vertex array, but indices are integers and vertexes are normally floats - 3 of them to be exact. Indexing saves a lot of memory.

Also not that when you specify a triangle you need not specify the closing leg. For instance specifying 0,1,2 to Direct3D will cause a line to be drawn from 0 to 1, 1 to 2, and 2 to 0. You need not specify 2,0 in your index array. Most APIs automatically close the triangle for you so you only need to specify 3 indexes per triangle. Specifying 0,1,2 is much more effienct than doing this:

0,1
1,2
2,0

So instead of specifying six indexes per triangle you can specify three.
• 10-04-2004
VirtualAce
I omitted the texture coords from my first picture. Here is another picture with the texture coords.

They are specified in (u,v) format where u is the horizontal and v is the vertical.

They are specified in range 0.0f to 1.0f - which means that your texture coords are independent of texture size. If you specify .50f,.50f on a 100x100 texture it will be 50,50. If you specify .50f,.50f on a 1000x1000 texture it will be 500x500. Notice both correspond to the center of the texture regardless of size. These are called normalized texture coordinates since they always fall in the range 0.0f to 1.0f.
Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last