Weiche Kamerafahrt: Welche Interpolation / Wie?

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

Fetze

Betreff: Weiche Kamerafahrt: Welche Interpolation / Wie?

BeitragSa, Apr 17, 2010 12:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

hänge gerade an einem vermutlich mathematischen Problem. Ich möchte weiche Kamerafahrten aus einem Satz einiger fester (oder sich bewegender!) Punkte berechnen, beispielsweise von der Verfolgerperspektive eines sich bewegenden Raumschiffes über einen fest gesetzten Wegpunkt auf der Karte, dann zur Verfolgerperspektive eines anderen Schiffes, etc.

Jetzt sitze ich hier seit einiger Zeit und weiß nicht recht, wo und wie ich anfangen soll. Alles, was ich bisher an Interpolation kenne oder verstehe, ist lineare Interpolation und die würde Zweifellos alles andere als gut aussehen.

Eine genauere Beschreibung des Problems: Jeder dieser Punkte sollte exakt passiert werden und beschreibt einen Satz aus Kameraeigenschaften, die die Kamera erfüllt, sobald sie sich genau an diesem Punkt befindet: Position (XYZ), Drehung/Winkel und Geschwindigkeit (XYZ). Was ich nun brauche ist eine Methode, aus zwei solchen Datensätzen (dem letzten passierten und dem gerade angesteuerten) und einer prozentualen Zeitposition dazwischen (0%: letzter Punkt, 100%: nächster Punkt) einen neuen, "aktuellen" Datensatz zu berechnen.
(Ideal wäre es im Grunde, einen festen Interpolationsschritt auf der Zeitskala zu haben, der dafür sorgt, dass die Ausgabegeschwindigkeit mit der relativen Veränderung der Position seit letztem Frame übereinstimmt.)

Zuerst dachte ich irgendwie an Splines und die Bilder, die ich davon im Internet gefunden habe, sahen auch ganz gut aus, aber ich hab irgendwie keine Ahnung, wie ich das jetzt auf mein Problem anwende. Ich hab ja nicht nur eine zu interpolierende Funktion f(x), sondern einen Funktionssatz xPos(t), yPos(t), zPos(t), angle(t), xVel(t), yVel(t), zVel(t) und am Ende muss auch alles noch zusammen passen..

Hilfe?

mpmxyz

BeitragSa, Apr 17, 2010 14:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Interpolationsverfahren, welche nur zwei Punkte aus allen Punkten brauchen und dabei nicht "lineare Interpolation" heißen, gibt es meines Wissens nach nicht.
Man braucht dazu mindestens noch die Daten der Nachbarpunkte.

Diese Funktionen sind unabhängig voneinander:
xPos(t), yPos(t), zPos(t) und angle(t)
Jede von ihnen kann einzeln interpoliert werden.
(z.B. mit einer eigenen Funktion "Interpolate:Float(Data:Float[],Times:Float[],Time:Float,ID:Int)")
Die Funktionen xVel(t), yVel(t) und zVel(t) sind die Ableitungen der Positionsfunktionen und daher eigentlich nicht nötig.
Zur eigentlichen Interpolation nimmst du dann einen der Algorithmen, die du gefunden hast.
mfG
mpmxyz
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer

Goodjee

BeitragSa, Apr 17, 2010 14:39
Antworten mit Zitat
Benutzer-Profile anzeigen
kannst du vllt ne bezierkurve dadurch legen mit den 4punkten:
punkta
punkta+geschwindigkeita*winkela
punktb-geschwindigkeitb*winkelb
punktb
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/

faeX

BeitragSa, Apr 17, 2010 15:18
Antworten mit Zitat
Benutzer-Profile anzeigen
=> Klick mich!

Noobody

BeitragSa, Apr 17, 2010 15:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich schätze, der Hermite Spline ist das, was du suchst. Das tolle am Hermite Spline ist, dass die Kurve durch alle Knotenpunkte geht, weswegen er auch bei der Interpolation zwischen Keyframes in Animationen benutzt wird.

Ich habe eine Implementation davon in einem Mathemodul von mir herumfliegen - es ist zwar auf beliebig viele Punkte und geschlossene Kurven ausgelegt, aber mithilfe von Wikipedia solltest du das schon umgeschrieben bekommen: BlitzMax: [AUSKLAPPEN]
SuperStrict

'------------------- Beispiel


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

While Not ( KeyHit( KEY_ESCAPE ) Or AppTerminate() )
Cls

DrawText "Linke Maustaste, um Punkte zu setzen", 0, 0

If MouseHit( MOUSE_LEFT ) Then
Spline.AddNode( Vec2( MouseX(), MouseY() ) )

Samples :+ 1
EndIf

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

Previous = Current
Next

Flip 0
WaitTimer Timer
Wend
End



'-------------------- Ende Beispiel

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
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

Fetze

BeitragSa, Apr 17, 2010 16:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke, Noobody, das sieht sehr vielversprechend aus! Ich sehe mir das mal genauer an und melde mich dann ggf. zurück!

Fetze

BeitragSa, Apr 17, 2010 17:57
Antworten mit Zitat
Benutzer-Profile anzeigen
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]

SuperStrict
Framework BRL.GlMax2D

Import BRL.System
Import BRL.Timer



'------------------- Beispiel


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



'-------------------- Ende Beispiel

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]

SuperStrict
Framework BRL.GlMax2D

Import BRL.System
Import BRL.Timer



'------------------- Beispiel


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



'-------------------- Ende Beispiel

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

Noobody

BeitragMo, Apr 19, 2010 13:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Den Spline in konstanter Schrittweite abzulaufen wird vermutlich nicht ohne weiteres möglich sein. Dieses Problem fiel mir auch schon bei anderen Splines (wie z.B. Bézier) auf, aber eine Lösung fand ich bisher noch keine.

Die Geschwindigkeit kannst du ganz normal wie die Koordinaten mitinterpolieren. In meinem Code kannst du einfach einen Vec4 statt einen Vec3 benutzen und die Geschwindigkeit als viertes Element einsetzen. Damit die Eigenschaft mit interpoliert wird, musst du aber noch beim Parameter 'UseW' in der Interpolate-Funktion True angeben.
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

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group