Pour les doubles, je ne sais pas, mais pense que ça ralentira forcément le code, vu que la précision des calculs sera doublement (

tu arrives à la déplacer ? vraiment ? et à la diriger ? et contrôler les réponses aux collisions ? c'est à dire choisir une collision glissante ou un rebond ?Progi1984 a écrit :SI on arrive à déplacer la balle, pourquoi n'arrive ton pas à déplacer un perso ?
si tu trouves comment faire, je suis curieux de voir çaProgi1984 a écrit :Ouh là, faudra que je modifie un peu plus l'exemple lol
Code : Tout sélectionner
;Comtois le 21/02/06
;PB4.0 beta 3
;Je me suis grandement inspiré du tutoriel de Fauerby http://www.peroxide.dk
#Focale = 38
Structure Parametres
AngleX.f
AngleY.f
AngleZ.f
EndStructure
;-Initialisation
If ExamineDesktops()
ScreenWidth = DesktopWidth(0)
ScreenHeight = DesktopHeight(0)
ScreenDepth = DesktopDepth(0)
EndIf
If InitEngine3D() = 0
MessageRequester( "Erreur" , "Impossible d'initialiser la 3D , vérifiez la présence de engine3D.dll" , 0 )
End
ElseIf InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or InitSound() = 0
MessageRequester( "Erreur" , "Impossible d'initialiser DirectX 7 Ou plus" , 0 )
End
ElseIf OpenScreen( ScreenWidth , ScreenHeight , ScreenDepth , "Demo 3D" ) = 0
MessageRequester( "Erreur" , "Impossible d'ouvrir l'écran " , 0 )
End
EndIf
Add3DArchive("Data\" , #PB_3DArchive_FileSystem)
Add3DArchive("Data\skybox.zip", #PB_3DArchive_Zip)
Parse3DScripts()
;-Informations de l'entity
InfosNinja.Car_Collision
;-Information Monde 3D
World3D.Car_WorldCollision
;-Entity
LoadPreference("Collision3D.ini",@World3D,@InfosNinja)
CreateListeTriangles(@InfosNinja,@World3D)
WorldMesh = LoadMesh(#PB_Any, World3D\FichierMesh)
CreateEntity(#PB_Any, MeshID(WorldMesh), 0)
;-SkyBox
If World3D\FichierSkyBox
SkyBox(World3D\FichierSkyBox)
EndIf
;-Camera
CreateCamera(0,0,0,100,100)
Camera.Parametres
With InfosNinja
CameraLocate(0,\PositionDansR3\x, \PositionDansR3\y + \RayonEllipsoide\y , \PositionDansR3\z)
CameraLookAt(0,\PositionDansR3\x + M3D_Cos(0) * 80, \PositionDansR3\y + \RayonEllipsoide\y ,\PositionDansR3\z - M3D_Sin(0) * 80)
EndWith
Define.f MouseX,MouseY,PasX,PasZ,Fov
Fov = #Focale
;/
;-La boucle principale
;/
Repeat
If ExamineMouse()
MouseX = -(MouseDeltaX()/10) * InfosNinja\Vitesse/2
MouseY = -(MouseDeltaY()/10) * InfosNinja\Vitesse/2
If MouseButton(1)
If InfosNinja\VitesseDansR3\y<#Epsilon
InfosNinja\VitesseDansR3\y = InfosNinja\Vitesse * 2
Else
InfosNinja\VitesseDansR3\y *1.1
EndIf
EndIf
If MouseButton(2)
Fov=M3D_CurveValue(Fov,5,50)
Else
Fov=M3D_CurveValue(Fov,#Focale,50)
EndIf
EndIf
Camera\AngleX = M3D_WrapValue( Camera\AngleX + MouseX)
RotateCamera(0,MouseX,0,0)
If MouseY > 0 And Camera\AngleY < 75
Camera\AngleY + MouseY
RotateCamera(0,0,MouseY,0)
ElseIf MouseY < 0 And Camera\AngleY > -75
Camera\AngleY + MouseY
RotateCamera(0,0,MouseY,0)
EndIf
If ExamineKeyboard()
If KeyboardPushed(#PB_Key_PageUp)
Fov + 0.1
EndIf
If KeyboardPushed(#PB_Key_PageDown)
Fov - 0.1
EndIf
;Touches du joueur
If KeyboardPushed(#PB_Key_Left)
InfosNinja\VitesseDansR3\x + M3D_Cos(Camera\AngleX+90) * InfosNinja\Vitesse
InfosNinja\VitesseDansR3\z - M3D_Sin(Camera\AngleX+90) * InfosNinja\Vitesse
ElseIf KeyboardPushed(#PB_Key_Right)
InfosNinja\VitesseDansR3\x + M3D_Cos(Camera\AngleX-90) * InfosNinja\Vitesse
InfosNinja\VitesseDansR3\z - M3D_Sin(Camera\AngleX-90) * InfosNinja\Vitesse
EndIf
If KeyboardPushed(#PB_Key_Up)
InfosNinja\VitesseDansR3\x + M3D_Cos(Camera\AngleX) * InfosNinja\Vitesse
InfosNinja\VitesseDansR3\z - M3D_Sin(Camera\AngleX) * InfosNinja\Vitesse
ElseIf KeyboardPushed(#PB_Key_Down)
InfosNinja\VitesseDansR3\x + M3D_Cos(Camera\AngleX) * -InfosNinja\Vitesse
InfosNinja\VitesseDansR3\z - M3D_Sin(Camera\AngleX) * -InfosNinja\Vitesse
EndIf
EndIf
GestionDeplacement1(@InfosNinja,@World3D)
Cx.f = M3D_CurveValue(CameraX(0),InfosNinja\PositionDansR3\x,200)
Cy.f = M3D_CurveValue(CameraY(0),InfosNinja\PositionDansR3\y+48,200)
Cz.f = M3D_CurveValue(CameraZ(0),InfosNinja\PositionDansR3\z,200)
CameraLocate(0,Cx, Cy, Cz)
CameraFOV(0,fov*0.0174533)
RenderWorld()
StartDrawing(ScreenOutput())
DrawText(0,0,StrF(Engine3DFrameRate(#PB_Engine3D_Current),0))
StopDrawing()
InfosNinja\VitesseDansR3\x = 0.0
InfosNinja\VitesseDansR3\z = 0.0
If InfosNinja\VitesseDansR3\y > 0
InfosNinja\VitesseDansR3\y + World3D\Gravite\y
ElseIf InfosNinja\VitesseDansR3\y < 1
InfosNinja\VitesseDansR3\y = 0
EndIf
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
Code : Tout sélectionner
;Comtois 21/02/06
;PB4.0 Beta 3
Source$="D:\Ogre\OgreCommandLineTools-1.0.6\WaterWorld.xml" ; <<<< Fichier du mesh dans le format Xml
Destination$="D:\Ogre\OgreCommandLineTools-1.0.6\WaterWorldTriangles.HD" ; <<<< Fichier contenant la liste des triangles
Structure Face
v1.l
v2.l
v3.l
EndStructure
Structure Point3D
x.f
y.f
z.f
EndStructure
Structure Vecteur
x.f
y.f
z.f
EndStructure
Structure Triangle
P1.Point3D
P2.Point3D
P3.Point3D
Constante.f
Normale.Vecteur
EndStructure
NewList Face.Face()
Global NewList ListTriangle.Triangle()
Define.f MiniX,MiniY,MiniZ,MaxiX,MaxiY,MaxiZ
Procedure.s StringFieldPerso(T$,Index)
Champ=0
Deb=0
Chaine$=""
For i=1 To Len(T$)
Car$=Mid(T$,i,1)
If Car$=Chr(34)
If Deb=0
Deb=1
Champ + 1
Continue
Else
Deb=0
EndIf
EndIf
If Champ=Index And Deb
Chaine$=Chaine$+Car$
EndIf
Next i
ProcedureReturn Chaine$
EndProcedure
OpenConsole()
SubMesh = 0
If OpenFile(0,Source$)
PrintN("Ouverture du fichier Xml : " + Source$)
While Eof(0)=0
Ligne$=ReadString(0)
If FindString(Ligne$,"<faces count=",1)
Pos=FindString(Ligne$,"count=",1)
Pos + 7
NbFace=Val(Mid(Ligne$,Pos,Len(Ligne$)-Pos-1))
SubMesh + 1
PrintN("SubMesh No : " + Str(SubMesh))
PrintN("Nombre de triangles : " + Str(NbFace))
;Lecture des Faces
ClearList(Face())
For i=1 To NbFace
Ligne$=ReadString(0)
AddElement(Face())
Face()\v1=Val(StringFieldPerso(Ligne$,1))
Face()\v2=Val(StringFieldPerso(Ligne$,2))
Face()\v3=Val(StringFieldPerso(Ligne$,3))
Next i
EndIf
;Cherche les vertices
If FindString(Ligne$,"<geometry vertexcount=",1)
Pos=FindString(Ligne$,"count=",1)
Pos + 7
NbVertex=Val(Mid(Ligne$,Pos,Len(Ligne$)-Pos-1))
PrintN("Nombre de sommets : " + Str(NbVertex))
Dim Vertex.Vecteur(NbVertex)
Dim Normale.Vecteur(NbVertex)
EndIf
If FindString(Ligne$,"<vertexbuffer",1)
Index=0
EndIf
;Lecture des vertex
If FindString(Ligne$,"<position",1)
Vertex(Index)\x=ValF(StringFieldPerso(Ligne$,1))
Vertex(Index)\y=ValF(StringFieldPerso(Ligne$,2))
Vertex(Index)\z=ValF(StringFieldPerso(Ligne$,3))
If Vertex(Index)\x < MiniX
MiniX = Vertex(Index)\x
ElseIf Vertex(Index)\x > MaxiX
MaxiX = Vertex(Index)\x
EndIf
If Vertex(Index)\y < MiniY
MiniY = Vertex(Index)\y
ElseIf Vertex(Index)\y > MaxiY
MaxiY = Vertex(Index)\y
EndIf
If Vertex(Index)\z < MiniZ
MiniZ = Vertex(Index)\z
ElseIf Vertex(Index)\z > MaxiZ
MaxiZ = Vertex(Index)\z
EndIf
EndIf
;Lecture des normales
If FindString(Ligne$,"<normal",1)
Normale(Index)\x=ValF(StringFieldPerso(Ligne$,1))
Normale(Index)\y=ValF(StringFieldPerso(Ligne$,2))
Normale(Index)\z=ValF(StringFieldPerso(Ligne$,3))
Index + 1
EndIf
;On peut enregistrer ce submesh
If FindString(Ligne$,"</vertexbuffer>",1)
ForEach Face()
AddElement(ListTriangle())
;v1
ListTriangle()\P1\x=Vertex(Face()\v1)\x
ListTriangle()\P1\y=Vertex(Face()\v1)\y
ListTriangle()\P1\z=Vertex(Face()\v1)\z
;v2
ListTriangle()\P2\x=Vertex(Face()\v2)\x
ListTriangle()\P2\y=Vertex(Face()\v2)\y
ListTriangle()\P2\z=Vertex(Face()\v2)\z
;v3
ListTriangle()\P3\x=Vertex(Face()\v3)\x
ListTriangle()\P3\y=Vertex(Face()\v3)\y
ListTriangle()\P3\z=Vertex(Face()\v3)\z
ListTriangle()\Normale\x=(Normale(Face()\v1)\x + Normale(Face()\v2)\x +Normale(Face()\v3)\x)/3
ListTriangle()\Normale\y=(Normale(Face()\v1)\y + Normale(Face()\v2)\y +Normale(Face()\v3)\y)/3
ListTriangle()\Normale\z=(Normale(Face()\v1)\z + Normale(Face()\v2)\z +Normale(Face()\v3)\z)/3
Next
EndIf
Wend
CloseFile(0)
PrintN("Total triangles : " + Str(CountList(ListTriangle())))
EndIf
;Génère un fichier contenant la liste des triangles
If CreateFile(0,Destination$)
PrintN("Creation du fichier triangle : " + Destination$)
WriteLong(0,CountList(ListTriangle()))
ForEach ListTriangle()
WriteData(0,@ListTriangle(),SizeOf(Triangle))
Next
CloseFile(0)
PrintN("Operation terminee")
PrintN("Pressez la touche [Entree] pour quitter")
EndIf
PrintN("MiniX = " + StrF(MiniX,3))
PrintN("MaxiX = " + StrF(MaxiX,3))
PrintN("MiniY = " + StrF(MiniY,3))
PrintN("MaxiY = " + StrF(MaxiY,3))
PrintN("MiniZ = " + StrF(MiniZ,3))
PrintN("MaxiZ = " + StrF(MaxiZ,3))
Input()
CloseConsole()
End
Code : Tout sélectionner
Nom$="temple"
Source$=Nom$+".mesh"
Destination$=Nom$+".xml"
RunProgram("OgreXMLConverter.exe",Source$ + " " + Destination$,"")
Code : Tout sélectionner
InitSprite3D()
Global Dim DelayBlur.l(20)
Global Dim Alpha.l(20)
Declare BlurScreen()
Code : Tout sélectionner
Procedure BlurScreen()
Shared DelayBlur.l,DelaybetweenD.l,EndAlpha.l
If DelaybetweenD<ElapsedMilliseconds()
DelaybetweenD=ElapsedMilliseconds()+25
For i = 1 To 15
If DelayBlur(i)<ElapsedMilliseconds()
DelayBlur(i)=ElapsedMilliseconds()+25*15
GrabSprite(i,0,0,1024,768,#PB_Sprite_Texture)
CreateSprite3D(i,i)
Alpha(i)=255/5
Goto Next_
EndIf
Next i
EndIf
Next_:
Start3D()
For i = 1 To 15
If EndAlpha<ElapsedMilliseconds()
EndAlpha=ElapsedMilliseconds()+25
For e = 1 To 15
Alpha(e)-1
Next
EndIf
If IsSprite3D(i)
DisplaySprite3D(i,0,0,Alpha(i))
EndIf
Next
Stop3D()
EndProcedure
Code : Tout sélectionner
ScreenWidth = DesktopWidth(0)
ScreenHeight = DesktopHeight(0)
ScreenDepth = DesktopDepth(0)
Code : Tout sélectionner
;Comtois le 21/02/06
#Epsilon=0.0001
Macro CopieVecteur(V,V1)
V\x=V1\x
V\y=V1\y
V\z=V1\z
EndMacro
Macro AdditionVecteur(V,V1,V2)
V\x=V1\x+V2\x
V\y=V1\y+V2\y
V\z=V1\z+V2\z
EndMacro
Macro SoustractionVecteur(V,V1,V2)
V\x=V1\x-V2\x
V\y=V1\y-V2\y
V\z=V1\z-V2\z
EndMacro
Macro DivisionVecteur(V,V1,V2)
V\x=V1\x/V2\x
V\y=V1\y/V2\y
V\z=V1\z/V2\z
EndMacro
Macro MultiplicationVecteur(V,V1,V2)
V\x=V1\x*V2\x
V\y=V1\y*V2\y
V\z=V1\z*V2\z
EndMacro
;- Les structures
Structure Parametres
AngleX.f
AngleY.f
AngleZ.f
EndStructure
Structure Vecteur
x.f
y.f
z.f
EndStructure
Structure Triangle
P1.Vecteur
P2.Vecteur
P3.Vecteur
Constante.f
Normale.Vecteur
EndStructure
Structure s_Collision
RayonEllipsoide.vecteur ; Rayon de l'ellipsoide
;Informations sur le déplacement dans le monde R3
VitesseDansR3.Vecteur
PositionDansR3.Vecteur
Vitesse.f
;Changement de Base vectorielle, BaseE = Base de l'ellipsoide
VitesseDansBaseE.Vecteur
VitesseDansBaseENormee.Vecteur
PointOrigine.Vecteur
;Informations collisions
CollisionDetectee.l
DistanceLaPlusCourte.f
PointIntersection.Vecteur
EndStructure
Structure Plan
Constante.f
Origine.Vecteur
Normale.Vecteur
EndStructure
Structure s_WorldCollision
FichierTriangles.s
FichierMesh.s
FichierSkyBox.s
NombreRebouclage.l
RebouclageMaxi.l
DistanceTresFaible.f
Gravite.Vecteur
*ListeTriangles.Triangle
NbTriangles.l
EndStructure
Structure s_Reponse
PositionFinale.Vecteur
PositionInitiale.Vecteur
Vitesse.Vecteur
*ListeTriangles.Triangle
EndStructure
;-Les procédures
Procedure SavePreferences(Fichier$)
If CreatePreferences(Fichier$)
PreferenceGroup("FICHIERS")
WritePreferenceString("Fichier triangles","CastleTriangles.HD")
WritePreferenceString("Fichier mesh","Castle.mesh")
WritePreferenceString("Fichier SkyBox","Stevecube.jpg")
PreferenceGroup("GRAVITE")
WritePreferenceFloat("X",0.0)
WritePreferenceFloat("Y",-9.0)
WritePreferenceFloat("Z",0.0)
PreferenceGroup("COLLISION")
WritePreferenceLong("Nombre de rebouclage", 5)
WritePreferenceFloat("Distance très faible",0.005)
PreferenceGroup("ENTITY")
WritePreferenceFloat("Vitesse",9.0)
WritePreferenceFloat("Largeur",20)
WritePreferenceFloat("Hauteur",70)
WritePreferenceFloat("Profondeur",20)
WritePreferenceFloat("Position X",250.0)
WritePreferenceFloat("Position Y",1250.0)
WritePreferenceFloat("Position Z",300.0)
ClosePreferences()
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
ProcedureDLL LoadPreference(Fichier$,*World3D.s_WorldCollision,*Entity.s_Collision)
If OpenPreferences(Fichier$)
PreferenceGroup("FICHIERS")
*World3D\FichierTriangles=ReadPreferenceString("Fichier triangles","TempleTriangles.HD")
*World3D\FichierMesh=ReadPreferenceString("Fichier mesh","Temple.mesh")
*World3D\FichierSkyBox=ReadPreferenceString("Fichier SkyBox","")
PreferenceGroup("GRAVITE")
*World3D\Gravite\x=ReadPreferenceFloat("X",0.0)
*World3D\Gravite\y=ReadPreferenceFloat("Y",-9)
*World3D\Gravite\z=ReadPreferenceFloat("Z",0.0)
PreferenceGroup("COLLISION")
*World3D\RebouclageMaxi=ReadPreferenceLong("Nombre de rebouclage", 5)
*World3D\DistanceTresFaible=ReadPreferenceFloat("Distance très faible",0.005)
PreferenceGroup("ENTITY")
*Entity\Vitesse=ReadPreferenceFloat("Vitesse",9.0)
*Entity\RayonEllipsoide\x=ReadPreferenceFloat("Largeur",25.0)
*Entity\RayonEllipsoide\y=ReadPreferenceFloat("Hauteur",70.0)
*Entity\RayonEllipsoide\z=ReadPreferenceFloat("Profondeur",25.0)
*Entity\PositionDansR3\x=ReadPreferenceFloat("Position X",250.0)
*Entity\PositionDansR3\y=ReadPreferenceFloat("Position Y",125.0)
*Entity\PositionDansR3\z=ReadPreferenceFloat("Position Z",300.0)
ClosePreferences()
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
Procedure.f ProduitScalaire(*V1.Vecteur, *V2.Vecteur)
ProcedureReturn *V1\x * *V2\x + *V1\y * *V2\y + *V1\z * *V2\z
EndProcedure
Procedure ProduitVectoriel(*N.Vecteur,*V1.Vecteur, *V2.Vecteur)
*N\x = ((*V1\y * *V2\z) - (*V1\z * *V2\y))
*N\y = ((*V1\z * *V2\x) - (*V1\x * *V2\z))
*N\z = ((*V1\x * *V2\y) - (*V1\y * *V2\x))
EndProcedure
Procedure Normalise(*N.Vecteur)
Norme.f=Sqr(*N\x * *N\x + *N\y * *N\y + *N\z * *N\z)
If Norme = 0.0
*N\x = 0.0
*N\y = 0.0
*N\z = 0.0
Else
*N\x / Norme
*N\y / Norme
*N\z / Norme
EndIf
EndProcedure
Procedure LongueurVecteur(*V.Vecteur,LongV.f)
Norme.f=Sqr(*V\x * *V\x + *V\y * *V\y + *V\z * *V\z)
*V\x * LongV / Norme
*V\y * LongV / Norme
*V\z * LongV / Norme
EndProcedure
Procedure.f Longueur(*V.Vecteur)
ProcedureReturn Sqr(*V\x * *V\x + *V\y * *V\y + *V\z * *V\z)
EndProcedure
Procedure.b TestPointDansTriangle1(*P.Vecteur, *A.Vecteur, *B.Vecteur, *C.Vecteur)
Protected PA.Vecteur,PB.Vecteur,PC.Vecteur,Somme.Vecteur
PA\x=*A\x-*P\x
PA\y=*A\y-*P\y
PA\z=*A\z-*P\z
Normalise(@PA)
PB\x=*B\x-*P\x
PB\y=*B\y-*P\y
PB\z=*B\z-*P\z
Normalise(@PB)
PC\x=*C\x-*P\x
PC\y=*C\y-*P\y
PC\z=*C\z-*P\z
Normalise(@PC)
Somme\x=PA\x+PB\x+PC\x
Somme\y=PA\y+PB\y+PC\y
Somme\z=PA\z+PB\z+PC\z
;on calcule la taille du vecteur Somme
If Longueur(Somme) > 1
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
Procedure.f NormeAuCarre(*V.Vecteur)
ProcedureReturn *V\x * *V\x + *V\y * *V\y + *V\z * *V\z
EndProcedure
Procedure.b ChercheLaPlusPetiteSolution(a.f, b.f, c.f, maxR.f,*Solution.Float)
;Cherche les solutions d'une équation de cette forme : At²+Bt+C=0
;http://fr.wikipedia.org/wiki/%C3%89quation_du_second_degr%C3%A9 (bas de la page "Gain de précision")
;Calcul le déterminant
Determinant.f = b * b - 4.0 * a * c
;Si le déterminant est inférieur ou égal à zéro , il n'y a pas d'intersection significative.
If Determinant < 0.0 : ProcedureReturn #False : EndIf
If a=0.0
t1.f=-c/b
t2.f=0.0
Else
;Calcul les deux solutions
If b<0.0
q.f=0.5 * (-b - Sqr(Determinant))
Else
q.f=0.5 * (-b + Sqr(Determinant))
EndIf
t1.f = q / a
t2.f = c / q
EndIf
;Renvoie la solution la plus petite si elle est valide
If t1 > 0 And t1 < maxR
*Solution\f = t1
ProcedureReturn #True
EndIf
If t2 > 0 And t2 < maxR
*Solution\f = t2
ProcedureReturn #True
EndIf
;Pas de solution
ProcedureReturn #False
EndProcedure
Procedure TestCollision(*Sphere.s_Collision,*World3D.s_WorldCollision)
Protected PlanTriangle.Plan
Protected a.f,b.f,c.f,NouveauT.f,NormeAreteAuCarre.f
Protected Sphere_p1.Vecteur, p1_Sphere.Vecteur
Protected Sphere_p2.Vecteur, p2_Sphere.Vecteur
Protected Sphere_p3.Vecteur, p3_Sphere.Vecteur
Protected Arete.Vecteur, PointCollision.Vecteur,PointIntersectionSurLePlan.Vecteur
*Ptr.Triangle=*World3D\ListeTriangles
For i = 1 To *World3D\NbTriangles
*Ptr + SizeOf(Triangle)
;A revoir , c'est pas utile de tout recopier , je pourrais utiliser directement la liste chainée ?
CopieVecteur(PlanTriangle\Normale, *Ptr\normale)
CopieVecteur(PlanTriangle\Origine, *Ptr\P1)
PlanTriangle\Constante=*Ptr\Constante
;Le produit scalaire <=0 si on se trouve face au triangle
If ProduitScalaire(@PlanTriangle\Normale, *Sphere\VitesseDansBaseENormee)>=0
;Inverse la normale ( C'est provisoire , en attendant de faire un éditeur correct qui oriente la normale dans le bon sens)
PlanTriangle\Normale\x * -1
PlanTriangle\Normale\y * -1
PlanTriangle\Normale\z * -1
PlanTriangle\Constante * -1
EndIf
;Initialise t0,t1
t0.f=0.0
t1.f=0.0
;Initialise un drapeau
SphereCoupeLePlan.l = #False
;Calcul la distance de la sphère au plan du triangle (d=N.S0+Cp : http://homeomath.imingo.net/displan.htm)
DistanceSpherePlan.f=ProduitScalaire(*Sphere\PointOrigine,@PlanTriangle\normale) + PlanTriangle\Constante
;Calcul le produit scalaire Normale du plan avec le vecteur vitesse
;Permet de déterminer si la sphère se déplace parallèlement au plan
PScalaireNormaleVitesse.f = ProduitScalaire(@PlanTriangle\normale, *Sphere\VitesseDansBaseE)
;Si la sphère se déplace parallèlement au plan
;If PScalaireNormaleVitesse>-#Epsilon And PScalaireNormaleVitesse<#Epsilon
If PScalaireNormaleVitesse=0.0
;Il n'y a pas de collision si la distance de la Sphère au Plan est supérieure au rayon de la sphère
If Abs(DistanceSpherePlan) > 1.0
;La sphère ne coupe pas le plan , il n'y a pas de collision
Continue
Else
;La sphère coupe le plan.elle est en collision dans l'intervalle [0..1]
SphereCoupeLePlan = #True
t0 = 0.0
t1 = 1.0
EndIf
Else
;Calcul l'intervalle dans lequel la sphère est en collision
t0=(-1.0-DistanceSpherePlan)/PScalaireNormaleVitesse
t1=( 1.0-DistanceSpherePlan)/PScalaireNormaleVitesse
;Swap si nécessaire
If t0 > t1
Swap t0,t1
EndIf
;Pas de collision si les deux résultats sont hors de l'intervalle [0..1]
If t0 > 1.0 Or t1 < 0.0
Continue
EndIf
;Recadre dans l'intervalle [0,1]
If t0 < 0.0 : t0 = 0.0 : EndIf
If t1 > 1.0 : t1 = 1.0 : EndIf
EndIf
;Maintenant on connait l'intervalle dans lequel il est possible qu'une collision se produise ,
; mais on ne sait pas encore où.
TriangleEnCollision.l = #False
t.f = 1.0
;Test si la collision est dans le triangle
If SphereCoupeLePlan=#False
;Position de la sphère à t0 - la Normale du plan
PointIntersectionSurLePlan\x=(*Sphere\PointOrigine\x + t0 * *Sphere\VitesseDansBaseE\x) - PlanTriangle\Normale\x
PointIntersectionSurLePlan\y=(*Sphere\PointOrigine\y + t0 * *Sphere\VitesseDansBaseE\y) - PlanTriangle\Normale\y
PointIntersectionSurLePlan\z=(*Sphere\PointOrigine\z + t0 * *Sphere\VitesseDansBaseE\z) - PlanTriangle\Normale\z
;Test si le point d'intersection se trouve dans le triangle
If (TestPointDansTriangle1(@PointIntersectionSurLePlan,*Ptr\p1,*Ptr\p2,*Ptr\p3))
TriangleEnCollision = #True
;Mémorise t et Le point en collision le plus proche
t = t0
CopieVecteur(PointCollision, PointIntersectionSurLePlan)
EndIf
EndIf
;S'il n'y a pas de collision à l'intérieur du triangle , il faut tester les sommets et les arêtes
If TriangleEnCollision = #False
NormeVitesseAuCarre.f = NormeAuCarre(*Sphere\VitesseDansBaseE)
;P1
SoustractionVecteur(Sphere_p1, *Sphere\PointOrigine, *Ptr\p1)
SoustractionVecteur(p1_Sphere, *Ptr\p1, *Sphere\PointOrigine)
b = 2.0 * ProduitScalaire(*Sphere\VitesseDansBaseE,@Sphere_p1)
c = NormeAuCarre(@p1_Sphere) - 1.0
If ChercheLaPlusPetiteSolution(NormeVitesseAuCarre,b,c, t, @NouveauT)
t = NouveauT
TriangleEnCollision = #True
CopieVecteur(PointCollision, *Ptr\p1)
EndIf
;p1 -> p2:
SoustractionVecteur(Arete, *Ptr\p2, *Ptr\p1)
NormeAreteAuCarre.f = NormeAuCarre(@Arete)
PScalaireAreteVitesse.f = ProduitScalaire(@Arete,*Sphere\VitesseDansBaseE)
PScalaireAreteP_Sphere.f = ProduitScalaire(@Arete,@p1_Sphere)
;Calcule les paramètres de l'équation
a = NormeAreteAuCarre*-NormeVitesseAuCarre + PScalaireAreteVitesse*PScalaireAreteVitesse
b = NormeAreteAuCarre*(2.0 * ProduitScalaire(*Sphere\VitesseDansBaseE,@p1_Sphere))-2.0*PScalaireAreteVitesse*PScalaireAreteP_Sphere
c = NormeAreteAuCarre*(1-NormeAuCarre(@p1_Sphere))+PScalaireAreteP_Sphere*PScalaireAreteP_Sphere
;Cherche si une intersection de la Sphere avec la ligne passant par l'arête existe
If ChercheLaPlusPetiteSolution(a,b,c, t, @NouveauT)
;Il faut vérifier que le point trouvé se trouve bien sur l'arete
f.f=(PScalaireAreteVitesse*NouveauT-PScalaireAreteP_Sphere)/NormeAreteAuCarre
If f >= 0.0 And f <= 1.0
t = NouveauT
TriangleEnCollision = #True
AdditionVecteur(PointCollision, *Ptr\p1, f * Arete)
EndIf
EndIf
;P2
SoustractionVecteur(Sphere_p2, *Sphere\PointOrigine, *Ptr\p2)
SousTractionVecteur(p2_Sphere, *Ptr\p2, *Sphere\PointOrigine)
b = 2.0 * ProduitScalaire(*Sphere\VitesseDansBaseE,@Sphere_p2)
c = NormeAuCarre(@p2_Sphere) - 1.0
If ChercheLaPlusPetiteSolution(NormeVitesseAuCarre,b,c, t, @NouveauT)
t = NouveauT
TriangleEnCollision = #True
CopieVecteur(PointCollision, *Ptr\p2)
EndIf
;p2 -> p3:
SoustractionVecteur(Arete,*Ptr\p3,*Ptr\p2)
NormeAreteAuCarre = NormeAuCarre(@Arete)
PScalaireAreteVitesse = ProduitScalaire(@Arete,*Sphere\VitesseDansBaseE)
PScalaireAreteP_Sphere = ProduitScalaire(@Arete,@p2_Sphere)
a = NormeAreteAuCarre*-NormeVitesseAuCarre + PScalaireAreteVitesse*PScalaireAreteVitesse
b = NormeAreteAuCarre*(2.0 * ProduitScalaire(*Sphere\VitesseDansBaseE,@p2_Sphere))-2.0*PScalaireAreteVitesse*PScalaireAreteP_Sphere
c = NormeAreteAuCarre*(1-NormeAuCarre(@p2_Sphere))+PScalaireAreteP_Sphere*PScalaireAreteP_Sphere
;Cherche si une intersection de la Sphere avec la ligne passant par l'arête existe
If ChercheLaPlusPetiteSolution(a,b,c, t, @NouveauT)
;Il faut vérifier que le point trouvé se trouve bien sur l'arete
f.f=(PScalaireAreteVitesse*NouveauT-PScalaireAreteP_Sphere)/NormeAreteAuCarre
If f >= 0.0 And f <= 1.0
t = NouveauT
TriangleEnCollision = #True
AdditionVecteur(PointCollision, *Ptr\p2, f * Arete)
EndIf
EndIf
;P3
SoustractionVecteur(Sphere_p3,*Sphere\PointOrigine,*Ptr\p3)
SoustractionVecteur(p3_Sphere,*Ptr\p3,*Sphere\PointOrigine)
b = 2.0 * ProduitScalaire(*Sphere\VitesseDansBaseE,@Sphere_p3)
c = NormeAuCarre(@p3_Sphere) - 1.0
If ChercheLaPlusPetiteSolution(NormeVitesseAuCarre,b,c, t, @NouveauT)
t = NouveauT
TriangleEnCollision = #True
CopieVecteur(PointCollision, *Ptr\p3)
EndIf
;p3 -> p1:
SoustractionVecteur(Arete, *Ptr\p1, *Ptr\p3)
NormeAreteAuCarre = NormeAuCarre(@Arete)
PScalaireAreteVitesse = ProduitScalaire(@Arete,*Sphere\VitesseDansBaseE)
PScalaireAreteP_Sphere = ProduitScalaire(@Arete,@p3_Sphere)
a = NormeAreteAuCarre*-NormeVitesseAuCarre +PScalaireAreteVitesse*PScalaireAreteVitesse
b = NormeAreteAuCarre*(2.0 * ProduitScalaire(*Sphere\VitesseDansBaseE,@p3_Sphere))-2.0*PScalaireAreteVitesse*PScalaireAreteP_Sphere
c = NormeAreteAuCarre*(1-NormeAuCarre(@p3_Sphere))+PScalaireAreteP_Sphere*PScalaireAreteP_Sphere
;Cherche si une intersection de la Sphere avec la ligne passant par l'arête existe
If ChercheLaPlusPetiteSolution(a,b,c, t, @NouveauT)
;Il faut vérifier que le point trouvé se trouve bien sur l'arete
f.f=(PScalaireAreteVitesse*NouveauT-PScalaireAreteP_Sphere)/NormeAreteAuCarre
If f >= 0.0 And f <= 1.0
t = NouveauT
TriangleEnCollision = #True
AdditionVecteur(PointCollision, *Ptr\p3, f * Arete)
EndIf
EndIf
EndIf
;Stock le résultat
If TriangleEnCollision = #True
;Calcul la distance que la sphère peut parcourir jusqu'au point en collision
DistancePointCollision.f = t * Longueur(*Sphere\VitesseDansBaseE)
;Si c'est le premier triangle en collision ou le plus près
If *Sphere\CollisionDetectee = #False Or DistancePointCollision < *Sphere\DistanceLaPlusCourte
;Informations nécessaires pour le calcul du glissement
*Sphere\DistanceLaPlusCourte = DistancePointCollision ; Pour sélectionner le triangle le plus proche
CopieVecteur(*Sphere\PointIntersection, PointCollision)
*Sphere\CollisionDetectee = #True
EndIf
EndIf
Next
EndProcedure
Procedure ReponseCollision(*Reponse.s_Reponse,*World3D.s_WorldCollision)
Protected PlanDeGlissement.Plan, Entity.s_Collision
Protected PointDestination.Vecteur, NouveauPointOrigine.Vecteur
Protected V.Vecteur, NouveauPointDestination.Vecteur, NouvelleVitesse.Vecteur
;Limite le rebouclage
If (*World3D\NombreRebouclage>*World3D\RebouclageMaxi)
CopieVecteur(*Reponse\PositionFinale, *Reponse\PositionInitiale)
ProcedureReturn
EndIf
;Stocke les informations nécessaires au test de collision
CopieVecteur(Entity\VitesseDansBaseE, *Reponse\Vitesse)
CopieVecteur(Entity\VitesseDansBaseENormee, *Reponse\Vitesse)
Normalise(@Entity\VitesseDansBaseENormee)
CopieVecteur(Entity\PointOrigine, *Reponse\PositionInitiale)
Entity\CollisionDetectee = #False
;Test les triangles , s'il y a collision , retourne le point d'intersection avec le triangle.
;Pour améliorer la vitesse , il faudrait sélectionner uniquement les triangles susceptibles d'être en collision
;Voir pour ajouter un octree , ou peut-être un quadtree pour commencer.
TestCollision(@Entity,*World3D)
;Il n'y a pas de collision, on peut se déplacer normalement
If Entity\CollisionDetectee = #False
AdditionVecteur(*Reponse\PositionFinale, *Reponse\PositionInitiale, *Reponse\Vitesse)
ProcedureReturn
EndIf
;Calcul le point de destination ( comme s'il n'y avait pas de collision)
AdditionVecteur(PointDestination, *Reponse\PositionInitiale, *Reponse\Vitesse)
CopieVecteur(NouveauPointOrigine, *Reponse\PositionInitiale)
;On se replace un peu avant le point de d'intersection calculé dans TestCollision()
If Entity\DistanceLaPlusCourte > *World3D\DistanceTresFaible
V\x = *Reponse\Vitesse\x
V\y = *Reponse\Vitesse\y
V\z = *Reponse\Vitesse\z
LongueurVecteur(@V, Entity\DistanceLaPlusCourte - *World3D\DistanceTresFaible)
NouveauPointOrigine\x + V\x
NouveauPointOrigine\y + V\y
NouveauPointOrigine\z + V\z
;Et on déplace aussi le point d'intersection de façon à ne pas être en collision sur le plan de glissement
Normalise(@V)
Entity\PointIntersection\x - *World3D\DistanceTresFaible * V\x
Entity\PointIntersection\y - *World3D\DistanceTresFaible * V\y
Entity\PointIntersection\z - *World3D\DistanceTresFaible * V\z
EndIf
;Determine le plan de glissement
CopieVecteur(PlanDeGlissement\Origine, Entity\PointIntersection)
SoustractionVecteur(PlanDeGlissement\Normale, NouveauPointOrigine, Entity\PointIntersection)
Normalise(@PlanDeGlissement\Normale)
PlanDeGlissement\Constante = -(PlanDeGlissement\Normale\x*PlanDeGlissement\Origine\x+PlanDeGlissement\Normale\y*PlanDeGlissement\Origine\y+PlanDeGlissement\Normale\z*PlanDeGlissement\Origine\z)
;Nouveau point de destination
Longueur1.f=ProduitScalaire(@Pointdestination,@PlanDeGlissement\normale) + PlanDeGlissement\Constante
SoustractionVecteur(NouveauPointDestination, PointDestination, Longueur1 * PlanDeGlissement\Normale)
;Calcul la nouvelle vitesse (le long du plan de glissement)
SoustractionVecteur(NouvelleVitesse, NouveauPointDestination, Entity\PointIntersection)
;Inutile de reboucler si la nouvelle vitesse est faible
If Longueur(@NouvelleVitesse) <= *World3D\DistanceTresFaible
CopieVecteur(*Reponse\PositionFinale, NouveauPointOrigine)
ProcedureReturn
EndIf
*World3D\NombreRebouclage + 1
;A voir si je garde la structure
*Reponse\PositionInitiale\x = NouveauPointOrigine\x
*Reponse\PositionInitiale\y = NouveauPointOrigine\y
*Reponse\PositionInitiale\z = NouveauPointOrigine\z
*Reponse\Vitesse\x = NouvelleVitesse\x
*Reponse\Vitesse\y = NouvelleVitesse\y
*Reponse\Vitesse\z = NouvelleVitesse\z
ReponseCollision(*Reponse,*World3D)
EndProcedure
ProcedureDLL GestionDeplacement1(*Entity.s_Collision,*World3D.s_WorldCollision)
Protected PositionDansBaseE.Vecteur, VitesseDansBaseE.Vecteur, PositionFinale.Vecteur
;Calcul la position et la vitesse dans la base de l'Ellipsoide
DivisionVecteur(PositionDansBaseE, *Entity\PositionDansR3, *Entity\RayonEllipsoide)
DivisionVecteur(VitesseDansBaseE , *Entity\VitesseDansR3 , *Entity\RayonEllipsoide)
;Gestion du déplacement
*World3D\NombreRebouclage = 0
Reponse.s_Reponse
CopieVecteur(Reponse\PositionFinale ,PositionFinale)
CopieVecteur(Reponse\PositionInitiale, PositionDansBaseE)
CopieVecteur(Reponse\Vitesse,VitesseDansBaseE)
;Reponse\ListeTriangles=*Entity\ListeTriangles
ReponseCollision(@Reponse,*World3D)
;Gestion de la gravité
DivisionVecteur(VitesseDansBaseE, *World3D\gravite, *Entity\RayonEllipsoide)
*World3D\NombreRebouclage = 0
CopieVecteur(Reponse\PositionInitiale,Reponse\PositionFinale)
CopieVecteur(Reponse\Vitesse,VitesseDansBaseE)
ReponseCollision(@Reponse,*World3D)
;Conversion de la position finale dans R3
MultiplicationVecteur(*Entity\PositionDansR3, Reponse\PositionFinale, *Entity\RayonEllipsoide)
EndProcedure
ProcedureDLL CreateListeTriangles(*Entity.s_Collision,*World3D.s_WorldCollision)
Protected p2_p1.Vecteur, p3_p1.Vecteur
;Génère un fichier contenant la liste des triangles
If ReadFile(0,*World3D\FichierTriangles)
*World3D\NbTriangles=ReadLong(0)
*World3D\ListeTriangles=AllocateMemory(SizeOf(Triangle) * *World3D\NbTriangles)
*Ptr.Triangle=*World3D\ListeTriangles
While Eof(0)=0
ReadData(0,*Ptr,SizeOf(Triangle))
*Ptr\P1\x / *Entity\RayonEllipsoide\x
*Ptr\P1\y / *Entity\RayonEllipsoide\y
*Ptr\P1\z / *Entity\RayonEllipsoide\z
*Ptr\P2\x / *Entity\RayonEllipsoide\x
*Ptr\P2\y / *Entity\RayonEllipsoide\y
*Ptr\P2\z / *Entity\RayonEllipsoide\z
*Ptr\P3\x / *Entity\RayonEllipsoide\x
*Ptr\P3\y / *Entity\RayonEllipsoide\y
*Ptr\P3\z / *Entity\RayonEllipsoide\z
;Calcul le plan
p2_p1\x = *Ptr\P2\x - *Ptr\P1\x
p2_p1\y = *Ptr\P2\y - *Ptr\P1\y
p2_p1\z = *Ptr\P2\z - *Ptr\P1\z
p3_p1\x = *Ptr\P3\x - *Ptr\P1\x
p3_p1\y = *Ptr\P3\y - *Ptr\P1\y
p3_p1\z = *Ptr\P3\z - *Ptr\P1\z
ProduitVectoriel(*Ptr\Normale,@p2_p1,@p3_p1)
Normalise(*Ptr\Normale)
*Ptr\Constante = -(*Ptr\Normale\x * *Ptr\P1\x + *Ptr\Normale\y * *Ptr\P1\y + *Ptr\Normale\z * *Ptr\P1\z)
*Ptr + SizeOf(Triangle)
Wend
CloseFile(0)
EndIf
EndProcedure