Jump to content

  • Log In with Google      Sign In   
  • 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