OGRE-Tutorial, Quat Rechnung ein C++ Experte gesucht

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
Makke
Beiträge: 156
Registriert: 24.08.2011 18:00
Computerausstattung: AMD Ryzen 7 5700X - AMD Radeon RX 6800 XT - 32 GB DDR4 SDRAM
Wohnort: Ruhrpott
Kontaktdaten:

OGRE-Tutorial, Quat Rechnung ein C++ Experte gesucht

Beitrag von Makke »

Hallo zusammen,

ich schaue gerade die Tutorials und Snippets von der OGRE Seite durch und bin auf folgendes Tutorial gestolpert: http://www.ogre3d.org/tikiwiki/tiki-ind ... =Tutorials

Nach dem durchlesen dachte ich, dass das doch auch gut und einfach mit PB umzusetzen wäre, hier also der Code (vorarb, er funktioniert nicht und ich weiß nicht warum):

Code: Alles auswählen

EnableExplicit

Structure lVector2
  x.l
  y.l
EndStructure

Structure fVector3
  x.f
  y.f
  z.f
EndStructure

Structure fQuaternion
  x.f
  y.f
  z.f
  w.f
EndStructure

Structure structKeysettings
  forward.i
  backward.i
  turnLeft.i
  turnRight.i
  strafeLeft.i
  strafeRight.i
EndStructure

Structure structPlayer
  init.b
  Keys.structKeysettings
  Rotation.fVector3
  Translate.fVector3
  camera.i
  nodeCamera.i
  nodeCameraYaw.i
  nodeCameraPitch.i
  nodeCameraRoll.i
EndStructure

Structure structLevel
  entFloor.i
  entCeil.i
  entWallLe.i
  entWallRi.i
  entWallFr.i
  entWallBa.i
  entBlock1.i
  entBlock2.i
  entBlock3.i
  entBlock4.i
EndStructure

Define.b            DoLoop = #True
Define.structPlayer Player
Define.structLevel  Level

Declare Level_Create()
Declare Player_Create()
Declare Player_UpdateControls()
Declare Player_Update()

; init
InitEngine3D()
InitSprite()
InitKeyboard()
InitMouse()

OpenWindow(0,0,0,1024,768,"Material Filter Modes",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0), WindowHeight(0), 0, 0, 0, #PB_Screen_WaitSynchronization)

Level_Create()
Player_Create()

Repeat
 
  While WindowEvent() : Wend
  
  Player_Update()
  
  RenderWorld()
  FlipBuffers()
 
Until DoLoop = #False

End

Macro GetOrientation(Object, Quaternion)
  If IsNode(Object)
    FetchOrientation(NodeID(Object))
  ElseIf IsEntity(Object)
    FetchOrientation(EntityID(Object))
  ElseIf IsCamera(Object)
    FetchOrientation(CameraID(Object))
  ElseIf IsLight(Object)
    FetchOrientation(LightID(Object))
  EndIf
  Quaternion\x = GetX()
  Quaternion\y = GetY()
  Quaternion\z = GetZ()
  Quaternion\w = GetW()
EndMacro

Procedure Quat_Multiply(*q1.fQuaternion, *q2.fQuaternion, *result.fQuaternion)
  *result\x =  *q1\x * *q2\w  +  *q1\y * *q2\z  -  *q1\z * *q2\y  +  *q1\w * *q2\x
  *result\y = -*q1\x * *q2\z  +  *q1\y * *q2\w  +  *q1\z * *q2\x  +  *q1\w * *q2\y
  *result\z =  *q1\x * *q2\y  -  *q1\y * *q2\x  +  *q1\z * *q2\w  +  *q1\w * *q2\z
  *result\w = -*q1\x * *q2\x  -  *q1\y * *q2\y  -  *q1\z * *q2\z  +  *q1\w * *q2\w
EndProcedure

