Today in Physics I was challanged to write a software renderer on my graphics calculator, and this is a (more sophisticated) version of the result. Because the calculator didn't have shades of colours pretty much the only thing you could do on the thing is draw vectors.
The calculator takes 5 seconds to render each frame of a cube rotating.
The code is really unfinished, and since I have had no experience of writing any kind of 3D engine I just made everything up as I went along. Use left and right keys to move the object. It's pitch and yaw is modified every frame aleardy.
Graphics 1024, 768, 32, 1
SetBuffer BackBuffer( )
Global CameraX#, CameraY#, CameraZ# = -5
Global FOV# = 30.0
Global Graphics_Width = GraphicsWidth( ), Graphics_Height = GraphicsHeight( )
Global Null_Vector.Vector = New Vector
entity.Entity = CreateCube( )
entity2.Entity = CreateObject( )
While Not KeyHit( 1 )
Render( entity )
Render( entity2 )
entity\rotation\x# = entity\rotation\x# + 5
entity2\rotation\x# = entity2\rotation\x# - 1
entity\rotation\y# = entity\rotation\y# + 2.5
entity2\rotation\y# = entity2\rotation\y# - 2.5
VWait( )
Flip
Cls
Wend
Type Entity
Field Position.Vector
Field Rotation.Vector
Field Vertex_Count
Field Link_Count
Field Vertices
Field Link1, Link2
End Type
Type Vertex
Field Vector.Vector
Field TempPosition.Vector
Field ProjectedCoords.Vector
End Type
Type Vector
Field X#, Y#, Z#
End Type
Type Vertex_Stack
Field Vector.Vector
End Type
Type Vertex_Link
Field Vertex0, Vertex1
End Type
Function CreateObject.Entity( )
Add_To_Vertex_Stack( -1, 1, -1 )
Add_To_Vertex_Stack( 1, 1, -1 )
Add_To_Vertex_Stack( -1, 1, 1 )
Add_To_Vertex_Stack( 1, 1, 1 )
Add_To_Vertex_Stack( -0.8, -1, -0.8 )
Add_To_Vertex_Stack( 0.8, -1, -0.8 )
Add_To_Vertex_Stack( -0.8, -1, 0.8 )
Add_To_Vertex_Stack( 0.8, -1, 0.8 )
Add_To_Vertex_Stack( 0, 2, 0 )
Vertex_Link( 1, 2 )
Vertex_Link( 1, 3 )
Vertex_Link( 3, 4 )
Vertex_Link( 2, 4 )
Vertex_Link( 5, 6 )
Vertex_Link( 5, 7 )
Vertex_Link( 7, 8 )
Vertex_Link( 6, 8 )
Vertex_Link( 1, 5 )
Vertex_Link( 2, 6 )
Vertex_Link( 3, 7 )
Vertex_Link( 4, 8 )
Vertex_Link( 1, 9 )
Vertex_Link( 2, 9 )
Vertex_Link( 3, 9 )
Vertex_Link( 4, 9 )
Return Build_Mesh( )
End Function
Function CreateCube.Entity( )
Add_To_Vertex_Stack( -1, 1, -1 )
Add_To_Vertex_Stack( 1, 1, -1 )
Add_To_Vertex_Stack( -1, 1, 1 )
Add_To_Vertex_Stack( 1, 1, 1 )
Add_To_Vertex_Stack( -1, -1, -1 )
Add_To_Vertex_Stack( 1, -1, -1 )
Add_To_Vertex_Stack( -1, -1, 1 )
Add_To_Vertex_Stack( 1, -1, 1 )
Vertex_Link( 1, 2 )
Vertex_Link( 1, 3 )
Vertex_Link( 3, 4 )
Vertex_Link( 2, 4 )
Vertex_Link( 5, 6 )
Vertex_Link( 5, 7 )
Vertex_Link( 7, 8 )
Vertex_Link( 6, 8 )
Vertex_Link( 1, 5 )
Vertex_Link( 2, 6 )
Vertex_Link( 3, 7 )
Vertex_Link( 4, 8 )
Return Build_Mesh( )
End Function
Function Add_To_Vertex_Stack( X#, Y#, Z# )
Local vs.Vertex_Stack = New Vertex_Stack
vs\Vector = New Vector
vs\Vector\X# = X#
vs\Vector\Y# = Y#
vs\Vector\Z# = Z#
End Function
Function Vertex_Link( v0, v1 )
Local link.Vertex_Link = New Vertex_Link
link\Vertex0 = v0
link\Vertex1 = v1
End Function
Function Build_Mesh.Entity( )
Local Entity.Entity = New Entity
Entity\Position = New Vector
Entity\Rotation = New Vector
Local Vertex.Vertex
Local Vertex_Count
Local Vertex_Link_Count
For Vertex_Stack.Vertex_Stack = Each Vertex_Stack
Vertex_Count = Vertex_Count + 1
Next
For Vertex_Link.Vertex_Link = Each Vertex_Link
Vertex_Link_Count = Vertex_Link_Count + 1
Next
Entity\Vertices = CreateBank( 4 * Vertex_Count )
Local Count = 0
For Vertex_Stack.Vertex_Stack = Each Vertex_Stack
Vertex.Vertex = New Vertex
Vertex\Vector = Vertex_Stack\Vector
Vertex\ProjectedCoords = New Vector
Vertex\TempPosition = New Vector
PokeInt( Entity\Vertices, Count * 4, Handle( Vertex ) )
Delete Vertex_Stack
Count = Count + 1
Next
Count = 0
Entity\Link1 = CreateBank( 4 * Vertex_Link_Count )
Entity\Link2 = CreateBank( 4 * Vertex_Link_Count )
For Vertex_Link.Vertex_Link = Each Vertex_Link
PokeInt( Entity\Link1, Count * 4, PeekInt( Entity\Vertices, ( Vertex_Link\Vertex0 - 1 ) * 4 ) )
PokeInt( Entity\Link2, Count * 4, PeekInt( Entity\Vertices, ( Vertex_Link\Vertex1 - 1 ) * 4 ) )
Delete Vertex_Link
Count = Count + 1
Next
Entity\Vertex_Count = Vertex_Count
Entity\Link_Count = Vertex_Link_Count
Return Entity
End Function
Function Render( Entity.Entity )
Local Count
Local Vertex.Vertex
For Count = 0 To ( Entity\Vertex_Count - 1 )
Vertex.Vertex = Object.Vertex( PeekInt( Entity\Vertices, Count * 4 ) )
Copy_Vector( Vertex\Vector, Vertex\TempPosition )
Rotate_Vector( Vertex\TempPosition, Null, Entity\Rotation )
Add_Vector( Entity\Position, Vertex\TempPosition )
Project( Vertex\TempPosition, Vertex\ProjectedCoords )
Next
For Count = 0 To ( Entity\Link_Count - 1 )
Vertex1.Vertex = Object.Vertex( PeekInt( Entity\Link1, Count * 4 ) )
Vertex2.Vertex = Object.Vertex( PeekInt( Entity\Link2, Count * 4 ) )
If Vertex1 <> Null And Vertex2 <> Null
; If Vertex1\Vector\Z# = 1.0 And Vertex2\Vector\Z# = 1.0
Line Vertex1\ProjectedCoords\X#, Vertex1\ProjectedCoords\Y#, Vertex2\ProjectedCoords\X#, Vertex2\ProjectedCoords\Y#
;
; EndIf
Else
RuntimeError "Link is Null"
EndIf
Next
End Function
Function Project( Vector1.Vector, Vector2.Vector )
Local X#, Y#, Z#
X# = Vector1\X# - CameraX#
Y# = Vector1\Y# - CameraY#
Z# = Vector1\Z# - CameraZ#
Local AngleX# = ATan2( X#, Z# )
Local AngleY# = ATan2( Y#, Z# )
Vector2\X# = ( ( AngleX# / FOV ) + 1.0 ) / 2.0 * Float( Graphics_Width )
Vector2\Y# = ( ( AngleY# / FOV ) + 1.0 ) / 2.0 * Float( Graphics_Height )
Plot Vector2\X#, Vector2\Y#
End Function
Function Copy_Vector( Vector1.Vector, Vector2.Vector )
Vector2\X# = Vector1\X#
Vector2\Y# = Vector1\Y#
Vector2\Z# = Vector1\Z#
End Function
Function Add_Vector( Vector1.Vector, Vector2.Vector )
Vector2\X# = Vector2\X# + Vector1\X#
Vector2\Y# = Vector2\Y# + Vector1\Y#
Vector2\Z# = Vector2\Z# + Vector1\Z#
End Function
;rotates vector1 about vector2 by vector3's pitch,yaw,roll
Function Rotate_Vector( Vector1.Vector, Vector2.Vector, Vector3.Vector )
Local PitchAngle#, YawAngle#, RollAngle#
Local aDist#
Local bDist#
Local Dist#
PitchAngle# = FindAngle#( Vector1\Y#, Vector1\Z# )
PitchAngle# = PitchAngle# + Vector3\X#
aDist# = ( Vector1\Y# )
bDist# = ( Vector1\Z# )
Dist# = Sqr( aDist# * aDist# + bDist# * bDist# )
Vector1\Y# = Dist# * Sin( PitchAngle# )
Vector1\Z# = Dist# * Cos( PitchAngle# )
YawAngle# = FindAngle#( Vector1\X#, Vector1\Z# )
YawAngle# = YawAngle# + Vector3\Y#
aDist# = ( Vector1\X# )
bDist# = ( Vector1\Z# )
Dist# = Sqr( aDist# * aDist# + bDist# * bDist# )
Vector1\X# = Dist# * Sin( YawAngle# )
Vector1\Z# = Dist# * Cos( YawAngle# )
End Function
Function FindAngle#( X#, Y# )
Return ATan2( X#, Y# )
End Function
|