Page 1 sur 1

Gravitation d'un personnage sur une mesh.

Publié : lun. 10/août/2009 15:47
par guerrier001
Salut tout le monde, j'ai encore un problème qui est a moitié régler. Mon personnage gravite sur une mapheight(terrain vu de haut) et moi je voudrait qu'il gravite sur une mesh. Aidez moi, merci. Voila le code:

Code : Tout sélectionner

;-Include Files
IncludePath "Include\"  :   IncludeFile "dreamotion3d.pbi"

Declare FrameFind( *pframe.D3DXFRAME , *frame.D3DXFRAME)
;-Globales
Global   anglex.f, angley.f, flagXDown.w
Global   mox.f, omx.f, moy.l, omy.l, PlayerSpeed.l
Global   mFar.f, hh.f


  Global   *camera.CEntity
  Global *texture.CTexture
  Global   *font.CFont
  Global Dim *tiny.CAnimX(30)
  Global Quit.b
   Global  i.l, flag.l
  Global  tab.l=0, *tFrame.D3DXFRAME
 
     Structure BULLET
    *mesh.CMesh
    pos.D3DXVECTOR3

  EndStructure
  Global Dim ball.BULLET(128)
  Global num_ball.l=0
 
Procedure MON_JEU()
    DM_InitPhysic()
  ;-Init PB modules
  If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
    End
  EndIf

  ;-set graphic window 3D
  DM_Graphics3D(800,600, 32,  0, 1)
  ;-load font
  *font = DM_LoadFont( "Tahoma",9 , 0)
  DM_TextColor(*font, 198,198,198,255)
  ;-change directory for media
  SetCurrentDirectory("media/")
 
  ;-Set ambient color
  DM_AmbientLight(250,  250,  250)
  DM_CreateLight(3)

