The 3D Story
Your guide to the third dimension.

Comments

The BOX1.CPP file is a short 3D engine that will demonstrate the rotation and projection formulas we've learned.
It uses the GFXMAN.CPP file.
The main problems involved in a 3D engine is how to represent the data. In this example the data is split in two. The 3D coordinates is called marks, these are rotates and projected. When that is done we'll iterate through a list of "lines", i.e. the indexes to two marks and a colour. These lines are then drawn between the projected marks.
The routines used for rotation and projection are called rotpoint and projpoint, these both return a 3D coordinate.
The coordinate returned from the rotpoint function simply returns the rotated point while the coordinate returned from projpoint returns the projected versions of X and Y but the untouched Z-coordinate.
This leaves us with calling the rotpoint and projpoint for each mark, and the draw all the lines.
Here is the actual code :

BOX1.CPP

#include <conio.h>			// For the keyboard
#include <math.h>			// For the sin(), cos() and pi
#include "gfxman.h"			// The graphics

#define MAXMARKS 8			// How many marks do we have
#define MAXLINES 12			// How many lines
#define DIST 256			// The dist value (try changing it)
#define MIDDLEX 160			// The x-coord for the origo
#define MIDDLEY 100			//  "  y-coord  "   "    "

void main(void);

struct point				// A 3D coordinate
{
	double x,y,z;
};

struct line				// A line
{
	int m1,m2;			// Index for two coordinates
	unsigned char colour;		// The colour
};

point rotpoint(point i,point a);	// Rotates a point
point projpoint(point i);		// Projects a point

void main(void)
{
	point rmark[MAXMARKS];

	point mark[]={{25,25,25},{-25,25,25},{-25,-25,25},{25,-25,25},
		      {25,25,-25},{-25,25,-25},{-25,-25,-25},{25,-25,-25}};

	line lines[]={{0,1,15},{1,2,15},{2,3,15},{3,0,15},
		      {4,5,15},{5,6,15},{6,7,15},{7,4,15},
		      {0,4,15},{1,5,15},{2,6,15},{3,7,15}};

	point angle={1*M_PI/180,0*M_PI/180,2*M_PI/180};


	SetVGA();

	do
	{
		Cls();


		for(int a=0;a
		{
			rmark[a]=projpoint(mark[a]=rotpoint(mark[a],angle));
		}



		for(a=0;a
			Line(rmark[lines[a].m1].x,rmark[lines[a].m1].y,
			     rmark[lines[a].m2].x,rmark[lines[a].m2].y,lines[a].colour);


		WaitRetrace();
	}
	while(!kbhit());

	getch();

	SetText();
}

point rotpoint(point i,point a)
{
	point r;

	r.x=cos(a.z)*i.x-sin(a.z)*i.y;
	r.y=sin(a.z)*i.x+cos(a.z)*i.y;
	r.z=i.z;

	i.x=cos(a.y)*r.x-sin(a.y)*r.z;
	i.y=r.y;
	i.z=sin(a.y)*r.x+cos(a.y)*r.z;

	r.x=i.x;
	r.y=sin(a.x)*i.z+cos(a.x)*i.y;
	r.z=cos(a.x)*i.z-sin(a.x)*i.y;

	return r;
}

point projpoint(point i)
{
	double t;
	point r;

	t=DIST+i.z;

	r.z=i.z;

	if(t)
	{
		r.x=i.x*DIST/t+MIDDLEX;
		r.y=i.y*DIST/t+MIDDLEY;
	}
	else
	{
		r.x=i.x+MIDDLEX;
		r.y=i.y+MIDDLEY;
	}

	return r;
}
There are three parts in the code that calls for some commenting. (Coloured areas)

The Initialization

Here all the variables are setup. The rmark vector will contain the projected coordinates while the mark contains the 3D coordinates.
The next line sets up the lines so that we get one square with indexes from 0 to 3 and one from 4 to 7, these are then connected (0 to 4, 1 to 5, etc). These values are indexes to the marks. The last value in each line is the colour.
The last line initiates the rotations (M_PI/180 is needed to transform the degrees to radians).

The Rotation and Projection

This loop simply iterates through all the marks. Each mark is rotated and projected. The assignment (mark[a]=rot...) is because the rotation is relative, i.e. we rotate it X degrees and then rotate the resulting coordinate X degrees the next loop and so on...
The point angle contains the relative rotation coordinates for the rotation around each axis.

The Drawing of the Lines

The lines are simply drawn by iterating through all lines and then draw a line between the projected coordinates in the assigned colour.
If you'd like to follow a line, just change the colour in the initialization part.

Compilation

To compile, just follow the instructions in the instructions in the VGA routines I appendix.
If you get any problems, just mail me at e8johan@etek.chalmers.se.



[ Previous | Main Page | Next ]
Copyright©1997 Johan E. Thelin