point's in z

BlitzMax Forums/BlitzMax Programming/point's in z

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

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