physique - Helicoptere

Généralités sur la programmation 3D
Avatar de l’utilisateur
Guillot
Messages : 529
Inscription : jeu. 25/juin/2015 16:18

physique - Helicoptere

Message 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()
Dernière modification par Guillot le mar. 30/avr./2019 9:34, modifié 2 fois.
Avatar de l’utilisateur
SPH
Messages : 4726
Inscription : mer. 09/nov./2005 9:53

Re: physique - Helicoptere

Message par SPH »

Je ne veux pas etre l'empecheur de tourner en rond mais... ca marche pas... :|
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: physique - Helicoptere

Message par falsam »

simulateur low-cost mais génial. Merci

Testé avec 5.70 LTS (x64)
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: physique - Helicoptere

Message 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()
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
Guillot
Messages : 529
Inscription : jeu. 25/juin/2015 16:18

Re: physique - Helicoptere

Message 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
Avatar de l’utilisateur
Guillot
Messages : 529
Inscription : jeu. 25/juin/2015 16:18

Re: physique - Helicoptere

Message 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 ?
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: physique - Helicoptere

Message 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 ?
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
Guillot
Messages : 529
Inscription : jeu. 25/juin/2015 16:18

Re: physique - Helicoptere

Message par Guillot »

cool
Avatar de l’utilisateur
SPH
Messages : 4726
Inscription : mer. 09/nov./2005 9:53

Re: physique - Helicoptere

Message par SPH »

Guillot a écrit :vous pouvez confirmer ?
Ca marche :idea:
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: physique - Helicoptere

Message 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.
Avatar de l’utilisateur
Guillot
Messages : 529
Inscription : jeu. 25/juin/2015 16:18

Re: physique - Helicoptere

Message 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 !
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: physique - Helicoptere

Message 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).
Répondre