• Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

### #ActualDracoLacertae

Posted 06 December 2012 - 01:13 PM

If you want to do simple 3d lines and such, an easy way to get going is to try simple perspective.  This is what I played around with before I went into matrix math.  You will probably get into matrices at some point, but if you just want something basic, you can start with this.

3d without rotation or translation:

A single perspective transform is as easy as this:

//sw is screen width, sh is screen height
//zcut is z plane cutoff (don't render anything closer to or behind z) WHY?  z=0 is forbidden.  z > 1 means point is in front of camera.  z=-1 means point is behind camera.  zcutoff of .1, .01 etc are reasonable.

int perspective(float x, float y, float z, int* sx, int* sy)
{
if (z < zcutoff)
return 0;   //refuse to transform

sx = x* sw / z;		//scale X by screen height and distance.
//So, an object sw pixels wide at Z=1 is the width of the screen.
//Z=2, half the widht of the screen.  Z=.5, twice the width of the screen. etc
sy = y* sh / z;
return 1;
}

To draw a line in 3d:
void line3d( float x, float y, float z, float x2, float y2, float z2)
{
int sx, sy, sx2, sy2;
//only draws if both points are in front of camera
//later, if you want to get fancy, if one is in front, and the other is behind, you clip at z=zcutoff

if (perspective(x,y,z, &sx, &sy) && perspective(x2,y2,z2,&sx2, &sy2))
draw_line(sx,sy,sx2,sy2);
}

With the above snippets, you should be able to draw a 3d perspective object from the point of view of the origin.

To move the camera around, just subtract the camera position from the coordinates:

int perspective(float x, float y, float z, int* sx, int* sy)
{

x -= camera_x;
y -= camera_y
z -= camera_z;

if (z < zcutoff)
return 0;   //refuse to transform
sx = x* sw / z;		//scale X by screen height and distance.
//So, an object sw pixels wide at Z=1 is the width of the screen.
//Z=2, half the widht of the screen.  Z=.5, twice the width of the screen. etc
sy = y* sh / z;
return 1;
}

With that, you should be able to move around the 3d environment, but view is constrained to always looking down the Z axis.  But, its a start.

The last thing you can do, is allow camera rotation along the y axis (like wolf3d).  It's been a while but if http://www.siggraph....tran/2drota.htm is correct, then:

int perspective(float x, float y, float z, int* sx, int* sy)
{

float xr, yr, zr;
//translate to camera position

x -= camera_x;
y-= camera_y
z -= camera_z;

//rotate 2D about y axis:

xr = x * cos(camera_angle) - z * sin(camera_angle);
zr = z* cos(camera_angle) + x * sin(camera_angle);
yr = y; // height does not change

if (zr < zcutoff)
return 0;   //refuse to transform
sx = xr* sw / zr;		//scale X by screen height and distance.
//So, an object sw pixels wide at Z=1 is the width of the screen.
//Z=2, half the widht of the screen.  Z=.5, twice the width of the screen. etc
sy = yr* sh / zr;
return 1;
}

That should give you 5 degrees of freedom:  You can move up/down, left/right, forward/back and rotate about Y.  So, it's 'DOOM' controls.  You can add another rotation to look up/down, but at the point you should consider trying to understand matrices.

### #1DracoLacertae

Posted 06 December 2012 - 01:10 PM

If you want to do simple 3d lines and such, an easy way to get going is to try simple perspective.  This is what I played around with before I went into matrix math.  You will probably get into matrices at some point, but if you just want something basic, you can start with this.

3d without rotation or translation:

A single perspective transform is as easy as this:

//sw is screen width, sh is screen height
//zcut is z plane cutoff (don't render anything closer to or behind z) WHY?  z=0 is forbidden.  z > 1 means point is in front of camera.  z=-1 means point is behind camera.  zcutoff of .1, .01 etc are reasonable.

int perspective(float x, float y, float z, int* sx, int* sy)
{
if (z < zcutoff)
return 0;   //refuse to transform

sx = x* sw / z;        //scale X by screen height and distance.
//So, an object sw pixels wide at Z=1 is the width of the screen.
//Z=2, half the widht of the screen.  Z=.5, twice the width of the screen. etc
sy = y* sh / z;
return 1;
}

To draw a line in 3d:
void line3d( float x, float y, float z, float x2, float y2, float z2)
{
int sx, sy, sx2, sy2;
//only draws if both points are in front of camera
//later, if you want to get fancy, if one is in front, and the other is behind, you clip at z=zcutoff

if (perspective(x,y,z, &sx, &sy) && perspective(x2,y2,z2,&sx2, &sy2))
draw_line(sx,sy,sx2,sy2);
}

With the above snippets, you should be able to draw a 3d perspective object from the point of view of the origin.

To move the camera around, just subtract the camera position from the coordinates:

int perspective(float x, float y, float z, int* sx, int* sy)
{

x -= camera_x;
y -= camera_y
z -= camera_z;

if (z < zcutoff)
return 0;   //refuse to transform
sx = x* sw / z;	    //scale X by screen height and distance.
//So, an object sw pixels wide at Z=1 is the width of the screen.
//Z=2, half the widht of the screen.  Z=.5, twice the width of the screen. etc
sy = y* sh / z;
return 1;
}

With that, you should be able to move around the 3d environment, but view is constrained to always looking down the Z axis.  But, its a start.

The last thing you can do, is allow camera rotation along the y axis (like wolf3d).  It's been a while but if http://www.siggraph.org/education/materials/HyperGraph/modeling/mod_tran/2drota.htm is correct, then:

int perspective(float x, float y, float z, int* sx, int* sy)
{

float xr, yr, zr;
//translate to camera position

x -= camera_x;
y-= camera_y
z -= camera_z;

//rotate 2D about y axis:

xr = x * cos(camera_angle) - z * sin(camera_angle);
zr = z* cos(camera_angle) + x * sin(camera_angle);
yr = y; // height does not change

if (zr < zcutoff)
return 0;   //refuse to transform
sx = xr* sw / zr;     //scale X by screen height and distance.
//So, an object sw pixels wide at Z=1 is the width of the screen.
//Z=2, half the widht of the screen.  Z=.5, twice the width of the screen. etc
sy = yr* sh / zr;
return 1;
}

[/code]

That should give you 5 degrees of freedom:  You can move up/down, left/right, forward/back and rotate about Y.  So, it's 'DOOM' controls.  You can add another rotation to look up/down, but at the point you should consider trying to understand matrices.

PARTNERS