Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

H_3D_Engine

0.00/5 (No votes)
27 Jan 2009 1  
Simple 3D Engine draws 3D shapes in wireframe

CoolCode2.JPG

Introduction

Welcome to my 3D engine.
It's called H3D Engine, and it draws 3D shapes in wireframe, dots.
I tried to make it easy to use, and the code is different and well understood (from my viewpoint, but your suggestions will be appreciated).

Background

  • A background in mathematics such as cos, sin, etc.
  • A background about matrices (addition, multiplication).
  • It would be better if you have a good idea about OOP, and if you don't that means this article may be not helpful for you, or it might be interesting, who knows?
  • Any background about 3Ds (vertices, triangles, etc.)

Using the Code

In our engine, we have four main structures that can help us to organize data. They are defined as:

public struct tri_angle
{
	public tri_angle(float x, float y, float z)
	{
		p1 = x; p2 = y; p3 = z;
	}
	public float p1, p2, p3;
}

public struct GVerts3D
{
	public GVerts3D(float x, float y, float z)
	{
		X = x; Y = y; Z = z;
	}
	public float X;
	public float Y;
	public float Z;
}

public struct GVerts2D
{
	public int X;
	public int Y;
}
public enum RenderType {
	DotsR = 1,
	Indx
}

The first structure tri_angle is used to describe our indices (triangles) and the second one GVerts3D is used to describe our 3D Geometry (Vertices). The third one would help us when we project from 3D to 2D since our screen is flat and the last one is enum, which can help us to determine the rendering type in an easy way.

Here I'm going to show you how to use H3D Engine and if you are interested in its design, you can download the source code (from the link at the top of this page) and check it yourself.

Here we define the two main objects, and the instance from the engine which is called h3d here.

private GVerts3D[] Geom;
private tri_angle[] trt;
private H3DX h3d;

The H3DX is defined as:

namespace H_3D_Engine
{
	class H3DX
	{
		// -------Constructors-------
		//public H3DX()
		//public H3DX(int w,int h,int FOVLens)

		// -------Methods-------
		//public void SetView(int w, int h)
		//public void SetStream(GVerts3D[] Verts)
		//public void SetStreamIndex(tri_angle[] indx)
		//public void SetMatrix(CMatrix4 TM)
		//public void Trnslate(int x,int y,int z)
		//public CMatrix4 GetMatrix()
		//public void SetRenderMode(RenderType t)
		//public RenderType GetRenderMode()
		//public void Clear(Color c)
		//public void Push()
		//public void Present(Graphics g)
		//
		//private GVerts2D Project2DD(GVerts3D Verts)

		// -------Variables-------
		//private Bitmap mb;
		//private Graphics tdc;
		//private CMatrix4 HMat = new CMatrix4();
		//private GVerts3D[] HVerts;
		//private tri_angle[] index;
		//private int HWidth;
		//private int Lens;
		//private int HHeight;
		//private int tx, ty, tz;
		//private bool Ver_Render = false;
	}
}

Now after we defined our variables, we can initialize them only once in Form1_Load as:

private void Form1_Load(object sender, EventArgs e)
{
	//variables needed for rotation
	Angle = xAngle = yAngle = zAngle = 0;
	iX = iZ = 0;
	iY = 1;
	//setup our cube
	SetupDefaultMesh();
	//initializing our variables...
	h3d = new H3DX(Paper.Width, Paper.Height, 256);
	hRotMatrixX = new CMatrix4();
	hRotMatrixY = new CMatrix4();
	hTrans = new CMatrix4();
	hscaleMatrix = new CMatrix4();
	objMatrix = new CMatrix4();
	g = Paper.CreateGraphics();
	text4.Text = ms.ToString();
}

Paper is just a PictureBox which we are drawing into.

But the question is: what is CMatrix4?
CMatrix4 is a very helpful class that helps us to Rotate, Translate, or Scale 3D objects in an easy way and it is defined as:

