PureBasic
;
; ------------------------------------------------------------
;
;   PureBasic - Pendulum waves experiment
;
;    (c) Fantaisie Software
;
; ------------------------------------------------------------
; Спасибо kelebrindae за этот хороший код.

#PB_Material_AmbientColor  = 2 

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

#CameraSpeed = 0.4

If InitEngine3D()
  
  InitSprite()
  InitKeyboard()
  InitMouse()

  
  If Screen3DRequester()
     
    ; Текстуры
    ;
    CreateTexture(0, 128, 128)
    StartDrawing(TextureOutput(0))
      Box(0, 0, 128, 128, $FFFFFF)
      StopDrawing()
      
    CreateTexture(1, 128, 128)    
    StartDrawing(TextureOutput(1))
      Box(0, 0, 128, 128, $000000)
      Box(0, 0, 64, 64, $BBBBBB)
      Box(64, 64, 64, 64, $BBBBBB)
    StopDrawing()
    
    ; Материалы
    ;
    CreateMaterial(1, TextureID(1))
    SetMaterialColor(1, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
    CreateMaterial(2, TextureID(0))
    SetMaterialColor(2, #PB_Material_AmbientColor, $D0B86B)
    CreateMaterial(3, TextureID(0))
    SetMaterialColor(3, #PB_Material_AmbientColor, $0077FF)
    
    ; Сущности
    ;
    CreatePlane(1, 40, 40, 20, 20, 15, 15)
    sol = CreateEntity(#PB_Any, MeshID(1), MaterialID(1))
    CreateEntityBody(sol, #PB_Entity_StaticBody)   
    
    CreateCube(2, 1)
    support = CreateEntity(#PB_Any, MeshID(2), MaterialID(3))
    ScaleEntity(support, 20, 0.3, 0.3)
    MoveEntity(support, 0, 10, 0, #PB_Absolute)
    CreateEntityBody(support, #PB_Entity_StaticBody)   
    
    support2 = CreateEntity(#PB_Any, MeshID(2), MaterialID(3))
    ScaleEntity(support2, 0.4, 12, 0.4)
    RotateEntity(support2, 30, 0, 0)
    MoveEntity(support2, 10, 5, -3, #PB_Absolute)
    CreateEntityBody(support2, #PB_Entity_StaticBody)   
    
    support3 = CreateEntity(#PB_Any, MeshID(2), MaterialID(3))
    ScaleEntity(support3, 0.4, 12, 0.4)
    RotateEntity(support3, -30, 0, 0)
    MoveEntity(support3, 10, 5, 3, #PB_Absolute)
    CreateEntityBody(support3, #PB_Entity_StaticBody)   
    
    support4 = CreateEntity(#PB_Any, MeshID(2), MaterialID(3))
    ScaleEntity(support4, 0.4, 12, 0.4)
    RotateEntity(support4, 30, 0, 0)
    MoveEntity(support4,-10,5,-3, #PB_Absolute)
    CreateEntityBody(support2, #PB_Entity_StaticBody)   
    
    support5 = CreateEntity(#PB_Any, MeshID(2), MaterialID(3))
    ScaleEntity(support5, 0.4, 12, 0.4)
    RotateEntity(support5, -30, 0, 0)
    MoveEntity(support5, -10, 5, 3, #PB_Absolute)
    CreateEntityBody(support5, #PB_Entity_StaticBody)   
    
    ; Маятники
    #NBPENDULUM = 16
    Global Dim sph.i(#NBPENDULUM + 1)
    Global position.f, stringLength.f
    CreateSphere(3, 0.5)
    For i=1 To #NBPENDULUM
      
      stringLength = 980.6 * Pow(15 / ( 2 * #PI * (24 + i) ), 2)
      position = -9.3 + i * 1.10
      
      ; Создать сферу
      sph(i) = CreateEntity(#PB_Any, MeshID(3), MaterialID(2))
      MoveEntity(sph(i), EntityX(support) + position, EntityY(support) - stringLength,EntityZ(support), #PB_Absolute)
      CreateEntityBody(sph(i), #PB_Entity_SphereBody)   
      
      ; Прикрепите опору и сферу
      PointJoint(#PB_Any, EntityID(support), position, 0, 0, EntityID(sph(i)), 0, stringLength, 0)
      CreateLine3D(100 + i, EntityX(support) + position, EntityY(support), EntityZ(support), $77FF00, EntityX(sph(i)), EntityY(sph(i)), EntityZ(sph(i)), $77FF00)
      
      ; Осторожно нажмите на сферу
      ApplyEntityImpulse(sph(i),0,0,4)
    Next 
    
    ; Камера
    ;
    CreateCamera(0, 0, 0, 100, 100)
    MoveCamera(0, 0, 12, 20, #PB_Absolute)
    CameraLookAt(0, 0, 5, 0)
    
    ; Свет
    ;
    AmbientColor(RGB(105, 105, 105))
    CreateLight(0,RGB(160, 160, 255), 0, 300, 0)
    WorldShadows(#PB_Shadow_Additive)
    
    
    ; - Главный цикл
    angle.f = 0
    angle2.f = 0
        
    Repeat
      Screen3DEvents()
      
      ;- F1, F2 : Сменить вид
      If ExamineKeyboard()
        If KeyboardReleased(#PB_Key_F2)
          MoveCamera(0, -15, 2.5, 0, #PB_Absolute)
          CameraLookAt(0, 0, 3, 0)
        EndIf
        If KeyboardReleased(#PB_Key_F3)
          MoveCamera(0, 0, 12, 20, #PB_Absolute)
          CameraLookAt(0, 0, 5, 0)
        EndIf
        
        ; - Возврат: Показать FPS
        If KeyboardReleased(#PB_Key_Return)
          MessageRequester("Инфо", "FPS = " + Str(Engine3DStatus(#PB_Engine3D_AverageFPS)))
        EndIf
        
      EndIf
      
      ; Перерисовать line3D, чтобы понять строки.
      For i=1 To #NBPENDULUM
        position = -9.3 + i * 1.10
        CreateLine3D(100 + i, EntityX(support) + position, EntityY(support), EntityZ(support), $77FF00, EntityX(sph(i)), EntityY(sph(i)), EntityZ(sph(i)), $77FF00)
      Next i
      
      RenderWorld()
      Screen3DStats()
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
  
Else
  MessageRequester("Ошибка", "3D Движок не может быть инициализирован", 0)
EndIf