Here is a little example/pseudo 3D thing I wrote a while ago. There is not much explaining comment so you have to figure it out yourself ;)
SuperStrict Global gBoxWidth# = 297 Global gBoxHeight# = 420 Global gBoxThickness# = 10 Graphics 800, 600, 32, 60 Global gWorld:TWorld = New TWorld Local cube:TCube = TCube.Create(9,.9,9) SetClsColor(255, 255, 255) Local theta# = gWorld.pfTheta Local phi# = gWorld.pfPhi Local st# = 1.5 While Not KeyHit(KEY_ESCAPE) Cls cube.Update() cube.Draw() If MouseDown(1) Then theta:+st gWorld.SetTheta(theta) End If If MouseDown(2) Then phi:+st gWorld.SetPhi(phi) End If Flip Wend End Type TPoint Field pfX:Float, pfY:Float Method New() pfX = 0 pfY = 0 End Method Method GetX#() Return pfX End Method Method GetY#() Return pfY End Method Method SetX(fX#) pfX = fX End Method Method SetY(fY#) pfY = fY End Method Method SetPoint(fx#, fy#) pfX = fx pfY = fy End Method Method AddX(dx#) pfX:+dx End Method Method AddY(dy#) pfY:+dy End Method Method Duplicate:TPoint() Local p:TPoint = New TPoint p.SetPoint(pfX, pfY) Return p End Method Method DistanceTo#(pos:TPoint) Return Sqr((pfX - pos.GetX()) ^ 2 + (pfY - pos.GetY()) ^ 2) End Method End Type Type TWorld Field pfD# = 50 Field pfVD# = 1400 Field pfTheta# Field pfPhi# Field pfSN1# Field pfCN1# Field pfSN2# Field pfCN2# Field pfTX# = GraphicsWidth() / 2 Field pfTY# = GraphicsHeight() / 2 Field pfScf# = 1.2 Field pfS# = 2 Field pfK1# = 7 Field pfK2# = 10 Field pfW# Method New() pfW = pfK2 / (pfK2 - pfK1) SetTheta(90) SetPhi(70) End Method Method SetTheta(fTheta#) pfTheta = fTheta pfSN1 = Sin(pfTheta) pfCN1 = Cos(pfTheta) End Method Method SetPhi(fPhi#) pfPhi = fPhi pfSN2 = Sin(pfPhi) pfCN2 = Cos(pfPhi) End Method Method GetEyeCoord:T3DVector(worldCoord:T3DVector) Local eyeCoord:T3DVector = New T3DVector eyeCoord.setX(-worldCoord.getX() * pfSN1 + worldCoord.getY() * pfCN1) eyeCoord.setY(-worldCoord.getX() * pfCN1 * pfCN2 - worldCoord.getY() * pfSN1 * pfCN2 + worldCoord.getZ() * pfSN2) eyeCoord.setZ(-worldCoord.getX() * pfSN2 * pfCN1 - worldCoord.getY() * pfSN1 * pfSN2 - worldCoord.getZ() * pfCN2 + pfD) Return eyeCoord End Method Method GetScreenCoord:T3DVector(eyeCoord:T3DVector) Local screenCoord:T3DVector = New T3DVector screenCoord.setX((pfVD / pfS) * (eyeCoord.getX() / eyeCoord.getZ()) ) screenCoord.setY((pfVD / pfS) * (eyeCoord.getY() / eyeCoord.getZ()) ) screenCoord.setZ(pfW * (1 - pfK1 / eyeCoord.getZ()) ) Return screenCoord End Method Method Get2DPoint:TPoint(worldCoord:T3DVector) Local x#, y# Local screen:T3DVector = getScreenCoord(getEyeCoord(worldCoord)) Local p:TPoint = New TPoint x = screen.getX() * pfScf + pfTX y = pfTY - screen.getY() p.SetPoint(x, y) Return p End Method Method GetLineOfSight:T3DVector() Local l:T3DVector = New T3DVector l.setX(pfD * pfSN2 * pfCN1) l.setY(pfD * pfSN2 * pfSN1) l.setZ(pfD * pfCN2) Return l End Method End Type Type T3DVector Field pfX# Field pfY# Field pfZ# Method SetX(fx#) pfX = fx End Method Method SetY(fy#) pfY = fy End Method Method SetZ(fz#) pfZ = fz End Method Method GetX#() Return pfX End Method Method GetY#() Return pfY End Method Method GetZ#() Return pfZ End Method End Type Type TCube Field paV:T3DVector[8] Field paSC:TPoint[8] Field paSF%[6, 5] Field paNPS%[6] Field paN:T3DVector[6] Field paVSF:Byte[6] Field paE%[12, 4] Field piNVE% Function Create:TCube(fWidth#, fHeight#, fDepth#) Local c:TCube = New TCube Local i%, j%, n%, x#, y#, z# RestoreData vertex For i = 0 To 7 c.paV[i] = New T3DVector c.paSc[i] = New TPoint ReadData x c.paV[i].setX(x * fWidth) ReadData y c.paV[i].setY(y * fHeight) ReadData z c.paV[i].setZ(z * fDepth) Next 'surface array RestoreData surface For i = 0 To 5 ReadData n c.paNPS[i] = n Next For i = 0 To 5 For j = 0 To (c.paNPS[i]-1) ReadData n c.paSF[i, j] = n-1 Next Next 'normal array Local u:T3DVector = New T3DVector Local w:T3DVector = New T3DVector For i = 0 To 5 c.paN[i] = New T3DVector u.setX(c.paV[c.paSF[i, 1]].getX() - c.paV[c.paSF[i, 0]].getX()) u.setY(c.paV[c.paSF[i, 1]].getY() - c.paV[c.paSF[i, 0]].getY()) u.setZ(c.paV[c.paSF[i, 1]].getZ() - c.paV[c.paSF[i, 0]].getZ()) w.setX(c.paV[c.paSF[i, 2]].getX() - c.paV[c.paSF[i, 0]].getX()) w.setY(c.paV[c.paSF[i, 2]].getY() - c.paV[c.paSF[i, 0]].getY()) w.setZ(c.paV[c.paSF[i, 2]].getZ() - c.paV[c.paSF[i, 0]].getZ()) c.paN[i].setX(u.getY() * w.getZ() - w.getY() * u.getZ()) c.paN[i].setY(u.getZ() * w.getX() - w.getZ() * u.getX()) c.paN[i].setZ(u.getX() * w.getY() - w.getX() * u.getY()) Next Return c End Function Method Update() Local i%, j%, k%, lx#, ly#, lz#, ft# 'visiblity test Local p:T3DVector = gWorld.GetLineOfSight() For i = 0 To 5 lx = p.getX() - paV[paSF[i, 0]].getX() ly = p.getY() - paV[paSF[i, 0]].getY() lz = p.getZ() - paV[paSF[i, 0]].getZ() ft = paN[i].getX() * lx + paN[i].getY() * ly + paN[i].getZ() * lz paVSF[i] = (ft>0) Next 'visible edge array 'clear edge array first For i = 0 To 11 For j = 0 To 3 paE[i, j] = 0 Next Next Local m% = 0, e1%, e2%, skip:Byte piNVE = 5 For i = 0 To 5 If paVSF[i] Then e1 = paSF[i, 0] For j = 1 To paNPS[i]-1 e2 = paSF[i, j] skip = False For k = 0 To m'(m-1) If paE[k, 0] = e2 And paE[k, 1] = e1 Then paE[k, 2] = 1 paE[k, 3] = i skip = True Exit End If Next If Not skip Then paE[m, 0] = e1 paE[m, 1] = e2 paE[m, 2] = 0 paE[m, 3] = i m:+1 End If e1 = e2 Next piNVE = m - 1 End If Next For i = 0 To 7 paSc[i] = gWorld.Get2Dpoint(paV[i]) Next End Method Method Draw() Local a#, b#, c#, d#, f1%, f2% SetLineWidth(2) For Local i% = 0 To piNVE If paE[i, 2] <> 999 Then f1 = paE[i, 0] f2 = paE[i, 1] a = paSC[f1].getX() b = paSC[f1].getY() c = paSC[f2].getX() d = paSC[f2].getY() SetColor(80, 60, 100) DrawLine(a,b,c,d) SetColor(100, 80, 60) DrawOval(c-7, d-7, 13, 13) End If Next End Method End Type #vertex DefData 1, 1,-1 DefData 1, 1, 1 DefData 1,-1, 1 DefData 1,-1,-1 DefData -1, 1,-1 DefData -1,-1,-1 DefData -1,-1, 1 DefData -1, 1, 1 #surface DefData 5,5,5,5,5,5 DefData 1,2,3,4,1 DefData 1,5,8,2,1 DefData 5,6,7,8,5 DefData 4,3,7,6,4 DefData 2,8,7,3,2 DefData 1,4,6,5,1