namespace H_3D_Engine
{
	class CMatrix4
	{
		// -------Constructors-------
		//public CMatrix4()

		// -------Methods-------
		//public void RotateX(double degree);        //| 0  1  2   3  |
		//public void RotateY(double degree);        //| 4  5  6   7  |
		//public void RotateZ(double degree);        //| 8  9  10  11 |
		//public void Scale(float s);		//| 12 13 14  15 |
		//public void Translate(GVerts3D v)

		//public static double ToRadian(double angle)

		//operators
		//static public CMatrix4 operator *(CMatrix4 m1, CMatrix4 m2)

		// -------Variables-------
		//public float[] _Mat = new float[16];

	}
}

Now we are ready to set up our geometry. Here is a simple procedure to define a simple cube:

void SetupDefaultMesh()
{
	Geom = new GVerts3D[]{
		new GVerts3D( 1 ,1, 1), //0 right up
		new GVerts3D(-1 ,1, 1), //1 left  up
		new GVerts3D(-1,-1, 1), //2 left  down
		new GVerts3D( 1,-1, 1), //3 right down

		new GVerts3D( 1 ,1, -1), //4
		new GVerts3D(-1 ,1, -1), //5
		new GVerts3D(-1,-1, -1), //6
		new GVerts3D( 1,-1, -1), //7

	};

	trt = new tri_angle[]{
		new tri_angle(0,3,1),
		new tri_angle(1,2,3),

		new tri_angle(0,4,7),
		new tri_angle(0,3,7),

		new tri_angle(1,5,6),
		new tri_angle(5,6,2),

		new tri_angle(1,5,4),
		new tri_angle(4,0,1),

		new tri_angle(6,7,3),
		new tri_angle(2,3,7),

		new tri_angle(4,5,6),
		new tri_angle(4,7,6),
	};
}

So here we are going to do the interesting thing, the DrawScene procedure, which is defined as:

void DrawScene()
{
	h3d.Clear(Color.Blue);
	objMatrix.LoadIdentity(45);

	//scale our mesh to 1
	hscaleMatrix.Scale(ms);
	objMatrix *= hscaleMatrix;

	//Translate to origin
	hTrans.Translate(new GVerts3D(0, 0, 0));
	objMatrix *= hTrans;

	//rotate around (-1,0,-1) in 3 steps
	//1.translate into that point
	hTrans.Translate(new GVerts3D(-1, 0, -1));
	objMatrix *= hTrans;

	//2. do rotation
	hRotMatrixY.RotateY(CMatrix4.ToRadian(yAngle));
	objMatrix *= hRotMatrixY;

	//3.Translate it back
	hTrans.Translate(new GVerts3D(1, 0, 1));
	objMatrix *= hTrans;

	//hRotMatrixZ.RotateZ(CMatrix.ToRadian(zAngle));
	//objMatrix *= hRotMatrixZ;

	h3d.SetMatrix(objMatrix);
	h3d.SetStream(Geom);
	h3d.SetStreamIndex(trt);
	//h3d.SetRenderMode(RenderType.Indx);
	h3d.Push();

	objMatrix.LoadIdentity(45);

	hscaleMatrix.Scale(ms);
	objMatrix *= hscaleMatrix;

	hTrans.Translate(new GVerts3D(4, 0, 0));
	objMatrix *= hTrans;

	hRotMatrixY.RotateY(CMatrix4.ToRadian(yAngle));
	objMatrix *= hRotMatrixY;

	h3d.SetMatrix(objMatrix);
	h3d.SetStream(Geom);
	h3d.SetStreamIndex(trt);
	//h3d.SetRenderMode(RenderType.DotsR);
	h3d.Push();
	//Present the scene...
	h3d.Present(g);
}

What did we do?
At first, we made the screen clear with blue background color and then we drew our cube two times, the first time around the point (-1, 0, -1) and the second time around its center.

Good luck!

History

  • 24th January, 2009: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here