Page 1 sur 2

Simulation de voiture avec le moteur physique de PB

Publié : mer. 15/mai/2013 8:48
par kelebrindae
Bonjour,

Après être tombé sur un post très intéressant de applePi sur le forum anglais, j'ai eu envie de refaire un petit test du moteur physique de PB. Et le résultat n'est pas mal du tout, je trouve 8).
Le code ci-dessous peut gérer de façon raisonnablement réaliste un nombre quelconque de roues, directrices, motrices, ou les deux. (Le moteur physique de PB commence à être vraiment bien: sans rien y connaître et avec assez peu d'éléments, on peut obtenir des résultats très sympas.)

Par contre, je crois que je n'ai toujours rien compris aux HingeJoints. :?
Je pensais que les paramètres "axis" servaient à restreindre les degrés de libertés du joint; par exemple, en mettant "0,1,0", l'articulation ne se faisait que sur l'axe Y. Or, j'ai remarqué que si un des éléments reçoit une impulsion sur un autre axe, l'articulation se tord avec une certaine élasticité avant de reprendre sa place.
Dans la démo, ça donne un effet "suspension", car les supports des roues (qui ne sont censés bouger qu'autour de l'axe Y pour les roues directrices, ou pas du tout pour les autres), bougent sur l'axe Z quand la voiture tombe sur le sol. Pas trop désagréable, certes, mais ce n'est pas ce que je voulais.

Il y a moyen d'empêcher ça?

[EDIT le 16/05/2013] Ajout d'une "carrosserie" sur la voiture + ajustement des paramètres par défaut (l'élasticité des Joints était due à une masse trop grande du chassis).

Code : Tout sélectionner

;************************************************************************************
;  Bullet Physics - Car demo
;  PB version: 5.11
;  Date: may, 5, 2013
;
;  Rough simulation of a car, using PB's physics engine.
;  
;  Controls:
;  - W -> Wireframe view
;  - P -> Display physics bodies
;  - [Return] -> Pause simulation
;  - [Cursor keys] -> Drive the car
;************************************************************************************

; Window size
#SCREENWIDTH = 1000
#SCREENHEIGHT = 500

#LEFTSIDE = -1
#RIGHTSIDE = 1

Enumeration
  #FWDRIVE
  #RWDRIVE
  #FOURWHEELDRIVE
  #TYRELLP34
EndEnumeration


Structure wheel_struct
  support.i ; entity
  wheel.i   ; entity
  supJoint.i    ; joint chassis <> support
  wheelJoint.i  ; joint support <> wheel
  
  wheelRadius.f
  wheelWidth.f  
  wheelMass.f  
  
  isSteer.b
  isDrive.b

EndStructure

Structure car_struct
  chassis.i     ; car's base entity
  body.i ; car's body entity
  bodyJoint.i   ; joint between the two
  
  width.f
  length.f
  height.f
  chassisHeight.f
  mass.f
  
  maxSteer.f
  maxSpeed.f
  accel.f
  
  List wheel.wheel_struct()
EndStructure
Global car.car_struct

Global i.i, wireframe.b, viewBodies.b, simRunning.b = #True, dontQuit.b = #True, eventId.i

Global txBlank.i, txGround.i, txStriped.i
Global mtGround.i, mtRed.i, mtBlue.i, mtCyanSt.i, mtWhiteSt.i

Global dimX.f, dimZ.i, ground.i, jump.i
Global planeMesh.i,cubeMesh.i, wheelMesh.i

Global distance.f ; used for camera movement


EnableExplicit

;************************************************************************************
;-                                 ---- Macros ----
;************************************************************************************

; Computes the square of the distance between coords (x1,y1,z1) and (x2,y2,z2)
Global DIST_X.f,DIST_Y.f,DIST_Z.f
Macro DISTANCE2(x1,y1,z1,x2,y2,z2,result)
  DIST_X = (x1)-(x2)
  DIST_Y = (y1)-(y2)
  DIST_Z = (z1)-(z2)
  result = DIST_X*DIST_X + DIST_Y*DIST_Y + DIST_Z*DIST_Z ; no sqr, it's faster
EndMacro


;************************************************************************************
;-                                 ---- Procedures ----
;************************************************************************************

