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

3D Vector Graphics Class

0.00/5 (No votes)
29 May 2012 1  
3D Vector Graphics class.

Introduction

About 3D Transformations

While displaying 3D objects on 2D, we have to convert the 3D Coordinates to corresponding 2D coordinates. Let us call it as projections. To create projections we have to do some sort of Vector Algebra.

Background 

Basically there are many types of projections; here we are referring only two types of projections

  1. Orthographic Projections
  2. In Orthographic projections, Projection P (x’, y’) on the 3D Point A(x, y, z) is computed as follows.

    x'=|Amag| *(Wx(.)A.Unitvector ());
    y’=|Amag|*(Wy(.)A.UnitVector ());

    Where Wx= [1 0 0]

    & Wy= [0 1 0]

    & (.) is the dot product of Vectors.

    Basically Wx &Wy are the Unit Vectors.

  3. Perspective Projections
  4. There are Three Types of Perspective Projections.

    1. Single Point Perspective.
    2. Two Point Perspective.
    3. Three Point Perspective.

Here we are discussing only Single Point perspective. The Perspective Projection is calculated by Matrix Multiplication.

X’=X/(rz+1);
Y’=Y/(rz+1);

Where r= -1/Zc

& Zc is the Distance at Z Direction from the Viewing Point.

Using the code

Compile and Build the code Provided with this article.

class C3DCanvas : public CDC  
{
	CBitmap		m_bitmap;		// Offscreen bitmap
	CBitmap*	m_oldBitmap;	// bitmap originally found in CMemDC
	CDC*		m_pDC;			// Saves CDC passed in constructor
	CRect		m_rect;			// Rectangle of drawing area.
	BOOL		m_bMemDC;
	CPen        m_penWhite;
	CPen        *m_oldPen;
	C3DVector   W_X;//(1,0,0);//Unit Vector for X Axis
	C3DVector   W_Y;//(0,1,0);//Unit Vector for Y Axis
	C3DVector   W_Z;//(0,0,1);//Unit Vector for Z Axis
	C3DVector   m_org;

	int m_winOrgX;
	int m_winOrgY;
	BOOL m_bPerpective;
public:
	C3DVector   m_camera;
	void SetCamera(double dx,double dy,double dz);
	void SetWindowOrg(int x,int y);
	void SetViewPortOrg(C3DVector v);
	void TranslateView(C3DVector v);
	void RotateView(float Angle,AXIS axis);
	void Line3D(C3DVector  P,C3DVector Q);
	void EnablePerspectiveView(BOOL bSet=TRUE)
	{
		m_bPerpective=bSet;
	}
	C3DCanvas(CDC* pDC, const CRect* pRect = NULL,COLORREF m_clrBkColor=0xffffff)
		:CDC(),
		W_X(1,0,0),
		W_Y(0,1,0),
		W_Z(0,0,1),
		m_org(0,0,0),
		m_winOrgX(0),
		m_winOrgY(0),
		m_camera(0,0,1000)
	{
		m_bPerpective=FALSE;
		ASSERT(pDC != NULL); 
		
		// Some initialization
		m_pDC = pDC;
		m_oldBitmap = NULL;
		m_bMemDC = !pDC->IsPrinting();

		// Get the rectangle to draw
		if (pRect == NULL) {
			pDC->GetClipBox(&m_rect);
		} else {
			m_rect = *pRect;
		}

		if (m_bMemDC) {
			// Create a Memory DC
			CreateCompatibleDC(pDC);
			pDC->LPtoDP(&m_rect);
			
			m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
			m_oldBitmap = SelectObject(&m_bitmap);
			
			SetMapMode(pDC->GetMapMode());

			SetWindowExt(pDC->GetWindowExt());
			SetViewportExt(pDC->GetViewportExt());

			pDC->DPtoLP(&m_rect);
			SetWindowOrg(m_rect.left, m_rect.top);
		} else {
			// Make a copy of the relevent parts of the current DC for printing
			m_bPrinting = pDC->m_bPrinting;
			m_hDC       = pDC->m_hDC;
			m_hAttribDC = pDC->m_hAttribDC;
		}

		// Fill background 
		FillSolidRect(m_rect, /*pDC->GetBkColor()*/m_clrBkColor);
		m_penWhite.CreatePen(PS_SOLID,1,RGB(255,255,255));
		m_oldPen=SelectObject(&m_penWhite);
		SetTextColor(RGB(255,255,255));
		
	}
	~C3DCanvas()
	{
		if (m_bMemDC) {
			// Copy the offscreen bitmap onto the screen.
			
			m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
				this, m_rect.left, m_rect.top, SRCCOPY);		
			//Swap back the original bitmap.
			SelectObject(m_oldBitmap);
			SelectObject(m_oldPen);
			m_penWhite.DeleteObject();
		} else {
			// All we need to do is replace the DC with an illegal value,
			// this keeps us from accidently deleting the handles associated with
			// the CDC that was passed to the constructor.			
			m_hDC = m_hAttribDC = NULL;
		}	
	}

	C3DVector ToPerspectiveView(C3DVector v, double z);
};

//

