Simpler Software - Rasterizer
Übersicht

![]() |
NoobodyBetreff: Simpler Software - Rasterizer |
![]() Antworten mit Zitat ![]() |
---|---|---|
Als Einstiegsprojekt in BMax habe ich einen kleinen Software - Rasterizer gebastelt.
Für diejenigen, denen der Begriff noch nicht so vertraut ist: Ein Rasterizer rendert Vektorfiguren, so dass sie auf dem Bildschirm dargestellt werden können. In diesem Fall also zeichnet das Programm ein paar 3D - Objekte, wie sie von einer Kamera aufgenommen werden - Eine sehr simple Software - Grafikkarte, wenn man so will. Um dies zu erreichen, bedient sich das Programm allerhand Vektor- und Matrizenrechnungen. Die Rechenreihenfolge habe ich aus schwachen Erinnerungen an einen Artikel über 3D - Transformationen in der Grafikkarte und Trial and Error hergeleitet, kann also sein, dass ich das sehr viel umständlicher mache, als es normalerweise gemacht wird ![]() Da ich mich mit OGL noch nicht wirklich auskenne, werden die Objekte einfach als Wireframe gezeichnet. Wenn zwei Objekte übereinander liegen, ist also nicht direkt erkennbar, welches Objekt nun vorne ist und welches hinten (ist manchmal ziemlich verwirrend). Abgesehen davon läuft das Programm aber relativ gut. Objekte werden nach B3D - ähnlichem Prinzip bewegt, skaliert und rotiert, einzig den Positionsbefehl musste ich von 'Position' in 'Locate' umtaufen, weil ein Field des Entity - Types den selben Namen hatte. Ein kleiner Screenshot: ![]() Der Code: [AUSKLAPPEN] SuperStrict
Const GWIDTH:Int = 800 Const GHEIGHT:Int = 600 Graphics GWIDTH, GHEIGHT, 0 Local Timer:TTimer = CreateTimer( 60 ) Local Cam:TCamera = TCamera.Camera() Cam.Move( Vec3( 0, 0, -15 ) ) Local Mesh:TMesh = Cam.AddMesh() Mesh.CreateCube() Local Cube:TMesh = Cam.AddMesh() Cube.CreateCube() Local Pivot:TEntity = New TEntity Cam.SetParent( Pivot ) MoveMouse( GWIDTH/2, GHEIGHT/2 ) Local OldMouseX:Int = MouseX(), OldMouseY:Int = MouseY(), OldMouseZ:Int = MouseZ() While Not KeyHit( KEY_ESCAPE ) Cls Cam.Render( GWIDTH, GHEIGHT ) Pivot.Turn( Vec3( OldMouseY - MouseY(), OldMouseX - MouseX(), 0 ) ) Cam.Move( Vec3( 0, 0, MouseZ() - OldMouseZ ) ) Local Angle:Float = ( MilliSecs() Mod 3600 )/10.0 Mesh.Turn( Vec3( 1, 2, 3 ) ) Mesh.Locate( Vec3( Sin( Angle )*2, 0, 0 ) ) Cube.Locate( Vec3( Cos( Angle )*3, Sin( Angle*2 )*2, 5 ) ) Cube.Turn( Vec3( 0, 2, 0 ) ) Cube.Scale( Vec3( Cos( Angle ) + 1.5, 0.5, 1 ) ) OldMouseX = MouseX() OldMouseY = MouseY() OldMouseZ = MouseZ() Flip 0 WaitTimer Timer Wend End Function Vec3:TVector( X:Float, Y:Float, Z:Float ) Return TVector.Vector( X, Y, Z ) End Function Function EntityCoords:String( Entity:TEntity ) If Entity.Parent Then Entity.Parent.InvTransform() Entity.Transform() Local Mat:TMatrix = Entity.Parent.InvFinalTransform.Copy().MatrixMultiply( Entity.FinalTransform ) Return Mat.A[ 0, 3 ] + " : " + Mat.A[ 1, 3 ] + " : " + Mat.A[ 2, 3 ] End Function Type TVector Field X:Float Field Y:Float Field Z:Float Field W:Float Method Add:TVector( B:TVector ) Self.X :+ B.X Self.Y :+ B.Y Self.Z :+ B.Z Return Self End Method Method Substract:TVector( B:TVector ) Self.X :- B.X Self.Y :- B.Y Self.Z :- B.Z Return Self End Method Method Multiply:TVector( Scalar:Float ) Self.X :* Scalar Self.Y :* Scalar Self.Z :* Scalar Return Self End Method Method Invert:TVector() Self.X = 1/Self.X Self.Y = 1/Self.Y Self.Z = 1/Self.Z Return Self End Method Method DotProduct:Float( B:TVector ) Return Self.X*B.X + Self.Y*B.Y + Self.Z*B.Z End Method Method CrossProduct:TVector( B:TVector ) Local NewX:Float = Self.Y*B.Z - Self.Z*B.Y Local NewY:Float = Self.Z*B.X - Self.X*B.Z Local NewZ:Float = Self.X*B.Y - Self.Y*B.X Self.X = NewX Self.Y = NewY Self.Z = NewZ Return Self End Method Method Copy:TVector() Return TVector.Vector( Self.X, Self.Y, Self.Z, Self.W ) End Method Function Vector:TVector( X:Float, Y:Float, Z:Float, W:Float = 1 ) Local Vector:TVector = New TVector Vector.X = X Vector.Y = Y Vector.Z = Z Vector.W = W Return Vector End Function End Type Type TMatrix Field A:Float[ 4, 4 ] Method Copy:TMatrix() Local Matrix:TMatrix = New TMatrix For Local Row:Int = 0 To 3 For Local Column:Int = 0 To 3 Matrix.A[ Row, Column ] = Self.A[ Row, Column ] Next Next Return Matrix End Method Method MatrixMultiply:TMatrix( B:TMatrix ) Local NewA:Float[ 4, 4 ] For Local Row:Int = 0 To 3 For Local Column:Int = 0 To 3 NewA[ Row, Column ] = Self.A[ Row, 0 ]*B.A[ 0, Column ] NewA[ Row, Column ] :+ Self.A[ Row, 1 ]*B.A[ 1, Column ] NewA[ Row, Column ] :+ Self.A[ Row, 2 ]*B.A[ 2, Column ] NewA[ Row, Column ] :+ Self.A[ Row, 3 ]*B.A[ 3, Column ] Next Next Self.A = NewA Return Self End Method Method VectorMultiply:TVector( B:TVector ) Local X:Float = Self.A[ 0, 0 ]*B.X + Self.A[ 0, 1 ]*B.Y + Self.A[ 0, 2 ]*B.Z + Self.A[ 0, 3 ]*B.W Local Y:Float = Self.A[ 1, 0 ]*B.X + Self.A[ 1, 1 ]*B.Y + Self.A[ 1, 2 ]*B.Z + Self.A[ 1, 3 ]*B.W Local Z:Float = Self.A[ 2, 0 ]*B.X + Self.A[ 2, 1 ]*B.Y + Self.A[ 2, 2 ]*B.Z + Self.A[ 2, 3 ]*B.W Local W:Float = Self.A[ 3, 0 ]*B.X + Self.A[ 3, 1 ]*B.Y + Self.A[ 3, 2 ]*B.Z + Self.A[ 3, 3 ]*B.W Return TVector.Vector( X, Y, Z, W ) End Method Function Identity:TMatrix() Local Matrix:TMatrix = New TMatrix Matrix.A[ 0, 0 ] = 1 Matrix.A[ 1, 1 ] = 1 Matrix.A[ 2, 2 ] = 1 Matrix.A[ 3, 3 ] = 1 Return Matrix End Function Function Translation:TMatrix( Vector:TVector ) Local Matrix:TMatrix = TMatrix.Identity() Matrix.A[ 0, 3 ] = Vector.X Matrix.A[ 1, 3 ] = Vector.Y Matrix.A[ 2, 3 ] = Vector.Z Return Matrix End Function Function Scale:TMatrix( Vector:TVector ) Local Matrix:TMatrix = New TMatrix Matrix.A[ 0, 0 ] = Vector.X Matrix.A[ 1, 1 ] = Vector.Y Matrix.A[ 2, 2 ] = Vector.Z Matrix.A[ 3, 3 ] = 1 Return Matrix End Function Function RotationX:TMatrix( Angle:Float ) Local Matrix:TMatrix = TMatrix.Identity() Matrix.A[ 1, 1 ] = Cos( Angle ) Matrix.A[ 1, 2 ] = Sin( Angle ) Matrix.A[ 2, 1 ] = -Sin( Angle ) Matrix.A[ 2, 2 ] = Cos( Angle ) Return Matrix End Function Function RotationY:TMatrix( Angle:Float ) Local Matrix:TMatrix = TMatrix.Identity() Matrix.A[ 0, 0 ] = Cos( Angle ) Matrix.A[ 0, 2 ] = Sin( Angle ) Matrix.A[ 2, 0 ] = -Sin( Angle ) Matrix.A[ 2, 2 ] = Cos( Angle ) Return Matrix End Function Function RotationZ:TMatrix( Angle:Float ) Local Matrix:TMatrix = TMatrix.Identity() Matrix.A[ 0, 0 ] = Cos( Angle ) Matrix.A[ 0, 1 ] = Sin( Angle ) Matrix.A[ 1, 0 ] = -Sin( Angle ) Matrix.A[ 1, 1 ] = Cos( Angle ) Return Matrix End Function Function RotationXYZ:TMatrix( Rotation:TVector ) Return TMatrix.RotationZ( Rotation.Z ).MatrixMultiply( RotationY( Rotation.Y ).MatrixMultiply( RotationX( Rotation.X ) ) ) End Function Function RotationZYX:TMatrix( Rotation:TVector ) Return TMatrix.RotationX( Rotation.X ).MatrixMultiply( RotationY( Rotation.Y ).MatrixMultiply( RotationZ( Rotation.Z ) ) ) End Function Method DebugDraw( X:Int, Y:Int ) DrawLine X - 5, Y - 6, X - 5, Y + 94 'Hardcoding \o/ DrawLine X - 5, Y - 6, X + 2, Y - 6 DrawLine X - 5, Y + 94, X + 2, Y + 94 Local ColumnWidth:Int For Local Column:Int = 0 To 3 For Local Row:Int = 0 To 3 Local Element:Float = Self.A[ Row, Column ] If Element < 0 Then DrawText Element, X, Y + Row*25 Else DrawText Element, X + TextWidth( "-" ), Y + Row*25 EndIf If TextWidth( Element ) > ColumnWidth Then ColumnWidth = TextWidth( Element ) Next X :+ 20 + ColumnWidth ColumnWidth = 0 Next DrawLine X - 5, Y - 6, X - 5, Y + 94 DrawLine X - 5, Y - 6, X - 12, Y - 6 DrawLine X - 5, Y + 94, X - 12, Y + 94 End Method End Type Type TVertex Extends TVector Field TFormedCoords:TVector Field ProjectedCoords:TVector Method Copy:TVertex() Return TVertex.Vertex( Vec3( Self.X, Self.Y, Self.Z ) ) End Method Function Vertex:TVertex( Position:TVector ) Local Vertex:TVertex = New TVertex Vertex.X = Position.X Vertex.Y = Position.Y Vertex.Z = Position.Z Vertex.W = 1 Vertex.ProjectedCoords = Vec3( 0, 0, 0 ) Return Vertex End Function End Type Type TTriangle Field V1:TVertex Field V2:TVertex Field V3:TVertex Field Normal:TVector Function Triangle:TTriangle( V1:TVertex, V2:TVertex, V3:TVertex ) Local Triangle:TTriangle = New TTriangle Triangle.V1 = V1 Triangle.V2 = V2 Triangle.V3 = V3 Triangle.Normal = V3.Copy().Substract( V1 ).CrossProduct( V2.Copy().Substract( V1 ) ) Return Triangle End Function End Type Type TEntity Field Parent:TEntity Field FinalTransform:TMatrix Field InvFinalTransform:TMatrix Field Position:TVector Field Scaling:TVector Field Rotation:TMatrix Field InvRotation:TMatrix Method New() Self.Locate( Vec3( 0, 0, 0 ) ) Self.Rotate( Vec3( 0, 0, 0 ) ) Self.Scale ( Vec3( 1, 1, 1 ) ) End Method Method Turn( Vector:TVector ) Self.Rotation = TMatrix.RotationXYZ( Vector ).MatrixMultiply( Self.Rotation ) Self.InvRotation = Self.InvRotation.MatrixMultiply( TMatrix.RotationZYX( Vector.Multiply( -1 ) ) ) End Method Method Move( Vector:TVector ) Self.Position.Add( Vector ) End Method Method Rotate( Vector:TVector, GlobalSystem:Int = False ) If GlobalSystem And Self.Parent <> Null Then Throw "Global rotation not yet implementet!" Else Self.Rotation = TMatrix.RotationXYZ( Vector ) Self.InvRotation = TMatrix.RotationZYX( Vector.Multiply( -1 ) ) EndIf End Method Method Locate( Vector:TVector, GlobalSystem:Int = False ) If GlobalSystem And Self.Parent <> Null Then Self.Parent.Transform() Self.Position = Self.Parent.FinalTransform.VectorMultiply( Vector ) Else Self.Position = Vector EndIf End Method Method Scale( Vector:TVector ) Self.Scaling = Vector End Method Method SetParent( Entity:TEntity ) Self.Parent = Entity End Method Method Transform() Self.FinalTransform = TMatrix.Translation( Self.Position ).Copy().MatrixMultiply( Self.Rotation.Copy().MatrixMultiply( TMatrix.Scale( Self.Scaling ) ) ) If Self.Parent Then Self.Parent.Transform() Self.FinalTransform.MatrixMultiply( Self.Parent.FinalTransform ) EndIf End Method Method InvTransform() Self.InvFinalTransform = TMatrix.Translation( Self.Position.Copy().Multiply( -1 ) ).MatrixMultiply( Self.InvRotation.Copy().MatrixMultiply( TMatrix.Scale( Self.Scaling ) ) ) If Self.Parent Then Self.Parent.InvTransform() Self.InvFinalTransform = Self.Parent.InvFinalTransform.Copy().MatrixMultiply( Self.InvFinalTransform ) EndIf End Method End Type Type TCamera Extends TEntity Field AOV:Float 'Angle of view Field Meshes:TList Method AddMesh:TMesh() Local Mesh:TMesh = TMesh.Mesh() Self.Meshes.AddLast( Mesh ) Return Mesh End Method Method Render( ScreenWidth:Int, ScreenHeight:Int ) Local PlaneDist:Float = 1/Tan( Self.AOV/2.0 ) Self.Transform() For Local Mesh:TMesh = EachIn Self.Meshes Mesh.InvTransform() Next For Local Mesh:TMesh = EachIn Self.Meshes For Local Vertex:TVertex = EachIn Mesh.Vertices Vertex.TFormedCoords = Self.FinalTransform.VectorMultiply( Mesh.InvFinalTransform.VectorMultiply( Vertex.Copy() ) ) Vertex.ProjectedCoords.X = ( Vertex.TFormedCoords.X*PlaneDist/Vertex.TFormedCoords.Z + 1 )*ScreenWidth/2 Vertex.ProjectedCoords.Y = ( ScreenHeight/Float( ScreenWidth ) - Vertex.TFormedCoords.Y*PlaneDist/Vertex.TFormedCoords.Z )*ScreenWidth/2 Next For Local Triangle:TTriangle = EachIn Mesh.Triangles DrawLine Triangle.V1.ProjectedCoords.X, Triangle.V1.ProjectedCoords.Y, Triangle.V2.ProjectedCoords.X, Triangle.V2.ProjectedCoords.Y DrawLine Triangle.V2.ProjectedCoords.X, Triangle.V2.ProjectedCoords.Y, Triangle.V3.ProjectedCoords.X, Triangle.V3.ProjectedCoords.Y DrawLine Triangle.V3.ProjectedCoords.X, Triangle.V3.ProjectedCoords.Y, Triangle.V1.ProjectedCoords.X, Triangle.V1.ProjectedCoords.Y Next Next End Method Function Camera:TCamera( AOV:Float = 60 ) Local Cam:TCamera = New TCamera Cam.AOV = AOV Cam.Meshes = New TList Return Cam End Function End Type Type TMesh Extends TEntity Field Vertices:TList Field Triangles:TList Method AddVertex:TVertex( Position:TVector ) Local Vertex:TVertex = TVertex.Vertex( Position ) Self.Vertices.AddLast( Vertex ) Return Vertex End Method Method AddTriangle:TTriangle( V1:TVertex, V2:TVertex, V3:TVertex ) Local Triangle:TTriangle = TTriangle.Triangle( V1, V2, V3 ) Self.Triangles.AddLAst( Triangle ) Return Triangle End Method Method CreateCube() Local V1:TVertex = Self.AddVertex( Vec3( -1, -1, -1 ) ) Local V2:TVertex = Self.AddVertex( Vec3( -1, -1, 1 ) ) Local V3:TVertex = Self.AddVertex( Vec3( 1, -1, 1 ) ) Local V4:TVertex = Self.AddVertex( Vec3( 1, -1, -1 ) ) Local V5:TVertex = Self.AddVertex( Vec3( -1, 1, -1 ) ) Local V6:TVertex = Self.AddVertex( Vec3( -1, 1, 1 ) ) Local V7:TVertex = Self.AddVertex( Vec3( 1, 1, 1 ) ) Local V8:TVertex = Self.AddVertex( Vec3( 1, 1, -1 ) ) Self.AddTriangle V1, V3, V2 Self.AddTriangle V1, V4, V3 Self.AddTriangle V5, V6, V7 Self.AddTriangle V5, V7, V8 Self.AddTriangle V3, V8, V7 Self.AddTriangle V3, V4, V8 Self.AddTriangle V1, V5, V8 Self.AddTriangle V1, V8, V4 Self.AddTriangle V1, V2, V6 Self.AddTriangle V1, V6, V5 Self.AddTriangle V2, V7, V6 Self.AddTriangle V2, V3, V7 End Method Function Mesh:TMesh() Local Mesh:TMesh = New TMesh Mesh.Vertices = New TList Mesh.Triangles = New TList Return Mesh End Function End Type Bei Verbesserungsvorschlägen und Tipps bin ich ganz Ohr, bei mir als BMax - Neuling haben sich sicher noch ein paar Schönheitsfehler reingeschlichen ![]() Edit: Ich habe das Programm noch um ein kleines Parent-Child System erweitert. |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
- Zuletzt bearbeitet von Noobody am Mi, Jul 15, 2009 20:49, insgesamt einmal bearbeitet
![]() |
ComNik |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zitat: Als Einstiegsprojekt in BMax habe ich einen kleinen Software - Rasterizer gebastelt.
wenn ich das schon höre... Tolle sache, und wie soll ich sagen ein sehr ausergehöhnliches EINSTEIGER Projekt... Der sinn ist mir allerdings noch nicht so entgegengesprungen ![]() mfg |
||
WIP: Vorx.Engine |
AvaGast |
![]() Antworten mit Zitat |
|
---|---|---|
Haha, wie geil ! ![]() PS: wenn Du Hilfe / Denkanstösse zu OpenGL benötigst, kann ich Dir ggf. gern weiterhelfen ![]() |
||
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
ComNik hat Folgendes geschrieben: Der sinn ist mir allerdings noch nicht so entgegengesprungen
![]() Naja, es ist auch nicht dazu gedacht, in einem Projekt verwendet zu werden (wie viele andere meiner Codes ![]() Es zeigt mehr, wie ein Rasterizer im Grunde funktioniert; ausserdem kann man die Vektor- bzw. Matrixklassen direkt rauskopieren, um diese in Verbindung mit irgendeiner anderen 3D - Bibliothek zu verwenden, die Matrizen erfordert. |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich habe den Code vor kurzem wieder ausgegraben und ihn als Vorbereitung auf ein ähnliches Projekt um ein Parent-Child System erweitert.
Dessen Funktionsweise ist gleich wie die in B3D - wenn man ein Objekt A als Parent des Objekts B setzt, so bewegt sich Objekt B automatisch mit, wenn A bewegt wird. Ausserdem (was fast noch wichtiger ist), dreht sich Objekt B um A, wenn ich A drehe. Falls ich also einen Mond um die Erde drehen lassen will, setze ich die Erde als Parent des Mondes. Wenn ich nun die Erde drehe, dreht sich der Mond mit und umkreist fortan die Erde. Im Beispielcode benutze ich das dazu, um einen unsichtbaren Punkt in die Mitte der Szene zu setzen, der als Parent der Kamera fungiert. Den Punkt lasse ich passend zu den Mausbewegungen drehen, wodurch man mit der Kamera die Szene aus beliebiger Richtung betrachten kann. Den neuen Code habe ich oben hineineditiert; die Bedienung erfolgt mit der Maus inklusive Scrollrad. Abgesehen von dem neu eingebauten System habe ich auch einige kleinere Bugs entfernt und zwei Hilfsfunktionen implementiert, um den Code eleganter zu machen. Das wird wohl das letzte Update für diesen Code sein - da er abgesehen vom Lernerfolg eh relativ nutzlos ist, lohnt es sich wohl kaum, ihn weiter auszufeilen ![]() |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group