Page 1 of 1

Pendulum Clock simulation

Posted: Tue Jun 21, 2016 4:32 pm
by applePi
more application using the new compound bodies in PB 5.50
info about pendulum clocks:
http://electronics.howstuffworks.com/ga ... /printable
http://static.howstuffworks.com/flash/c ... pement.swf
in short there are main gear powered by either a spring or a falling weight, it has tilted teeth, normaly it will rotate very speedy and in 3 seconds the spring will lost all its energy, but the existence of swinging pendulum with its 2 pieces LeftStop and RighStop prevent the gear from rotating speedily, also the gear gives the pendulum itself small push.

i have some problems with the tik tok sound, look the code, may someone elaborate it. the tik tok works the best in windows xp/32 and works the worst in my windows 7/x64

keys:
1-mouse and arrows to move and rotate camera so you can inspect the clock closely
2- D : display worldDebug info
3- S : toggle sound (tik tok) on/of
4- if gears stuck press Z or/and space
5- X: toggle stop/run the main gear
you need this sound file: save it to the same folder as the code
http://s000.tinyupload.com/index.php?fi ... 3582948230

PB 5.50 beta 2, tested in windows xp/32 win7/x64 ubuntu 14.x x/64
Note: the LeftStop and RightStop pieces are passed as concave geometry (#PB_Entity_StaticBody) for exact touch to the Escapement gear teeth
needs PB 5.50 beta 2 + http://s000.tinyupload.com/index.php?fi ... 3582948230

Code: Select all

;
;
; ------------------------------------------------------------
;
;   PureBasic - CompoundBody
;
;
;    (c) Fantaisie Software
;
; ------------------------------------------------------------
;
Structure pendulum
  pendulum.l
  escapeRod.l
  RightStop.l
  LeftStop.l
  Rod.l
  sphere.l
EndStructure

IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"

#CameraSpeed = 0.1

Define.f KeyX, KeyY, MouseX, MouseY
Declare Gear_Make()

If InitEngine3D()
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If InitSound() = 0
  MessageRequester("Error", "Can't open DirectX 7 Or Sound Card is not present", 0)
  End
  EndIf
  
  LoadSound(0, "tik.wav")
  
  If Screen3DRequester()
    
    Add3DArchive("." , #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/"              , #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures"  , #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Models"    , #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts"    , #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/GUI"        , #PB_3DArchive_FileSystem)
    Parse3DScripts()
    
    ;WorldDebug(#PB_World_DebugBody)
    ;-------------------------------
    CreateLight(0, RGB(255,255,255), 10, 0, 10)
    CreateLight(1, RGB(255,255,255), -10, 5, -10)
    CreateLight(2, RGB(255,255,255), 10, -1, 0)
    ; create  material
    GetScriptMaterial(5, "Color/Green")
    SetMaterialColor(5, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    
    GetScriptMaterial(6, "Color/Yellow")
    SetMaterialColor(6, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    
    GetScriptMaterial(7, "Color/Red")
    SetMaterialColor(7, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    
    CreateMaterial(1, LoadTexture(1, "Wood.jpg"))
    SetMaterialColor(1, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    ; 
    CreateMaterial(2, LoadTexture(2, "Dirt.jpg"))
    SetMaterialColor(2, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    
    CreateMaterial(3, LoadTexture(3, "MRAMOR6X6.jpg"))
    SetMaterialColor(3, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    
    CreateMaterial(4, LoadTexture(4, "ground_diffuse.png"))
    
    CreateMaterial(8, LoadTexture(8, "Tire_Shi.png"))
    AddMaterialLayer(8, TextureID(1) , #PB_Material_Modulate      )

  
    ;-------------------------------
;construction of a gear with 18 teeth
ang=40 ; the angle wanted for every tooth of the gear

CreateCylinder(50, 1, 0.3)
CreateEntity(50, MeshID(50),MaterialID(1),  0, 0, 0)
RotateEntity(50, 90,0, 0, #PB_Absolute)
CreateCube(1, 1)

Global EscapeGear = CreateEntity(#PB_Any,0,0)
For i=1 To 18
angle.f+20
x.f = Cos(Radian(angle)) * 1: z.f = Sin(Radian(angle)) * 1
CreateEntity(i, MeshID(1),MaterialID(1),  x, z, 0)
ScaleEntity(i, 0.5, 0.05, 0.2)
ang+20
RotateEntity(i, 0,0, ang, #PB_Absolute)
AddSubEntity(EscapeGear, i, #PB_Entity_BoxBody) 
Next
AddSubEntity(EscapeGear, 50, #PB_Entity_CylinderBody) 
;Gear1
; the component of the smaller yellow gear which will be attached later to the main woody gear (EscapeGear)
;Global Gear1 = CreateCylinder(#PB_Any, 3, 1 , 3, 1, 1)
Global Gear1 = CreateCube(#PB_Any, 1)
For i=81 To 84
    CreateEntity(i, MeshID(Gear1),MaterialID(6),  0, 0, -1)
    RotateEntity(i, 0,0,rot, #PB_Absolute)
      ScaleEntity(i, 0.7,0.7,0.3)
      rot + 30
      If i = 101
       SetEntityMaterial(101, MaterialID(8))
       MoveEntity(101, 0,0, 0.01)
      EndIf
      AddSubEntity(EscapeGear, i, #PB_Entity_BoxBody) 
 Next
  
; a useless axis, just a shape to fill the gap between the EscapeGear and the small tellow gear  
axis = CreateEntity(#PB_Any, MeshID(50),MaterialID(1),  0, 0, -0.5)
RotateEntity(axis, 90,0, 0, #PB_Absolute)  
ScaleEntity(axis, 0.1,3,0.1)
AddSubEntity(EscapeGear, axis, #PB_Entity_ConvexHullBody) 
CreateEntityBody(EscapeGear, #PB_Entity_CompoundBody, 10, 0.0, 0.2)
SetEntityAttribute(EscapeGear, #PB_Entity_DisableContactResponse, 1) ;disable collision

Global Gear2 = CreateEntity(#PB_Any,0,0)
Gear_Make() ; call proc to make the big green gear
CreateEntityBody(Gear2, #PB_Entity_CompoundBody, 1, 0.0, 0.5)
SetEntityAttribute(Gear2, #PB_Entity_DisableContactResponse, 1) ;disable collision
    
;-----------------------------------------
pendulum.pendulum
pendulum\pendulum= CreateEntity(#PB_Any,0,0)
;the rod above the gear teeth
pendulum\escapeRod = CreateEntity(#PB_Any, MeshID(1),MaterialID(3),  0, 0, 0)
ScaleEntity(pendulum\escapeRod, 1.5, 0.05, 0.2)

;the right small piece attached to the rod
CreateCylinder(200, 0.7, 1 , 3, 1, 1)
pendulum\RightStop = CreateEntity(#PB_Any, MeshID(200),MaterialID(2),  0.5, -0.1, 0)
ScaleEntity(pendulum\RightStop, 0.1, 0.1, 0.3)
;RotateEntity(RightStop , 90,30,0, #PB_Absolute)
RotateEntity(pendulum\RightStop , 90,0,0, #PB_Absolute)

AddSubEntity(pendulum\pendulum, pendulum\escapeRod, #PB_Entity_BoxBody) 
AddSubEntity(pendulum\pendulum, pendulum\RightStop, #PB_Entity_StaticBody) ;HasContactResponse

;the left small piece attached To the rod
pendulum\LeftStop = CreateEntity(#PB_Any, MeshID(1),MaterialID(2),  -0.6, -0.1, 0)
ScaleEntity(pendulum\LeftStop, 0.5,0.05,0.2)
RotateEntity(pendulum\LeftStop , 0 , 0, -90, #PB_Absolute)
AddSubEntity(pendulum\pendulum, pendulum\LeftStop, #PB_Entity_StaticBody) 

; pendulum
pendulum\Rod = CreateEntity(#PB_Any, MeshID(1),MaterialID(2),  0, -1.3, 0.3)
ScaleEntity(pendulum\Rod, 0.05,2.5,0.05)

AddSubEntity(pendulum\pendulum, pendulum\Rod, #PB_Entity_BoxBody) 
pendulum\sphere = CreateSphere(#PB_Any,0.5)
TransformMesh(pendulum\sphere, 0,0,0,1,1,0.2,0,0,0) ; make thin sphere
pendulum\sphere = CreateEntity(#PB_Any, MeshID(pendulum\sphere), MaterialID(7) ,0, -2.3,  0.5)
MoveEntity(pendulum\sphere, 0,-0.7, 0)

AddSubEntity(pendulum\pendulum, pendulum\sphere, #PB_Entity_ConvexHullBody) 
CreateEntityBody(pendulum\pendulum, #PB_Entity_CompoundBody, 30, 0, 1); 0.2
SetEntityAttribute(pendulum\pendulum, #PB_Entity_DisableContactResponse, 1) ;disable collision
MoveEntity(pendulum\pendulum, 0,0.1,1,#PB_Absolute)
    
    ;Ground
    Ground = CreateEntity(#PB_Any, MeshID(1), MaterialID(4), 0, -7, 0)
    ScaleEntity(Ground, 40, 0.4, 40)
    CreateEntityBody(Ground, #PB_Entity_StaticBody)
        
    GenericJoint(4,EntityID(Ground), 0, 4, 0,EntityID(EscapeGear), 0, 0, 0)
    SetJointAttribute(4, #PB_Joint_EnableSpring, #True, 5)
    SetJointAttribute(4, #PB_Joint_Stiffness, 5, 5)
    SetJointAttribute(4, #PB_Joint_Damping, 0.0, 5)
    
    GenericJoint(5,EntityID(Ground), 2.52, 4, -1,EntityID(Gear2), 0, 0, 0)
    ;SetJointAttribute(5, #PB_Joint_NoLimit , 0, 5)
    SetJointAttribute(5, #PB_Joint_EnableSpring, #True, 5)
    SetJointAttribute(5, #PB_Joint_Stiffness, 5, 5)
    SetJointAttribute(5, #PB_Joint_Damping, 0.0, 5)
    
    GenericJoint(6,EntityID(Ground), 0, 5.1, 0.0,EntityID(pendulum\pendulum), 0, -0.3, 0)
    SetJointAttribute(6, #PB_Joint_EnableSpring, #True, 5)
    SetJointAttribute(6, #PB_Joint_Stiffness, 1000, 5)
    SetJointAttribute(6, #PB_Joint_Damping, 0.5, 5);
        
     ; camera
    CreateCamera(0, 0, 0, 100, 100, #True)
    MoveCamera(0,1,-2,10, #PB_Absolute)
    CameraLookAt(0, 1,-3.2,0)
    CameraBackColor(0, RGB(231,232,240))

    ; GUI
    OpenWindow3D(0, 0, 0, 50 , 10 , "")
    HideWindow3D(0,1)
    ShowGUI(128, 0) ; Display the GUI, semi-transparent and display the mouse cursor
    ;SetWindowTitle(0, "PureBasic-3D Demos ....  Press 'Space' to apply initial push to the pendulum")
 
   tm.f = ElapsedMilliseconds(); we need to wait 1 second for the whole gears construction to fit together before enabling the collison again
   
   Repeat
      Screen3DEvents()
      
      If ExamineMouse()
        MouseX = -MouseDeltaX() * #CameraSpeed * 0.5
        MouseY = -MouseDeltaY() * #CameraSpeed * 0.5
        InputEvent3D(MouseX(), MouseY(),0)
        BodyPick(CameraID(0), MouseButton(#PB_MouseButton_Left), MouseX(), MouseY(), 1)
      EndIf
    
      If ExamineKeyboard()
        
        If KeyboardPushed(#PB_Key_Space) ; in case gears teeth stuck
           ApplyEntityImpulse(pendulum\pendulum, -0.2, 0, 0, 0, 10,0)
         EndIf
         
         If KeyboardPushed(#PB_Key_Z) ; if gear2 stuck push it
            ApplyEntityImpulse(Gear2, -10, 0, 0, 0, 10,0)
           
         EndIf
         If KeyboardReleased(#PB_Key_S) 
         soundOn ! 1
         EndIf
         If KeyboardReleased(#PB_Key_X)
           torque ! 1 ; stop or initiate torque on the EscapeGear
         EndIf  
       
         If KeyboardReleased(#PB_Key_D)
           debugWire ! 1
           If debugWire
             WorldDebug(#PB_World_DebugBody)
           Else
             WorldDebug(#PB_World_DebugNone  )
           EndIf
             
         EndIf
         
        
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed
        Else
          KeyY = 0
        EndIf
        
      EndIf
            
      If torque=0
      ApplyEntityTorque(EscapeGear, 0, 0, 100)
      ;ApplyEntityTorque(EscapeGear, 0, 0, 50)
      EndIf
    
      
      MoveCamera  (0, KeyX, 0, KeyY)
      RotateCamera(0,  MouseY, MouseX, 0, #PB_Relative)
      
      ;If EntityCollide(EscapeGear, pendulum\pendulum) ; does not work
        ;Debug "ok"
        ;PlaySound(0, 0, 100)
        ;EndIf
      If soundOn
      If ExamineWorldCollisions(#True) ; get also contacts
                
        While NextWorldCollision()
          
          If FirstWorldCollisionEntity() = EscapeGear And SecondWorldCollisionEntity() = pendulum\pendulum
            If chaosTime2.f >= 600
              PlaySound(0, 0, 100)
              chaosTime.f = ElapsedMilliseconds()
              
            EndIf
          chaosTime2.f = ElapsedMilliseconds() - chaosTime  
          EndIf
          
        Wend
        
      EndIf
    EndIf
    
      
      RenderWorld()
      ;Screen3DStats()
      FlipBuffers()
      
       If oneSecond = 0 
      tm2.f = ElapsedMilliseconds()
      If (tm2-tm) >= 300 ; after 1 second enable the collison
        ;enable the collision for the green big gear
        SetEntityAttribute(Gear2, #PB_Entity_DisableContactResponse, 0)
        SetEntityAttribute(pendulum\pendulum, #PB_Entity_DisableContactResponse, 0)
        SetEntityAttribute(EscapeGear, #PB_Entity_DisableContactResponse, 0)
                
        oneSecond =1 
        
      EndIf
    EndIf
    
    
    If soundOn:StopSound(0,#PB_All):EndIf
    ;Delay(1)
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
    
  EndIf
  
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
End


Procedure Gear_Make()
  ;the big gear made from 60 teeth
  CreateCube(101, 1)
  For i=101 To 115
      CreateEntity(i, MeshID(1),MaterialID(5),  0, 0, 0)
      RotateEntity(i, 0,0,rot, #PB_Absolute)
      ScaleEntity(i, 3,3,0.5)
      rot + 6
      If i = 101
      SetEntityMaterial(101, MaterialID(8))
      MoveEntity(101, 0,0, 0.01)
    EndIf
      AddSubEntity(Gear2, i, #PB_Entity_BoxBody) 
      
  Next
    
  
  ;RotateEntity(Gear2, 90,0,0)
  
    
EndProcedure

Re: Pendulum Clock simulation

Posted: Tue Jun 21, 2016 5:46 pm
by Comtois
Very nice.

Next step, la pascaline ?

Re: Pendulum Clock simulation

Posted: Wed Jun 22, 2016 8:05 am
by applePi
Thank You Comtois, it is the purebasic new additions which make mechanical simulations possible, and this (usually) will show its importance after some time and not immediately
regarding the pascaline it is a funny project i will think about it, some of its parts needs abstraction.
i have collected some docs
there is a may be simpler version here: https://www.youtube.com/watch?v=X9EVhlVk2qM
Inkscape represenation of pascaline: https://www.cse.iitb.ac.in/~abhishektha ... 1-sub.html
Pascaline Replica, SolidWorks files : http://www.cs.cmu.edu/~dst/Pascaline/
on the other hand regarding the clock , before posting the above code i have tried first to make the gears from rotating triangles (triangulated cylinders), the geometry of the triangles of the big green gear (Gear2) are passed as concave geometry with #PB_Entity_StaticBody) while the triangles of the yellow small gear (gear1) passed as #PB_Entity_ConvexHullBody Line 112
AddSubEntity(EscapeGear, i, #PB_Entity_ConvexHullBody)
but look at it with WorldDebug(#PB_World_DebugBody) , the physical body is much larger than the graphical body

the AddSubEntity seems have this structure (it still lack the doc):

Code: Select all

AddSubEntity(compound body, entity to add, Type of geometry, physicsBodyX, physicsBodyY, physicsBodyZ, physicsBody ScaleX, physicsBody ScaleY, physicsBody ScaleZ) 
so i have tried to resize the body size so it fits the graphics size, but we can't scale it if the triangulated cylinders passed as #PB_Entity_ConvexHullBody, while the body resize is possible with any thing else like #PB_Entity_BoxBody
but i think this is related to a similar issue, in docs of CreateEntityBody :

Code: Select all

The bounding box size of the body. It only applies to the following body type: 
  #PB_Entity_BoxBody     : SizeX, SizeY and SizeZ are available.
  #PB_Entity_SphereBody  : SizeX is available.
  #PB_Entity_ConeBody    : SizeX and SizeY are available.
  #PB_Entity_CylinderBody: SizeX and SizeY are available.
  #PB_Entity_CapsuleBody : SizeX, SizeY and SizeZ are available.
there is no mention about #PB_Entity_ConvexHullBody , may be will be added in the future especially with AddSubEntity()


the same keys as above example, if the teeth stuck press Z
needs PB 5.50 Beta 2 + http://s000.tinyupload.com/index.php?fi ... 3582948230

Code: Select all

;
;
; ------------------------------------------------------------
;
;   PureBasic - CompoundBody 
;
;
;    (c) Fantaisie Software
;
; ------------------------------------------------------------
;
Structure pendulum
  pendulum.l
  escapeRod.l
  RightStop.l
  LeftStop.l
  Rod.l
  sphere.l
EndStructure

IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"

#CameraSpeed = 0.1

Define.f KeyX, KeyY, MouseX, MouseY
Declare Gear_Make()

If InitEngine3D()
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If InitSound() = 0
  MessageRequester("Error", "Can't open DirectX 7 Or Sound Card is not present", 0)
  End
  EndIf
  
  LoadSound(0, "tik.wav")
  
  If Screen3DRequester()
    
    Add3DArchive("." , #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/"              , #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures"  , #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Models"    , #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts"    , #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/GUI"        , #PB_3DArchive_FileSystem)
    Parse3DScripts()
    
    WorldDebug(#PB_World_DebugBody)
       
    ;-------------------------------
    CreateLight(0, RGB(255,255,255), 10, 0, 10)
    CreateLight(1, RGB(255,255,255), -10, 5, -10)
    CreateLight(2, RGB(255,255,255), 10, -1, 0)
    ; create  material
    GetScriptMaterial(5, "Color/Green")
    SetMaterialColor(5, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    
    GetScriptMaterial(6, "Color/Yellow")
    SetMaterialColor(6, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    
    GetScriptMaterial(7, "Color/Red")
    SetMaterialColor(7, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    
    CreateMaterial(1, LoadTexture(1, "Wood.jpg"))
    SetMaterialColor(1, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    ; 
    CreateMaterial(2, LoadTexture(2, "Dirt.jpg"))
    SetMaterialColor(2, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    
    CreateMaterial(3, LoadTexture(3, "MRAMOR6X6.jpg"))
    SetMaterialColor(3, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    
    CreateMaterial(4, LoadTexture(4, "ground_diffuse.png"))
    
    CreateMaterial(8, LoadTexture(8, "Tire_Shi.png"))
    AddMaterialLayer(8, TextureID(1) , #PB_Material_Modulate      )
    
  
    ;-------------------------------
;construction of a gear with 18 teeth
ang=40 ; the angle wanted for every tooth of the gear

CreateCylinder(50, 1, 0.3)
CreateEntity(50, MeshID(50),MaterialID(1),  0, 0, 0)
RotateEntity(50, 90,0, 0, #PB_Absolute)
CreateCube(1, 1)

Global EscapeGear = CreateEntity(#PB_Any,0,0)
For i=1 To 18
angle.f+20
x.f = Cos(Radian(angle)) * 1: z.f = Sin(Radian(angle)) * 1
CreateEntity(i, MeshID(1),MaterialID(1),  x, z, 0)
ScaleEntity(i, 0.5, 0.05, 0.2)
ang+20
RotateEntity(i, 0,0, ang, #PB_Absolute)
AddSubEntity(EscapeGear, i, #PB_Entity_BoxBody) 
Next
AddSubEntity(EscapeGear, 50, #PB_Entity_CylinderBody) 
;Gear1
; the component of red smaller yellow gear which will attached later to the main woody gear (EscapeGear)
Global Gear1 = CreateCylinder(#PB_Any, 3, 1 , 3, 1, 1)
For i=81 To 84
    
  CreateEntity(i, MeshID(Gear1),MaterialID(6),  0, 0, -1)
  ScaleEntity(i, 0.2,0.2,0.2)
    
    RotateEntity(i, 90,90+rot,0, #PB_Absolute)
    rot+30

    AddSubEntity(EscapeGear, i, #PB_Entity_ConvexHullBody) 
  Next
  
; a useless axis, just shape to fill the gap between the EscapeGear and the small gear  
axis = CreateEntity(#PB_Any, MeshID(50),MaterialID(1),  0, 0, -0.5)
RotateEntity(axis, 90,0, 0, #PB_Absolute)  
ScaleEntity(axis, 0.1,3,0.1)
AddSubEntity(EscapeGear, axis, #PB_Entity_ConvexHullBody) 
CreateEntityBody(EscapeGear, #PB_Entity_CompoundBody, 10, 0.0, 0.2)
SetEntityAttribute(EscapeGear, #PB_Entity_DisableContactResponse, 1)

Global Gear2 = CreateEntity(#PB_Any,0,0)
Gear_Make()
CreateEntityBody(Gear2, #PB_Entity_CompoundBody, 1, 0.0, 0.5)
SetEntityAttribute(Gear2, #PB_Entity_DisableContactResponse, 1) ;disable collision
    
;-----------------------------------------
pendulum.pendulum
pendulum\pendulum= CreateEntity(#PB_Any,0,0)
;the rod above the gear teeth
pendulum\escapeRod = CreateEntity(#PB_Any, MeshID(1),MaterialID(3),  0, 0, 0)
ScaleEntity(pendulum\escapeRod, 1.5, 0.05, 0.2)

;the right small piece attached to the rod
CreateCylinder(200, 0.7, 1 , 3, 1, 1)
pendulum\RightStop = CreateEntity(#PB_Any, MeshID(200),MaterialID(2),  0.5, -0.1, 0)
ScaleEntity(pendulum\RightStop, 0.1, 0.1, 0.3)
;RotateEntity(RightStop , 90,30,0, #PB_Absolute)
RotateEntity(pendulum\RightStop , 90,0,0, #PB_Absolute)

AddSubEntity(pendulum\pendulum, pendulum\escapeRod, #PB_Entity_BoxBody) 
AddSubEntity(pendulum\pendulum, pendulum\RightStop, #PB_Entity_StaticBody) ;HasContactResponse

;the left small piece attached To the rod
pendulum\LeftStop = CreateEntity(#PB_Any, MeshID(1),MaterialID(2),  -0.6, -0.1, 0)
ScaleEntity(pendulum\LeftStop, 0.5,0.05,0.2)
RotateEntity(pendulum\LeftStop , 0 , 0, -90, #PB_Absolute)
AddSubEntity(pendulum\pendulum, pendulum\LeftStop, #PB_Entity_StaticBody) 

; pendulum
pendulum\Rod = CreateEntity(#PB_Any, MeshID(1),MaterialID(2),  0, -1.3, 0.3)
ScaleEntity(pendulum\Rod, 0.05,2.5,0.05)

AddSubEntity(pendulum\pendulum, pendulum\Rod, #PB_Entity_BoxBody) 
pendulum\sphere = CreateSphere(#PB_Any,0.5)
TransformMesh(pendulum\sphere, 0,0,0,1,1,0.2,0,0,0) ; make thin sphere
pendulum\sphere = CreateEntity(#PB_Any, MeshID(pendulum\sphere), MaterialID(7) ,0, -2.3,  0.5)
MoveEntity(pendulum\sphere, 0,-0.7, 0)

AddSubEntity(pendulum\pendulum, pendulum\sphere, #PB_Entity_ConvexHullBody) 
CreateEntityBody(pendulum\pendulum, #PB_Entity_CompoundBody, 30, 0.0, 0.2)
SetEntityAttribute(pendulum\pendulum, #PB_Entity_DisableContactResponse, 1)
MoveEntity(pendulum\pendulum, 0,0.1,1,#PB_Absolute)
    
    ;Ground
    Ground = CreateEntity(#PB_Any, MeshID(1), MaterialID(4), 0, -7, 0)
    ScaleEntity(Ground, 40, 0.4, 40)
    CreateEntityBody(Ground, #PB_Entity_StaticBody)
        
    GenericJoint(4,EntityID(Ground), 0, 4, 0,EntityID(EscapeGear), 0, 0, 0)
    SetJointAttribute(4, #PB_Joint_EnableSpring, #True, 5)
    SetJointAttribute(4, #PB_Joint_Stiffness, 5, 5)
    SetJointAttribute(4, #PB_Joint_Damping, 0.0, 5)
    
    GenericJoint(5,EntityID(Ground), 3.45, 4, -1,EntityID(Gear2), 0, 0, 0)
    ;SetJointAttribute(5, #PB_Joint_NoLimit , 0, 5)
    SetJointAttribute(5, #PB_Joint_EnableSpring, #True, 5)
    SetJointAttribute(5, #PB_Joint_Stiffness, 5, 5)
    SetJointAttribute(5, #PB_Joint_Damping, 0.0, 5)
    
    GenericJoint(6,EntityID(Ground), 0, 5.1, 0.0,EntityID(pendulum\pendulum), 0, -0.3, 0)
    SetJointAttribute(6, #PB_Joint_EnableSpring, #True, 5)
    SetJointAttribute(6, #PB_Joint_Stiffness, 1000, 5)
    SetJointAttribute(6, #PB_Joint_Damping, 0.5, 5);
        
     ; camera
    CreateCamera(0, 0, 0, 100, 100, #True)
    MoveCamera(0,1,-2,-10, #PB_Absolute)
    CameraLookAt(0, 1,-3.2,0)
    CameraBackColor(0, RGB(231,232,240))

    ; GUI
    OpenWindow3D(0, 0, 0, 50 , 10 , "")
    HideWindow3D(0,1)
    ShowGUI(128, 0) ; Display the GUI, semi-transparent and display the mouse cursor
    ;SetWindowTitle(0, "PureBasic-3D Demos ....  Press 'Space' to apply initial push to the pendulum")
  
    tm.f = ElapsedMilliseconds(); we need to wait 1 second for the whole gears construction to fit together before enabling the collison again
        
    Repeat
      Screen3DEvents()
      
      If ExamineMouse()
        MouseX = -MouseDeltaX() * #CameraSpeed * 0.5
        MouseY = -MouseDeltaY() * #CameraSpeed * 0.5
        InputEvent3D(MouseX(), MouseY(),0)
        BodyPick(CameraID(0), MouseButton(#PB_MouseButton_Left), MouseX(), MouseY(), 1)
      EndIf
    
      If ExamineKeyboard()
        
        If KeyboardPushed(#PB_Key_Space) ; in case gears teeth stuck
           ApplyEntityImpulse(pendulum\pendulum, -0.2, 0, 0, 0, 10,0)
         EndIf
         
         If KeyboardPushed(#PB_Key_Z) ; if gear2 stuck push it
            ApplyEntityImpulse(Gear2, -10, 0, 0, 0, 10,0)
           
         EndIf
         If KeyboardReleased(#PB_Key_S) 
         soundOn ! 1
         EndIf
         If KeyboardReleased(#PB_Key_X)
           torque ! 1 ; stop or initiate torque on the EscapeGear
         EndIf  
       
         If KeyboardReleased(#PB_Key_D)
           debugWire ! 1
           If debugWire
             WorldDebug(#PB_World_DebugNone)
           Else
             WorldDebug(#PB_World_DebugBody )
           EndIf
             
         EndIf
        
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed
        Else
          KeyY = 0
        EndIf
        
      EndIf
            
      If torque=0
      ApplyEntityTorque(EscapeGear, 0, 0, 100)
      ;ApplyEntityTorque(EscapeGear, 0, 0, 50)
      EndIf
      
      MoveCamera  (0, KeyX, 0, KeyY)
      RotateCamera(0,  MouseY, MouseX, 0, #PB_Relative)
      
      ;If EntityCollide(EscapeGear, pendulum\pendulum) ; does not work
        ;Debug "ok"
        ;PlaySound(0, 0, 100)
        ;EndIf
      If soundOn
      If ExamineWorldCollisions(#True) ; get also contacts
                
        While NextWorldCollision()
          
          If FirstWorldCollisionEntity() = EscapeGear And SecondWorldCollisionEntity() = pendulum\pendulum
            If chaosTime2.f >= 600
              PlaySound(0, 0, 100)
              chaosTime.f = ElapsedMilliseconds()
              
            EndIf
          chaosTime2.f = ElapsedMilliseconds() - chaosTime  
          EndIf
          
        Wend
        
      EndIf
    EndIf
    
    
      
      RenderWorld()
      ;Screen3DStats()
      FlipBuffers()
      
       If oneSecond = 0 
      tm2.f = ElapsedMilliseconds()
      If (tm2-tm) >= 1000 ; after 1 second enable the collison
        ;enable the collision for the green big gear
        SetEntityAttribute(Gear2, #PB_Entity_DisableContactResponse, 0)
        SetEntityAttribute(pendulum\pendulum, #PB_Entity_DisableContactResponse, 0)
        SetEntityAttribute(EscapeGear, #PB_Entity_DisableContactResponse, 0)
                
        
        oneSecond =1 
        
      EndIf
    EndIf
    
    
    If soundOn:StopSound(0,#PB_All):EndIf
    ;StopSound3D(0)
    ;Delay(1)
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
    
  EndIf
  
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
End


Procedure Gear_Make()
 ;the big gear made from 60 teeth
  CreateCylinder(101, 3, 0.2 , 3, 1, 1)
  For i=101 To 120
    
    CreateEntity(i, MeshID(101),MaterialID(5),  0, 0, 0)
    RotateEntity(i, 0,90+rot,0, #PB_Absolute)
    rot+6 ; note that 360/60 = 6 degree between each 2 teeth
    If i = 101
      SetEntityMaterial(101, MaterialID(8))
      MoveEntity(101, 0,-0.01, 0)
    EndIf
    
    AddSubEntity(Gear2, i, #PB_Entity_StaticBody) 
  Next
  RotateEntity(Gear2, 90,0,0)
  
    
EndProcedure

Re: Pendulum Clock simulation

Posted: Wed Jun 22, 2016 7:00 pm
by Comtois
applePi wrote: there is no mention about #PB_Entity_ConvexHullBody , may be will be added in the future especially with AddSubEntity()
I forgotten it :oops:

Added 'Size' for ConvexHullBody for next release

About doc for AddSubEntity(), here is a quick help :
AddSubEntity(#Entity, #SubEntity, Type, OffsetX, OffsetY, OffsetZ, SizeX, SizeY, SizeZ, AxisX, AxisY, AxisZ)
OffsetX, OffsetY, OffsetZ = Translate body
SizeX, SizeY, SizeZ = Body's Size
If SizeX = -1 --> use BoundingBox Else use SizeX, SizeY And sizeZ
AxisX, AxisY, AxisZ = Body's Orientation