PlayerSpeed = 5
  ; ---------------------------------------
  ;-a little skybox, well here a skydome must be define in first
  ;
  ; ---------------------------------------
  *sky.CSkySphere = DM_LoadSkySphere("grassenvmap1024.dds", 50)
  DM_TranslateEntity(*sky, 0,-10,0)



  DM_TextureMipLevel( 0 )
  ; ---------------------------------------
       ;-create terrain with terrain engine
  ;    
  ; ---------------------------------------
  ;-create base terrain with heightmap "map.jpg"
  *terrain = DM_CreateTerrain("Height113.bmp", 1.5, #False)
  *brush = DM_CreateBrush("terrain")
  DM_LoadTexture("sol113.jpg", DM_GetTexture(*brush))
  DM_LoadTexture("detail3.bmp", DM_GetTexture(*brush,1))
  DM_PaintTerrain(*terrain, *brush )
  DM_FreeBrush(*brush)  
  mFar=800.0

*sphere = DM_LoadAnimMesh("tiger.x")
DM_TranslateEntity(*sphere, 0,20,90)

  *tiny  = DM_LoadAnimMesh("bones_all.x")
  DM_ScaleEntity(*tiny, 13,13,13)
  DM_AnimateSpeed(*tiny, 0.01)
  DM_RotateEntity(*tiny, 0,225,0)


 *cube = DM_CreateCube()
 *frame.l = DM_AnimateFindChild(*tiny, "R_hand")
 DM_FrameChild(*tiny, *frame, *cube )


  ; ---------------------------------------
            ;-create camera
  ; ---------------------------------------
  *camera   = DM_CreateCamera(800,600,*tiny)
  DM_MoveEntity(*camera, 0,2,4)
  DM_TurnEntity(*camera, 10,180,0)
  DM_CameraClsColor(*camera, 125, 125, 125)
  DM_CameraProjRatio(*camera, 800,600, mFar)


  ; ---------------------------------------
             ;-main loop
  ; ---------------------------------------
  ;-if fullscreen, must do it for keep mouse cursor
  ;-change_curseur( #IDC_ARROW  )
  Repeat
         ExamineMouse()
        If flagXdown=0

           flagXDown=11
        Else
           moy = MouseDeltaY()/10*PlayerSpeed/2
          
         
           mox = MouseDeltaX()/10*PlayerSpeed/2
          
          
          DM_TurnEntity(*tiny, 0,mox,0)


        EndIf
        
       ExamineKeyboard()

     ;-if Escape Key, exit
     If KeyboardReleased(#PB_Key_Escape) Or WindowEvent()=#PB_Event_CloseWindow
       Quit=1
     EndIf

        If KeyboardReleased(#PB_Key_Space)
    ball(num_ball)\mesh = DM_CreateSphere(32)
    num_ball+1
    DM_PositionEntity( ball(i)\mesh, DM_EntityX(*cube), DM_EntityY(*cube), DM_EntityZ(*cube))
      alpha.f = DM_EntityYaw(*tiny)
      DM_RotateEntity(ball(i)\mesh, 0, alpha, 0)              
  EndIf
  If(num_ball)
     For i=0 To num_ball-1
       DM_MoveEntity( ball(i)\mesh, 0,0,-5)
     Next
  EndIf
(DM

  
      h.f = DM_GetTerrainHeight(*terrain, DM_EntityX(*tiny), DM_EntityZ(*tiny))

    If KeyboardPushed(#PB_Key_Down)
        DM_AnimateIndex(*tiny, 1)
      DM_MoveEntity(*tiny, 0,0,4)
      DM_PositionEntity(*tiny, DM_EntityX(*tiny), h+5, DM_EntityZ(*tiny))
    EndIf
          If KeyboardReleased(#PB_Key_Down)
      DM_AnimateIndex(*tiny, 0)
            DM_MoveEntity(*tiny, 0,0,0)
      DM_PositionEntity(*tiny, DM_EntityX(*tiny), h+5, DM_EntityZ(*tiny))
    EndIf
    If KeyboardPushed(#PB_Key_Up)
        DM_AnimateIndex(*tiny, 1)
      DM_MoveEntity(*tiny, 0,0,-4)
      DM_PositionEntity(*tiny, DM_EntityX(*tiny), h+5, DM_EntityZ(*tiny))
    EndIf
      If KeyboardReleased(#PB_Key_Up)
      DM_AnimateIndex(*tiny, 0)
            DM_MoveEntity(*tiny, 0,0,0)
      DM_PositionEntity(*tiny, DM_EntityX(*tiny), h+5, DM_EntityZ(*tiny))
    EndIf

  If KeyboardPushed(#PB_Key_Right)
    DM_TurnEntity(*tiny, 0,1,0)
  EndIf

  If KeyboardPushed(#PB_Key_Left)
    DM_TurnEntity(*tiny, 0,-1,0)
  EndIf


      h.f = DM_GetTerrainHeight(*terrain, DM_EntityX(*sphere), DM_EntityZ(*sphere))

    If KeyboardPushed(#PB_Key_S)
      DM_MoveEntity(*sphere, 0,0,4)
      DM_PositionEntity(*sphere, DM_EntityX(*sphere), h+5, DM_EntityZ(*sphere))
    EndIf
          If KeyboardReleased(#PB_Key_S)
            DM_MoveEntity(*sphere, 0,0,0)
      DM_PositionEntity(*sphere, DM_EntityX(*sphere), h+5, DM_EntityZ(*sphere))
    EndIf
    If KeyboardPushed(#PB_Key_W)
      DM_MoveEntity(*sphere, 0,0,-4)
      DM_PositionEntity(*sphere, DM_EntityX(*sphere), h+5, DM_EntityZ(*sphere))
    EndIf
      If KeyboardReleased(#PB_Key_W)
            DM_MoveEntity(*sphere, 0,0,0)
      DM_PositionEntity(*sphere, DM_EntityX(*sphere), h+5, DM_EntityZ(*sphere))
    EndIf
    
  If KeyboardPushed(#PB_Key_D)
    DM_TurnEntity(*sphere, 0,1,0)
  EndIf

  If KeyboardPushed(#PB_Key_A)
    DM_TurnEntity(*sphere, 0,-1,0)
  EndIf
     ; ---------------
           ;-Render
     ; ---------------
           If flag=0 : DM_UpdateWorld() : EndIf
     DM_BeginScene()
       DM_RenderWorld(*camera)
        ;-draw some informations
        DM_DrawText(*font, 10, 15, "FPS: "+Str(DM_FPS()))  
     DM_EndScene()
  Until quit=1
  ;-end
  DM_ClearGraphics()
 
EndProcedure
 
  Procedure FrameFind( *pframe.D3DXFRAME , *frame.D3DXFRAME)
  Protected a$
 
  a$=Space(tab)
  Repeat
    *frame = DM_AnimateGetChild(*tiny, *pframe, *frame)
    If *frame
      Debug a$+DM_AnimFrameName(*frame)
      tab+3
      FrameFind(*frame, #Null)
    EndIf
  Until *frame=#Null
  tab-3
 
EndProcedure

Publié : ven. 14/août/2009 4:20
par Ollivier
Le problème c'est que vu que tu t'es lancé dans DreamMotion3D, ça restreind le nombre de personnes qui peuvent te filer un coup de main! Et vu que c'est les vacances, je crois même que ça annule momentanément le nombre de personnes qui peuvent te filer un coup de main...

Publié : ven. 14/août/2009 13:30
par guerrier001
J'attendrais septembre alors ^_^

Publié : dim. 16/août/2009 1:17
par Anonyme
pas besoin , il te faut quelque notions de Vecteur 3D et connaitre l'utilisation des fonction physique du moteur.

Le principe est simple :

Imagine que tu as une sphère qui represente la planete avec comme vecteur de position 100,200,150

et que tu as un objet à soumettre à la gravité qui se trouve à 250,320,450


Il te faut dans un premier temps , désactivé la gravité de base dans le moteur.
Tu connais ensuite la position ( vecteur3 ) de ton objet qui attire les autres.
La gravité est une sorte de Dégradé , plus t'es loin , moins tu est attiré.
Donc on en déduis que la gravité vaut 1 à la position de l'objet [100,200,150]
Mais combien vaut la gravité à l'objet qui est en [250,320,450] ?
C'est simple , tu calcules la distance entre tes vecteurs :


x = A\x - B\x
y = A\y - B\y
z = A\z - B\z
Distance.f = sqr( (x * x) + (y * y) + (z * z) )

Dans notre cas Distance vaut environ 356.
il y a donc 356 unité qui sépare nos objets.
ensuite tu dois déterminer en fonction de ton choix la force d'attraction de ton objet qui attire les autres, ici on va dire 400.


On connais donc la position de tout les objets , la distance qui les sépare , la force. Vu la distance qui sépare les 2 objets , le second est attiré par l'attraction qui vaut 400 , mais comme l'attraction est progressive , il faut calculé , la force qui est soumis à cet objet.

un simple produit en croix inversé suffit.

donc à 400 unité de distance la gravité vaut 0
à 0 unité de distance la gravité vaut 1
à 200 unité la gravité vaut 0.5
etc...


on inverse :

400 vaut 1
0 vaut 0

notre produit en croix :

400 1
356 ?

356 * 1 / 400 = 0.89

on inverse encore une fois pour avoir la bonne valeur
Force_a_appliquer = 1 - 0.89 = 0.11


Tu connais la force qu'il faut appliqué à l'objet pour l'attirer vers l'autre. mais dans quelle direction ?

Pour connaitre la direction , c'est très simple

Resultat_Vector3 = PointViser_Vector3 - ObjetADiriger_Vector3
Tu normalizes le vecteur resultat , et tu as la direction de l'attraction

Pour avoir la bonne direction il est impératif de soustraire de cette maniere :
Cible - Position



se qui nous donne les valeurs suivantes :

X = -0.42107596993446
Y = -0.33686077594757
Z = -0.84215193986893



ensuite tu multiplie ton vecteur normalizé par la Force_a_appliquer
en gros , tu scales ton vecteur 3d par la force. se qui donne :

X = -0.046318356692790622
Y = -0.037054685354232723
Z = -0.092636713385582298


Tu récupères la position de ton objet , et tu additionne le resultat :

X = 250 + -0.046318356692790622
Y = 320 + -0.037054685354232723
Z = 450 + -0.092636713385582298

Maintenant :

X = 249.95368164330722
Y = 319.96294531464576
Z = 449.90736328661444

Ton objet se rapproche ! tu repetes l'opération tout le temps , car plus il se rapproche , plus il est soumis à la force d'attraction !
pour les collisions , tu laisses la main au moteur physique !

si le moteur physique te le permet , tu peut directement ajouté une force à l'objet , plus besoin donc de soustraire le resultat à la position.

je sais que tu n'a pas de notion de vecteur , néanmoins , je t'ai donné les pistes pour que tu cherches sur le net les opérations sur les vecteurs 3d
normalisation , echelle ( scale ) , addition , etc...
une fois que tu auras saisi le concept , plus rien ne t'échappera en 3D !

Publié : dim. 16/août/2009 1:57
par Ollivier
@Cpl.Bator

Ah... Moi, je croyais qu'il voulait tout ce qui touche les collisions conséquentes à l'attraction entre deux objets, et là c'est une belle galère.

Juste une toute petite correction pour le calcul de la force :
F = K * (M1 * M2) / (D * D)

K : c'est une constante
M1 : c'est la masse de l'un des deux objets
M2 : c'est la masse de l'autre objet
D : c'est la distance entre les deux objets

C'est Isaac Newton qui s'en est aperçu en se prenant une pomme en pleine poire.
Et Albert Einstein a remplacé la constante K par une autre équation bien trash en fonction des masses et de la distance aussi, mais comme je doute que Guerrier001 ne soit en train de modéliser des galaxies, des étoiles et des trous noirs, ça sert à rien que j'aille trop loin.

En tout cas, bien vu Cpl, j'allais le laisser galérer encore deux semaines!

Ollivier

Publié : dim. 16/août/2009 4:36
par Anonyme
c'est ce que j'allais répondre , il n'a pas parlé d'orbite ^^ je suppose que les vecteur 3d l'on envoyé sur l'orbite de pluton :D

Sinon , si tu veut appliqué la formule de newton , K ( je l'aurais appeler G ) vaut 9.8 pour la gravité terrestre.

Tu peut aussi utilisé la technique décrite plus haut pour faire des explosions , ta juste a inversé la force.

Publié : dim. 16/août/2009 5:39
par guerrier001
tu allais me laisser galerer pendant 2 semaine? tu veux mamort c'est ca ? bon merci cpl.bator je vais l'essayer demain. ollivier, la prochaine fois je t'envoie directent un mp. :lol: :lol:

Publié : dim. 16/août/2009 8:01
par tmyke
[APARTé]
Si je puis me permettre, tu aurais un certains intérêt de lacher DM3D (qui n'est plus maintenu pour PB),
et passer à N3xtD, la syntaxe générale ne te déroutera pas (très proche de celle de DM3D), et tu partiras sur un moteur 3D
mis à jour, plus complet et doté d'une certaine pérennité. ;)
[/APARTé]

Publié : dim. 16/août/2009 12:31
par guerrier001
Ok je vais l'essayer

Publié : dim. 16/août/2009 15:59
par Anonyme
Voila avec n3xtd un code brut :

Code : Tout sélectionner

IncludePath "includes"   :   IncludeFile "n3xtD_PB.pbi"


Global NewList Dynamic_body()
ExamineDesktops()
iSetAntiAlias(#True)
*app=iCreateGraphics3D(DesktopWidth(0),DesktopHeight(0),DesktopDepth(0), 0, #True, #EDT_OPENGL)
If *app= #Null
  End
EndIf

SetCurrentDirectory("media/") 

WSize = 10000
iSetWorldSize(-WSize,-WSize,-WSize,WSize,WSize,WSize)
iGravityForce(0,0,0)


*light = iCreateLight($FFFFFF,5000)
iPositionNode(*light,1000,500,500)
iAttenuationLight(*light, 1, 1.0/5000, 0)


*Cam = iCreateCamera()
iPositionNode(*Cam,150,150,150)
iPointTargetNode(*Cam,0,0,0)



Magnetic = iCreateSphere(100,60)
iSetCollideForm(#SPHERE_PRIMITIVE)
*body_Magnetic = iCreateBody(Magnetic,#False)





Procedure new_dynamic_body(x,y,z)
Mesh = iCreateSphere(5,10)
iPositionNode(Mesh,x,y,z)
	iSetCollideForm(#SPHERE_PRIMITIVE)
		*body_Magnetic = iCreateBody(Mesh)
		AddElement(Dynamic_body())
			Dynamic_body() = *body_Magnetic

EndProcedure





For i = 0 To 499
	new_dynamic_body(-Random(1000)+Random(1000),-Random(1000)+Random(1000),-Random(1000)+Random(1000))
Next



; iAddFilePostProcessingXEffect("XShaders/BlurVP")
; iAddFilePostProcessingXEffect("XShaders/BlurHP")

G = 9.8
Mult = 50
Repeat



iPointTargetNode(*Cam,0,0,0)


; Camera Orbitale ^^
Nx.f = 150 * Cos(ElapsedMilliseconds()/2500)
Ny.f = (100 + 100 * Cos(ElapsedMilliseconds()/2000))+150
Nz.f = 150 * Sin(ElapsedMilliseconds()/5000)
iPositionNode(*Cam,Nx,Ny,Nz)



  If iGetMouseEvent(#MOUSE_BUTTON_LEFT)
  		If flagXDown=0
  			omx = iGetMouseX()
  			omy = iGetMouseY()
  			flagXDown=11
  		Else
  			moy = iGetMouseY()-omy
  			angley=(moy/10.0)
  			omy= iGetMouseY()
  			mox = iGetMouseX()-omx
  			anglex=(mox/10.0)
  			omx= iGetMouseX()
  			iTurnNode(*cam, angley, anglex,0)
  		EndIf
  Else
  	 		flagXDown=0
  EndIf


	; if Escape Key, exit	
  If iGetKeyDown(#KEY_ESCAPE)
    Quit=1
  EndIf

	If iGetKeyDown(#KEY_ARROW_UP) And KeyFlag = 0
	 KeyFlag = 1
    Mult = -1*Mult
  EndIf

	If Not iGetKeyDown(#KEY_Space) And KeyFlag = 1
	 KeyFlag = 0
  EndIf


ForEach Dynamic_body()

A.VECTOR3 
VECTOR3_(A,iBodyX(Dynamic_body()),iBodyY(Dynamic_body()),iBodyZ(Dynamic_body()))

B.VECTOR3 
VECTOR3_(B,iBodyX(*body_Magnetic),iBodyY(*body_Magnetic),iBodyZ(*body_Magnetic))


Distance.f = Vec3_GetDistanceFrom(@A,@B)
Force.q = G*(10000000000000000*0.001)/(Distance*Distance)

Direction.VECTOR3
Impulse.VECTOR3
Vec3_Sub(@Direction,B,A)
Vec3_Normalize(@Direction)
Vec3_MulF(@Impulse,@Direction,@Force)
Vec3_Normalize(@Impulse)


iForceBody(Dynamic_body(),Impulse\x*Mult,Impulse\y*Mult,Impulse\z*Mult)

Next 






  	; ---------------
  	;      Render
  	; ---------------
  iBeginScene()
     iDrawScene()
  iEndScene()



Until Quit=1
; end
iFreeEngine()

Publié : mar. 18/août/2009 16:48
par guerrier001
Comment on fait si c'est animé car quand l'entité est animé il traverse la mesh.

Publié : mar. 18/août/2009 18:08
par tmyke
Heu, peux tu être plus précis ?

Publié : mar. 18/août/2009 20:10
par guerrier001
quand on initialise l'entité je met qu'elle est animmesh elle travers n'importe quelle terrain mais quand je ne la met pas en animmesh elle fait ce que je lui demande c'est a dire de ne pas bouger quand elle se cogne sur le terrain

Publié : mer. 19/août/2009 18:58
par Anonyme
arf , as tu vu ton orthographe , même si moi je fait des fotes , toi tu abuses.
ton landeau à pris feu quand tu était petit et ton père l'a éteint à coup de pioche ?

Publié : mer. 19/août/2009 20:35
par guerrier001
un quoi ?(désoler pour les fautes d'orthographe j'écris trops vite sur le clavier et je ne revérifie pas)