Page 1 sur 1

physique - Helicoptere

Publié : mer. 24/avr./2019 21:15
par Guillot
un simulateur d'helico mini budget
mais à peu pres réaliste d'un point de vu physique
pour les commandes cf titre de la fenêtre
(au niveau des ombres, vous étonnez pas, ça foire (j'ai pas encore trouvé pourquoi) )

EDIT 25/04/2019
ajout des parametres optionnels pour CreateCone(1,0.3,3.5,16,1)


EDIT 30/04/2019
ombres ok
simplification
plus de tremblement (avec la physique il faut fixer le nombre de millisecondes avec RenderWorld (16))

Code : Tout sélectionner

;Physics - Helicopter - Pf Shadoko - 2019

EnableExplicit

Structure Vector3
  x.f
  y.f
  z.f
EndStructure

Structure PB_MeshVertexV  
  p.vector3
  n.vector3
  t.vector3
  u.f
  v.f
  color.l
EndStructure

Macro vec3d(v,vx,vy,vz)
  v\x=vx
  v\y=vy
  v\z=vz
EndMacro

Macro sub3D(p,p1,p2)
  p\x=p1\x-p2\x
  p\y=p1\y-p2\y
  p\z=p1\z-p2\z
EndMacro

Macro mul3d(p1,v)
  p1\x*(v)
  p1\y*(v)
  p1\z*(v)
EndMacro

Procedure.f POM(v.f)
  ProcedureReturn (Random(v*1000)-v*500)/500
EndProcedure

Procedure perlinarray2d(Array pa.f(2),rnd,periode,amplitude.f=1)
  Protected i,ii,dx=ArraySize(pa(),1),ddx=dx/periode,
            j,jj,dy=ArraySize(pa(),2),ddy=dy/periode
  Protected.f x,y,y0,y1,wx,wy
  
  RandomSeed(rnd)
  Dim t.f(ddx+1,ddy+1)
  For i=0 To ddx:For j=0 To ddy:t(i,j)=pom(amplitude):Next:Next
  For i=0 To ddx+1:t(i,ddy+1)=t(i,0):Next
  For j=0 To ddy+1:t(ddx+1,j)=t(0,j):Next
  
  For jj=0 To ddy
    For ii=0 To ddx
      For i=0 To periode-1
        x=i/periode
        wx=x*x*(3-2*x)
        For j=0 To periode-1
          y0=t(ii+1,jj  )*wx+t(ii,jj  )*(1-wx)
          y1=t(ii+1,jj+1)*wx+t(ii,jj+1)*(1-wx)
          y=j/periode
          wy=y*y*(3-2*y)
          pa(ii*periode+i,jj*periode+j)=y1*wy+y0*(1-wy)
        Next
      Next
    Next
  Next
EndProcedure

Procedure AddMesh(mesho,Mesh,mat, NewX.f=0 , NewY.f=0, NewZ.f=0, ScaleX.f=1, ScaleY.f=1, ScaleZ.f=1, RotateX.f=0, RotateY.f=0, RotateZ.f=0)
  Protected Dim MeshDataV.PB_MeshVertex(0)
  Protected Dim MeshDataF.PB_MeshFace(0)
  Protected i,meshc
  
  meshc=CopyMesh(mesh,-1)
  TransformMesh(Meshc, NewX,NewY,NewZ, ScaleX,ScaleY,ScaleZ, RotateX,RotateY,RotateZ)
  GetMeshData(Meshc,0, MeshDataV(), #PB_Mesh_Vertex |#PB_Mesh_Color | #PB_Mesh_UVCoordinate| #PB_Mesh_Normal, 0, MeshVertexCount(Meshc, 0)-1)
  GetMeshData(Meshc,0, MeshDataF(), #PB_Mesh_Face, 0, MeshIndexCount(Meshc, 0)-1)
  FreeMesh(meshc) 
  
  AddSubMesh()
  For i=0 To ArraySize(MeshDataV())
    With MeshDatav(i)
      MeshVertex(\x,\y,\z,\u,\v,$ffffff,\NormalX,\NormalY,\NormalZ)
    EndWith
  Next     
  For i=0 To ArraySize(MeshDataF()) Step 3
    MeshFace(MeshDataF(i)\Index, MeshDataF(i+1)\Index,MeshDataF(i+2)\Index)
  Next
  If mat>=0:SetMeshMaterial(mesho, MaterialID(mat), SubMeshCount(mesho)-1):EndIf
EndProcedure

;##########################################################################################################################################################
Global ex,ey,h.f

Procedure matiere(num,dx,dy,c1,c2, brillance=$888888,alpha=0,scale.f=1)
  CreateTexture(num,dx,dy)
  StartDrawing(TextureOutput(num))
  If alpha:DrawingMode(#PB_2DDrawing_AllChannels):EndIf
  Box(0,0,dx,dy,c2)
  Box(2,2,dx-4,dy-4,c1) 
  StopDrawing()
  CreateMaterial(num, TextureID(num))
  MaterialFilteringMode(num,#PB_Material_Anisotropic,4)
  ScaleMaterial(num,scale,scale)
  If brillance:SetMaterialColor(num, #PB_Material_SpecularColor, brillance):MaterialShininess(num, 40):EndIf
  If alpha:MaterialBlendingMode(num,#PB_Material_AlphaBlend):EndIf
EndProcedure

Procedure mesh_terrain(mesh,n) 
  Protected.f h, vx, vy
  Protected i,j,dt=4,n2=n/2
  Dim pa.f(n-1,n-1)
  
  perlinarray2d(pa(),0,8,16)
  
  Dim t.PB_MeshVertexV(n,n)
  RandomSeed(0)
  For j=0 To n
    For i=0 To n
      With t(i,j)  
        \p\x=(i-n2)*4
        \p\z=(j-n2)*4
        \p\y=pa(i & (n-1),j & (n-1))+8:If \p\y<0:\p\y=0:EndIf
        \u=i
        \v=j
        \color=$ffffff
      EndWith 
    Next
  Next
  CreateDataMesh(mesh,t())
  NormalizeMesh(mesh);UpdateMeshBoundingBox(mesh);BuildMeshShadowVolume(mesh)
EndProcedure

Procedure Init()
  Protected i
  InitEngine3D():InitSprite():InitKeyboard():InitMouse()
  
  OpenWindow(0, 0, 0, 800,600, "",#PB_Window_Maximize|#PB_Window_BorderLess)
  ex=WindowWidth (0,#PB_Window_InnerCoordinate)
  ey=WindowHeight(0,#PB_Window_InnerCoordinate)
  OpenWindowedScreen(WindowID(0), 0, 0, ex, ey, 0, 0, 0)
  LoadFont(0,"arial",12)
  
  EnableWorldPhysics(#True)
  EnableWorldCollisions(#True)
  WorldGravity(-10)
  
  CreateCamera(0, 0, 0, 100, 100):MoveCamera(0,0,10,-20)
  CameraBackColor(0,$ff8888) 
  
  CreateLight(0,$888888, 1000,1000,0):SetLightColor(0, #PB_Light_SpecularColor, $ffffff)
  AmbientColor($444444)  
  
  ; -------------------- terrain
  matiere(0,256,256,$ff448888,$ff88cccc,0)
  mesh_terrain(100,256)
  CreateEntity(100,MeshID(100),MaterialID(0)):CreateEntityBody(100,#PB_Entity_StaticBody,1,0,1)
  EntityRenderMode(100,0)
  matiere(1,256,256,$aaaaaa,$ffffff,0,0,0.25)
  CreateCylinder(101,5,1,32,1,1)
  CreateEntity(101,MeshID(101),MaterialID(1)):CreateEntityBody(101,#PB_Entity_StaticBody,1,0,1)
  
  ; -------------------- helico
  CreateMesh(0)
  matiere(10,256,256,$88444444,$88444444,$ffffff,1)
  CreateSphere(1,0.75):AddMesh(0,1,10,0,0,0.5, 0.8,1,1.4)
  matiere(11,256,256,$ff0000ff,$8888ff,$ffffff,0,4)
  CreateCone(1,0.3,3.5,16,1):AddMesh(0,1,11,0,0,-1.8,0.8,1,1,-90,0,0)
  matiere(12,256,256,$00ffff,$88ffff,$88ffff,0,4)
  CreateCapsule(1,0.15,1.5):AddMesh(0,1,12,0.6,-1,0,1,1,1,90,0,0):AddMesh(0,1,12,-0.6,-1,0,1,1,1,90,0,0)
  FinishMesh(1):NormalizeMesh(0);UpdateMeshBoundingBox(0);BuildMeshShadowVolume(0)
  CreateEntity(0, MeshID(0), #PB_Material_None,0,1.2+0.5,0):CreateEntityBody(0, #PB_Entity_ConvexHullBody ,10, 0.0,0.3);EntityRenderMode(0, 0)
  SetEntityAttribute(0,#PB_Entity_LinearSleeping,0)
  ; rotor principal
  matiere(13,256,256,$444444,$444444)
  CreateCapsule(2, 0.05,1):TransformMesh(2,0,0,0,1,6,2,0,0,90):NormalizeMesh(2):UpdateMeshBoundingBox(2);:BuildMeshShadowVolume(2)
  CreateEntity(2, MeshID(2), MaterialID(13),0,1,0) 
  AttachEntityObject(0,"",EntityID(2))
  ; rotor arriere
  CreateCapsule(3, 0.05,1):TransformMesh(3,0,0,0,0.5,1,1,0,0,0):NormalizeMesh(3);:BuildMeshShadowVolume(3)
  CreateEntity(3, MeshID(3), MaterialID(13),0.1,0,-3.5)  
  AttachEntityObject(0,"",EntityID(3))
  
  WorldShadows(#PB_Shadow_Additive); use #PB_Shadow_Modulative if it lags
  ;WorldDebug(#PB_World_DebugBody)
EndProcedure

Procedure menu()
  Protected p=4
  Macro DT(t1,t2="")
    DrawText(8,p,t1)
    DrawText(100,p,t2)
    p+20
  EndMacro
  CreateSprite(0,180,108,#PB_Sprite_AlphaBlending)
  StartDrawing(SpriteOutput(0))
  DrawingMode(#PB_2DDrawing_AllChannels)
  DrawingFont(FontID(0))
  Box(0,0,OutputWidth(),OutputHeight(),$44000000)
  DrawingMode(#PB_2DDrawing_AllChannels|#PB_2DDrawing_Outlined)
  Box(0,0,OutputWidth(),OutputHeight(),$44ffffff)
  BackColor($44000000)
  FrontColor($ffffffff)
  dt("Controls:")
  dt("Arrow keys + Mouse")
  dt("[Pad 0-1]","Engine")
  dt("[F1]","Camera")
  dt("[Esc]","Quit")
  StopDrawing()
EndProcedure

Procedure stabilise(entity,f.f)
  Protected.f x,y,z
  x=GetEntityAttribute(entity,#PB_Entity_AngularVelocityX)
  y=GetEntityAttribute(entity,#PB_Entity_AngularVelocityY)
  z=GetEntityAttribute(entity,#PB_Entity_AngularVelocityZ)
  ApplyEntityTorque(entity,-x*f,-y*f,-z*f,#PB_World )
EndProcedure

Procedure affiche3d()
  Protected i,ii,j,c,l,dis=1,vdis=1<<dis-1,shadows
  Protected.f inclx,inclz,  droty,rotp,rota,fportance,decx,decz,cx=3,alt=1+1.2-1
  Protected.vector3 apos,pos,vit,ftrainee
  
  Macro KBdep(k1,k2):(Bool(KeyboardPushed(k1))-Bool(KeyboardPushed(k2))) :EndMacro
  
  menu()
  MouseLocate(ex/2,ey/2)
  Repeat 
    WindowEvent()
    ExamineMouse()
    ExamineKeyboard()
    If KeyboardReleased(#PB_Key_F1):dis=(dis+1)%3:vdis=1<<dis-1:EndIf
    
    ; info: position, vitesse, inclinaison x/z
    apos=pos
    vec3d(pos,EntityX(0),EntityY(0),EntityZ(0))
    sub3d(vit,pos,apos):mul3d(vit,60)
    ConvertLocalToWorldPosition(EntityID(0),1,0,0):inclx=EntityY(0)-GetY()
    ConvertLocalToWorldPosition(EntityID(0),0,0,1):inclz=EntityY(0)-GetY()
    
    ; portance
    alt+KBdep(#PB_Key_Pad1,#PB_Key_Pad0)*0.1
    fportance=100-(pos\y-alt+vit\y)*20
    decx-KBdep(#PB_Key_Left,#PB_Key_Right)*0.1+inclx*0.2:decx*0.9
    decz+KBdep(#PB_Key_Down,#PB_Key_Up   )*0.12+inclz*0.2:decz*0.9
    ApplyEntityForce(0, 0,fportance,0,decx,1,decz,#PB_Local )
    
    ; rotation
    droty-MouseDeltaX()*0.4:droty*0.9
    ApplyEntityTorque(0, 0,droty,0,#PB_Local) 
    
    ; trainée
    ftrainee=vit:mul3d(ftrainee,-cx)
    ApplyEntityForce(0,ftrainee\x,ftrainee\y,ftrainee\z)
    
    stabilise(0,100)
    
    rotp=fportance/5:RotateEntity(2,0,rotp,0,#PB_Relative)
    rota=fportance/5:RotateEntity(3,rota,0,0,#PB_Relative)
    
    CameraFollow(0, EntityID(0), -180,EntityY(0)+vdis, 6*vdis+0.1, 0.05, 1)
    RenderWorld(16)
    DisplayTransparentSprite(0,8,8)
    FlipBuffers() 
  Until KeyboardPushed(#PB_Key_Escape)
EndProcedure

init()
affiche3d()

Re: physique - Helicoptere

Publié : mer. 24/avr./2019 21:20
par SPH
Je ne veux pas etre l'empecheur de tourner en rond mais... ca marche pas... :|

Re: physique - Helicoptere

Publié : mer. 24/avr./2019 21:27
par falsam
simulateur low-cost mais génial. Merci

Testé avec 5.70 LTS (x64)

Re: physique - Helicoptere

Publié : jeu. 25/avr./2019 11:05
par comtois
Faut tester avec quelle version ?

ça ne marche pas chez moi avec la 5.70 LTS x86

J'ai ajouté un debug "1" à la fin de la procédure init() , pas de souci il s'affiche bien
Par contre j'ai ajouté un debug "2" juste après l'appel de la procédure init(), rien ne s'affiche, le prog est bloqué.
Si je désactive le débogueur le programme ne se lance pas (je ne vois même pas la fenêtre s'ouvrir)

[EDIT]
Je viens de retester avec le sous système opengl , c'est pareil.
J'ai écrit une connerie tout à l'heure, la fenêtre s'affiche bien même avec le débogueur désactivé, et se ferme après quelques secondes.

Code : Tout sélectionner

init()
debug "2"
affiche3d()

Re: physique - Helicoptere

Publié : jeu. 25/avr./2019 14:32
par Guillot
tester sur x64

ouai, sur x86, c'est tres curieux, il plante à la sortie de la procedure init

si je commente la ligne 166 (CreateCone...), ça marche
y'a peut etre une boulette dans la fonction CreateCone

Re: physique - Helicoptere

Publié : jeu. 25/avr./2019 15:58
par Guillot
ajout des parametres optionnels pour CreateCone (ligne 166)
CreateCone(1,0.3,3.5,16,1)
chez moi, ça corrige le plantages sur x86
vous pouvez confirmer ?

Re: physique - Helicoptere

Publié : jeu. 25/avr./2019 16:01
par comtois
Ok ça fonctionne avec le nouveau code.

Super la démo.

Concernant CreateCone() y'a effectivement une erreur dans le code (faut enlever les 2 derniers paramètres à CreateCone()) , elle est peut-être aussi dans le wrap de Fred ?

Re: physique - Helicoptere

Publié : jeu. 25/avr./2019 16:15
par Guillot
cool

Re: physique - Helicoptere

Publié : jeu. 25/avr./2019 16:48
par SPH
Guillot a écrit :vous pouvez confirmer ?
Ca marche :idea:

Re: physique - Helicoptere

Publié : jeu. 25/avr./2019 21:01
par Ollivier
Sans pouvoir tester, j'ai regardé le code : la précession m'intéressait et ça semble bien représenté. Pense à rajouter de l'inertie au rotor. Quand tu atterris trop vite tangué en arrière, le rotor vient (dans la réalité) découper la queue.

Re: physique - Helicoptere

Publié : mar. 30/avr./2019 9:58
par Guillot
EDIT 30/04/2019
ombres ok
simplification
plus de tremblement (avec la physique il faut fixer le nombre de millisecondes avec RenderWorld (16))


à Olivier :
l'inertie c'est le moteur physique qui s'en charge, mais on gere pas le softbody (corps deformable)
donc pas de risque de se faire couper la queue !

Re: physique - Helicoptere

Publié : mar. 30/avr./2019 12:25
par Ollivier
Surtout que c'est une inertie "faussée" : c'est de la gyroscopie. Plus le rotor tourne, plus il faut de force pour dévier sa course, tout comme pour ralentir sa déviation (mot inexact). Ça s'apparente à une inertie variable en fonction de la vitesse du rotor.

La gyroscopie peut donc être fatale. Mais c'est aussi un plan virtuel sur lequel elle s'applique. Et c'est par rapport à ce plan que se contraint la nutation. Nutation, qui est un effet dûe à une contrainte trop importante de "déviation" du rotor. Cette contrainte est absorbée et répartie de façon périodique jusqu'à nullité.

Donc suite à un choc trop violent, le rotor peut "résonner" et créer de rares "miracles" en évitant la queue, alors qu'un choc bien plus faible entraine la destruction. Question de synchro et de coïncidence (angle de départ du choc par rapport à la queue).