3D Vector Graphics Class






4.83/5 (4 votes)
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
- Orthographic Projections
- Perspective Projections
- Single Point Perspective.
- Two Point Perspective.
- Three Point Perspective.
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.
There are Three Types of Perspective Projections.
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.