Code : Tout sélectionner
; This source file is part of OGRE
; (Object-oriented Graphics Rendering Engine)
; For the latest info, see http://www.ogre3d.org/
;
; Copyright (c) 2000-2009 Torus Knot Software Ltd
;An example of using SimpleSpline To make an Entity smoothly
;follow a predefined path With spline interpolation.
IncludeFile "Screen3DRequester.pb"
Structure Vector3
x.f
y.f
z.f
EndStructure
Structure Spline
NbPoint.i
Array mPoints.Vector3(0)
Array mTangents.Vector3(0)
pos.Vector3
EndStructure
Macro CopyVector3(a, b)
a\x = b\x
a\y = b\y
a\z = b\z
EndMacro
Global Dim mCoeffs.f(3,3)
Declare recalcTangents(*Spline.Spline)
Declare interpolate2(*Spline.Spline, fromIndex, t.f)
; Set up matrix
; Hermite polynomial
mCoeffs(0,0) = 2
mCoeffs(0,1) = -2
mCoeffs(0,2) = 1
mCoeffs(0,3) = 1
mCoeffs(1,0) = -3
mCoeffs(1,1) = 3
mCoeffs(1,2) = -2
mCoeffs(1,3) = -1
mCoeffs(2,0) = 0
mCoeffs(2,1) = 0
mCoeffs(2,2) = 1
mCoeffs(2,3) = 0
mCoeffs(3,0) = 1
mCoeffs(3,1) = 0
mCoeffs(3,2) = 0
mCoeffs(3,3) = 0
Procedure CreateSpline()
*mem = AllocateMemory(SizeOf(Spline))
InitializeStructure(*mem, Spline)
ProcedureReturn *mem
EndProcedure
Procedure concatenate(Array r.f(2), Array m.f(2), Array m2.f(2))
r(0,0) = m(0,0) * m2(0,0) + m(0,1) * m2(1,0) + m(0,2) * m2(2,0) + m(0,3) * m2(3,0);
r(0,1) = m(0,0) * m2(0,1) + m(0,1) * m2(1,1) + m(0,2) * m2(2,1) + m(0,3) * m2(3,1);
r(0,2) = m(0,0) * m2(0,2) + m(0,1) * m2(1,2) + m(0,2) * m2(2,2) + m(0,3) * m2(3,2);
r(0,3) = m(0,0) * m2(0,3) + m(0,1) * m2(1,3) + m(0,2) * m2(2,3) + m(0,3) * m2(3,3);
r(1,0) = m(1,0) * m2(0,0) + m(1,1) * m2(1,0) + m(1,2) * m2(2,0) + m(1,3) * m2(3,0);
r(1,1) = m(1,0) * m2(0,1) + m(1,1) * m2(1,1) + m(1,2) * m2(2,1) + m(1,3) * m2(3,1);
r(1,2) = m(1,0) * m2(0,2) + m(1,1) * m2(1,2) + m(1,2) * m2(2,2) + m(1,3) * m2(3,2);
r(1,3) = m(1,0) * m2(0,3) + m(1,1) * m2(1,3) + m(1,2) * m2(2,3) + m(1,3) * m2(3,3);
r(2,0) = m(2,0) * m2(0,0) + m(2,1) * m2(1,0) + m(2,2) * m2(2,0) + m(2,3) * m2(3,0);
r(2,1) = m(2,0) * m2(0,1) + m(2,1) * m2(1,1) + m(2,2) * m2(2,1) + m(2,3) * m2(3,1);
r(2,2) = m(2,0) * m2(0,2) + m(2,1) * m2(1,2) + m(2,2) * m2(2,2) + m(2,3) * m2(3,2);
r(2,3) = m(2,0) * m2(0,3) + m(2,1) * m2(1,3) + m(2,2) * m2(2,3) + m(2,3) * m2(3,3);
r(3,0) = m(3,0) * m2(0,0) + m(3,1) * m2(1,0) + m(3,2) * m2(2,0) + m(3,3) * m2(3,0);
r(3,1) = m(3,0) * m2(0,1) + m(3,1) * m2(1,1) + m(3,2) * m2(2,1) + m(3,3) * m2(3,1);
r(3,2) = m(3,0) * m2(0,2) + m(3,1) * m2(1,2) + m(3,2) * m2(2,2) + m(3,3) * m2(3,2);
r(3,3) = m(3,0) * m2(0,3) + m(3,1) * m2(1,3) + m(3,2) * m2(2,3) + m(3,3) * m2(3,3);
EndProcedure
Procedure Multiplication(Array r.f(1), Array v.f(1), Array m.f(2))
r(0) = m(0,0) * v(0) + m(1,0) * v(1) + m(2,0) * v(2) + m(3,0) * v(3)
r(1) = m(0,1) * v(0) + m(1,1) * v(1) + m(2,1) * v(2) + m(3,1) * v(3)
r(2) = m(0,2) * v(0) + m(1,2) * v(1) + m(2,2) * v(2) + m(3,2) * v(3)
r(3) = m(0,3) * v(0) + m(1,3) * v(1) + m(2,3) * v(2) + m(3,3) * v(3)
EndProcedure
Procedure AddPointSpline(*Spline.Spline, x.f, y.f, z.f)
Protected Index.s
*Spline\mPoints(*Spline\NbPoint)\x = x
*Spline\mPoints(*Spline\NbPoint)\y = y
*Spline\mPoints(*Spline\NbPoint)\z = z
*Spline\NbPoint + 1
ReDim *spline\mPoints.Vector3(*Spline\NbPoint)
recalcTangents(*Spline)
EndProcedure
Procedure interpolateSpline(*Spline.Spline, t.f)
;Currently assumes points are evenly spaced, will cause velocity
;change where this is Not the Case
;TODO: base on arclength?
; Work out which segment this is in
fSeg.f = t * (*spline\NbPoint - 1)
segIdx = Int(fSeg)
; Apportion t
t = fSeg - segIdx
interpolate2(*Spline, segIdx, t)
EndProcedure
Procedure interpolate2(*Spline.Spline, fromIndex, t.f)
;// Bounds check
If *spline\NbPoint=0
ProcedureReturn
EndIf
If (fromIndex + 1) = *spline\NbPoint
;// Duff request, cannot blend To nothing
;// Just Return source
CopyVector3(*Spline\pos, *Spline\mPoints(fromIndex))
ProcedureReturn
EndIf
;// Fast special cases
If t = 0.0
CopyVector3(*Spline\pos, *Spline\mPoints(fromIndex))
ProcedureReturn
ElseIf t = 1.0
CopyVector3(*Spline\pos, *Spline\mPoints(fromIndex + 1))
ProcedureReturn
EndIf
;// Real interpolation
;// Form a vector of powers of t
Define.f t2, t3
t2 = t * t
t3 = t2 * t
Dim powers.f(3)
powers(0) = t3
powers(1) = t2
powers(2) = t
powers(3) = 1
;// Algorithm is ret = powers * mCoeffs * Matrix4(point1, point2, tangent1, tangent2)
Define.Vector3 point1, point2, tan1, tan2
CopyVector3(point1, *Spline\mPoints(fromIndex))
CopyVector3(point2, *Spline\mPoints(fromIndex+1))
CopyVector3(tan1 , *Spline\mTangents(fromIndex))
CopyVector3(tan2 , *Spline\mTangents(fromIndex+1))
Dim pt.f(3,3)
pt(0,0) = point1\x
pt(0,1) = point1\y
pt(0,2) = point1\z
pt(0,3) = 1.0
pt(1,0) = point2\x
pt(1,1) = point2\y
pt(1,2) = point2\z
pt(1,3) = 1.0
pt(2,0) = tan1\x
pt(2,1) = tan1\y
pt(2,2) = tan1\z
pt(2,3) = 1.0
pt(3,0) = tan2\x
pt(3,1) = tan2\y
pt(3,2) = tan2\z
pt(3,3) = 1.0
Dim ret.f(3)
Dim r.f(3,3)
;ret = powers * mCoeffs * pt;
concatenate(r(), mCoeffs(), pt())
Multiplication(ret(), powers(), r())
*Spline\pos\x = ret(0)
*Spline\pos\y = ret(1)
*Spline\pos\z = ret(2)
EndProcedure
Procedure recalcTangents(*Spline.Spline)
; // Catmull-Rom approach
; //
; // tangent[i] = 0.5 * (point[i+1] - point[i-1])
; //
; // Assume endpoint tangents are parallel With line With neighbour
Define.i i, numPoints, isClosed
numPoints = *spline\NbPoint
If numPoints < 2
; Can't do anything yet
ProcedureReturn
EndIf
; Closed Or open?
If *Spline\mPoints(0) = *Spline\mPoints(numPoints-1)
isClosed = #True
Else
isClosed = #False
EndIf
ReDim *Spline\mTangents.Vector3(numPoints)
For i = 0 To numPoints-1
If i =0
; Special Case start
If isClosed
; Use numPoints-2 since numPoints-1 is the last point And == [0]
*spline\mTangents(i)\x = 0.5 * (*spline\mPoints(1)\x - *spline\mPoints(numPoints-2)\x)
*spline\mTangents(i)\y = 0.5 * (*spline\mPoints(1)\y - *spline\mPoints(numPoints-2)\y)
*spline\mTangents(i)\z = 0.5 * (*spline\mPoints(1)\z - *spline\mPoints(numPoints-2)\z)
Else
*spline\mTangents(i)\x = 0.5 * (*spline\mPoints(1)\x - *spline\mPoints(0)\x)
*spline\mTangents(i)\y = 0.5 * (*spline\mPoints(1)\y - *spline\mPoints(0)\y)
*spline\mTangents(i)\z = 0.5 * (*spline\mPoints(1)\z - *spline\mPoints(0)\z)
EndIf
ElseIf i = numPoints-1
; Special Case End
If isClosed
; Use same tangent As already calculated For [0]
*spline\mTangents(i)\x = *spline\mTangents(0)\x
*spline\mTangents(i)\y = *spline\mTangents(0)\y
*spline\mTangents(i)\z = *spline\mTangents(0)\z
Else
*spline\mTangents(i)\x = 0.5 * (*spline\mPoints(i)\x - *spline\mPoints(i-1)\x)
*spline\mTangents(i)\y = 0.5 * (*spline\mPoints(i)\y - *spline\mPoints(i-1)\y)
*spline\mTangents(i)\z = 0.5 * (*spline\mPoints(i)\z - *spline\mPoints(i-1)\z)
EndIf
Else
*spline\mTangents(i)\x = 0.5 * (*spline\mPoints(i+1)\x - *spline\mPoints(i-1)\x)
*spline\mTangents(i)\y = 0.5 * (*spline\mPoints(i+1)\y - *spline\mPoints(i-1)\y)
*spline\mTangents(i)\z = 0.5 * (*spline\mPoints(i+1)\z - *spline\mPoints(i-1)\z)
EndIf
Next
EndProcedure
Define.f Time, pas = 1, x, y, z
If InitEngine3D()
InitSprite()
InitKeyboard()
InitMouse()
If Screen3DRequester()
Add3DArchive("Data/" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Textures" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Models" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Scripts" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Packs/skybox.zip", #PB_3DArchive_Zip)
Parse3DScripts()
WorldShadows(#PB_Shadow_Modulative)
;- Ground
CreateMaterial(0, LoadTexture(0, "Dirt.jpg"))
CreatePlane(0, 1200, 1200, 1, 1, 5, 5)
CreateEntity(0, MeshID(0), MaterialID(0), 500, 0, -500)
;- Cylinder - check point
CreateCylinder(3, 10, 100)
CreateEntity(4, MeshID(3), #PB_Material_None, 50, 0, 50)
CreateEntity(5, MeshID(3), #PB_Material_None, 50, 0, -950)
CreateEntity(6, MeshID(3), #PB_Material_None, 950, 0, -950)
CreateEntity(7, MeshID(3), #PB_Material_None, 950, 0, 50)
CreateEntity(8, MeshID(3), #PB_Material_None, 450, 0, -450)
;- Robot
;
LoadMesh(1, "robot.mesh")
CreateEntity(1, MeshID(1), #PB_Material_None, 0, 0, 0)
ScaleEntity(1, 3, 3, 3)
AnimateEntity(1, "Walk")
;- Camera
;
CreateCamera(0, 0, 0, 100, 100)
CameraLocate(0, 500, 1500, 1450)
CameraFOV(0, 25)
CameraBackColor(0,$846748)
CameraLookAt(0, 500, 0, -500)
;- Light
;
AmbientColor(RGB(25, 25, 25))
CreateLight(0, RGB(200, 200, 200), -750, 750, -750)
;- Spline
;
*spline.Spline = CreateSpline()
AddPointSpline(*spline, EntityX(4), 0, EntityZ(4))
AddPointSpline(*spline, EntityX(8), 0, EntityZ(8))
AddPointSpline(*spline, EntityX(5), 0, EntityZ(5))
AddPointSpline(*spline, EntityX(6), 0, EntityZ(6))
AddPointSpline(*spline, EntityX(8), 0, EntityZ(8))
AddPointSpline(*spline, EntityX(7), 0, EntityZ(7))
AddPointSpline(*spline, EntityX(4), 0, EntityZ(4))
Repeat
Screen3DEvents()
ExamineKeyboard()
InterpolateSpline(*Spline, time)
EntityLookAt(1, *Spline\pos\x, EntityY(1), *Spline\pos\z)
EntityLocate(1, *Spline\pos\x, *Spline\pos\y, *Spline\pos\z)
time + pas * 0.017 / 35
If time > 1
Time = 1
pas = - pas
ElseIf time < 0
Time = 0
pas = - pas
EndIf
RenderWorld()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
End
EndIf
Else
MessageRequester("Error","Can't initialize engine3D")
EndIf
FreeMemory(*Spline)