Okay, das Grundprinzip hab ich denke ich verstanden, wenn auch nicht die mathematischen Feinheiten innerhalb der Interpolationsmethode. Ich denke, in dieser Form sollte es kein Problem sein, das dahingehend umzubauen, dass ich keinen "Loop" aus Punkten habe und dass ich die entsprechenden Parameter ordnungsgemäß setze.
Allerdings ist das Ergebnis dann nicht ganz das, was ich brauche und ich weiß nicht recht, wie ich von dort aus dann dahin kommen soll. Ich dachte mir bisher, dass ich die Geschwindigkeitsvektoren der Referenzpunkte für die Kamera in normalisierter Form als Tangenten verwende. Aber wie bringe ich die Geschwindigkeit an sich mit in die Gleichung? Wenn ich zwei Animationspunkte der Kamera habe, die linear verbunden sind und Punkt #1 hat einen Geschwindigkeitsvektor der Länge 0.01 und #2 einen Geschwindigkeitsvektor der Länge 1.0, dann soll die Kamera an #1 mit der Geschwindigkeit 0.01 starten und bis zur Geschwindigkeit 1.0 immer schneller werden, während der Spline-Pfad abgewandert wird.
Es wäre auch in Ordnung, wenn die räumliche Distanz der so errechneten Punkte konstant und nur abhängig von der Sampleschrittweite wäre, aber auch das scheint hier nicht der Fall zu sein. Wie würde ich nun beispielsweise einen Punkt dazu bekommen, den Splinepfad mit konstanter Geschwindigkeit entlang zu wandern? Gibt es einen Weg dazu, indem ich den Interpolationsalgorithmus abändere oder muss ich mir dazu irgendwas halbgares zusammenbasteln?
Edit:
Ich hab mal herumprobiert. Das hier ist meine halbgare Bastellösung für Reisen auf der Spline mit konstanter Geschwindigkeit. Das Problem hier ist, dass der Punkt nicht auf Veränderungen der Spline reagiert: Wenn man es mit sich bewegenden Referenzpunkten zu tun hat, dann wird das nicht mehr funktionieren - es ist also für mich keine Lösung. Hat jemand eine Idee, wie ich das Reisen mit konstanter Geschwindigkeit anders realisieren kann?
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] SuperStrict Framework BRL.GlMax2D
Import BRL.System Import BRL.Timer
Graphics 800, 600
Local Timer:TTimer = CreateTimer( 60 )
Local Spline:THermiteSpline = New THermiteSpline
Spline.AddNode( Vec2( 400.0, 200.0 ) ) Spline.AddNode( Vec2( 200.0, 400.0 ) ) Spline.AddNode( Vec2( 600.0, 400.0 ) )
Local Samples:Int = 3 Local pF:Float = 0.05 Local pF2:Float = 0.05 Local p:TVector = Vec2( 400.0, 200.0 ) Local p2:TVector = Vec2( 400.0, 200.0 )
While Not ( KeyHit( KEY_ESCAPE ) Or AppTerminate() ) Cls DrawText "Linke Maustaste, um Punkte zu setzen", 0, 0 Spline.NodePosition[0].X = MouseX() Spline.NodePosition[0].Y = MouseY() Spline.UpdateChanges() If MouseHit( MOUSE_LEFT ) Then Spline.AddNode( Vec2( MouseX(), MouseY() ) ) Samples :+ 1 EndIf SetColor 255, 0, 255 For Local I:Int = 0 To Spline.NodePosition.Length - 1 DrawRect Spline.NodePosition[i].X - 3, Spline.NodePosition[i].Y - 3, 7, 7 Next SetColor 255, 255, 255 Local Previous:TVector = Spline.Interpolate( 0.0 ) For Local I:Float = 0.05 Until Samples Step 0.05 Local Current:TVector = Spline.Interpolate( I ) DrawLine Previous.X, Previous.Y, Current.X, Current.Y DrawRect Current.X, Current.Y, 3, 3 Previous = Current Next pF :+ 0.01 p = Spline.Interpolate( pF Mod Samples ) Local dTemp:TVector dTemp = Spline.Interpolate( pF2 Mod Samples ).Substract(p2) While dTemp.Length() <= 5.0 pF2 :+ 0.05 dTemp = Spline.Interpolate( pF2 Mod Samples ).Substract(p2) Wend p2 = p2.Add(dTemp.Normalize().Multiply(5.0)) SetColor 0, 255, 0 DrawRect p.X - 5, p.Y - 5, 10, 10 SetColor 255, 0, 0 DrawRect p2.X - 5, p2.Y - 5, 10, 10 SetColor 255, 255, 255 Flip 0 WaitTimer Timer Wend End
Function Vec2:TVector( X:Float, Y:Float ) Return TVector.Vector( X, Y, 0 ) End Function
Function Vec3:TVector( X:Float, Y:Float, Z:Float ) Return TVector.Vector( X, Y, Z ) End Function
Function Vec4:TVector( X:Float, Y:Float, Z:Float, W:Float ) Return TVector.Vector( X, Y, Z, W ) End Function
Function Mat4:TMatrix( Elements:Int[] ) Local Matrix:TMatrix = New TMatrix For Local Row:Int = 0 To 3 For Local Column:Int = 0 To 3 Matrix.A[ Row, Column ] = Elements[ Row*4 + Column ] Next Next Return Matrix End Function
Type TVector Field X:Float Field Y:Float Field Z:Float Field W:Float Method Add:TVector( B:TVector ) X :+ B.X Y :+ B.Y Z :+ B.Z Return Self End Method Method Substract:TVector( B:TVector ) X :- B.X Y :- B.Y Z :- B.Z Return Self End Method Method Multiply:TVector( Scalar:Float ) X :* Scalar Y :* Scalar Z :* Scalar Return Self End Method Method Divide:TVector( Scalar:Float ) X :/ Scalar Y :/ Scalar Z :/ Scalar Return Self End Method Method DotP:Float( B:TVector ) Return X*B.X + Y*B.Y + Z*B.Z End Method Method Length:Float() Return Sqr( X*X + Y*Y + Z*Z ) End Method Method Add4:TVector( B:TVector ) X :+ B.X Y :+ B.Y Z :+ B.Z W :+ B.W Return Self End Method Method Substract4:TVector( B:TVector ) X :- B.X Y :- B.Y Z :- B.Z W :- B.W Return Self End Method Method Multiply4:TVector( Scalar:Float ) X :* Scalar Y :* Scalar Z :* Scalar W :* Scalar Return Self End Method Method Divide4:TVector( Scalar:Float ) X :/ Scalar Y :/ Scalar Z :/ Scalar W :/ Scalar Return Self End Method Method DotP4:Float( B:TVector ) Return X*B.X + Y*B.Y + Z*B.Z + W*B.W End Method Method Length4:Float() Return Sqr( X*X + Y*Y + Z*Z + W*W ) End Method Method CrossProduct:TVector( B:TVector ) Local NewX:Float = Y*B.Z - Z*B.Y Local NewY:Float = Z*B.X - X*B.Z Local NewZ:Float = X*B.Y - Y*B.X X = NewX Y = NewY Z = NewZ Return Self End Method Method Invert:TVector() X = 1/X Y = 1/Y Z = 1/Z Return Self End Method Method Normalize:TVector() Local Length:Float = Sqr( X*X + Y*Y + Z*Z ) X = X/Length Y = Y/Length Z = Z/Length Return Self End Method Method Absolute:TVector() X = Abs( X ) Y = Abs( Y ) Z = Abs( Z ) Return Self End Method Method ToRGB:Int() Return ( Int( X ) Shl 16 ) + ( Int( Y ) Shl 8 ) + Int( Z ) End Method Method ToRGBA:Int() Return ( Int( X ) Shl 24 ) + ( Int( Y ) Shl 16 ) + ( Int( Z ) Shl 8 ) + Int( W ) End Method Method Copy:TVector() Return TVector.Vector( X, Y, Z, W ) End Method Method QuaternionMultiply:TVector( B:TVector ) Local NewX:Float = X*B.X - Y*B.Y - Z*B.Z - W*B.W Local NewY:Float = X*B.Y + B.X*Y + Z*B.W - W*B.Z Local NewZ:Float = X*B.Z + B.X*Z + W*B.Y - Y*B.W Local NewW:Float = X*B.W + B.X*W + Y*B.Z - Z*B.Y X = NewX Y = NewY Z = NewZ W = NewW Return Self End Method Method QuaternionSquare:TVector() Local NewX:Float = X*X - Y*Y - Z*Z - W*W Local NewY:Float = 2.0*X*Y Local NewZ:Float = 2.0*X*Z Local NewW:Float = 2.0*X*W X = NewX Y = NewY Z = NewZ W = NewW Return Self 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 ] = 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 ] = A[ Row, 0 ]*B.A[ 0, Column ] NewA[ Row, Column ] :+ A[ Row, 1 ]*B.A[ 1, Column ] NewA[ Row, Column ] :+ A[ Row, 2 ]*B.A[ 2, Column ] NewA[ Row, Column ] :+ A[ Row, 3 ]*B.A[ 3, Column ] Next Next A = NewA Return Self End Method Method VectorMultiply:TVector( B:TVector ) Local X:Float = A[ 0, 0 ]*B.X + A[ 0, 1 ]*B.Y + A[ 0, 2 ]*B.Z + A[ 0, 3 ]*B.W Local Y:Float = A[ 1, 0 ]*B.X + A[ 1, 1 ]*B.Y + A[ 1, 2 ]*B.Z + A[ 1, 3 ]*B.W Local Z:Float = A[ 2, 0 ]*B.X + A[ 2, 1 ]*B.Y + A[ 2, 2 ]*B.Z + A[ 2, 3 ]*B.W Local W:Float = A[ 3, 0 ]*B.X + A[ 3, 1 ]*B.Y + A[ 3, 2 ]*B.Z + 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 End Type
Type THermiteSpline Global Polynomial:TMatrix = Mat4( .. [ 2, -3, 0, 1, .. -2, 3, 0, 0, .. 1, -2, 1, 0, .. 1, -1, 0, 0 ] ) Field NodePosition:TVector[] Field NodeTangent:TVector[] Method AddNode( Position:TVector ) NodePosition = NodePosition + [ Position ] If NodePosition.Length > 2 Then Local Index:Int = NodePosition.Length Local Node0:TVector = NodePosition[ 0 ] Local Node1:TVector = NodePosition[ 1 ] Local Node2:TVector = NodePosition[ ( Index*2 - 3 ) Mod Index ] Local Node3:TVector = NodePosition[ Index - 2 ] Local Node4:TVector = NodePosition[ Index - 1 ] Local T0:TVector = Node1.Copy().Substract4( Node4 ).Divide4( 2.0 ) Local T2:TVector = Node4.Copy().Substract4( Node2 ).Divide4( 2.0 ) Local T3:TVector = Node0.Copy().Substract4( Node3 ).Divide4( 2.0 ) NodeTangent = NodeTangent + [ T3 ] NodeTangent[ 0 ] = T0 NodeTangent[ Index - 2 ] = T2 Else NodeTangent = NodeTangent + [ Vec4( 0, 0, 0, 0 ) ] EndIf End Method Method UpdateChanges() Local Boundary:Int = NodePosition.Length For Local NodeIndex:Int = 0 To Boundary - 1 Local Prev:TVector = NodePosition[ ( NodeIndex - 1 + Boundary ) Mod Boundary ] Local Succ:TVector = NodePosition[ ( NodeIndex + 1 ) Mod Boundary ] NodeTangent[ NodeIndex ] = Succ.Copy().Substract4( Prev ).Divide4( 2.0 ) Next End Method Method Interpolate:TVector( T:Float, UseZ:Int = False, UseW:Int = False ) If Not NodePosition.Length Then Return Vec4( 0.0, 0.0, 0.0, 0.0 ) Local Index1:Int = Floor( T ) Mod NodePosition.Length Local Index2:Int = ( Index1 + 1 ) Mod NodePosition.Length Local P1:TVector = NodePosition[ Index1 ] Local T1:TVector = NodeTangent[ Index1 ] Local P2:TVector = NodePosition[ Index2 ] Local T2:TVector = NodeTangent[ Index2 ] T = T Mod 1.0 Local S:TVector = Vec3( T*T*T, T*T, T ) Local CX:TVector = Vec4( P1.X, P2.X, T1.X, T2.X ) Local CY:TVector = Vec4( P1.Y, P2.Y, T1.Y, T2.Y ) Local ResultX:Float = Polynomial.VectorMultiply( S ).DotP4( CX ) Local ResultY:Float = Polynomial.VectorMultiply( S ).DotP4( CY ) Local ResultZ:Float = 0 Local ResultW:Float = 1 If UseZ Then Local CZ:TVector = Vec4( P1.Z, P2.Z, T1.Z, T2.Z ) ResultZ = Polynomial.VectorMultiply( S ).DotP4( CZ ) If UseW Then Local CW:TVector = Vec4( P1.W, P2.W, T1.W, T2.W ) ResultW = Polynomial.VectorMultiply( S ).DotP4( CW ) EndIf EndIf Return Vec4( ResultX, ResultY, ResultZ, ResultW ) End Method End Type
Edit2:
Okay, ich hab meine halbgare Hack-Lösung etwas weiter vorangetrieben. So wie jetzt könnte man's schon fast als Basis implementieren und darauf dann separat interpolierte Geschwindigkeit einbauen. Hier:
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] SuperStrict Framework BRL.GlMax2D
Import BRL.System Import BRL.Timer
Graphics 800, 600
Local Timer:TTimer = CreateTimer( 60 )
Local Spline:THermiteSpline = New THermiteSpline
Spline.AddNode( Vec2( 400.0, 200.0 ) ) Spline.AddNode( Vec2( 200.0, 400.0 ) ) Spline.AddNode( Vec2( 600.0, 400.0 ) )
Local Samples:Int = 3 Local pF:Float = 0.05 Local pF2:Float = 0.05 Local p:TVector = Vec2( 400.0, 200.0 ) Local p2:TVector = Vec2( 400.0, 200.0 ) Local p2SLast:TVector
While Not ( KeyHit( KEY_ESCAPE ) Or AppTerminate() ) Cls DrawText "Linke Maustaste, um Punkte zu setzen", 0, 0 Spline.NodePosition[0].X = MouseX() Spline.NodePosition[0].Y = MouseY() Spline.UpdateChanges() If MouseHit( MOUSE_LEFT ) Then Spline.AddNode( Vec2( MouseX(), MouseY() ) ) Samples :+ 1 EndIf SetColor 255, 0, 255 For Local I:Int = 0 To Spline.NodePosition.Length - 1 DrawRect Spline.NodePosition[i].X - 3, Spline.NodePosition[i].Y - 3, 7, 7 Next SetColor 255, 255, 255 Local Previous:TVector = Spline.Interpolate( 0.0 ) For Local I:Float = 0.05 Until Samples Step 0.05 Local Current:TVector = Spline.Interpolate( I ) DrawLine Previous.X, Previous.Y, Current.X, Current.Y DrawRect Current.X, Current.Y, 3, 3 Previous = Current Next pF :+ 0.01 p = Spline.Interpolate( pF Mod Samples )
Local dTemp:TVector p2 = p2.Add(Spline.Interpolate( pF2 Mod Samples ).Substract(p2SLast)) dTemp = Spline.Interpolate( pF2 Mod Samples ).Substract(p2) While dTemp.Length() <= 5.0 pF2 :+ 0.05 dTemp = Spline.Interpolate( pF2 Mod Samples ).Substract(p2) Wend p2SLast = Spline.Interpolate( pF2 Mod Samples ) p2 = p2.Add(dTemp.Normalize().Multiply(5.0)) SetColor 0, 255, 0 DrawRect p.X - 5, p.Y - 5, 10, 10 SetColor 255, 0, 0 DrawRect p2.X - 5, p2.Y - 5, 10, 10 SetColor 255, 255, 255 Flip 0 WaitTimer Timer Wend End
Function Vec2:TVector( X:Float, Y:Float ) Return TVector.Vector( X, Y, 0 ) End Function
Function Vec3:TVector( X:Float, Y:Float, Z:Float ) Return TVector.Vector( X, Y, Z ) End Function
Function Vec4:TVector( X:Float, Y:Float, Z:Float, W:Float ) Return TVector.Vector( X, Y, Z, W ) End Function
Function Mat4:TMatrix( Elements:Int[] ) Local Matrix:TMatrix = New TMatrix For Local Row:Int = 0 To 3 For Local Column:Int = 0 To 3 Matrix.A[ Row, Column ] = Elements[ Row*4 + Column ] Next Next Return Matrix End Function
Type TVector Field X:Float Field Y:Float Field Z:Float Field W:Float Method Add:TVector( B:TVector ) X :+ B.X Y :+ B.Y Z :+ B.Z Return Self End Method Method Substract:TVector( B:TVector ) X :- B.X Y :- B.Y Z :- B.Z Return Self End Method Method Multiply:TVector( Scalar:Float ) X :* Scalar Y :* Scalar Z :* Scalar Return Self End Method Method Divide:TVector( Scalar:Float ) X :/ Scalar Y :/ Scalar Z :/ Scalar Return Self End Method Method DotP:Float( B:TVector ) Return X*B.X + Y*B.Y + Z*B.Z End Method Method Length:Float() Return Sqr( X*X + Y*Y + Z*Z ) End Method Method Add4:TVector( B:TVector ) X :+ B.X Y :+ B.Y Z :+ B.Z W :+ B.W Return Self End Method Method Substract4:TVector( B:TVector ) X :- B.X Y :- B.Y Z :- B.Z W :- B.W Return Self End Method Method Multiply4:TVector( Scalar:Float ) X :* Scalar Y :* Scalar Z :* Scalar W :* Scalar Return Self End Method Method Divide4:TVector( Scalar:Float ) X :/ Scalar Y :/ Scalar Z :/ Scalar W :/ Scalar Return Self End Method Method DotP4:Float( B:TVector ) Return X*B.X + Y*B.Y + Z*B.Z + W*B.W End Method Method Length4:Float() Return Sqr( X*X + Y*Y + Z*Z + W*W ) End Method Method CrossProduct:TVector( B:TVector ) Local NewX:Float = Y*B.Z - Z*B.Y Local NewY:Float = Z*B.X - X*B.Z Local NewZ:Float = X*B.Y - Y*B.X X = NewX Y = NewY Z = NewZ Return Self End Method Method Invert:TVector() X = 1/X Y = 1/Y Z = 1/Z Return Self End Method Method Normalize:TVector() Local Length:Float = Sqr( X*X + Y*Y + Z*Z ) X = X/Length Y = Y/Length Z = Z/Length Return Self End Method Method Absolute:TVector() X = Abs( X ) Y = Abs( Y ) Z = Abs( Z ) Return Self End Method Method ToRGB:Int() Return ( Int( X ) Shl 16 ) + ( Int( Y ) Shl 8 ) + Int( Z ) End Method Method ToRGBA:Int() Return ( Int( X ) Shl 24 ) + ( Int( Y ) Shl 16 ) + ( Int( Z ) Shl 8 ) + Int( W ) End Method Method Copy:TVector() Return TVector.Vector( X, Y, Z, W ) End Method Method QuaternionMultiply:TVector( B:TVector ) Local NewX:Float = X*B.X - Y*B.Y - Z*B.Z - W*B.W Local NewY:Float = X*B.Y + B.X*Y + Z*B.W - W*B.Z Local NewZ:Float = X*B.Z + B.X*Z + W*B.Y - Y*B.W Local NewW:Float = X*B.W + B.X*W + Y*B.Z - Z*B.Y X = NewX Y = NewY Z = NewZ W = NewW Return Self End Method Method QuaternionSquare:TVector() Local NewX:Float = X*X - Y*Y - Z*Z - W*W Local NewY:Float = 2.0*X*Y Local NewZ:Float = 2.0*X*Z Local NewW:Float = 2.0*X*W X = NewX Y = NewY Z = NewZ W = NewW Return Self 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 ] = 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 ] = A[ Row, 0 ]*B.A[ 0, Column ] NewA[ Row, Column ] :+ A[ Row, 1 ]*B.A[ 1, Column ] NewA[ Row, Column ] :+ A[ Row, 2 ]*B.A[ 2, Column ] NewA[ Row, Column ] :+ A[ Row, 3 ]*B.A[ 3, Column ] Next Next A = NewA Return Self End Method Method VectorMultiply:TVector( B:TVector ) Local X:Float = A[ 0, 0 ]*B.X + A[ 0, 1 ]*B.Y + A[ 0, 2 ]*B.Z + A[ 0, 3 ]*B.W Local Y:Float = A[ 1, 0 ]*B.X + A[ 1, 1 ]*B.Y + A[ 1, 2 ]*B.Z + A[ 1, 3 ]*B.W Local Z:Float = A[ 2, 0 ]*B.X + A[ 2, 1 ]*B.Y + A[ 2, 2 ]*B.Z + A[ 2, 3 ]*B.W Local W:Float = A[ 3, 0 ]*B.X + A[ 3, 1 ]*B.Y + A[ 3, 2 ]*B.Z + 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 End Type
Type THermiteSpline Global Polynomial:TMatrix = Mat4( .. [ 2, -3, 0, 1, .. -2, 3, 0, 0, .. 1, -2, 1, 0, .. 1, -1, 0, 0 ] ) Field NodePosition:TVector[] Field NodeTangent:TVector[] Method AddNode( Position:TVector ) NodePosition = NodePosition + [ Position ] If NodePosition.Length > 2 Then Local Index:Int = NodePosition.Length Local Node0:TVector = NodePosition[ 0 ] Local Node1:TVector = NodePosition[ 1 ] Local Node2:TVector = NodePosition[ ( Index*2 - 3 ) Mod Index ] Local Node3:TVector = NodePosition[ Index - 2 ] Local Node4:TVector = NodePosition[ Index - 1 ] Local T0:TVector = Node1.Copy().Substract4( Node4 ).Divide4( 2.0 ) Local T2:TVector = Node4.Copy().Substract4( Node2 ).Divide4( 2.0 ) Local T3:TVector = Node0.Copy().Substract4( Node3 ).Divide4( 2.0 ) NodeTangent = NodeTangent + [ T3 ] NodeTangent[ 0 ] = T0 NodeTangent[ Index - 2 ] = T2 Else NodeTangent = NodeTangent + [ Vec4( 0, 0, 0, 0 ) ] EndIf End Method Method UpdateChanges() Local Boundary:Int = NodePosition.Length For Local NodeIndex:Int = 0 To Boundary - 1 Local Prev:TVector = NodePosition[ ( NodeIndex - 1 + Boundary ) Mod Boundary ] Local Succ:TVector = NodePosition[ ( NodeIndex + 1 ) Mod Boundary ] NodeTangent[ NodeIndex ] = Succ.Copy().Substract4( Prev ).Divide4( 2.0 ) Next End Method Method Interpolate:TVector( T:Float, UseZ:Int = False, UseW:Int = False ) If Not NodePosition.Length Then Return Vec4( 0.0, 0.0, 0.0, 0.0 ) Local Index1:Int = Floor( T ) Mod NodePosition.Length Local Index2:Int = ( Index1 + 1 ) Mod NodePosition.Length Local P1:TVector = NodePosition[ Index1 ] Local T1:TVector = NodeTangent[ Index1 ] Local P2:TVector = NodePosition[ Index2 ] Local T2:TVector = NodeTangent[ Index2 ] T = T Mod 1.0 Local S:TVector = Vec3( T*T*T, T*T, T ) Local CX:TVector = Vec4( P1.X, P2.X, T1.X, T2.X ) Local CY:TVector = Vec4( P1.Y, P2.Y, T1.Y, T2.Y ) Local ResultX:Float = Polynomial.VectorMultiply( S ).DotP4( CX ) Local ResultY:Float = Polynomial.VectorMultiply( S ).DotP4( CY ) Local ResultZ:Float = 0 Local ResultW:Float = 1 If UseZ Then Local CZ:TVector = Vec4( P1.Z, P2.Z, T1.Z, T2.Z ) ResultZ = Polynomial.VectorMultiply( S ).DotP4( CZ ) If UseW Then Local CW:TVector = Vec4( P1.W, P2.W, T1.W, T2.W ) ResultW = Polynomial.VectorMultiply( S ).DotP4( CW ) EndIf EndIf Return Vec4( ResultX, ResultY, ResultZ, ResultW ) End Method End Type
|