Heck I'm pretty proud of myself, a rotating cube ! now some more depth...
#1 Members  Reputation: 122
Posted 16 July 2001  02:25 AM
defining the cube :
typedef struct POINT{
float x,y,z;
}POINT;
POINT polygons[12][3]; /*3d*/
POINT poly2d[12][3];
I transform the 3d polygons into 2d like this :
...
for(i=0;i<8;i++)
for(j=0;j<3;j++)
flatten(polygons[j].x,polygons[i][j].y,polygons[i][j].z,i,j);
...
void flatten(float x, float y, float z, short i, short j)
{
poly2d[i][j].x=x; /*See? No real depth yet...*/
poly2d[i][j].y=y;
}
Here''s how I draw the cube :
for(i=0;i<8&&!key[KEY_ESC];i++)
{line(buffer,320+poly2d[i][0].x,240+poly2d[i][0].y,320+poly2d[i][1].x,240+poly2d[i][1].y,makecol(255,255,255));
line(buffer,320+poly2d[i][1].x,240+poly2d[i][1].y,320+poly2d[i][2].x,240+poly2d[i][2].y,makecol(255,255,255));
That just draws a line from triangles first point to second and from second to third so that the order goes like this :
2___1


3 (so that it won''t go from point 1 to 3)
Here are a few 4by4 rotation matrices that I use to rotate the cube around x and y axels :
X Rotational Matrix M = [ 1 0 0 0 ] (A is 0.3, guess it''s not degrees, because 1 is way too big rotation)
[ 0 cos A sin A 0 ]
[ 0 sin A cos A 0 ]
[ 0 0 0 1 ]
Y Rotational Matrix M = [ cos A 0 sin A 0 ]
[ 0 1 0 0 ]
[ sin A 0 cos A 0 ]
[ 0 0 0 1 ]
// matrix A contains the result of scaling, rotational and translation matrices combined
new_x = ( A.m[0][0] * x ) + ( A.m[1][0] * y ) + ( A.m[2][0] * z ) + A.m[3][0];
new_y = ( A.m[0][1] * x ) + ( A.m[1][1] * y ) + ( A.m[2][1] * z ) + A.m[3][1];
new_z = ( A.m[0][2] * x ) + ( A.m[1][2] * y ) + ( A.m[2][2] * z ) + A.m[3][2];
(I''m quoting straight from the website that helped me to do it)
Now, this all works fine, I get a nice cube that rotates... But, further looks smaller so I add this to flatten function :
void flatten(float x, float y, float z, short i, short j)
{
if(z!=0)
{poly2d[i][j].x=40*x/z;
poly2d[i][j].y=(40*y/z);}
else
{poly2d[i][j].x=x;
poly2d[i][j].y=y;}
}
At first it looks just like I wanted it. When the cube is in the original position :
.___
\_/
.
/\
.
But when I press the buttons to rotate it into either one of the directions it gets all strange. When I only rotate it a bit to one direction it looses most of its sides and only has two left with crossed lines on the other side. After that when I rotate it a bit to the other dir, it gets all tangled up, can''t explain how it looks after that.
The possible values for x, y and z are 50/50 for x and y and 0/50 for z.
Can you make any assumptions on what''s wrong with my code based on this information? I feel a great urge to be skilled in 3d programming, so please help me :p. Thanks..
#2 Members  Reputation: 150
Posted 18 July 2001  06:57 AM

Vash the Stampede
"Love & Peace!"
#3 Members  Reputation: 2076
Posted 18 July 2001  07:23 AM
Unfortunately, the "default" or "natural" axis of rotastion is the origin  (0,0,0)  meaning that portions of your cube may be rotated behind the camera! To solve that problem, define your cube''s vertices relative to an object axis. This object axis is located as some position relative to the camera, so the object position is added to all the vertices of the cube before projection (flatten()).
ie

Hope that helps. For a more complete discussion on 3D theory, search for a recent article on 3D from the basics, or something like that.
#4 Members  Reputation: 122
Posted 18 July 2001  08:23 AM
#5 Members  Reputation: 2076
Posted 18 July 2001  09:16 AM
quote:
Original post by Afterlife
I presume struct + struct is some sort of neat c++ trick to add the same struct components together?
Whoops!
The line:

should be replaced by the lines:

and cube_position should be declared as:

where POINT3 is a struct with x, y and z components.
My bad. If you're using C++, however, you can overload the addition operator( + ) so you can add your structs together (POINTS are simply 2D vectors). But maybe I should let you learn the language properly first...
Good luck. If you need more explanation, post (I'll monitor this thread for a few days).
Edited by  Oluseyi on July 18, 2001 4:20:35 PM
#6 Members  Reputation: 122
Posted 18 July 2001  10:36 AM
#7 Members  Reputation: 2076
Posted 19 July 2001  01:09 PM
To determine whether a polygon is facing the screen/camera, take the cross product of two of it edges (adjacent edges require only 3 vertices  which make up a triangle anyway). The order of specifying your vertices must be consistent across all your polys: either clockwise or counterclockwise. I provide the 3D operation, using 3D points (x,y,z).

If you want I can even show you how to do Cosine shading... post back here.
#8 Members  Reputation: 122
Posted 20 July 2001  01:28 AM
quote:
If you want I can even show you how to do Cosine shading... post back here.
Sure, that''d be great. And thanks for the previouse code, alltough I had some problems with it, it leaves out polygons, but the wrong ones. Can you see what I screwed up with this one? :

#9 Members  Reputation: 2076
Posted 23 July 2001  03:12 PM
To determine if that''s the problem, simply switch the test from less than to greater than.ie:

instead of

Now, the basics of Cosine Shading.
There are 2 types of light we consider in a simple 3D scene: ambient (or diffuse ) and specular . Ambient light is everywhere in the scene. It''s the "background" light that makes things visible and illuminates all objects the same (you can simulate a "dark" scene by having very low ambient lighting).
Specular lighting refers to the effects of "point sources" of light  closer, more direct source that reflect off surfaces in different amounts. Lambert''s Law states that the reflection of light from a perfectly diffusing surface varies as the cosine of the angle between the normal to the surface and the direction of the reflected ray. Thus, cosine shading.
Okay, enough theory. This all boils down to the proportion of the intensity of a point light source that is "reflected" by a surface for the eye to see is the cosine of the angle between the normal of the surface and the direction vector of the light. We know that the desired cosine can be obtained as the dot product of the normalized vectors. So:
Fraction of light intensity = dotp( surface_normal, light_dir_vector)
Say you had a ray of light in the direction l = (lx, ly, lz) with a magnitude L and RGB color values (lr, lg, lb). To determine the color of a white triangle (ambient lighting set to 0.2 so we can see something):

At this point I''d advocate C++ as your programming language if only because you can replace ugly functions like dotp(), etc with operators (symbols) like * (dot product), ^ (crossproduct) and you can overload them so that you can add RGB values using +. Cleaner to read and understand, and very powerful.
Okay, I don''t check GameDev too often right now (I''m travelling this weekend, and moving once I get back), so email me if you have more questions you''d like me to answer.
Good luck.