Procedure Quat_MultiplyVector(*quat.fQuaternion, *vec.fVector3, *result.fVector3)
  Protected.f n01, n02, n03, n04, n05, n06, n07, n08, n09, n10, n11, n12
  n01 = *quat\x * 2.0
  n02 = *quat\y * 2.0
  n03 = *quat\z * 2.0
  n04 = *quat\x * n01
  n05 = *quat\y * n02
  n06 = *quat\z * n03
  n07 = *quat\x * n02
  n08 = *quat\x * n03
  n09 = *quat\y * n03
  n10 = *quat\w * n01
  n11 = *quat\w * n02
  n12 = *quat\w * n03
  *result\x = (1.0 - (n05 + n06)) * *vec\x + (n07 - n12) * *vec\y + (n08 + n11) * *vec\z
  *result\y = (n07 + n12) * *vec\x + (1.0 - (n04 + n06)) * *vec\y + (n09 - n10) * *vec\z
  *result\z = (n08 - n11) * *vec\x + (n09 + n10) * *vec\y + (1.0 - (n04 + n05)) * *vec\z
EndProcedure

Procedure Level_Create()
  
  Shared      Level
  Protected.i u, v, c, tempTexture, tempMaterial, tempMesh
  
  ; ceiling
  tempTexture = CreateTexture(#PB_Any, 256, 512)
  StartDrawing(TextureOutput(tempTexture))
  Box(0, 0, TextureWidth(tempTexture), TextureHeight(tempTexture), RGB(0, 0, 0))
  For u = 0 To TextureWidth(tempTexture)-1 Step 2
    For v = 0 To TextureHeight(tempTexture)-1 Step 2
      If Random(100) > 98
        c = Random(128)
        Circle(u, v, 1, RGB(c+128, c+128, c+128))
      EndIf
    Next
  Next
  StopDrawing()
  tempMaterial = CreateMaterial(#PB_Any, TextureID(tempTexture))
  MaterialFilteringMode(tempMaterial, #PB_Material_Anisotropic, 8)
  MaterialShadingMode(tempMaterial, #PB_Material_Phong)
  MaterialBlendingMode(tempMaterial, #PB_Material_Add)
  ScrollMaterial(tempMaterial, 0.1, 0.05, #PB_Material_Animated)
  tempMesh = CreatePlane(#PB_Any, 512, 1024, 1, 1, 1, 1)
  Level\entCeil = CreateEntity(#PB_Any, MeshID(tempMesh), MaterialID(tempMaterial))
  MoveEntity(Level\entCeil, 0, 40, 0)
  RotateEntity(Level\entCeil, 180, 0, 0)
  FreeMesh(tempMesh)
  FreeMaterial(tempMaterial)
  FreeTexture(tempTexture)
  
  ; floor
  tempTexture = CreateTexture(#PB_Any, 64, 64)
  StartDrawing(TextureOutput(tempTexture))
  Box(0, 0, TextureWidth(tempTexture), TextureHeight(tempTexture), RGB(0, 0, 0))
  Box(0, 0, TextureWidth(tempTexture)/2, TextureHeight(tempTexture)/2, RGB(139, 69, 19))
  Box(TextureWidth(tempTexture)/2, TextureHeight(tempTexture)/2, TextureWidth(tempTexture)/2, TextureHeight(tempTexture)/2, RGB(139, 69, 19))
  Box(0, TextureHeight(tempTexture)/2, TextureWidth(tempTexture)/2, TextureHeight(tempTexture)/2, RGB(255, 222, 173))
  Box(TextureWidth(tempTexture)/2, 0, TextureWidth(tempTexture)/2, TextureHeight(tempTexture)/2, RGB(255, 222, 173))
  StopDrawing()
  tempMaterial = CreateMaterial(#PB_Any, TextureID(tempTexture))
  MaterialFilteringMode(tempMaterial, #PB_Material_Anisotropic, 8)
  tempMesh = CreatePlane(#PB_Any, 512, 1024, 1, 1, 8, 16)
  Level\entFloor = CreateEntity(#PB_Any, MeshID(tempMesh), MaterialID(tempMaterial))
  MoveEntity(Level\entFloor, 0, -10, 0)
  FreeMesh(tempMesh)
  FreeMaterial(tempMaterial)
  FreeTexture(tempTexture)
  
  ; walls Left & Right
  tempTexture = CreateTexture(#PB_Any, 64, 64)
  StartDrawing(TextureOutput(tempTexture))
  Box(0, 0, TextureWidth(tempTexture), TextureHeight(tempTexture), RGB(0, 0, 0))
  Box(0, 0, TextureWidth(tempTexture)/2, TextureHeight(tempTexture), RGB(128, 128, 128))
  Box(TextureWidth(tempTexture)/2, 0, TextureWidth(tempTexture)/2, TextureHeight(tempTexture), RGB(160, 160, 160))
  StopDrawing()
  tempMaterial = CreateMaterial(#PB_Any, TextureID(tempTexture))
  MaterialFilteringMode(tempMaterial, #PB_Material_Anisotropic, 8)
  tempMesh = CreatePlane(#PB_Any, 1024, 50, 1, 1, 10, 1)
  Level\entWallLe = CreateEntity(#PB_Any, MeshID(tempMesh), MaterialID(tempMaterial))
  MoveEntity(Level\entWallLe, -256, 15, 0)
  RotateEntity(Level\entWallLe, 90, 90, 0)
  Level\entWallRi = CreateEntity(#PB_Any, MeshID(tempMesh), MaterialID(tempMaterial))
  MoveEntity(Level\entWallRi, 256, 15, 0)
  RotateEntity(Level\entWallRi, 90, 270, 0)
  FreeMesh(tempMesh)
  
  ; walls Front & Back
  tempMesh = CreatePlane(#PB_Any, 512, 50, 1, 1, 5, 1)
  Level\entWallFr = CreateEntity(#PB_Any, MeshID(tempMesh), MaterialID(tempMaterial))
  MoveEntity(Level\entWallFr, 0, 15, -512)
  RotateEntity(Level\entWallFr, 90, 0, 0)
  Level\entWallBa = CreateEntity(#PB_Any, MeshID(tempMesh), MaterialID(tempMaterial))
  MoveEntity(Level\entWallBa, 0, 15, 512)
  RotateEntity(Level\entWallBa, 270, 0, 0)
  FreeMesh(tempMesh)
  FreeMaterial(tempMaterial)
  FreeTexture(tempTexture)
  
  ; blocks
  tempTexture = CreateTexture(#PB_Any, 64, 64)
  StartDrawing(TextureOutput(tempTexture))
  Box(0, 0, TextureWidth(tempTexture), TextureHeight(tempTexture), RGB(0, 0, 0))
  Box(0, 0, TextureWidth(tempTexture), TextureHeight(tempTexture)/2, RGB(255, 235, 205))
  Box(0, TextureHeight(tempTexture)/2, TextureWidth(tempTexture), TextureHeight(tempTexture)/2, RGB(250, 240, 230))
  StopDrawing()
  tempMaterial = CreateMaterial(#PB_Any, TextureID(tempTexture))
  MaterialFilteringMode(tempMaterial, #PB_Material_Anisotropic, 8)
  tempMesh = CreateCylinder(#PB_Any, 5, 50)
  Level\entBlock1 = CreateEntity(#PB_Any, MeshID(tempMesh), MaterialID(tempMaterial))
  MoveEntity(Level\entBlock1, -128, 15, -256)
  Level\entBlock2 = CreateEntity(#PB_Any, MeshID(tempMesh), MaterialID(tempMaterial))
  MoveEntity(Level\entBlock2, 128, 15, -256)
  Level\entBlock3 = CreateEntity(#PB_Any, MeshID(tempMesh), MaterialID(tempMaterial))
  MoveEntity(Level\entBlock3, 128, 15, 256)
  Level\entBlock4 = CreateEntity(#PB_Any, MeshID(tempMesh), MaterialID(tempMaterial))
  MoveEntity(Level\entBlock4, -128, 15, 256)
  FreeMesh(tempMesh)
  FreeMaterial(tempMaterial)
  FreeTexture(tempTexture)
  
  ; done !
  
EndProcedure

Procedure Player_Create()
  
  Shared Player
  
  With Player
    
    \nodeCamera      = CreateNode(#PB_Any)
    \nodeCameraYaw   = CreateNode(#PB_Any)
    \nodeCameraPitch = CreateNode(#PB_Any)
    \nodeCameraRoll  = CreateNode(#PB_Any)
    
    \camera = CreateCamera(#PB_Any, 0, 0, 100, 100)
    
    MoveNode(\nodeCamera, 0, 1, 1, #PB_Absolute)
    
    AttachNodeObject(\nodeCamera, NodeID(\nodeCameraYaw))
    AttachNodeObject(\nodeCameraYaw, NodeID(\nodeCameraPitch))
    AttachNodeObject(\nodeCameraPitch, NodeID(\nodeCameraRoll))
    AttachNodeObject(\nodeCameraRoll, CameraID(\camera))
    
    \Keys\forward     = #PB_Key_W
    \Keys\backward    = #PB_Key_S
    \Keys\turnLeft    = #PB_Key_A
    \Keys\turnRight   = #PB_Key_D
    \Keys\strafeLeft  = #PB_Key_Q
    \Keys\strafeRight = #PB_Key_E
    
  EndWith
  
EndProcedure

Procedure Player_UpdateControls()
  
  Shared Player, DoLoop
  
  If ExamineKeyboard()
    
    If KeyboardReleased(#PB_Key_Escape)
      DoLoop = #False
    EndIf
    
    With Player\Keys
    
      If KeyboardPushed(\forward)
        Player\Translate\z = -1
      ElseIf KeyboardPushed(\backward)
        Player\Translate\z = 1
      Else
        Player\Translate\z = 0
      EndIf
      
      If KeyboardPushed(\strafeLeft)
        Player\Translate\x = -1
      ElseIf KeyboardPushed(\strafeRight)
        Player\Translate\x = 1
      Else
        Player\Translate\x = 0
      EndIf
        
    EndWith
      
  EndIf
  
  If ExamineMouse()
    
    Player\Rotation\x = -MouseDeltaX()
    Player\Rotation\y = -MouseDeltaY()
    
  EndIf
  
EndProcedure

Procedure Player_Update()
  
  Shared                Player
  Protected.f           pitchAngle, pitchAngleSign
  Protected.fVector3    resultVec
  Protected.fQuaternion yawOrientation, pitchOrientation, resultQuat
  
  Player_UpdateControls()
  
  With Player
    
    RotateNode(\nodeCameraYaw, 0, \Rotation\x, 0, #PB_Relative)
    GetOrientation(\nodeCameraYaw, yawOrientation)
    
    RotateNode(\nodeCameraPitch, \Rotation\y, 0, 0, #PB_Relative)
    GetOrientation(\nodeCameraPitch, pitchOrientation)
    
    Quat_Multiply(yawOrientation, pitchOrientation, resultQuat)
    Quat_MultiplyVector(resultQuat, \Translate, resultVec)
    MoveNode(\nodeCamera, resultVec\x, resultVec\y, resultVec\z, #PB_Relative)
    
    pitchAngle     = 2 * Degree(ACos(pitchOrientation\w))
    pitchAngleSign = pitchOrientation\x
    
;     If pitchAngle > 90.0
;       
;       If pitchAngleSign > 0
;         SetOrientation(NodeID(\nodeCameraPitch), Sqr(0.5), Sqr(0.5), 0, 0)
;       ElseIf pitchAngleSign < 0
;         SetOrientation(NodeID(\nodeCameraPitch), Sqr(0.5), -Sqr(0.5), 0, 0)
;       EndIf
;        
;     EndIf
       
  EndWith

EndProcedure
Einmal weiß ich nicht ob die Quaterion Berechnungen richtig sind (Q*Q glaube ich schon, aber Q*V habe ich irgendwie aus dem Netz rekonstruiert), da ich denke das die Original C++ Code Zeile aus dem Tutorial die Rechnung (und Beschreibung) schon von der Multiplikation die Rede ist:

Code: Alles auswählen

// NOTE: We multiply the mTranslateVector by the cameraPitchNode's
 // orientation quaternion and the cameraYawNode's orientation
 // quaternion to translate the camera accoding to the camera's
 // orientation around the Y-axis and the X-axis.
 this->cameraNode->translate(this->cameraYawNode->getOrientation() *
                             this->cameraPitchNode->getOrientation() *
                             this->mTranslateVector,
                             Ogre::SceneNode::TS_LOCAL);
Der Teil mit der Begrenzung der Auf- und Abschauens funktioniert auch nicht. Da ich mich in C++ kaum auskenne und vielleicht mal ein Experte drüber schuen möchte was ich hier so alles falsch gemacht habe und nicht verstanden habe.

Vielen Dank.
---
Windows 11 (64 bit)