void C3DCanvas::Line3D(C3DVector P, C3DVector Q)
{
	int x1,y1,x2,y2;
	P=P-m_org;
	Q=Q-m_org;
	double r=1;
	
	if(m_bPerpective)
	{
		P=ToPerspectiveView(P,m_camera.Magnetude());
		Q=ToPerspectiveView(Q,m_camera.Magnetude());
	}
	
	double dMag1=P.Magnetude();
	x1=(int)( ( ( dMag1 ) * ( P.UnitVector() * W_X ) ) )-m_winOrgX;
	y1=(int)( ( ( dMag1 ) * ( P.UnitVector() * W_Y ) ) )-m_winOrgY;
	
	double dMag2=Q.Magnetude();
	x2=(int)( ( ( dMag2 ) * ( Q.UnitVector() * W_X) ) )-m_winOrgX;
	y2=(int)( ( ( dMag2 ) * ( Q.UnitVector() * W_Y) ) )-m_winOrgY;
	
	MoveTo(x1,y1);
	LineTo(x2,y2);
}

C3DVector C3DCanvas::ToPerspectiveView(C3DVector v, double z)
{
	double r=0;
	
	r=-1/z;
	v.m_x=v.m_x/((r*v.m_z)+1);
	v.m_y=v.m_y/((r*v.m_z)+1);
	v.m_z=v.m_z/((r*v.m_z)+1);
	
	return v;
}

void CMy3DTransformationsView::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	CRect rectClient ;
	GetClientRect(rectClient);
	C3DCanvas canvas(&dc,&rectClient,RGB(0,0,0));
	C3DVector v(-x1,-y1,-z1);
	canvas.SetViewPortOrg(v);
	canvas.EnablePerspectiveView(TRUE);
	canvas.SetCamera(0,0,1650);
	canvas.m_camera.Rotate(x,X_AXIS);
	canvas.m_camera.Rotate(y,Y_AXIS);
	canvas.m_camera.Rotate(z,Z_AXIS);
	canvas.SetWindowOrg(-600,-300);
	C3DVector v1(0,-300,0),v2(0,300,0);
	CPen pen1(PS_DASHDOT,1,RGB(255,0,0));
	CPen *oldPen=canvas.SelectObject(&pen1);
	v1.Rotate(x,X_AXIS);
	v1.Rotate(y,Y_AXIS);
	v1.Rotate(z,Z_AXIS);
	v2.Rotate(x,X_AXIS);
	v2.Rotate(y,Y_AXIS);
	v2.Rotate(z,Z_AXIS);
	canvas.Line3D(v1,v2);
	canvas.SelectObject(oldPen);
	
	CPen pen2(PS_DASHDOT,1,RGB(0,255,0));
	C3DVector v3(-300,0,0),v4(300,0,0);
	v3.Rotate(x,X_AXIS);
	v3.Rotate(y,Y_AXIS);
	v3.Rotate(z,Z_AXIS);
	v4.Rotate(x,X_AXIS);
	v4.Rotate(y,Y_AXIS);
	v4.Rotate(z,Z_AXIS);
	oldPen=canvas.SelectObject(&pen2);
	canvas.Line3D(v3,v4);
	canvas.SelectObject(oldPen);

	CPen pen3(PS_DASHDOT,1,RGB(0,0,255));
	C3DVector v5(0,0,-300),v6(0,0,300);
	v5.Rotate(x,X_AXIS);
	v5.Rotate(y,Y_AXIS);
	v5.Rotate(z,Z_AXIS);
	v6.Rotate(x,X_AXIS);
	v6.Rotate(y,Y_AXIS);
	v6.Rotate(z,Z_AXIS);
	oldPen=canvas.SelectObject(&pen3);
	canvas.Line3D(v5,v6);
	canvas.SelectObject(oldPen);
	CPen pen4(PS_SOLID,1,RGB(122,255,255));
	oldPen=canvas.SelectObject(&pen4);

	C3DVector vect[8];

	vect[0].m_x=50;
	vect[0].m_y=50;
	vect[0].m_z=50;

	vect[1].m_x=250;
	vect[1].m_y=50;
	vect[1].m_z=50;

	vect[2].m_x=50;
	vect[2].m_y=250;
	vect[2].m_z=50;
	
	vect[3].m_x=250;
	vect[3].m_y=250;
	vect[3].m_z=50;
	
	vect[4].m_x=250;
	vect[4].m_y=250;
	vect[4].m_z=250;
	
	vect[5].m_x=50;
	vect[5].m_y=250;
	vect[5].m_z=250;
	
	vect[6].m_x=250;
	vect[6].m_y=50;
	vect[6].m_z=250;

	vect[7].m_x=50;
	vect[7].m_y=50;
	vect[7].m_z=250;
	for(int i=0;i<8;i++)
	{	vect[i].Rotate(x,X_AXIS);
		vect[i].Rotate(y,Y_AXIS);
		vect[i].Rotate(z,Z_AXIS);
	}
	canvas.Line3D(vect[0],vect[1]);
	canvas.Line3D(vect[2],vect[0]);
	canvas.Line3D(vect[3],vect[1]);
	canvas.Line3D(vect[3],vect[2]);
	canvas.Line3D(vect[3],vect[4]);
	canvas.Line3D(vect[5],vect[4]);
	canvas.Line3D(vect[5],vect[2]);
	canvas.Line3D(vect[4],vect[6]);
	canvas.Line3D(vect[7],vect[6]);
	canvas.Line3D(vect[7],vect[0]);
	canvas.Line3D(vect[7],vect[5]);
	canvas.Line3D(vect[6],vect[1]);
	canvas.SelectObject(oldPen);
}

Enjoy 3D Vector Graphics.

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