; Add a wheel to a car
Procedure createWheel(*ptrcar.car_struct,side.i, supportZpos.f, isSteer.b, isDrive.b, 
                       radius.f = 0.5, width.f = 0.3, mass.f = 1, resti.f = 0.9, friction.f = 1)
  Protected supportWidth.f = 0.6, supportHeight.f = 0.1, supportLength.f = 0.4
  Protected supportXpos.f, supportYpos.f, wheelXpos.f, wheelMat.i
  
  ; Add the wheel
  AddElement(*ptrcar\wheel())
  
  ; Define its parameters
  *ptrcar\wheel()\wheelRadius = radius
  *ptrcar\wheel()\wheelWidth = width
  *ptrcar\wheel()\wheelMass = mass
  *ptrcar\wheel()\isDrive = isDrive
  *ptrcar\wheel()\isSteer = isSteer
  
  ; Position
  supportXpos = (*ptrcar\width/2) * side
  supportYpos = (*ptrcar\chassisHeight/2) + (supportHeight/2)
  wheelXpos = supportXpos + ((width/2) + (supportWidth/2)) * side
  
  ; Support entity + joint
  *ptrcar\wheel()\support = CreateEntity(#PB_Any,MeshID(cubeMesh),MaterialID(mtRed),EntityX(car\chassis)+supportXpos,EntityY(car\chassis)+supportYpos,EntityZ(car\chassis)+supportZpos)
  ScaleEntity(*ptrcar\wheel()\support,supportWidth,supportHeight,supportLength)
  EntityPhysicBody(*ptrcar\wheel()\support,#PB_Entity_BoxBody,1,0,0)
  
  *ptrcar\wheel()\supJoint = HingeJoint(#PB_Any,EntityID(*ptrcar\wheel()\support),-(supportWidth/2) * side,-(supportHeight/2),0, 0,1,0,EntityID(*ptrcar\chassis),((*ptrcar\width/2) - (supportWidth/2)) * side,(*ptrcar\chassisHeight/2),supportZpos, 0,1,0)
  If isSteer = #True    
    SetJointAttribute(*ptrcar\wheel()\supJoint,#PB_HingeJoint_LowerLimit,-15)
    SetJointAttribute(*ptrcar\wheel()\supJoint,#PB_HingeJoint_UpperLimit,15)
  Else
    SetJointAttribute(*ptrcar\wheel()\supJoint,#PB_HingeJoint_LowerLimit,0)
    SetJointAttribute(*ptrcar\wheel()\supJoint,#PB_HingeJoint_UpperLimit,0)
  EndIf  
  
  ; Wheel entity + joint
  If isDrive = #True
    wheelMat = MaterialID(mtCyanSt)
  Else
    wheelMat = MaterialID(mtWhiteSt)
  EndIf
  
  *ptrcar\wheel()\wheel = CreateEntity(#PB_Any,MeshID(wheelMesh),wheelMat,EntityX(car\chassis)+wheelXpos,EntityY(car\chassis)+supportYpos,EntityZ(car\chassis)+supportZpos)
  ScaleEntity(*ptrcar\wheel()\wheel,*ptrcar\wheel()\wheelRadius,*ptrcar\wheel()\wheelWidth,*ptrcar\wheel()\wheelRadius)
  RotateEntity(*ptrcar\wheel()\wheel,0,0,-90 * side)
  EntityPhysicBody(*ptrcar\wheel()\wheel,#PB_Entity_CylinderBody,mass,resti,friction)
  
  *ptrcar\wheel()\wheelJoint = HingeJoint(#PB_Any,EntityID(*ptrcar\wheel()\wheel),0,0,0, 0,side,0, EntityID(*ptrcar\wheel()\support),((*ptrcar\wheel()\wheelWidth/2) + (supportWidth/2)) * side,0,0, 1,0,0)
  
EndProcedure

; Destroy a car
Procedure killCar(*ptrCar.car_struct)
  ForEach *ptrCar\wheel()
    FreeJoint(*ptrCar\wheel()\supJoint)
    FreeJoint(*ptrCar\wheel()\wheelJoint)
    
    FreeEntity(*ptrCar\wheel()\wheel)
    FreeEntity(*ptrCar\wheel()\support)
  Next *ptrCar\wheel()
  ClearList(*ptrCar\wheel())
  
  If IsEntity(*ptrCar\body) 
    FreeEntity(*ptrCar\body)
  EndIf
  If IsEntity(*ptrCar\chassis) 
    FreeEntity(*ptrCar\chassis)
  EndIf
EndProcedure

; Create a car
Procedure createCar(*ptrCar.car_struct, template.i=#FWDRIVE,
                    width.f = 2,length.f = 4,height.f = 1.5, mass.f = 1.15,
                    maxSteer.f = 15,maxSpeed.f = 40,accel.f = 0.5,
                    wheelRadius.f = 0.5, wheelWidth.f = 0.3, wheelMass.f = 0.85, wheelResti.f = 0.9, wheelFriction.f = 1)
  
  If IsEntity(*ptrCar\chassis)
    killCar(*ptrCar)
  EndIf
  
  *ptrCar\width = width
  *ptrCar\length = length
  *ptrCar\height = height
  *ptrCar\chassisHeight = 0.2 ; this one is fixed
  *ptrCar\mass = mass
  *ptrCar\maxSteer = maxSteer
  *ptrCar\maxSpeed = maxSpeed
  *ptrCar\accel = accel
  
  ; Create the chassis
  *ptrCar\chassis = CreateEntity(#PB_Any,MeshID(cubeMesh),MaterialID(mtBlue),0,2,0)
  ScaleEntity(*ptrCar\chassis,*ptrCar\width,*ptrCar\chassisHeight,*ptrCar\length)
  EntityPhysicBody(*ptrCar\chassis,#PB_Entity_BoxBody,*ptrCar\mass,0,1)
  
  ; Create the car's body
  *ptrCar\body = CreateEntity(#PB_Any,MeshID(cubeMesh),MaterialID(mtBlue),0,EntityY(*ptrCar\chassis) + *ptrCar\chassisHeight + *ptrCar\height/2,0,0)
  ScaleEntity(*ptrCar\body,*ptrCar\width-0.1,*ptrCar\height,*ptrCar\length-0.1)
  EntityPhysicBody(*ptrCar\body,#PB_Entity_BoxBody,*ptrCar\mass,0,1)  
  *ptrCar\bodyJoint = SliderJoint(#PB_Any,EntityID(*ptrCar\chassis),0,*ptrCar\chassisHeight,0,EntityID(*ptrCar\body),0,-*ptrCar\height/2,0)
  SetJointAttribute(*ptrCar\bodyJoint,#PB_SliderJoint_LowerLimit,0)
  SetJointAttribute(*ptrCar\bodyJoint,#PB_SliderJoint_UpperLimit,0)
  
  ; Add the wheels
  Select template
    Case #FWDRIVE
      createWheel(@car,#LEFTSIDE,-(*ptrCar\length/2 - 0.7),#True,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,-(*ptrCar\length/2 - 0.7),#True,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#LEFTSIDE,(*ptrCar\length/2 - 0.7),#False,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,(*ptrCar\length/2 - 0.7),#False,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      
    Case #RWDRIVE
      createWheel(@car,#LEFTSIDE,-(*ptrCar\length/2 - 0.7),#True,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,-(*ptrCar\length/2 - 0.7),#True,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#LEFTSIDE,(*ptrCar\length/2 - 0.7),#False,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,(*ptrCar\length/2 - 0.7),#False,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      
    Case #FOURWHEELDRIVE
      createWheel(@car,#LEFTSIDE,-(*ptrCar\length/2 - 0.7),#True,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,-(*ptrCar\length/2 - 0.7),#True,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#LEFTSIDE,(*ptrCar\length/2 - 0.7),#False,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,(*ptrCar\length/2 - 0.7),#False,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      
    Case #TYRELLP34
      createWheel(@car,#LEFTSIDE,-(*ptrCar\length/2 - 0.4),#True,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,-(*ptrCar\length/2 - 0.4),#True,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#LEFTSIDE,-(*ptrCar\length/2 - 1.7),#True,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,-(*ptrCar\length/2 - 1.7),#True,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#LEFTSIDE,(*ptrCar\length/2 - 0.5),#False,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,(*ptrCar\length/2 - 0.5),#False,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      
  EndSelect

EndProcedure


; Window procedures
Global Wmain
Global Frame3D_0, BT_reset, CB_template, FL_mass, label_mass, FL_height, label_height, FL_steer, label_steer, FL_maxspeed, label_maxSpeed, FL_accel, label_accel, FL_length, label_length, FL_width, label_width, FL_radius, label_radius, FL_wheelwidth, label_wheelWidth, FL_wheelMass, label_wheelMass, FL_friction, label_friction, FL_resti, label_resti
Procedure OpenWmain()
  Wmain = OpenWindow(#PB_Any, 0, 0, #SCREENWIDTH, #SCREENHEIGHT, "Car physics", #PB_Window_SystemMenu)
  Frame3D_0 = Frame3DGadget(#PB_Any, 1, 0, 298, 500, "Parameters")
  BT_reset = ButtonGadget(#PB_Any, 104, 465, 100, 25, "Reset")
  GadgetToolTip(BT_reset, "Reset simulation with new parameters.")
  CB_template = ComboBoxGadget(#PB_Any, 70, 23, 190, 25)
  GadgetToolTip(CB_template, "Pre-defined vehicles")
  
  FL_length = StringGadget(#PB_Any, 141, 56, 100, 25, "4")
  GadgetToolTip(FL_length, "Length of the vehicle")
  label_length = TextGadget(#PB_Any, 37, 62, 100, 20, "Length:", #PB_Text_Right)
  FL_width = StringGadget(#PB_Any, 141, 86, 100, 25, "2")
  GadgetToolTip(FL_width, "Width of the vehicle")
  label_width = TextGadget(#PB_Any, 37, 92, 100, 20, "Width:", #PB_Text_Right)
  
  FL_height = StringGadget(#PB_Any, 141, 116, 100, 25, "1.5")
  GadgetToolTip(FL_height, "Height of the vehicle's body")
  label_height = TextGadget(#PB_Any, 37, 122, 100, 20, "Height:", #PB_Text_Right)
  FL_mass = StringGadget(#PB_Any, 141, 146, 100, 25, "1.15")
  GadgetToolTip(FL_mass, "Mass of the vehicle")
  label_mass = TextGadget(#PB_Any, 37, 152, 100, 20, "Mass:", #PB_Text_Right)
  
  FL_steer = StringGadget(#PB_Any, 141, 186, 100, 25, "15")
  GadgetToolTip(FL_steer, "Steering angle of the vehicle.")
  label_steer = TextGadget(#PB_Any, 37, 192, 100, 20, "Steering angle:", #PB_Text_Right)
  FL_maxspeed = StringGadget(#PB_Any, 141, 216, 100, 25, "40")
  GadgetToolTip(FL_maxspeed, "Maximum linear speed of the drive wheels")
  label_maxSpeed = TextGadget(#PB_Any, 37, 222, 100, 20, "Max speed:", #PB_Text_Right)
  FL_accel = StringGadget(#PB_Any, 141, 246, 100, 25, "0.2")
  GadgetToolTip(FL_accel, "Acceleration")
  label_accel = TextGadget(#PB_Any, 37, 252, 100, 20, "Acceleration:", #PB_Text_Right)
  
  FL_radius = StringGadget(#PB_Any, 141, 286, 100, 25, "0.5")
  label_radius = TextGadget(#PB_Any, 37, 292, 100, 20, "Wheel radius:", #PB_Text_Right)
  FL_wheelwidth = StringGadget(#PB_Any, 141, 316, 100, 25, "0.3")
  label_wheelWidth = TextGadget(#PB_Any, 37, 322, 100, 20, "Wheel width:", #PB_Text_Right)
  FL_wheelMass = StringGadget(#PB_Any, 141, 346, 100, 25, "0.85")
  label_wheelMass = TextGadget(#PB_Any, 37, 352, 100, 20, "Wheel mass:", #PB_Text_Right)
  FL_friction = StringGadget(#PB_Any, 141, 376, 100, 25, "1")
  label_friction = TextGadget(#PB_Any, 37, 382, 100, 20, "Wheel friction:", #PB_Text_Right)
  FL_resti = StringGadget(#PB_Any, 141, 406, 100, 25, "0.9")
  label_resti = TextGadget(#PB_Any, 37, 412, 100, 20, "Wheel restitution:", #PB_Text_Right)
  
  ; Combo-box initialization
  AddGadgetItem(CB_template,#FWDRIVE,"Front-wheels drive")
  AddGadgetItem(CB_template,#RWDRIVE,"Rear-wheels drive")
  AddGadgetItem(CB_template,#FOURWHEELDRIVE,"4x4 drive")
  AddGadgetItem(CB_template,#TYRELLP34,"Tyrell P34")
  SetGadgetState(CB_template,0)
EndProcedure

Procedure Wmain_Events(event)
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False

    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect

    Case #PB_Event_Gadget
      Select EventGadget()
        Case BT_reset ; Create a new car
          createCar(@car, 
                    GetGadgetState(CB_template),
                    ValF(GetGadgetText(FL_width)),
                    ValF(GetGadgetText(FL_length)),
                    ValF(GetGadgetText(FL_height)),
                    ValF(GetGadgetText(FL_mass)),
                    ValF(GetGadgetText(FL_steer)),
                    ValF(GetGadgetText(FL_maxspeed)),
                    ValF(GetGadgetText(FL_accel)),
                    ValF(GetGadgetText(FL_radius)),
                    ValF(GetGadgetText(FL_wheelwidth)),
                    ValF(GetGadgetText(FL_wheelMass)),
                    ValF(GetGadgetText(FL_resti)),
                    ValF(GetGadgetText(FL_friction)) )
      EndSelect
  EndSelect
  ProcedureReturn #True
EndProcedure

;************************************************************************************
;-                                 ---- Main program ----
;************************************************************************************

;- Initialization
InitEngine3D()
InitSprite()
InitKeyboard()

;- Window
OpenWmain()
OpenWindowedScreen(WindowID(Wmain), 300, 0, #SCREENWIDTH-300,#SCREENHEIGHT, 0, 0, 0,#PB_Screen_SmartSynchronization)

;-Textures
txBlank = CreateTexture(#PB_Any,4,4)
StartDrawing(TextureOutput(txBlank))
  Box(0, 0, 4,4, $FFFFFF)
StopDrawing()

txStriped = CreateTexture(#PB_Any,256,256)
StartDrawing(TextureOutput(txStriped))
  Box(0, 0, 256,256, $FFFFFF)
  For i = 0 To 255 Step 32
    Box(i,0,16,256,$777777)
  Next i
StopDrawing()

txGround = CreateTexture(#PB_Any,256,256)
StartDrawing(TextureOutput(txGround))
  Box(0, 0, 256,256, $007700)
  DrawingMode(#PB_2DDrawing_Outlined)
  Box(0, 0, 256,256, $00BB00)
StopDrawing()

;-Materials
mtGround= CreateMaterial(#PB_Any,TextureID(txGround))

mtRed = CreateMaterial(#PB_Any,TextureID(txBlank))
SetMaterialColor(mtRed,#PB_Material_AmbientColor,$0000FF)

mtBlue = CreateMaterial(#PB_Any,TextureID(txBlank))
SetMaterialColor(mtBlue,#PB_Material_AmbientColor,$FF0000)

mtCyanSt = CreateMaterial(#PB_Any,TextureID(txStriped))
SetMaterialColor(mtCyanSt,#PB_Material_AmbientColor,$FFFF00)

mtWhiteSt = CreateMaterial(#PB_Any,TextureID(txStriped))


;- Terrain
dimX = 300:dimZ = 300
planeMesh = CreatePlane(#PB_Any,dimX,dimZ,1,1,dimX,dimZ)
ground  = CreateEntity(#PB_Any, MeshID(planeMesh), MaterialID(mtGround))
EntityPhysicBody(ground, #PB_Entity_StaticBody,0,0,1)

cubeMesh = CreateCube(#PB_Any,1)
jump = CreateEntity(#PB_Any,MeshID(cubeMesh),MaterialID(mtWhiteSt))
ScaleEntity(jump,8,4,4)
RotateEntity(jump,0,0,-15)
MoveEntity(jump,-10,-1,0, #PB_Absolute)
EntityPhysicBody(jump, #PB_Entity_BoxBody,0,0,1)


;- Car
wheelMesh = CreateCylinder(#PB_Any,1,1)
createCar(@car) ; all parameters are set to default values

;- Camera
CreateCamera(0, 0, 0, 100, 100)
MoveCamera(0,0,5,10,#PB_Absolute)
CameraLookAt(0,0,0,0)

;-Light
AmbientColor($333333)
CreateLight(0,$FFFFFF,200,400,200)
WorldShadows(#PB_Shadow_Additive)

;- Main loop
KeyboardMode(#PB_Keyboard_International)
Repeat
  Delay(1)
  
  ; Windows events (reset button)
  eventID = WindowEvent()
  While eventID <> 0 And dontQuit = #True
    dontQuit = Wmain_Events(eventId)
    eventID = WindowEvent()
  Wend
  ExamineKeyboard()
  
  ; Activate wireframe render
  If KeyboardReleased(#PB_Key_W)
    wireframe = 1-wireframe
    If wireframe = #True
      CameraRenderMode(0,#PB_Camera_Wireframe)
    Else
      CameraRenderMode(0,#PB_Camera_Textured)
    EndIf
  EndIf
  ; Activate physics render
  If KeyboardReleased(#PB_Key_P)
    viewBodies = 1-viewBodies 
    If viewBodies  = #True
      WorldDebug(#PB_World_DebugBody)
    Else
      WorldDebug(#PB_World_DebugNone)
    EndIf
  EndIf
  ; Start/pause simulation
  If KeyboardReleased(#PB_Key_Return)
    simRunning = 1-simRunning
    EnableWorldPhysics(simRunning)
  EndIf
  
  ; If the car exists, you can control it
  If IsEntity(car\chassis)
    ; Avoid that the car's physics body "goes to sleep" when not moving enough.
    DisableEntityBody(car\chassis,#False)
    
    ;- Steering
    If KeyboardPushed(#PB_Key_Left)
      ForEach car\wheel()
        If car\wheel()\isSteer = #True
          EnableHingeJointAngularMotor(car\wheel()\supJoint, #True, 5, 10)
          SetJointAttribute(car\wheel()\supJoint,#PB_HingeJoint_LowerLimit,-car\maxSteer)
          SetJointAttribute(car\wheel()\supJoint,#PB_HingeJoint_UpperLimit,car\maxSteer)
        EndIf
      Next car\wheel()
    ElseIf KeyboardPushed(#PB_Key_Right)
      ForEach car\wheel()
        If car\wheel()\isSteer = #True
          EnableHingeJointAngularMotor(car\wheel()\supJoint, #True, -5, 10)
          SetJointAttribute(car\wheel()\supJoint,#PB_HingeJoint_LowerLimit,-car\maxSteer)
          SetJointAttribute(car\wheel()\supJoint,#PB_HingeJoint_UpperLimit,car\maxSteer)
        EndIf
      Next car\wheel()  
    Else
      ForEach car\wheel()
        If car\wheel()\isSteer = #True
          SetJointAttribute(car\wheel()\supJoint,#PB_HingeJoint_LowerLimit,0)
          SetJointAttribute(car\wheel()\supJoint,#PB_HingeJoint_UpperLimit,0)
        EndIf
      Next car\wheel()  
    EndIf
    
    ;- Forward / backward acceleration
    If KeyboardPushed(#PB_Key_Up)
      ForEach car\wheel()
        If car\wheel()\isDrive = #True
          EnableHingeJointAngularMotor(car\wheel()\wheelJoint, #True, -car\maxSpeed, car\accel)
        EndIf
      Next car\wheel()  
    ElseIf KeyboardPushed(#PB_Key_Down)
      ForEach car\wheel()
        If car\wheel()\isDrive = #True
          EnableHingeJointAngularMotor(car\wheel()\wheelJoint, #True, car\maxSpeed, car\accel)
        EndIf
      Next car\wheel()  
    Else
      ForEach car\wheel()
        If car\wheel()\isDrive = #True
          EnableHingeJointAngularMotor(car\wheel()\wheelJoint, #False, 0,0)
        EndIf
      Next car\wheel()  
    EndIf
    
    ;- Camera management
    CameraLookAt(0,EntityX(car\chassis),EntityY(car\chassis),EntityZ(car\chassis))
    DISTANCE2(CameraX(0),CameraY(0),CameraZ(0),EntityX(car\chassis),EntityY(car\chassis),EntityZ(car\chassis),distance)
    If distance > 200
      MoveCamera(0,0,0,-0.2)
      If CameraY(0) < 5.0
        MoveCamera(0,CameraX(0),5,CameraZ(0),#PB_Absolute)
        CameraLookAt(0,EntityX(car\chassis),EntityY(car\chassis),EntityZ(car\chassis))
      EndIf
    EndIf
  EndIf
    
  ; Render
  RenderWorld()
  FlipBuffers()

Until KeyboardPushed(#PB_Key_Escape) Or dontQuit = #False

End

Re: Simulation de voiture avec le moteur physique de PB

Publié : mer. 15/mai/2013 11:20
par G-Rom
Super sympa ! Manque plus qu'a rajouté la hauteur du véhicule pour faire des tonneaux & une remorque avec des cylindres en guise de bidon dedans :mrgreen:

Re: Simulation de voiture avec le moteur physique de PB

Publié : mer. 15/mai/2013 11:24
par Fred
Excellent :)

Re: Simulation de voiture avec le moteur physique de PB

Publié : mer. 15/mai/2013 11:37
par Frenchy Pilou
Il n'y a pas un .exe dans un coin ?

Est-ce que le moteur physique de PureBasic est le moteur Physique Bullet ?

Sinon un simulateur physique free 2D bien sympathique Algodoo
http://www.youtube.com/watch?v=Uy9JuTCnTNM

Re: Simulation de voiture avec le moteur physique de PB

Publié : mer. 15/mai/2013 11:54
par Ar-S
Excellent kelebrindae ! Je me suis amusé comme un fou :)
Le potentiel est grand :P

Re: Simulation de voiture avec le moteur physique de PB

Publié : mer. 15/mai/2013 13:12
par Kwai chang caine
Genial !!!!
Pour une fois que du graphisme marche sur mon PC....moi aussi j'ai roulé noir et comme un fou :D
Je me suis même jeté dans le vide intersideral :mrgreen:
J'ai aussi pris la rampe comme dans "l'homme qui tombe a pic"
Avec un boulot comme ça...c'est que ça me ferais presque aimer le graphisme...faut que je fasse gaffe :? :mrgreen:
DREAMWORKS te guette :wink:
Merci pour ce partage 8)

Re: Simulation de voiture avec le moteur physique de PB

Publié : mer. 15/mai/2013 17:52
par venom
Bravo pour ce code, excellent je me suis aussi amusé comme un fou :P







@++

Re: Simulation de voiture avec le moteur physique de PB

Publié : mer. 15/mai/2013 19:15
par comtois
Très bel exemple, si tu es d'accord je l'ajouterai dans la doc (dans la section examples/3D/Demo)

Re: Simulation de voiture avec le moteur physique de PB

Publié : mer. 15/mai/2013 22:27
par graph100
Comme l'a fait remarqué Kelebrindae (que je félicite pour ce petit exemple directement fonctionnel et rigolo), les articulations sont élastiques.

Un "pro" pourrait-il nous dire si PB donne la possibilité de modifier cette élasticité ? Ou bien es-ce quelque chose qui dépend entièrement du moteur physique externe et qui n'a pas été rendu accessible sur PB.
Je ne conçois pas qu'un moteur physique ne prenne pas en compte la possibilité de modifier ce comportement. Il peut être très gênant pour concevoir des systèmes plus complexes.

Re: Simulation de voiture avec le moteur physique de PB

Publié : jeu. 16/mai/2013 10:30
par kelebrindae
Merci à tous! :D
J'ai un peu modifié le code pour ajouter une "carrosserie" à la voiture et ajuster les paramètres par défaut (plus de détails à ce sujet ci-dessous).

@Comtois:
Oui, avec plaisir. Prends plutôt la dernière version; j'y ai corrigé quelques bugs.

@Graph100:
La torsion des articulations étaient en partie dues au fait que je m'étais planté dans le paramétrage de la masse des entités.

En effet, comme l'a expliqué G-Rom dans un autre post, le paramètre "mass" n'est pas le poids de l'entité mais un rapport (cf. masse volumique): une box de 1x1x1 avec une masse de 2 pèse la même chose qu'une box de 2x1x1 avec une masse de 2.
Donc, mon chassis (l'objet le plus gros) à qui j'avais mis une masse = 10 était bien trop lourd (poids = masse x volume).

Bullet mesure les objets en mètres et n'aime pas les valeurs trop petites ou trop grandes: il faut rester entre 5cm et 10m http://bulletphysics.org/mediawiki-1.5. ... _The_World).
Par contre, il ne donne pas d'unités pour la masse, mais n'aime pas les valeurs trop éloignées de 1.
=> Conclusion: je crois qu'il faut prendre un objet de référence, lui donner un masse de 1 ou presque, et calculer la masse des autres en fonction de celui-là.

Exemple: un Scenic mesure 4.3x1.8x1.6 mètres et pèse 1430kg. Le volume d'une box le représentant est donc de 12.384m3 et par conséquent sa masse volumique est de 1430/12.384 = 115. Comme ce nombre est trop grand pour Bullet, je divise par 100 et décide (arbitrairement) que son paramètre "masse" sera égal à 1.15.
Ensuite, si je veux que les objets se comportent correctement les uns par rapport aux autres, je dois déterminer leur masse avec le même calcul (poids en Kg / volume en m3, divisé par 100). Pour les roues, (cylindres de 0.7 de diamètre sur 0.3 de large pesant 10Kg), ça donne 0.86.

C'est très approximatif, très arbitraire, mais ça donne une idée des valeurs à positionner par défaut; ensuite, on ajuste "à vue de nez" pour obtenir ce que l'on veut... :wink:

Re: Simulation de voiture avec le moteur physique de PB

Publié : jeu. 16/mai/2013 12:30
par Fred
N'hesite pas à reposter dans son thread ton nouvel exemple, ca lui donnera surement des idées !

Re: Simulation de voiture avec le moteur physique de PB

Publié : jeu. 16/mai/2013 12:46
par Kwai chang caine
Einstein a écrit :le paramètre "mass" n'est pas le poids de l'entité ...... masse volumique .....Bullet .....Scenic mesure 4.3x1.8x1.6 mètres et pèse 1430kg.... volume d'une box .....est donc de 12.384m3 ....masse volumique est de 1430/12.384 = 115........poids en Kg / volume en m3, divisé par 100.......cylindres de 0.7 de diamètre sur 0.3 de large pesant 10Kg..., ça donne 0.86.
Il y est des domaines... ou les explications, contrairement à leur habitudes, ne font qu'amplifier le coté impressionant 8O
Je savais pas qu'il fallait calculer les poids et tout le toutim comme dans la vraie vie
Un seul bémol...j'ai vu ta carosserie.....pour Pixart et Dreamworks.....c'est l'autoroute....mais pour bosser chez porshe ou ferrari....je crois que l'as encore un peu de boulot pour ce qui est de la ligne, elle va consommer un max :lol:
En tout cas..trop fort !!

Re: Simulation de voiture avec le moteur physique de PB

Publié : jeu. 16/mai/2013 13:21
par Ar-S
Pourrais tu inclure un petit systeme de sauvegarde des paramètres d'un véhicule ?

Re: Simulation de voiture avec le moteur physique de PB

Publié : jeu. 18/juil./2013 9:31
par kelebrindae
Désolé, je n'ai pas beaucoup de temps à consacrer à PB en ce moment...
J'ai tout de même testé le code avec la 5.20b6 (ça marche). J'ai ajouté le nouveau "FollowCamera", modifié un peu la forme de la "voiture", ajouté des objets sur le terrain...

Remarque: Malgré un frame rate normal (environ 60fps), le "FollowCamera" donne un résultat un peu saccadé chez moi; Observez-vous la même chose? :?

Code : Tout sélectionner

;************************************************************************************
;  Bullet Physics - Car demo
;  PB version: 5.20b6
;  Date: may, 5, 2013
;
;  Rough simulation of a car, using PB's physics engine.
;
;  Controls:
;  - W -> Wireframe view
;  - P -> Display physics bodies
;  - [Return] -> Pause simulation
;  - [Cursor keys] -> Drive the car
;************************************************************************************

; Window size
#SCREENWIDTH = 1000
#SCREENHEIGHT = 500

#LEFTSIDE = -1
#RIGHTSIDE = 1

Enumeration
  #FWDRIVE
  #RWDRIVE
  #FOURWHEELDRIVE
  #TYRELLP34
EndEnumeration

; Used for camera management
Structure Vector3
  x.f
  y.f
  z.f
EndStructure


Structure wheel_struct
  support.i ; entity
  wheel.i   ; entity
  supJoint.i    ; joint chassis <> support
  wheelJoint.i  ; joint support <> wheel
  
  wheelRadius.f
  wheelWidth.f
  wheelMass.f
  
  isSteer.b
  isDrive.b

EndStructure

Structure car_struct
  chassis.i     ; car's base entity
  body.i ; car's body entity
  bodyJoint.i   ; joint between the two
  
  width.f
  length.f
  height.f
  chassisHeight.f
  mass.f
  
  maxSteer.f
  maxSpeed.f
  accel.f
  
  List wheel.wheel_struct()
EndStructure
Global car.car_struct

Global i.i, temp.i, wireframe.b, viewBodies.b, simRunning.b = #True, dontQuit.b = #True, eventId.i

Global txBlank.i, txGround.i, txStriped.i
Global mtGround.i, mtRed.i, mtPurple.i, mtBlue.i, mtCyanSt.i, mtWhiteSt.i

Global dimX.f, dimZ.i, ground.i, jump.i, jump2.i
Global planeMesh.i,cubeMesh.i, wheelMesh.i

Global distance.f ; used for camera movement


EnableExplicit


;************************************************************************************
;-                                 ---- Procedures ----
;************************************************************************************


; ****************** Car building ********************
; Add a wheel to a car
Procedure createWheel(*ptrcar.car_struct,side.i, supportZpos.f,
                        isSteer.b, isDrive.b,
                        radius.f = 0.5, width.f = 0.3, mass.f = 1,resti.f = 0.9, friction.f = 1)
  Protected supportWidth.f = 0.6, supportHeight.f = 0.1,supportLength.f = 0.4
  Protected supportXpos.f, supportYpos.f, wheelXpos.f, wheelMat.i

  ; Add the wheel
  AddElement(*ptrcar\wheel())

  ; Define its parameters
  *ptrcar\wheel()\wheelRadius = radius
  *ptrcar\wheel()\wheelWidth = width
  *ptrcar\wheel()\wheelMass = mass
  *ptrcar\wheel()\isDrive = isDrive
  *ptrcar\wheel()\isSteer = isSteer

  ; Position
  supportXpos = (*ptrcar\width/2) * side
  supportYpos = -((*ptrcar\chassisHeight/2) + (supportHeight/2))
  wheelXpos = supportXpos + ((width/2) + (supportWidth/2)) * side

  ; Support entity + joint
  *ptrcar\wheel()\support = CreateEntity(#PB_Any,MeshID(cubeMesh),MaterialID(mtRed),EntityX(car\chassis)+supportXpos,EntityY(car\chassis)+supportYpos,EntityZ(car\chassis)+supportZpos)
  ScaleEntity(*ptrcar\wheel()\support,supportWidth,supportHeight,supportLength)
  EntityPhysicBody(*ptrcar\wheel()\support,#PB_Entity_BoxBody,1,0,0)

  *ptrcar\wheel()\supJoint = HingeJoint(#PB_Any,EntityID(*ptrcar\wheel()\support),-(supportWidth/2) * side,(supportHeight/2),0, 0,1,0,EntityID(*ptrcar\chassis),((*ptrcar\width/2) - (supportWidth/2)) * side,-(*ptrcar\chassisHeight/2),supportZpos, 0,1,0)
  If isSteer = #True
    SetJointAttribute(*ptrcar\wheel()\supJoint,#PB_HingeJoint_LowerLimit,-15)
    SetJointAttribute(*ptrcar\wheel()\supJoint,#PB_HingeJoint_UpperLimit,15)
  Else
    SetJointAttribute(*ptrcar\wheel()\supJoint,#PB_HingeJoint_LowerLimit,0)
    SetJointAttribute(*ptrcar\wheel()\supJoint,#PB_HingeJoint_UpperLimit,0)
  EndIf

  ; Wheel entity + joint
  If isDrive = #True
    wheelMat = MaterialID(mtCyanSt)
  Else
    wheelMat = MaterialID(mtWhiteSt)
  EndIf

  *ptrcar\wheel()\wheel = CreateEntity(#PB_Any,MeshID(wheelMesh),wheelMat,EntityX(car\chassis)+wheelXpos,EntityY(car\chassis)+supportYpos,EntityZ(car\chassis)+supportZpos) 
  ScaleEntity(*ptrcar\wheel()\wheel,*ptrcar\wheel()\wheelRadius,*ptrcar\wheel()\wheelWidth,*ptrcar\wheel()\wheelRadius)
  RotateEntity(*ptrcar\wheel()\wheel,0,0,-90 * side)
  EntityPhysicBody(*ptrcar\wheel()\wheel,#PB_Entity_CylinderBody,mass,resti,friction)

  *ptrcar\wheel()\wheelJoint = HingeJoint(#PB_Any,EntityID(*ptrcar\wheel()\wheel),0,0,0, 0,side,0, EntityID(*ptrcar\wheel()\support),((*ptrcar\wheel()\wheelWidth/2) + (supportWidth/2)) * side,0,0, 1,0,0)

EndProcedure

; Destroy a car
Procedure killCar(*ptrCar.car_struct)
  ForEach *ptrCar\wheel()
    FreeJoint(*ptrCar\wheel()\supJoint)
    FreeJoint(*ptrCar\wheel()\wheelJoint)
    
    FreeEntity(*ptrCar\wheel()\wheel)
    FreeEntity(*ptrCar\wheel()\support)
  Next *ptrCar\wheel()
  ClearList(*ptrCar\wheel())
  
  If IsEntity(*ptrCar\body)
    FreeEntity(*ptrCar\body)
  EndIf
  If IsEntity(*ptrCar\chassis)
    FreeEntity(*ptrCar\chassis)
  EndIf
EndProcedure

; Create a car
Procedure createCar(*ptrCar.car_struct, template.i=#FWDRIVE,
                     width.f = 2,length.f = 4,height.f = 1.25, mass.f = 1.15,
                     maxSteer.f = 15,maxSpeed.f = 40,accel.f = 0.5,
                     wheelRadius.f = 0.5, wheelWidth.f = 0.3,wheelMass.f = 0.85, wheelResti.f = 0.9, wheelFriction.f = 1)

  If IsEntity(*ptrCar\chassis)
    killCar(*ptrCar)
  EndIf
  
  *ptrCar\width = width - wheelWidth*2 - 0.6
  *ptrCar\length = length
  *ptrCar\height = height
  *ptrCar\chassisHeight = 0.3 + wheelRadius / 2
  *ptrCar\mass = mass
  *ptrCar\maxSteer = maxSteer
  *ptrCar\maxSpeed = maxSpeed
  *ptrCar\accel = accel
  
  ; Create the chassis
  *ptrCar\chassis = CreateEntity(#PB_Any,MeshID(cubeMesh),MaterialID(mtBlue),0,2,0)
  ScaleEntity(*ptrCar\chassis,*ptrCar\width,*ptrCar\chassisHeight,*ptrCar\length)
  EntityPhysicBody(*ptrCar\chassis,#PB_Entity_BoxBody,*ptrCar\mass,0,1)
  
  ; Create the car's body
  *ptrCar\body = CreateEntity(#PB_Any,MeshID(cubeMesh),MaterialID(mtBlue),0,EntityY(*ptrCar\chassis) + *ptrCar\chassisHeight + *ptrCar\height/2,0,0)
  ScaleEntity(*ptrCar\body,*ptrCar\width+wheelWidth+0.6,*ptrCar\height,*ptrCar\length-0.1)
  EntityPhysicBody(*ptrCar\body,#PB_Entity_BoxBody,*ptrCar\mass,0,1)
  *ptrCar\bodyJoint = SliderJoint(#PB_Any,EntityID(*ptrCar\chassis),0,*ptrCar\chassisHeight/2,0,EntityID(*ptrCar\body),0,-*ptrCar\height/2,0)
  SetJointAttribute(*ptrCar\bodyJoint,#PB_SliderJoint_LowerLimit,0)
  SetJointAttribute(*ptrCar\bodyJoint,#PB_SliderJoint_UpperLimit,0)
  
  ; Add the wheels
  Select template
    Case #FWDRIVE
      createWheel(@car,#LEFTSIDE,-(*ptrCar\length/2 - 0.7),#True,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,-(*ptrCar\length/2 - 0.7),#True,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#LEFTSIDE,(*ptrCar\length/2 - 0.7),#False,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,(*ptrCar\length/2 - 0.7),#False,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
    
    Case #RWDRIVE
      createWheel(@car,#LEFTSIDE,-(*ptrCar\length/2 - 0.7),#True,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,-(*ptrCar\length/2 - 0.7),#True,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#LEFTSIDE,(*ptrCar\length/2 - 0.7),#False,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,(*ptrCar\length/2 - 0.7),#False,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
    
    Case #FOURWHEELDRIVE
      createWheel(@car,#LEFTSIDE,-(*ptrCar\length/2 - 0.7),#True,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,-(*ptrCar\length/2 - 0.7),#True,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#LEFTSIDE,(*ptrCar\length/2 - 0.7),#False,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,(*ptrCar\length/2 - 0.7),#False,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
    
    Case #TYRELLP34
      createWheel(@car,#LEFTSIDE,-(*ptrCar\length/2 - 0.4),#True,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,-(*ptrCar\length/2 - 0.4),#True,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#LEFTSIDE,-(*ptrCar\length/2 - 1.7),#True,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,-(*ptrCar\length/2 - 1.7),#True,#False,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#LEFTSIDE,(*ptrCar\length/2 - 0.5),#False,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
      createWheel(@car,#RIGHTSIDE,(*ptrCar\length/2 - 0.5),#False,#True,wheelRadius,wheelWidth,wheelMass, wheelResti, wheelFriction)
    
    EndSelect

EndProcedure
; ************* End of car building *************


; ************** Window procedures **************
Global Wmain
Global Frame3D_0, BT_reset, CB_template, FL_mass, label_mass, FL_height,
        label_height, FL_steer, label_steer, FL_maxspeed, label_maxSpeed,
        FL_accel, label_accel, FL_length, label_length, FL_width, label_width,
        FL_radius, label_radius, FL_wheelwidth, label_wheelWidth, FL_wheelMass,
        label_wheelMass, FL_friction, label_friction, FL_resti, label_resti
Procedure OpenWmain()
  Wmain = OpenWindow(#PB_Any, 0, 0, #SCREENWIDTH, #SCREENHEIGHT, "Car physics", #PB_Window_SystemMenu)
  
  Frame3D_0 = Frame3DGadget(#PB_Any, 1, 0, 298, 500, "Parameters")
  BT_reset = ButtonGadget(#PB_Any, 104, 465, 100, 25, "Reset")
  GadgetToolTip(BT_reset, "Reset simulation with new parameters.")
  CB_template = ComboBoxGadget(#PB_Any, 70, 23, 190, 25)
  GadgetToolTip(CB_template, "Pre-defined vehicles")
  
  FL_length = StringGadget(#PB_Any, 141, 56, 100, 25, "4")
  GadgetToolTip(FL_length, "Length of the vehicle")
  label_length = TextGadget(#PB_Any, 37, 62, 100, 20, "Length:",#PB_Text_Right)
  FL_width = StringGadget(#PB_Any, 141, 86, 100, 25, "2.0")
  GadgetToolTip(FL_width, "Width of the vehicle")
  label_width = TextGadget(#PB_Any, 37, 92, 100, 20, "Width:",#PB_Text_Right)
  
  FL_height = StringGadget(#PB_Any, 141, 116, 100, 25, "1.25")
  GadgetToolTip(FL_height, "Height of the vehicle's body")
  label_height = TextGadget(#PB_Any, 37, 122, 100, 20, "Height:",#PB_Text_Right)
  FL_mass = StringGadget(#PB_Any, 141, 146, 100, 25, "1.15")
  GadgetToolTip(FL_mass, "Mass of the vehicle")
  label_mass = TextGadget(#PB_Any, 37, 152, 100, 20, "Mass:",#PB_Text_Right)
  
  FL_steer = StringGadget(#PB_Any, 141, 186, 100, 25, "15")
  GadgetToolTip(FL_steer, "Steering angle of the vehicle.")
  label_steer = TextGadget(#PB_Any, 37, 192, 100, 20, "Steering angle:", #PB_Text_Right)
  FL_maxspeed = StringGadget(#PB_Any, 141, 216, 100, 25, "40")
  GadgetToolTip(FL_maxspeed, "Maximum linear speed of the drive wheels")
  label_maxSpeed = TextGadget(#PB_Any, 37, 222, 100, 20, "Max speed:",#PB_Text_Right)
  FL_accel = StringGadget(#PB_Any, 141, 246, 100, 25, "0.2")
  GadgetToolTip(FL_accel, "Acceleration")
  label_accel = TextGadget(#PB_Any, 37, 252, 100, 20, "Acceleration:",#PB_Text_Right)
  
  FL_radius = StringGadget(#PB_Any, 141, 286, 100, 25, "0.5")
  label_radius = TextGadget(#PB_Any, 37, 292, 100, 20, "Wheel radius:",#PB_Text_Right)
  FL_wheelwidth = StringGadget(#PB_Any, 141, 316, 100, 25, "0.3")
  label_wheelWidth = TextGadget(#PB_Any, 37, 322, 100, 20, "Wheel width:", #PB_Text_Right)
  FL_wheelMass = StringGadget(#PB_Any, 141, 346, 100, 25, "0.85")
  label_wheelMass = TextGadget(#PB_Any, 37, 352, 100, 20, "Wheel mass:", #PB_Text_Right)
  FL_friction = StringGadget(#PB_Any, 141, 376, 100, 25, "1")
  label_friction = TextGadget(#PB_Any, 37, 382, 100, 20, "Wheel friction:", #PB_Text_Right)
  FL_resti = StringGadget(#PB_Any, 141, 406, 100, 25, "0.9")
  label_resti = TextGadget(#PB_Any, 37, 412, 100, 20, "Wheel restitution:", #PB_Text_Right)
  
  ; Combo-box initialization
  AddGadgetItem(CB_template,#FWDRIVE,"Front-wheels drive")
  AddGadgetItem(CB_template,#RWDRIVE,"Rear-wheels drive")
  AddGadgetItem(CB_template,#FOURWHEELDRIVE,"4x4 drive")
  AddGadgetItem(CB_template,#TYRELLP34,"Tyrell P34")
  SetGadgetState(CB_template,0)
EndProcedure

Procedure Wmain_Events(event)
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False
  
    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect
  
    Case #PB_Event_Gadget
      Select EventGadget()
        Case BT_reset ; Create a new car
          createCar(@car,
                    GetGadgetState(CB_template),
                    ValF(GetGadgetText(FL_width)),
                    ValF(GetGadgetText(FL_length)),
                    ValF(GetGadgetText(FL_height)),
                    ValF(GetGadgetText(FL_mass)),
                    ValF(GetGadgetText(FL_steer)),
                    ValF(GetGadgetText(FL_maxspeed)),
                    ValF(GetGadgetText(FL_accel)),
                    ValF(GetGadgetText(FL_radius)),
                    ValF(GetGadgetText(FL_wheelwidth)),
                    ValF(GetGadgetText(FL_wheelMass)),
                    ValF(GetGadgetText(FL_resti)),
                    ValF(GetGadgetText(FL_friction)) )
      EndSelect
  EndSelect
  
  ProcedureReturn #True
EndProcedure
; ************* End of window procedures *************


;************************************************************************************
;-                                 ---- Main program ----
;************************************************************************************

;- Initialization
InitEngine3D()
InitSprite()
InitKeyboard()

;- Window
OpenWmain()
OpenWindowedScreen(WindowID(Wmain), 300, 0, #SCREENWIDTH - 300,#SCREENHEIGHT, 0, 0, 0,#PB_Screen_SmartSynchronization)

;-Textures
txBlank = CreateTexture(#PB_Any,4,4)
StartDrawing(TextureOutput(txBlank))
  Box(0, 0, 4,4, $FFFFFF)
StopDrawing()

txStriped = CreateTexture(#PB_Any,256,256)
StartDrawing(TextureOutput(txStriped))
  Box(0, 0, 256,256, $FFFFFF)
  For i = 0 To 255 Step 32
    Box(i,0,16,256,$777777)
  Next i
StopDrawing()

txGround = CreateTexture(#PB_Any,256,256)
StartDrawing(TextureOutput(txGround))
  Box(0, 0, 256,256, $007700)
  DrawingMode(#PB_2DDrawing_Outlined)
  Box(0, 0, 256,256, $00BB00)
StopDrawing()

;-Materials
mtGround = CreateMaterial(#PB_Any,TextureID(txGround))

mtRed = CreateMaterial(#PB_Any,TextureID(txBlank))
SetMaterialColor(mtRed,#PB_Material_AmbientColor,$0000FF)

mtPurple = CreateMaterial(#PB_Any,TextureID(txBlank))
SetMaterialColor(mtPurple,#PB_Material_AmbientColor,$FF00FF)

mtBlue = CreateMaterial(#PB_Any,TextureID(txBlank))
SetMaterialColor(mtBlue,#PB_Material_AmbientColor,$FF0000)

mtCyanSt = CreateMaterial(#PB_Any,TextureID(txStriped))
SetMaterialColor(mtCyanSt,#PB_Material_AmbientColor,$FFFF00)

mtWhiteSt = CreateMaterial(#PB_Any,TextureID(txStriped))


;- Terrain
dimX = 500:dimZ = 500
planeMesh = CreatePlane(#PB_Any,dimX,dimZ,1,1,dimX,dimZ)
ground  = CreateEntity(#PB_Any, MeshID(planeMesh), MaterialID(mtGround))
EntityPhysicBody(ground, #PB_Entity_StaticBody,0,1,1)

cubeMesh = CreateCube(#PB_Any,1)
jump = CreateEntity(#PB_Any,MeshID(cubeMesh),MaterialID(mtWhiteSt))
ScaleEntity(jump,8,4,4)
RotateEntity(jump,0,0,-15)
MoveEntity(jump,-10,-1,5, #PB_Absolute)
EntityPhysicBody(jump, #PB_Entity_BoxBody,0,0,1)

jump2 = CreateEntity(#PB_Any,MeshID(cubeMesh),MaterialID(mtWhiteSt))
ScaleEntity(jump2,12,4.4,4)
RotateEntity(jump2,0,0,-20)
MoveEntity(jump2,-10,0,-5, #PB_Absolute)
EntityPhysicBody(jump2, #PB_Entity_BoxBody,0,0,1)


;- Boxes
For i = 1 To 5
  temp = CreateEntity(#PB_Any, MeshID(cubeMesh), MaterialID(mtPurple),-50,0.5,(i*1.1)-3.3)
  EntityPhysicBody(temp, #PB_Entity_BoxBody, 0.25)
Next i
For i = 1 To 4
  temp = CreateEntity(#PB_Any, MeshID(cubeMesh), MaterialID(mtPurple),-50,1.5,(i*1.1)-2.8)
  EntityPhysicBody(temp, #PB_Entity_BoxBody, 0.25)
Next i
For i = 1 To 3
  temp = CreateEntity(#PB_Any, MeshID(cubeMesh), MaterialID(mtPurple),-50,2.5,(i*1.1)-2.3)
  EntityPhysicBody(temp, #PB_Entity_BoxBody, 0.25)
Next i


;- Car
wheelMesh = CreateCylinder(#PB_Any,1,1)
createCar(@car) ; all parameters are set to default values

;- Camera
CreateCamera(0, 0, 0, 100, 100)
MoveCamera(0,0,5,10,#PB_Absolute)
CameraLookAt(0,0,0,0)

;-Light
AmbientColor($333333)
CreateLight(0,$FFFFFF,200,400,200)
WorldShadows(#PB_Shadow_Additive)


;- Main loop
KeyboardMode(#PB_Keyboard_International)
Repeat
  Delay(1)
  
  ; Windows events (reset button)
  eventID = WindowEvent()
  While eventID <> 0 And dontQuit = #True
    dontQuit = Wmain_Events(eventId)
    eventID = WindowEvent()
  Wend
  ExamineKeyboard()
  
  ; Activate wireframe render
  If KeyboardReleased(#PB_Key_W)
    wireframe = 1-wireframe
    If wireframe = #True
      CameraRenderMode(0,#PB_Camera_Wireframe)
    Else
      CameraRenderMode(0,#PB_Camera_Textured)
    EndIf
  EndIf
  
  ; Activate physics render
  If KeyboardReleased(#PB_Key_P)
    viewBodies = 1-viewBodies
    If viewBodies  = #True
      WorldDebug(#PB_World_DebugBody)
    Else
      WorldDebug(#PB_World_DebugNone)
    EndIf
  EndIf
  ; Start/pause simulation
  If KeyboardReleased(#PB_Key_Return)
    simRunning = 1-simRunning
    EnableWorldPhysics(simRunning)
  EndIf
  
  ; If the car exists, you can control it
  If IsEntity(car\chassis)
    ; Avoid that the car's physics body "goes to sleep" when not moving enough.
    DisableEntityBody(car\chassis,#False)
    
    ;- Steering
    If KeyboardPushed(#PB_Key_Left)
      ForEach car\wheel()
        If car\wheel()\isSteer = #True
          EnableHingeJointAngularMotor(car\wheel()\supJoint, #True, 5, 10)
          SetJointAttribute(car\wheel()\supJoint,#PB_HingeJoint_LowerLimit,-car\maxSteer)
          SetJointAttribute(car\wheel()\supJoint,#PB_HingeJoint_UpperLimit,car\maxSteer)
        EndIf
      Next car\wheel()
    ElseIf KeyboardPushed(#PB_Key_Right)
      ForEach car\wheel()
        If car\wheel()\isSteer = #True
          EnableHingeJointAngularMotor(car\wheel()\supJoint, #True, -5, 10)
          SetJointAttribute(car\wheel()\supJoint,#PB_HingeJoint_LowerLimit,-car\maxSteer)
          SetJointAttribute(car\wheel()\supJoint,#PB_HingeJoint_UpperLimit,car\maxSteer)
        EndIf
      Next car\wheel()
    Else
      ForEach car\wheel()
        If car\wheel()\isSteer = #True
          SetJointAttribute(car\wheel()\supJoint,#PB_HingeJoint_LowerLimit,0)
          SetJointAttribute(car\wheel()\supJoint,#PB_HingeJoint_UpperLimit,0)
        EndIf
      Next car\wheel()
    EndIf
  
    ;- Forward / backward acceleration
    If KeyboardPushed(#PB_Key_Up)
      ForEach car\wheel()
        If car\wheel()\isDrive = #True
          EnableHingeJointAngularMotor(car\wheel()\wheelJoint, #True,-car\maxSpeed, car\accel)
        EndIf
      Next car\wheel()
    ElseIf KeyboardPushed(#PB_Key_Down)
      ForEach car\wheel()
        If car\wheel()\isDrive = #True
          EnableHingeJointAngularMotor(car\wheel()\wheelJoint, #True, car\maxSpeed, car\accel)
        EndIf
      Next car\wheel()
    Else
      ForEach car\wheel()
        If car\wheel()\isDrive = #True
          EnableHingeJointAngularMotor(car\wheel()\wheelJoint, #False, 0,0)
        EndIf
      Next car\wheel()
    EndIf
  
    ;- Camera management
    CameraFollow(0, EntityID(car\body), 0, EntityY(car\body) + 2, 10, 1,0.1)

  EndIf
  
  ; Render
  RenderWorld()
  FlipBuffers()

Until KeyboardPushed(#PB_Key_Escape) Or dontQuit = #False

End

Re: Simulation de voiture avec le moteur physique de PB

Publié : jeu. 18/juil./2013 9:46
par falsam
kelebrindae a écrit :Malgré un frame rate normal (environ 60fps), le "FollowCamera" donne un résultat un peu saccadé chez moi; Observez-vous la même chose? :?
Bonjour kelebrindae par rapport au code précédent que j'ai testé (Au passage, j'adore :) ) je ne vois pas de différence. Mon pc est un portable pas très récent sur la base d'un intel Core2 Duo P8600 à 2.40 Ghz et ma carte vidéo est une Nvidia GeForce 9600M avec la derniere version du driver NVidia (320.49) et c'est plutôt une entrée de gamme.