Smooth align Player to Object/Terrain he's standing
Re: Smooth align Player to Object/Terrain he's standing
Please post a snippet showing the issue if you want help.
Re: Smooth align Player to Object/Terrain he's standing
how to use normalX/Y/Z() ? here an example (smooth's stuff is not done)
Code: Select all
IncludeFile "Screen3DRequester.pb"
#TerrainMiniX = 0
#TerrainMiniY = 0
#TerrainMaxiX = 0
#TerrainMaxiY = 0
#PlayerSpeed = 6
#CameraSpeed = 1
Define.f KeyX, KeyY, MouseX, MouseY, TimeSinceLastFrame
Declare InitBlendMaps()
Structure Vector3
x.f
y.f
z.f
EndStructure
Structure s_Key
Up.i
Down.i
Left.i
Right.i
StrafeLeft.i
StrafeRight.i
Jump.i
EndStructure
Structure s_Entity
Entity.i
EntityBody.i
BodyOffsetY.f
elapsedTime.f
Key.s_Key
MainNode.i
SightNode.i
CameraNode.i
ForwardNode.i
StrafeNode.i
EndStructure
Structure s_Camera
Camera.i
Tightness.f
CameraNode.i
TargetNode.i
EndStructure
Macro GetNodePosition(Position, Node)
Position\x = NodeX(Node)
Position\y = NodeY(Node)
Position\z = NodeZ(Node)
EndMacro
Macro SubVector3(V, V1, V2)
V\x = V1\x - V2\x
V\y = V1\y - V2\y
V\z = V1\z - V2\z
EndMacro
;-Declare
Declare HandleEntity(*Entity.s_Entity)
Declare CameraTrack(*Camera.s_Camera, *Entity.s_Entity)
Declare OnGround(*Entity.s_Entity)
Define Robot.s_Entity
Define Camera.s_Camera
; OpenGL needs to have CG enabled to work (Linux and OS X have OpenGL by default)
;
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows Or Subsystem("OpenGL")
Flags = #PB_Engine3D_EnableCG
CompilerEndIf
If InitEngine3D(Flags)
InitSprite()
InitKeyboard()
InitMouse()
If Screen3DRequester()
Add3DArchive("Data/Textures/" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Models" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Scripts" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Textures/nvidia" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Packs/desert.zip", #PB_3DArchive_Zip)
Parse3DScripts()
WorldShadows(#PB_Shadow_Modulative, 200, RGB(120, 120, 120))
MaterialFilteringMode(#PB_Default, #PB_Material_Anisotropic, 8)
;- Light
;
light = CreateLight(#PB_Any ,RGB(185, 185, 185), 4000, 1200, 1000, #PB_Light_Directional)
SetLightColor(light, #PB_Light_SpecularColor, RGB(255*0.4, 255*0.4,255*0.4))
LightDirection(light ,0.55, -0.3, -0.75)
AmbientColor(RGB(5, 5,5))
;- Camera
;
CreateCamera(0, 0, 0, 100, 100)
CameraBackColor(0, RGB(5, 5, 10))
;----------------------------------
;-terrain definition
SetupTerrains(LightID(Light), 300, #PB_Terrain_NormalMapping)
;-initialize terrain
CreateTerrain(0, 513, 1200, 60, 3, "TerrainPhysic", "dat")
;-set all texture will be use when terrrain will be constructed
AddTerrainTexture(0, 0, 10, "dirt_grayrocky_diffusespecular.jpg", "dirt_grayrocky_normalheight.jpg")
AddTerrainTexture(0, 1, 3, "grass_green-01_diffusespecular.jpg", "grass_green-01_normalheight.jpg")
AddTerrainTexture(0, 2, 20, "growth_weirdfungus-03_diffusespecular.jpg", "growth_weirdfungus-03_normalheight.jpg")
;-Construct terrains
For ty = #TerrainMiniY To #TerrainMaxiY
For tx = #TerrainMiniX To #TerrainMaxiX
Imported = DefineTerrainTile(0, tx, ty, "terrain513.png", ty % 2, tx % 2)
Next
Next
BuildTerrain(0)
If Imported = #True
InitBlendMaps()
UpdateTerrain(0)
; If enabled, it will save the terrain as a (big) cache for a faster load next time the program is executed
; SaveTerrain(0, #False)
EndIf
; enable shadow terrain
TerrainRenderMode(0, 0)
;Add Physic
TerrainPhysicBody(0, 0.1, 1)
;Texture
CreateTexture(1, 256, 256)
StartDrawing(TextureOutput(1))
Box(0, 0, 256, 256, $002255)
DrawingMode(#PB_2DDrawing_Outlined)
Box(0, 0, 256, 256, $FFFFFF)
Box(10, 10, 236, 236, $FFFF)
StopDrawing()
;Material
CreateMaterial(0, LoadTexture(0, "r2skin.jpg"))
CreateMaterial(1, TextureID(1))
CreateMaterial(2, LoadTexture(2, "Dirt.jpg"))
CreateMaterial(3, LoadTexture(3, "Wood.jpg"))
GetScriptMaterial(4, "Scene/GroundBlend")
;Robot
CreateSphere(0, 1)
Rob = LoadMesh(#PB_Any, "Robot.mesh")
CreateEntity (0, MeshID(Rob), #PB_Material_None)
ScaleEntity(0, 0.1, 0.1, 0.1)
StartEntityAnimation(0, "Walk")
;Robot Body
CreateEntity(1, MeshID(0), #PB_Material_None, 0, 426, 0)
HideEntity(1, 1)
;Body
EntityPhysicBody(1, #PB_Entity_SphereBody, 1, 0, 0)
; Skybox
SkyBox("desert07.jpg")
;
With Robot
\Entity = 0
\EntityBody = 1
\BodyOffsetY = 1
\Key\Down = #PB_Key_Down
\Key\Left = #PB_Key_Left
\Key\Right = #PB_Key_Right
\Key\Up = #PB_Key_Up
\Key\StrafeLeft = #PB_Key_X
\Key\StrafeRight = #PB_Key_C
\Key\Jump = #PB_Key_Space
\MainNode = CreateNode(#PB_Any) ; Entity position
\SightNode = CreateNode(#PB_Any, 12, 2, 0) ; For cameraLookAt
\CameraNode = CreateNode(#PB_Any, -14, 10, 0) ; Camera position
\ForwardNode = CreateNode(#PB_Any, 1, 0, 0) ; Direction normalized
\StrafeNode = CreateNode(#PB_Any, 0, 0, -1) ; Direction normalized
AttachNodeObject(\MainNode, NodeID(\SightNode))
AttachNodeObject(\MainNode, NodeID(\CameraNode))
AttachNodeObject(\MainNode, NodeID(\ForwardNode))
AttachNodeObject(\MainNode, NodeID(\StrafeNode))
AttachNodeObject(\MainNode, EntityID(\Entity))
EndWith
;-Camera
With Camera
\Camera = 0
\Tightness = 0.035
; Camera use 2 nodes
\CameraNode = CreateNode(#PB_Any, -3000, 700, 0) ; Camera position
\TargetNode = CreateNode(#PB_Any) ; For cameraLookAt
AttachNodeObject(\CameraNode, CameraID(\Camera))
EndWith
;==================================
; create material
Red = GetScriptMaterial(#PB_Any, "Color/Red")
Blue = GetScriptMaterial(#PB_Any, "Color/Blue")
Yellow = GetScriptMaterial(#PB_Any, "Color/Yellow")
Green = GetScriptMaterial(#PB_Any, "Color/Green")
;==================================
; create Sphere
MeshSphere = CreateSphere(#PB_Any, 1.0)
For i = 0 To 5
Entity=CreateEntity(#PB_Any, MeshID(MeshSphere), MaterialID(Green))
MoveEntity(Entity, Random(200)-100, 80, Random(400)-200, #PB_Absolute)
; create bodies
EntityPhysicBody(Entity, #PB_Entity_SphereBody, 1.0)
Next
;==================================
; create Cylinder
MeshCylinder = CreateCylinder(#PB_Any, 1.0, 6)
For i = 0 To 5
Entity=CreateEntity(#PB_Any, MeshID(MeshCylinder), MaterialID(Red))
MoveEntity(Entity, Random(200)-100, 80, Random(400)-200, #PB_Absolute)
; create bodies
EntityPhysicBody(Entity, #PB_Entity_CylinderBody, 1.0, 0, 1)
Next
;==================================
; create Cube
MeshCube = CreateCube(#PB_Any, 0.25)
For i = 0 To 5
Entity=CreateEntity(#PB_Any, MeshID(MeshCube), MaterialID(Yellow))
MoveEntity(Entity, Random(200)-100, 80, Random(400)-200, #PB_Absolute)
; create bodies
EntityPhysicBody(Entity, #PB_Entity_BoxBody, 1.0)
Next
Repeat
Screen3DEvents()
Robot\elapsedTime = TimeSinceLastFrame
HandleEntity(@Robot)
CameraTrack(@Camera, @Robot)
TimeSinceLastFrame = RenderWorld(60) * 40 / 1000
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
End
EndIf
Else
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows Or Subsystem("OpenGL")
;
; Terrain on Linux/OSX and Windows with OpenGL needs CG toolkit from nvidia
; It can be freely downloaded and installed from this site: https://developer.nvidia.com/cg-toolkit-download
;
MessageRequester("Error","Can't initialize engine3D (Please ensures than CG Toolkit from nvidia is correcly installed)")
CompilerElse
MessageRequester("Error","Can't initialize engine3D")
CompilerEndIf
EndIf
Procedure Clamp(*var.float, min.f, max.f)
If *var\f < min
*var\f = min
ElseIf *var\f > max
*var\f = max
EndIf
EndProcedure
Procedure InitBlendMaps()
minHeight1.f = 7
fadeDist1.f = 40
minHeight2.f = 7
fadeDist2.f = 15
For ty = #TerrainMiniY To #TerrainMaxiY
For tx = #TerrainMiniX To #TerrainMaxiX
Size = TerrainTileLayerMapSize(0, tx, ty)
For y = 0 To Size-1
For x = 0 To Size-1
Height.f = TerrainTileHeightAtPosition(0, tx, ty, 1, x, y)
val.f = (Height - minHeight1) / fadeDist1
Clamp(@val, 0, 1)
SetTerrainTileLayerBlend(0, tx, ty, 1, x, y, val)
val.f = (Height - minHeight2) / fadeDist2
Clamp(@val, 0, 1)
SetTerrainTileLayerBlend(0, tx, ty, 2, x, y, val)
Next
Next
UpdateTerrainTileLayerBlend(0, tx, ty, 1)
UpdateTerrainTileLayerBlend(0, tx, ty, 2)
Next
Next
EndProcedure
Procedure OnGround(*Entity.s_Entity)
With *Entity
Result = RayCollide(EntityX(\EntityBody), EntityY(\EntityBody), EntityZ(\EntityBody), EntityX(\EntityBody), EntityY(\EntityBody)-7, EntityZ(\EntityBody))
;CreateLine3D(20,EntityX(\EntityBody), EntityY(\EntityBody), EntityZ(\EntityBody), $FFFF, EntityX(\EntityBody), EntityY(\EntityBody)-7, EntityZ(\EntityBody), $FFFF)
Delta.f = EntityY(\EntityBody) - PickY() - \BodyOffsetY
If Result=-1 Or (Result>-1 And (delta >= 1))
ProcedureReturn 0
Else
CreateLine3D(20,PickX(), PickY(), PickZ(), $FFFF, PickX()+NormalX()*6, PickY()+NormalY()*6, PickZ()+NormalZ()*6, $FFFF)
RotateEntity(\Entity, Degree(ASin(NormalZ())), 0, Degree(ASin(-NormalX())))
ProcedureReturn 1
EndIf
EndWith
EndProcedure
Procedure HandleEntity(*Entity.s_Entity)
Protected.Vector3 Forward, Strafe, PosMain, PosDir, PosStrafe
Protected.f Speed, Speed2, x, y, MouseX, MouseY
Static Jump.f, MemJump.i, Rot.Vector3, Trans.Vector3, Clic
With *Entity
GetNodePosition(PosMain, \MainNode)
GetNodePosition(PosDir, \ForwardNode)
GetNodePosition(PosStrafe, \StrafeNode)
SubVector3(Forward, PosDir, PosMain)
SubVector3(Strafe, PosStrafe, PosMain)
Speed = #PlayerSpeed * \elapsedTime
Speed2 = Speed / 2
If ExamineKeyboard()
If KeyboardReleased(#PB_Key_F5)
WorldDebug(#PB_World_DebugBody)
ElseIf KeyboardReleased(#PB_Key_F6)
WorldDebug(#PB_World_DebugEntity)
ElseIf KeyboardReleased(#PB_Key_F7)
WorldDebug(#PB_World_DebugNone)
EndIf
If KeyboardPushed(\Key\Jump) And OnGround(*Entity)
Jump = 2
MemJump = 1
EndIf
Rot\x * 0.30
Rot\y * 0.30
Rot\z * 0.30
Trans\x * 0.20
Trans\y = Jump
Trans\z * 0.20
If KeyboardPushed(\Key\Up)
Trans\x + Forward\x * Speed
Trans\z + Forward\z * Speed
ElseIf KeyboardPushed(\Key\Down)
Trans\x + Forward\x * -Speed2
Trans\z + Forward\z * -Speed2
EndIf
If KeyboardPushed(\Key\Left)
Rot\y + 2 * \elapsedTime
ElseIf KeyboardPushed(\Key\Right)
Rot\y - 2 * \elapsedTime
EndIf
If KeyboardPushed(\Key\StrafeLeft)
Trans\x + Strafe\x * Speed2
Trans\z + Strafe\z * Speed2
ElseIf KeyboardPushed(\Key\StrafeRight)
Trans\x + Strafe\x * -Speed2
Trans\z + Strafe\z * -Speed2
EndIf
If OnGround(*Entity)
Jump = 0
ElseIf MemJump
Jump + 2 * \elapsedTime
If Jump > 15
MemJump = 0
EndIf
Else
Jump - 9
EndIf
EndIf
MoveEntity (\EntityBody, Trans\x, Trans\y, Trans\z)
RotateEntity(\EntityBody, 0, Rot\y, 0, #PB_Relative)
MoveNode(\MainNode, EntityX(\EntityBody), EntityY(\EntityBody)-\BodyOffsetY, EntityZ(\EntityBody), #PB_Absolute)
RotateNode(\MainNode, 0, EntityYaw(\EntityBody), 0)
EndWith
EndProcedure
Procedure CameraTrack(*Camera.s_Camera, *Entity.s_Entity)
Protected.Vector3 CameraPosition, TargetPosition
Protected.f x, y, z
GetNodePosition(CameraPosition, *Entity\CameraNode)
GetNodePosition(TargetPosition, *Entity\SightNode)
x = NodeX(*Camera\CameraNode)
y = NodeY(*Camera\CameraNode)
z = NodeZ(*Camera\CameraNode)
x = (CameraPosition\x - x) * *Camera\Tightness
y = (CameraPosition\y - y) * *Camera\Tightness
z = (CameraPosition\z - z) * *Camera\Tightness
MoveNode(*Camera\CameraNode, x, y, z)
x = NodeX(*Camera\TargetNode)
y = NodeY(*Camera\TargetNode)
z = NodeZ(*Camera\TargetNode)
x = (TargetPosition\x - x) * *Camera\Tightness
y = (TargetPosition\y - y) * *Camera\Tightness
z = (TargetPosition\z - z) * *Camera\Tightness
MoveNode(*Camera\TargetNode, x, y, z)
CameraLookAt(*Camera\Camera, NodeX(*Camera\TargetNode), NodeY(*Camera\TargetNode), NodeZ(*Camera\TargetNode))
EndProcedurePlease correct my english
http://purebasic.developpez.com/
http://purebasic.developpez.com/
Re: Smooth align Player to Object/Terrain he's standing
added smooth orientation
Code: Select all
;
; ------------------------------------------------------------
;
; PureBasic - Terrain : Physic
;
; (c) 2012 - Fantaisie Software
;
; ------------------------------------------------------------
;
IncludeFile "Screen3DRequester.pb"
#TerrainMiniX = 0
#TerrainMiniY = 0
#TerrainMaxiX = 0
#TerrainMaxiY = 0
#PlayerSpeed = 6
#CameraSpeed = 1
Define.f KeyX, KeyY, MouseX, MouseY, TimeSinceLastFrame
Declare InitBlendMaps()
Structure Vector3
x.f
y.f
z.f
EndStructure
Structure Quaternion
w.f
x.f
y.f
z.f
EndStructure
Structure Colonne3
n.f[3]
EndStructure
Structure Matrix3
m.Colonne3[3]
EndStructure
Structure s_Key
Up.i
Down.i
Left.i
Right.i
StrafeLeft.i
StrafeRight.i
Jump.i
EndStructure
Structure s_Entity
Entity.i
EntityBody.i
BodyOffsetY.f
elapsedTime.f
Key.s_Key
MainNode.i
SightNode.i
Direction.i
EndStructure
Structure s_Camera
Camera.i
Tightness.f
CameraNode.i
TargetNode.i
EndStructure
Macro GetNodePosition(Position, Node)
Position\x = NodeX(Node)
Position\y = NodeY(Node)
Position\z = NodeZ(Node)
EndMacro
Macro SubVector3(V, V1, V2)
V\x = V1\x - V2\x
V\y = V1\y - V2\y
V\z = V1\z - V2\z
EndMacro
Macro AddVector3(V, V1, V2)
V\x = V1\x + V2\x
V\y = V1\y + V2\y
V\z = V1\z + V2\z
EndMacro
Macro PRODUIT_VECTORIEL(N, V1, V2)
N\x = ((V1\y * V2\z) - (V1\z * V2\y))
N\y = ((V1\z * V2\x) - (V1\x * V2\z))
N\z = ((V1\x * V2\y) - (V1\y * V2\x))
EndMacro
;-Declare
Declare HandleEntity(*Entity.s_Entity)
Declare CameraTrack(*Camera.s_Camera, *Entity.s_Entity)
Declare OnGround(*Entity.s_Entity)
Define Robot.s_Entity
Define Camera.s_Camera
Global R.Quaternion
; OpenGL needs to have CG enabled to work (Linux and OS X have OpenGL by default)
;
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows Or Subsystem("OpenGL")
Flags = #PB_Engine3D_EnableCG
CompilerEndIf
If InitEngine3D(Flags)
InitSprite()
InitKeyboard()
InitMouse()
If Screen3DRequester()
Add3DArchive("Data/Textures/" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Models" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Scripts" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Textures/nvidia" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Packs/desert.zip", #PB_3DArchive_Zip)
Parse3DScripts()
WorldShadows(#PB_Shadow_Modulative, 200, RGB(120, 120, 120))
MaterialFilteringMode(#PB_Default, #PB_Material_Anisotropic, 8)
;- Light
;
light = CreateLight(#PB_Any ,RGB(185, 185, 185), 4000, 1200, 1000, #PB_Light_Directional)
SetLightColor(light, #PB_Light_SpecularColor, RGB(255*0.4, 255*0.4,255*0.4))
LightDirection(light ,0.55, -0.3, -0.75)
AmbientColor(RGB(5, 5,5))
;----------------------------------
;-terrain definition
SetupTerrains(LightID(Light), 300, #PB_Terrain_NormalMapping)
;-initialize terrain
CreateTerrain(0, 513, 1200, 60, 3, "TerrainPhysic", "dat")
;-set all texture will be use when terrrain will be constructed
AddTerrainTexture(0, 0, 10, "dirt_grayrocky_diffusespecular.jpg", "dirt_grayrocky_normalheight.jpg")
AddTerrainTexture(0, 1, 3, "grass_green-01_diffusespecular.jpg", "grass_green-01_normalheight.jpg")
AddTerrainTexture(0, 2, 20, "growth_weirdfungus-03_diffusespecular.jpg", "growth_weirdfungus-03_normalheight.jpg")
;-Construct terrains
For ty = #TerrainMiniY To #TerrainMaxiY
For tx = #TerrainMiniX To #TerrainMaxiX
Imported = DefineTerrainTile(0, tx, ty, "terrain513.png", ty % 2, tx % 2)
Next
Next
BuildTerrain(0)
If Imported = #True
InitBlendMaps()
UpdateTerrain(0)
; If enabled, it will save the terrain as a (big) cache for a faster load next time the program is executed
; SaveTerrain(0, #False)
EndIf
; enable shadow terrain
TerrainRenderMode(0, 0)
;Add Physic
TerrainPhysicBody(0, 0.1, 1)
;Texture
CreateTexture(1, 256, 256)
StartDrawing(TextureOutput(1))
Box(0, 0, 256, 256, $002255)
DrawingMode(#PB_2DDrawing_Outlined)
Box(0, 0, 256, 256, $FFFFFF)
Box(10, 10, 236, 236, $FFFF)
StopDrawing()
;Material
CreateMaterial(0, LoadTexture(0, "r2skin.jpg"))
CreateMaterial(1, TextureID(1))
CreateMaterial(2, LoadTexture(2, "Dirt.jpg"))
CreateMaterial(3, LoadTexture(3, "Wood.jpg"))
GetScriptMaterial(4, "Scene/GroundBlend")
;Robot
CreateSphere(0, 1)
Rob = LoadMesh(#PB_Any, "Robot.mesh")
CreateEntity (0, MeshID(Rob), #PB_Material_None)
ScaleEntity(0, 0.1, 0.1, 0.1)
StartEntityAnimation(0, "Walk")
;Robot Body
CreateEntity(1, MeshID(0), #PB_Material_None, 0, 426, 0)
HideEntity(1, 1)
;Body
EntityPhysicBody(1, #PB_Entity_SphereBody, 1, 0, 0)
; Skybox
SkyBox("desert07.jpg")
;
With Robot
\Entity = 0
\EntityBody = 1
\BodyOffsetY = 1
\Key\Down = #PB_Key_Down
\Key\Left = #PB_Key_Left
\Key\Right = #PB_Key_Right
\Key\Up = #PB_Key_Up
\Key\StrafeLeft = #PB_Key_X
\Key\StrafeRight = #PB_Key_C
\Key\Jump = #PB_Key_Space
;\MainNode = CreateNode(#PB_Any) ; Entity position
\Direction = CreateNode(#PB_Any, 1, 0, 0) ; For cameraLookAt
\SightNode = CreateNode(#PB_Any, 12, 2, 0) ; For cameraLookAt
AttachEntityObject(\EntityBody, "", NodeID(\Direction))
AttachEntityObject(\EntityBody, "", NodeID(\SightNode))
;AttachNodeObject(\MainNode, EntityID(\Entity))
EndWith
;- Camera
;
CreateCamera(0, 0, 0, 100, 100)
CameraBackColor(0, RGB(5, 5, 10))
;==================================
; create material
Red = GetScriptMaterial(#PB_Any, "Color/Red")
Blue = GetScriptMaterial(#PB_Any, "Color/Blue")
Yellow = GetScriptMaterial(#PB_Any, "Color/Yellow")
Green = GetScriptMaterial(#PB_Any, "Color/Green")
;==================================
; create Sphere
MeshSphere = CreateSphere(#PB_Any, 1.0)
For i = 0 To 5
Entity=CreateEntity(#PB_Any, MeshID(MeshSphere), MaterialID(Green))
MoveEntity(Entity, Random(200)-100, 80, Random(400)-200, #PB_Absolute)
; create bodies
EntityPhysicBody(Entity, #PB_Entity_SphereBody, 1.0)
Next
;==================================
; create Cylinder
MeshCylinder = CreateCylinder(#PB_Any, 1.0, 6)
For i = 0 To 5
Entity=CreateEntity(#PB_Any, MeshID(MeshCylinder), MaterialID(Red))
MoveEntity(Entity, Random(200)-100, 80, Random(400)-200, #PB_Absolute)
; create bodies
EntityPhysicBody(Entity, #PB_Entity_CylinderBody, 1.0, 0, 1)
Next
;==================================
; create Cube
MeshCube = CreateCube(#PB_Any, 0.25)
For i = 0 To 5
Entity=CreateEntity(#PB_Any, MeshID(MeshCube), MaterialID(Yellow))
MoveEntity(Entity, Random(200)-100, 80, Random(400)-200, #PB_Absolute)
; create bodies
EntityPhysicBody(Entity, #PB_Entity_BoxBody, 1.0)
Next
Repeat
Screen3DEvents()
Robot\elapsedTime = TimeSinceLastFrame
HandleEntity(@Robot)
CameraFollow(0, EntityID(Robot\Entity), -90, EntityY(Robot\Entity) + 10, 25, 0.1, 0.1, 0)
CameraLookAt(0, NodeX(Robot\SightNode), NodeY(Robot\SightNode), NodeZ(Robot\SightNode))
TimeSinceLastFrame = RenderWorld(60) * 40 / 1000
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
End
EndIf
Else
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows Or Subsystem("OpenGL")
;
; Terrain on Linux/OSX and Windows with OpenGL needs CG toolkit from nvidia
; It can be freely downloaded and installed from this site: https://developer.nvidia.com/cg-toolkit-download
;
MessageRequester("Error","Can't initialize engine3D (Please ensures than CG Toolkit from nvidia is correcly installed)")
CompilerElse
MessageRequester("Error","Can't initialize engine3D")
CompilerEndIf
EndIf
Procedure Clamp(*var.float, min.f, max.f)
If *var\f < min
*var\f = min
ElseIf *var\f > max
*var\f = max
EndIf
EndProcedure
Procedure InitBlendMaps()
minHeight1.f = 7
fadeDist1.f = 40
minHeight2.f = 7
fadeDist2.f = 15
For ty = #TerrainMiniY To #TerrainMaxiY
For tx = #TerrainMiniX To #TerrainMaxiX
Size = TerrainTileLayerMapSize(0, tx, ty)
For y = 0 To Size-1
For x = 0 To Size-1
Height.f = TerrainTileHeightAtPosition(0, tx, ty, 1, x, y)
val.f = (Height - minHeight1) / fadeDist1
Clamp(@val, 0, 1)
SetTerrainTileLayerBlend(0, tx, ty, 1, x, y, val)
val.f = (Height - minHeight2) / fadeDist2
Clamp(@val, 0, 1)
SetTerrainTileLayerBlend(0, tx, ty, 2, x, y, val)
Next
Next
UpdateTerrainTileLayerBlend(0, tx, ty, 1)
UpdateTerrainTileLayerBlend(0, tx, ty, 2)
Next
Next
EndProcedure
Procedure Normalize(*V.Vector3)
Protected.f magSq, oneOverMag
magSq = *V\x * *V\x + *V\y * *V\y + *V\z * *V\z
If magsq > 0
oneOverMag = 1.0 / Sqr(magSq)
*V\x * oneOverMag
*V\y * oneOverMag
*V\z * oneOverMag
EndIf
EndProcedure
Procedure.f QuaternionNormalise(*Q.Quaternion)
Protected.f magSq, oneOverMag
magSq = *Q\w**Q\w+*Q\x**Q\x+*Q\y**Q\y+*Q\z**Q\z
oneOverMag = 1.0 / Sqr(magSq)
*Q\w * oneOverMag
*Q\x * oneOverMag
*Q\y * oneOverMag
*Q\z * oneOverMag
EndProcedure
Procedure.f DotProduct(*V1.Vector3, *V2.Vector3)
ProcedureReturn *V1\x * *V2\x + *V1\y * *V2\y + *V1\z * *V2\z
EndProcedure
Procedure.f QuaternionDot(*Q.Quaternion, *rkQ.Quaternion)
ProcedureReturn *Q\w**rkQ\w+*Q\x**rkQ\x+*Q\y**rkQ\y+*Q\z**rkQ\z
EndProcedure
Procedure FromRotationMatrix(*Q.Quaternion, *kRot.Matrix3)
; Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
; article "Quaternion Calculus and Fast Animation".
fTrace.f = *kRot\m[0]\n[0]+*kRot\m[1]\n[1]+*kRot\m[2]\n[2]
fRoot.f
If fTrace > 0.0
; |w| > 1/2, may As well choose w > 1/2
fRoot =Sqr(fTrace + 1.0); 2w
*Q\w = 0.5*fRoot
fRoot = 0.5/fRoot; 1/(4w)
*Q\x = (*kRot\m[2]\n[1]-*kRot\m[1]\n[2])*fRoot;
*Q\y = (*kRot\m[0]\n[2]-*kRot\m[2]\n[0])*fRoot;
*Q\z = (*kRot\m[1]\n[0]-*kRot\m[0]\n[1])*fRoot;
Else
; |w| <= 1/2
Dim s_iNext(2)
s_iNext(0) = 1
s_iNext(1) = 2
s_iNext(2) = 0
i = 0
If *kRot\m[1]\n[1] > *kRot\m[0]\n[0]
i = 1
EndIf
If *kRot\m[2]\n[2] > *kRot\m[i]\n[i]
i = 2
EndIf
j = s_iNext(i)
k = s_iNext(j)
fRoot =Sqr(*kRot\m[i]\n[i]-*kRot\m[j]\n[j]-*kRot\m[k]\n[k] + 1.0)
Dim *apkQuat.Float(2)
*apkQuat(0) = @*Q\x
*apkQuat(1) = @*Q\y
*apkQuat(2) = @*Q\z
*apkQuat(i)\f = 0.5*fRoot
fRoot = 0.5/fRoot
*Q\w = (*kRot\m[k]\n[j]-*kRot\m[j]\n[k])*fRoot
*apkQuat(j)\f = (*kRot\m[j]\n[i]+*kRot\m[i]\n[j])*fRoot
*apkQuat(k)\f = (*kRot\m[k]\n[i]+*kRot\m[i]\n[k])*fRoot
EndIf
EndProcedure
Procedure QuaternionFromAxes(*Q.Quaternion, *xaxis.Vector3, *yaxis.Vector3, *zaxis.Vector3)
Protected kRot.Matrix3
kRot\m[0]\n[0] = *xaxis\x
kRot\m[1]\n[0] = *xaxis\y
kRot\m[2]\n[0] = *xaxis\z
kRot\m[0]\n[1] = *yaxis\x
kRot\m[1]\n[1] = *yaxis\y
kRot\m[2]\n[1] = *yaxis\z
kRot\m[0]\n[2] = *zaxis\x
kRot\m[1]\n[2] = *zaxis\y
kRot\m[2]\n[2] = *zaxis\z
FromRotationMatrix(*Q, @kRot)
EndProcedure
Procedure Slerp(*t.Quaternion, fT.f, *rkP.Quaternion, *rkQ.Quaternion, shortestPath)
msEpsilon = 1e-03
fCos.f = QuaternionDot(*rkP, *rkQ)
rkT.Quaternion
; Do we need To invert rotation?
If Bool((fCos < 0.0) And shortestPath)
fCos = -fCos
rkT\w = -*rkQ\w
rkT\x = -*rkQ\x
rkT\y = -*rkQ\y
rkT\z = -*rkQ\z
Else
rkT\w = *rkQ\w
rkT\x = *rkQ\x
rkT\y = *rkQ\y
rkT\z = *rkQ\z
EndIf
If (Abs(fCos) < 1 - msEpsilon)
; Standard Case (slerp)
fSin.f = Sqr(1 - (fCos*fCos))
fAngle.f =ATan2(fSin, fCos)
fInvSin.f = 1.0 / fSin;
fCoeff0.f = Sin((1.0 - fT) * fAngle) * fInvSin
fCoeff1.f = Sin(fT * fAngle) * fInvSin
*t\w = fCoeff0 * *rkP\w + fCoeff1 * rkT\w
*t\x = fCoeff0 * *rkP\x + fCoeff1 * rkT\x
*t\y = fCoeff0 * *rkP\y + fCoeff1 * rkT\y
*t\z = fCoeff0 * *rkP\z + fCoeff1 * rkT\z
Else
; There are two situations:
; 1. "rkP" And "rkQ" are very close (fCos ~= +1), so we can do a linear
; interpolation safely.
; 2. "rkP" And "rkQ" are almost inverse of each other (fCos ~= -1), there
; are an infinite number of possibilities interpolation. but we haven't
; have method To fix this Case, so just use linear interpolation here.
*t\w = (1.0 - fT) * *rkP\w + fT * rkT\w
*t\x = (1.0 - fT) * *rkP\x + fT * rkT\x
*t\y = (1.0 - fT) * *rkP\y + fT * rkT\y
*t\z = (1.0 - fT) * *rkP\z + fT * rkT\z
; taking the complement requires renormalisation
QuaternionNormalise(*t)
EndIf
EndProcedure
Procedure OnGround(*Entity.s_Entity)
Protected.Quaternion S, Q
Protected.Vector3 xaxis, yaxis, zaxis
With *Entity
Result = RayCollide(EntityX(\EntityBody), EntityY(\EntityBody), EntityZ(\EntityBody), EntityX(\EntityBody), EntityY(\EntityBody)-7, EntityZ(\EntityBody))
;CreateLine3D(20,EntityX(\EntityBody), EntityY(\EntityBody), EntityZ(\EntityBody), $FFFF, EntityX(\EntityBody), EntityY(\EntityBody)-7, EntityZ(\EntityBody), $FFFF)
Delta.f = EntityY(\EntityBody) - PickY() - \BodyOffsetY
If Result=-1 Or (Result>-1 And (delta >= 1))
ProcedureReturn 0
Else
;CreateLine3D(20,PickX(), PickY(), PickZ(), $FFFF, PickX()+NormalX()*6, PickY()+NormalY()*6, PickZ()+NormalZ()*6, $FFFF)
xaxis\x = NodeX(\Direction) - EntityX(\EntityBody)
xaxis\y = NodeY(\Direction) - EntityY(\EntityBody)
xaxis\z = NodeZ(\Direction) - EntityZ(\EntityBody)
yaxis\x = NormalX()
yaxis\y = NormalY()
yaxis\z = NormalZ()
PRODUIT_VECTORIEL(zaxis, xaxis, yaxis)
PRODUIT_VECTORIEL(xaxis, yaxis, zaxis)
QuaternionFromAxes(@Q, @xaxis, @yaxis, @zaxis)
FetchOrientation(EntityID(\Entity))
S\w = GetW()
S\x = GetX()
S\y = GetY()
S\z = GetZ()
Slerp(@R, 0.05, @S, @Q, 0)
SetOrientation(EntityID(\Entity),r\x, r\y, r\z, r\w)
ProcedureReturn 1
EndIf
EndWith
EndProcedure
Procedure HandleEntity(*Entity.s_Entity)
Protected.f Speed, Speed2, x, y, MouseX, MouseY
Static Jump.f, MemJump.i, Rot.Vector3, Trans.Vector3, Clic
With *Entity
Speed = #PlayerSpeed * \elapsedTime
Speed2 = Speed / 2
If ExamineKeyboard()
If KeyboardReleased(#PB_Key_F5)
WorldDebug(#PB_World_DebugBody)
ElseIf KeyboardReleased(#PB_Key_F6)
WorldDebug(#PB_World_DebugEntity)
ElseIf KeyboardReleased(#PB_Key_F7)
WorldDebug(#PB_World_DebugNone)
EndIf
If KeyboardPushed(\Key\Jump) And OnGround(*Entity)
Jump = 2
MemJump = 1
EndIf
Rot\x * 0.30
Rot\y * 0.30
Rot\z * 0.30
Trans\x * 0.20
Trans\y = Jump
Trans\z * 0.20
If KeyboardPushed(\Key\Up)
Trans\x = Speed
ElseIf KeyboardPushed(\Key\Down)
Trans\x = -Speed2
EndIf
If KeyboardPushed(\Key\Left)
Rot\y + 2 * \elapsedTime
ElseIf KeyboardPushed(\Key\Right)
Rot\y - 2 * \elapsedTime
EndIf
If KeyboardPushed(\Key\StrafeLeft)
Trans\z = -Speed2
ElseIf KeyboardPushed(\Key\StrafeRight)
Trans\z = Speed2
EndIf
If OnGround(*Entity)
Jump = 0
ElseIf MemJump
Jump + 2 * \elapsedTime
If Jump > 15
MemJump = 0
EndIf
Else
Jump - 9
EndIf
EndIf
MoveEntity (\EntityBody, Trans\x, Trans\y, Trans\z, #PB_Local)
RotateEntity(\EntityBody, 0, Rot\y, 0, #PB_Relative)
MoveEntity(\Entity, EntityX(\EntityBody), EntityY(\EntityBody)-\BodyOffsetY, EntityZ(\EntityBody), #PB_Absolute)
EndWith
EndProcedure
Last edited by Comtois on Sun Sep 08, 2013 3:36 pm, edited 1 time in total.
Please correct my english
http://purebasic.developpez.com/
http://purebasic.developpez.com/
Re: Smooth align Player to Object/Terrain he's standing
there is a bug (code edited)
replace this
by this
How it work :
- 1 - Create quaternion using normal and Entity's direction (the axes are assumed to be orthonormal.)
- 2 - Get entity's orientation (quaternion)
- 3 - interpolate orientation
replace this
Code: Select all
xaxis\x = NodeX(\Direction) - EntityX(\Entity)
xaxis\y = NodeY(\Direction) - EntityY(\Entity)
xaxis\z = NodeZ(\Direction) - EntityZ(\Entity)Code: Select all
xaxis\x = NodeX(\Direction) - EntityX(\EntityBody)
xaxis\y = NodeY(\Direction) - EntityY(\EntityBody)
xaxis\z = NodeZ(\Direction) - EntityZ(\EntityBody)yes this is an example, there are still things to do.Edit: oh, and by pressing Space it freezes
How it work :
- 1 - Create quaternion using normal and Entity's direction (the axes are assumed to be orthonormal.)
Code: Select all
xaxis\x = NodeX(\Direction) - EntityX(\EntityBody)
xaxis\y = NodeY(\Direction) - EntityY(\EntityBody)
xaxis\z = NodeZ(\Direction) - EntityZ(\EntityBody)
yaxis\x = NormalX()
yaxis\y = NormalY()
yaxis\z = NormalZ()
PRODUIT_VECTORIEL(zaxis, xaxis, yaxis)
PRODUIT_VECTORIEL(xaxis, yaxis, zaxis)
QuaternionFromAxes(@Q, @xaxis, @yaxis, @zaxis)Code: Select all
FetchOrientation(EntityID(\Entity))
S\w = GetW()
S\x = GetX()
S\y = GetY()
S\z = GetZ()Code: Select all
Slerp(@R, 0.05, @S, @Q, 0)Please correct my english
http://purebasic.developpez.com/
http://purebasic.developpez.com/
Re: Smooth align Player to Object/Terrain he's standing
small change to show you how to keep the robot on the ground. Another solution would be to calculate slope of the land and move the robot along the slope. I added the calculation of the slope and a 3D line to materialize it.
Code: Select all
;
; ------------------------------------------------------------
;
; PureBasic - Terrain : Physic
;
; (c) 2012 - Fantaisie Software
;
; ------------------------------------------------------------
;
IncludeFile "Screen3DRequester.pb"
#TerrainMiniX = 0
#TerrainMiniY = 0
#TerrainMaxiX = 0
#TerrainMaxiY = 0
#PlayerSpeed = 6
#CameraSpeed = 1
Define.f KeyX, KeyY, MouseX, MouseY, TimeSinceLastFrame
Declare InitBlendMaps()
Structure Vector3
x.f
y.f
z.f
EndStructure
Structure Quaternion
w.f
x.f
y.f
z.f
EndStructure
Structure Colonne3
n.f[3]
EndStructure
Structure Matrix3
m.Colonne3[3]
EndStructure
Structure s_Key
Up.i
Down.i
Left.i
Right.i
StrafeLeft.i
StrafeRight.i
Jump.i
EndStructure
Structure s_Entity
Entity.i
EntityBody.i
BodyOffsetY.f
elapsedTime.f
Key.s_Key
MainNode.i
SightNode.i
Direction.i
EndStructure
Structure s_Camera
Camera.i
Tightness.f
CameraNode.i
TargetNode.i
EndStructure
Macro GetNodePosition(Position, Node)
Position\x = NodeX(Node)
Position\y = NodeY(Node)
Position\z = NodeZ(Node)
EndMacro
Macro SubVector3(V, V1, V2)
V\x = V1\x - V2\x
V\y = V1\y - V2\y
V\z = V1\z - V2\z
EndMacro
Macro AddVector3(V, V1, V2)
V\x = V1\x + V2\x
V\y = V1\y + V2\y
V\z = V1\z + V2\z
EndMacro
Macro PRODUIT_VECTORIEL(N, V1, V2)
N\x = ((V1\y * V2\z) - (V1\z * V2\y))
N\y = ((V1\z * V2\x) - (V1\x * V2\z))
N\z = ((V1\x * V2\y) - (V1\y * V2\x))
EndMacro
;-Declare
Declare HandleEntity(*Entity.s_Entity)
Declare CameraTrack(*Camera.s_Camera, *Entity.s_Entity)
Declare OnGround(*Entity.s_Entity)
Define Robot.s_Entity
Define Camera.s_Camera
Global R.Quaternion
; OpenGL needs to have CG enabled to work (Linux and OS X have OpenGL by default)
;
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows Or Subsystem("OpenGL")
Flags = #PB_Engine3D_EnableCG
CompilerEndIf
If InitEngine3D(Flags)
InitSprite()
InitKeyboard()
InitMouse()
If Screen3DRequester()
Add3DArchive("Data/Textures/" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Models" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Scripts" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Textures/nvidia" , #PB_3DArchive_FileSystem)
Add3DArchive("Data/Packs/desert.zip", #PB_3DArchive_Zip)
Parse3DScripts()
WorldShadows(#PB_Shadow_Modulative, 200, RGB(120, 120, 120))
MaterialFilteringMode(#PB_Default, #PB_Material_Anisotropic, 8)
;- Light
;
light = CreateLight(#PB_Any ,RGB(185, 185, 185), 4000, 1200, 1000, #PB_Light_Directional)
SetLightColor(light, #PB_Light_SpecularColor, RGB(255*0.4, 255*0.4,255*0.4))
LightDirection(light ,0.55, -0.3, -0.75)
AmbientColor(RGB(5, 5,5))
;----------------------------------
;-terrain definition
SetupTerrains(LightID(Light), 300, #PB_Terrain_NormalMapping)
;-initialize terrain
CreateTerrain(0, 513, 1200, 60, 3, "TerrainPhysic", "dat")
;-set all texture will be use when terrrain will be constructed
AddTerrainTexture(0, 0, 10, "dirt_grayrocky_diffusespecular.jpg", "dirt_grayrocky_normalheight.jpg")
AddTerrainTexture(0, 1, 3, "grass_green-01_diffusespecular.jpg", "grass_green-01_normalheight.jpg")
AddTerrainTexture(0, 2, 20, "growth_weirdfungus-03_diffusespecular.jpg", "growth_weirdfungus-03_normalheight.jpg")
;-Construct terrains
For ty = #TerrainMiniY To #TerrainMaxiY
For tx = #TerrainMiniX To #TerrainMaxiX
Imported = DefineTerrainTile(0, tx, ty, "terrain513.png", ty % 2, tx % 2)
Next
Next
BuildTerrain(0)
If Imported = #True
InitBlendMaps()
UpdateTerrain(0)
; If enabled, it will save the terrain as a (big) cache for a faster load next time the program is executed
; SaveTerrain(0, #False)
EndIf
; enable shadow terrain
TerrainRenderMode(0, 0)
;Add Physic
TerrainPhysicBody(0, 0, 0.5)
;Texture
CreateTexture(1, 256, 256)
StartDrawing(TextureOutput(1))
Box(0, 0, 256, 256, $002255)
DrawingMode(#PB_2DDrawing_Outlined)
Box(0, 0, 256, 256, $FFFFFF)
Box(10, 10, 236, 236, $FFFF)
StopDrawing()
;Material
CreateMaterial(0, LoadTexture(0, "r2skin.jpg"))
CreateMaterial(1, TextureID(1))
CreateMaterial(2, LoadTexture(2, "Dirt.jpg"))
CreateMaterial(3, LoadTexture(3, "Wood.jpg"))
GetScriptMaterial(4, "Scene/GroundBlend")
;Robot
CreateSphere(0, 1)
Rob = LoadMesh(#PB_Any, "Robot.mesh")
CreateEntity (0, MeshID(Rob), #PB_Material_None)
ScaleEntity(0, 0.1, 0.1, 0.1)
StartEntityAnimation(0, "Walk")
;Robot Body
CreateEntity(1, MeshID(0), #PB_Material_None, 0, 426, 0)
HideEntity(1, 1)
;Body
EntityPhysicBody(1, #PB_Entity_SphereBody, 1, 0, 0.5)
; Skybox
SkyBox("desert07.jpg")
;
With Robot
\Entity = 0
\EntityBody = 1
\BodyOffsetY = 1
\Key\Down = #PB_Key_Down
\Key\Left = #PB_Key_Left
\Key\Right = #PB_Key_Right
\Key\Up = #PB_Key_Up
\Key\StrafeLeft = #PB_Key_X
\Key\StrafeRight = #PB_Key_C
\Key\Jump = #PB_Key_Space
;\MainNode = CreateNode(#PB_Any) ; Entity position
\Direction = CreateNode(#PB_Any, 1, 0, 0) ; For cameraLookAt
\SightNode = CreateNode(#PB_Any, 12, 2, 0) ; For cameraLookAt
AttachEntityObject(\EntityBody, "", NodeID(\Direction))
AttachEntityObject(\EntityBody, "", NodeID(\SightNode))
;AttachNodeObject(\MainNode, EntityID(\Entity))
EndWith
;- Camera
;
CreateCamera(0, 0, 0, 100, 100)
CameraBackColor(0, RGB(5, 5, 10))
;==================================
; create material
Red = GetScriptMaterial(#PB_Any, "Color/Red")
Blue = GetScriptMaterial(#PB_Any, "Color/Blue")
Yellow = GetScriptMaterial(#PB_Any, "Color/Yellow")
Green = GetScriptMaterial(#PB_Any, "Color/Green")
;==================================
; create Sphere
MeshSphere = CreateSphere(#PB_Any, 1.0)
For i = 0 To 5
Entity=CreateEntity(#PB_Any, MeshID(MeshSphere), MaterialID(Green))
MoveEntity(Entity, Random(200)-100, 80, Random(400)-200, #PB_Absolute)
; create bodies
EntityPhysicBody(Entity, #PB_Entity_SphereBody, 1.0)
Next
;==================================
; create Cylinder
MeshCylinder = CreateCylinder(#PB_Any, 1.0, 6)
For i = 0 To 5
Entity=CreateEntity(#PB_Any, MeshID(MeshCylinder), MaterialID(Red))
MoveEntity(Entity, Random(200)-100, 80, Random(400)-200, #PB_Absolute)
; create bodies
EntityPhysicBody(Entity, #PB_Entity_CylinderBody, 1.0, 0, 1)
Next
;==================================
; create Cube
MeshCube = CreateCube(#PB_Any, 3)
For i = 0 To 5
Entity=CreateEntity(#PB_Any, MeshID(MeshCube), MaterialID(Yellow))
MoveEntity(Entity, Random(200)-100, 80, Random(400)-200, #PB_Absolute)
; create bodies
EntityPhysicBody(Entity, #PB_Entity_BoxBody, 1.0)
Next
Repeat
Screen3DEvents()
Robot\elapsedTime = TimeSinceLastFrame
HandleEntity(@Robot)
CameraFollow(0, EntityID(Robot\Entity), -90, EntityY(Robot\Entity) + 10, 25, 0.1, 0.1, 0)
CameraLookAt(0, NodeX(Robot\SightNode), NodeY(Robot\SightNode), NodeZ(Robot\SightNode))
TimeSinceLastFrame = RenderWorld(60) * 40 / 1000
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
End
EndIf
Else
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows Or Subsystem("OpenGL")
;
; Terrain on Linux/OSX and Windows with OpenGL needs CG toolkit from nvidia
; It can be freely downloaded and installed from this site: https://developer.nvidia.com/cg-toolkit-download
;
MessageRequester("Error","Can't initialize engine3D (Please ensures than CG Toolkit from nvidia is correcly installed)")
CompilerElse
MessageRequester("Error","Can't initialize engine3D")
CompilerEndIf
EndIf
Procedure Clamp(*var.float, min.f, max.f)
If *var\f < min
*var\f = min
ElseIf *var\f > max
*var\f = max
EndIf
EndProcedure
Procedure InitBlendMaps()
minHeight1.f = 7
fadeDist1.f = 40
minHeight2.f = 7
fadeDist2.f = 15
For ty = #TerrainMiniY To #TerrainMaxiY
For tx = #TerrainMiniX To #TerrainMaxiX
Size = TerrainTileLayerMapSize(0, tx, ty)
For y = 0 To Size-1
For x = 0 To Size-1
Height.f = TerrainTileHeightAtPosition(0, tx, ty, 1, x, y)
val.f = (Height - minHeight1) / fadeDist1
Clamp(@val, 0, 1)
SetTerrainTileLayerBlend(0, tx, ty, 1, x, y, val)
val.f = (Height - minHeight2) / fadeDist2
Clamp(@val, 0, 1)
SetTerrainTileLayerBlend(0, tx, ty, 2, x, y, val)
Next
Next
UpdateTerrainTileLayerBlend(0, tx, ty, 1)
UpdateTerrainTileLayerBlend(0, tx, ty, 2)
Next
Next
EndProcedure
Procedure Normalize(*V.Vector3)
Protected.f magSq, oneOverMag
magSq = *V\x * *V\x + *V\y * *V\y + *V\z * *V\z
If magsq > 0
oneOverMag = 1.0 / Sqr(magSq)
*V\x * oneOverMag
*V\y * oneOverMag
*V\z * oneOverMag
EndIf
EndProcedure
Procedure.f QuaternionNormalise(*Q.Quaternion)
Protected.f magSq, oneOverMag
magSq = *Q\w**Q\w+*Q\x**Q\x+*Q\y**Q\y+*Q\z**Q\z
oneOverMag = 1.0 / Sqr(magSq)
*Q\w * oneOverMag
*Q\x * oneOverMag
*Q\y * oneOverMag
*Q\z * oneOverMag
EndProcedure
Procedure.f DotProduct(*V1.Vector3, *V2.Vector3)
ProcedureReturn *V1\x * *V2\x + *V1\y * *V2\y + *V1\z * *V2\z
EndProcedure
Procedure.f QuaternionDot(*Q.Quaternion, *rkQ.Quaternion)
ProcedureReturn *Q\w**rkQ\w+*Q\x**rkQ\x+*Q\y**rkQ\y+*Q\z**rkQ\z
EndProcedure
Procedure FromRotationMatrix(*Q.Quaternion, *kRot.Matrix3)
; Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
; article "Quaternion Calculus and Fast Animation".
fTrace.f = *kRot\m[0]\n[0]+*kRot\m[1]\n[1]+*kRot\m[2]\n[2]
fRoot.f
If fTrace > 0.0
; |w| > 1/2, may As well choose w > 1/2
fRoot =Sqr(fTrace + 1.0); 2w
*Q\w = 0.5*fRoot
fRoot = 0.5/fRoot; 1/(4w)
*Q\x = (*kRot\m[2]\n[1]-*kRot\m[1]\n[2])*fRoot;
*Q\y = (*kRot\m[0]\n[2]-*kRot\m[2]\n[0])*fRoot;
*Q\z = (*kRot\m[1]\n[0]-*kRot\m[0]\n[1])*fRoot;
Else
; |w| <= 1/2
Dim s_iNext(2)
s_iNext(0) = 1
s_iNext(1) = 2
s_iNext(2) = 0
i = 0
If *kRot\m[1]\n[1] > *kRot\m[0]\n[0]
i = 1
EndIf
If *kRot\m[2]\n[2] > *kRot\m[i]\n[i]
i = 2
EndIf
j = s_iNext(i)
k = s_iNext(j)
fRoot =Sqr(*kRot\m[i]\n[i]-*kRot\m[j]\n[j]-*kRot\m[k]\n[k] + 1.0)
Dim *apkQuat.Float(2)
*apkQuat(0) = @*Q\x
*apkQuat(1) = @*Q\y
*apkQuat(2) = @*Q\z
*apkQuat(i)\f = 0.5*fRoot
fRoot = 0.5/fRoot
*Q\w = (*kRot\m[k]\n[j]-*kRot\m[j]\n[k])*fRoot
*apkQuat(j)\f = (*kRot\m[j]\n[i]+*kRot\m[i]\n[j])*fRoot
*apkQuat(k)\f = (*kRot\m[k]\n[i]+*kRot\m[i]\n[k])*fRoot
EndIf
EndProcedure
Procedure QuaternionFromAxes(*Q.Quaternion, *xaxis.Vector3, *yaxis.Vector3, *zaxis.Vector3)
Protected kRot.Matrix3
kRot\m[0]\n[0] = *xaxis\x
kRot\m[1]\n[0] = *xaxis\y
kRot\m[2]\n[0] = *xaxis\z
kRot\m[0]\n[1] = *yaxis\x
kRot\m[1]\n[1] = *yaxis\y
kRot\m[2]\n[1] = *yaxis\z
kRot\m[0]\n[2] = *zaxis\x
kRot\m[1]\n[2] = *zaxis\y
kRot\m[2]\n[2] = *zaxis\z
FromRotationMatrix(*Q, @kRot)
EndProcedure
Procedure Slerp(*t.Quaternion, fT.f, *rkP.Quaternion, *rkQ.Quaternion, shortestPath)
msEpsilon = 1e-03
fCos.f = QuaternionDot(*rkP, *rkQ)
rkT.Quaternion
; Do we need To invert rotation?
If Bool((fCos < 0.0) And shortestPath)
fCos = -fCos
rkT\w = -*rkQ\w
rkT\x = -*rkQ\x
rkT\y = -*rkQ\y
rkT\z = -*rkQ\z
Else
rkT\w = *rkQ\w
rkT\x = *rkQ\x
rkT\y = *rkQ\y
rkT\z = *rkQ\z
EndIf
If (Abs(fCos) < 1 - msEpsilon)
; Standard Case (slerp)
fSin.f = Sqr(1 - (fCos*fCos))
fAngle.f =ATan2(fSin, fCos)
fInvSin.f = 1.0 / fSin;
fCoeff0.f = Sin((1.0 - fT) * fAngle) * fInvSin
fCoeff1.f = Sin(fT * fAngle) * fInvSin
*t\w = fCoeff0 * *rkP\w + fCoeff1 * rkT\w
*t\x = fCoeff0 * *rkP\x + fCoeff1 * rkT\x
*t\y = fCoeff0 * *rkP\y + fCoeff1 * rkT\y
*t\z = fCoeff0 * *rkP\z + fCoeff1 * rkT\z
Else
; There are two situations:
; 1. "rkP" And "rkQ" are very close (fCos ~= +1), so we can do a linear
; interpolation safely.
; 2. "rkP" And "rkQ" are almost inverse of each other (fCos ~= -1), there
; are an infinite number of possibilities interpolation. but we haven't
; have method To fix this Case, so just use linear interpolation here.
*t\w = (1.0 - fT) * *rkP\w + fT * rkT\w
*t\x = (1.0 - fT) * *rkP\x + fT * rkT\x
*t\y = (1.0 - fT) * *rkP\y + fT * rkT\y
*t\z = (1.0 - fT) * *rkP\z + fT * rkT\z
; taking the complement requires renormalisation
QuaternionNormalise(*t)
EndIf
EndProcedure
Procedure OnGround(*Entity.s_Entity)
Protected.Quaternion S, Q
Protected.Vector3 xaxis, yaxis, zaxis
With *Entity
Result = RayCollide(EntityX(\EntityBody), EntityY(\EntityBody), EntityZ(\EntityBody), EntityX(\EntityBody), EntityY(\EntityBody)-7, EntityZ(\EntityBody))
;CreateLine3D(20,EntityX(\EntityBody), EntityY(\EntityBody), EntityZ(\EntityBody), $FFFF, EntityX(\EntityBody), EntityY(\EntityBody)-7, EntityZ(\EntityBody), $FFFF)
Delta.f = EntityY(\EntityBody) - PickY() - \BodyOffsetY
If Result=-1 Or (Result>-1 And (delta >= 1))
ProcedureReturn 0
Else
xaxis\x = NodeX(\Direction) - EntityX(\EntityBody)
xaxis\y = NodeY(\Direction) - EntityY(\EntityBody)
xaxis\z = NodeZ(\Direction) - EntityZ(\EntityBody)
yaxis\x = NormalX()
yaxis\y = NormalY()
yaxis\z = NormalZ()
PRODUIT_VECTORIEL(zaxis, xaxis, yaxis)
PRODUIT_VECTORIEL(xaxis, yaxis, zaxis)
CreateLine3D(20,EntityX(\EntityBody), EntityY(\EntityBody), EntityZ(\EntityBody), $FFFF, EntityX(\EntityBody)+xaxis\x*3, EntityY(\EntityBody)+xaxis\y*3, EntityZ(\EntityBody)+xaxis\z*3, $FFFF)
QuaternionFromAxes(@Q, @xaxis, @yaxis, @zaxis)
FetchOrientation(EntityID(\Entity))
S\w = GetW()
S\x = GetX()
S\y = GetY()
S\z = GetZ()
Slerp(@R, 0.05, @S, @Q, 0)
SetOrientation(EntityID(\Entity),r\x, r\y, r\z, r\w)
ProcedureReturn 1
EndIf
EndWith
EndProcedure
Procedure HandleEntity(*Entity.s_Entity)
Protected.f Speed, Speed2, x, y, MouseX, MouseY
Static Jump.f, MemJump.i, Rot.Vector3, Trans.Vector3, Clic
With *Entity
Speed = #PlayerSpeed * \elapsedTime
Speed2 = Speed / 2
If ExamineKeyboard()
If KeyboardReleased(#PB_Key_F5)
WorldDebug(#PB_World_DebugBody)
ElseIf KeyboardReleased(#PB_Key_F6)
WorldDebug(#PB_World_DebugEntity)
ElseIf KeyboardReleased(#PB_Key_F7)
WorldDebug(#PB_World_DebugNone)
EndIf
If KeyboardPushed(\Key\Jump) And OnGround(*Entity)
Jump = 90
MemJump = 1
EndIf
Rot\x * 0.30
Rot\y * 0.30
Rot\z * 0.30
Trans\x * 0.20
Trans\y = Sin(Radian(Jump)) * 5
Trans\z * 0.20
If KeyboardPushed(\Key\Up)
Trans\x = Speed
ElseIf KeyboardPushed(\Key\Down)
Trans\x = -Speed2
EndIf
If KeyboardPushed(\Key\Left)
Rot\y + 2 * \elapsedTime
ElseIf KeyboardPushed(\Key\Right)
Rot\y - 2 * \elapsedTime
EndIf
If KeyboardPushed(\Key\StrafeLeft)
Trans\z = -Speed2
ElseIf KeyboardPushed(\Key\StrafeRight)
Trans\z = Speed2
EndIf
OnGround = OnGround(*Entity)
If OnGround And MemJump = 0
MoveEntity (\EntityBody, EntityX(\EntityBody), TerrainHeight(0, EntityX(\EntityBody), EntityZ(\EntityBody))+1,EntityZ(\EntityBody),#PB_Absolute)
ElseIf MemJump
Jump - 9 * \elapsedTime
If Jump < -90
Jump = -90
EndIf
If OnGround And Jump < 0
MemJump = 0
Jump = 0
EndIf
Else
MoveEntity (\EntityBody, EntityX(\EntityBody), TerrainHeight(0, EntityX(\EntityBody), EntityZ(\EntityBody))+1,EntityZ(\EntityBody),#PB_Absolute)
EndIf
EndIf
MoveEntity (\EntityBody, Trans\x,Trans\y, Trans\z, #PB_Local)
RotateEntity(\EntityBody, 0, Rot\y, 0, #PB_Relative)
MoveEntity(\Entity, EntityX(\EntityBody), EntityY(\EntityBody)-\BodyOffsetY, EntityZ(\EntityBody), #PB_Absolute)
EndWith
EndProcedurePlease correct my english
http://purebasic.developpez.com/
http://purebasic.developpez.com/
Re: Smooth align Player to Object/Terrain he's standing
@Comtois.
Nice example, Comtois
But it's a little bit buggy. Move around and suddently the robot pops below the terrain.
Keep walking and our 'Cylon from Battlestar Galactica' 'pops' above ground again and starts a nice jitterbug.
Keep walking and now he begins to walk again until it all starts over again.
Nice example, Comtois
But it's a little bit buggy. Move around and suddently the robot pops below the terrain.
Keep walking and our 'Cylon from Battlestar Galactica' 'pops' above ground again and starts a nice jitterbug.
Keep walking and now he begins to walk again until it all starts over again.
Current configurations:
Ubuntu 20.04/64 bit - Window 10 64 bit
Intel 6800K, GeForce Gtx 1060, 32 gb ram.
Amd Ryzen 9 5950X, GeForce 3070, 128 gb ram.
Ubuntu 20.04/64 bit - Window 10 64 bit
Intel 6800K, GeForce Gtx 1060, 32 gb ram.
Amd Ryzen 9 5950X, GeForce 3070, 128 gb ram.


