Publié : dim. 27/nov./2005 12:35
Je n'ai que le sol et le ciel; la carte s'affiche correctement, c'est fluide, mais pas de murs!
Forums PureBasic - Français
https://www.purebasic.fr/french/
Code : Tout sélectionner
;Comtois - Collision Glissante le 09/12/05
;PB 3.94 avec la beta 1.03 d'ogre
;- Constantes
#Hauteur = 64
#Echelle = 1
#CameraSpeed = 4
#Epsilon=0.0001
; Liste des meshes possibles
#PB_Mesh_Vertex = 1 << 0
#PB_Mesh_Color = 1 << 1
#PB_Mesh_Normal = 1 << 2
#PB_Mesh_UVCoordinate = 1 << 3
;Additionnnal flag To specify the faces
#PB_Mesh_Face = 1 << 4
;- Les structures
Declare MakeMesh(No.l,U,V)
Structure Vertex
px.f
py.f
pz.f
nx.f
ny.f
nz.f
U.f
V.f
EndStructure
Structure Parametres
AngleX.f
AngleY.f
AngleZ.f
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
Origine.Vecteur
Normale.Vecteur
EndStructure
Structure Face
Point.Point3D[4]
EndStructure
Structure Sommet
No.l
X.l
Y.l
EndStructure
Structure Segment
Sommet1.l
x1.l
Y1.l
Sommet2.l
x2.l
Y2.l
Long.l ; Longueur d'un segment ( pour le calcul du chemin le plus court d'un sommet à un autre )
EndStructure
Structure s_Collision
RayonEllipsoide.vecteur ; Rayon de l'ellipsoide
;Informations sur le déplacement dans le monde R3
VitesseDansR3.Vecteur
PositionDansR3.Vecteur
;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
Global NombreDeRebouclage.l
Global Gravite.Vecteur
Global RayonEllipsoide.Vecteur
Global SphereI
Global TirA.Vecteur
NewList ListTriangle.Triangle()
NewList Sommet.Sommet()
NewList Segment.Segment()
Global Camera.Parametres
;-Les procédures
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 > #Epsilon And t1 < maxR
*Solution\f = t1
ProcedureReturn #True
EndIf
If t2 > #Epsilon And t2 < maxR
*Solution\f = t2
ProcedureReturn #True
EndIf
;Pas de solution
ProcedureReturn #False
EndProcedure
Procedure TestCollision(*Sphere.s_Collision)
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
Protected *p1.Vecteur, *p2.Vecteur, *p3.Vecteur
ForEach ListTriangle()
;A revoir , c'est pas utile de tout recopier , je pourrais utiliser directement la liste chainée ?
PlanTriangle\Normale\x=ListTriangle()\normale\x
PlanTriangle\Normale\y=ListTriangle()\normale\y
PlanTriangle\Normale\z=ListTriangle()\normale\z
PlanTriangle\Origine\x=ListTriangle()\Origine\x
PlanTriangle\Origine\y=ListTriangle()\Origine\y
PlanTriangle\Origine\z=ListTriangle()\Origine\z
PlanTriangle\Constante=ListTriangle()\Constante
*p1=ListTriangle()\p1
*p2=ListTriangle()\p2
*p3=ListTriangle()\p3
;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 = 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
temp.f = t1
t1 = t0
t0 = temp
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,*p1,*p2,*p3))
TriangleEnCollision = #True
;Mémorise t et Le point en collision le plus proche
t = t0
PointCollision\x = PointIntersectionSurLePlan\x
PointCollision\y = PointIntersectionSurLePlan\y
PointCollision\z = PointIntersectionSurLePlan\z
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
Sphere_p1\x = *Sphere\PointOrigine\x - *p1\x
Sphere_p1\y = *Sphere\PointOrigine\y - *p1\y
Sphere_p1\z = *Sphere\PointOrigine\z - *p1\z
p1_Sphere\x = *p1\x - *Sphere\PointOrigine\x
p1_Sphere\y = *p1\y - *Sphere\PointOrigine\y
p1_Sphere\z = *p1\z - *Sphere\PointOrigine\z
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
PointCollision\x = *p1\x
PointCollision\y = *p1\y
PointCollision\z = *p1\z
EndIf
;p1 -> p2:
Arete\x = *p2\x-*p1\x
Arete\y = *p2\y-*p1\y
Arete\z = *p2\z-*p1\z
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
PointCollision\x = *p1\x + f * Arete\x
PointCollision\y = *p1\y + f * Arete\y
PointCollision\z = *p1\z + f * Arete\z
EndIf
EndIf
;P2
Sphere_p2\x = *Sphere\PointOrigine\x - *p2\x
Sphere_p2\y = *Sphere\PointOrigine\y - *p2\y
Sphere_p2\z = *Sphere\PointOrigine\z - *p2\z
p2_Sphere\x = *p2\x - *Sphere\PointOrigine\x
p2_Sphere\y = *p2\y - *Sphere\PointOrigine\y
p2_Sphere\z = *p2\z - *Sphere\PointOrigine\z
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
PointCollision\x = *p2\x
PointCollision\y = *p2\y
PointCollision\z = *p2\z
EndIf
;p2 -> p3:
Arete\x = *p3\x-*p2\x
Arete\y = *p3\y-*p2\y
Arete\z = *p3\z-*p2\z
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
PointCollision\x = *p2\x + f * Arete\x
PointCollision\y = *p2\y + f * Arete\y
PointCollision\z = *p2\z + f * Arete\z
EndIf
EndIf
;P3
Sphere_p3\x = *Sphere\PointOrigine\x - *p3\x
Sphere_p3\y = *Sphere\PointOrigine\y - *p3\y
Sphere_p3\z = *Sphere\PointOrigine\z - *p3\z
p3_Sphere\x = *p3\x - *Sphere\PointOrigine\x
p3_Sphere\y = *p3\y - *Sphere\PointOrigine\y
p3_Sphere\z = *p3\z - *Sphere\PointOrigine\z
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
PointCollision\x = *p3\x
PointCollision\y = *p3\y
PointCollision\z = *p3\z
EndIf
;p3 -> p1:
Arete\x = *p1\x-*p3\x
Arete\y = *p1\y-*p3\y
Arete\z = *p1\z-*p3\z
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
PointCollision\x = *p3\x + f * Arete\x
PointCollision\y = *p3\y + f * Arete\y
PointCollision\z = *p3\z + f * Arete\z
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
*Sphere\PointIntersection\x=PointCollision\x
*Sphere\PointIntersection\y=PointCollision\y
*Sphere\PointIntersection\z=PointCollision\z
*Sphere\CollisionDetectee = #True
EndIf
EndIf
Next
EndProcedure
Procedure ReponseCollision(*PositionFinale.Vecteur, *PositionInitiale.Vecteur, *Vitesse.Vecteur)
Protected PlanDeGlissement.Plan, InfosCollision.s_Collision
Protected PointDestination.Vecteur, NouveauPointOrigine.Vecteur
Protected V.Vecteur, NouveauPointDestination.Vecteur, NouvelleVitesse.Vecteur
DistanceTresFaible.f = 0.005
;Limite le rebouclage
If (NombreDeRebouclage>5)
*PositionFinale\x = *PositionInitiale\x
*PositionFinale\y = *PositionInitiale\y
*PositionFinale\z = *PositionInitiale\z
ProcedureReturn
EndIf
;Stocke les informations nécessaires au test de collision
InfosCollision\VitesseDansBaseE\x = *Vitesse\x
InfosCollision\VitesseDansBaseE\y = *Vitesse\y
InfosCollision\VitesseDansBaseE\z = *Vitesse\z
InfosCollision\VitesseDansBaseENormee\x = *Vitesse\x
InfosCollision\VitesseDansBaseENormee\y = *Vitesse\y
InfosCollision\VitesseDansBaseENormee\z = *Vitesse\z
Normalise(@InfosCollision\VitesseDansBaseENormee)
InfosCollision\PointOrigine\x = *PositionInitiale\x
InfosCollision\PointOrigine\y = *PositionInitiale\y
InfosCollision\PointOrigine\z = *PositionInitiale\z
InfosCollision\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(@InfosCollision)
;Il n'y a pas de collision, on peut se déplacer normalement
If InfosCollision\CollisionDetectee = #False
*PositionFinale\x = *PositionInitiale\x + *Vitesse\x
*PositionFinale\y = *PositionInitiale\y + *Vitesse\y
*PositionFinale\z = *PositionInitiale\z + *Vitesse\z
ProcedureReturn
EndIf
;Calcul le point de destination ( comme s'il n'y avait pas de collision)
PointDestination\x = *PositionInitiale\x + *Vitesse\x
PointDestination\y = *PositionInitiale\y + *Vitesse\y
PointDestination\z = *PositionInitiale\z + *Vitesse\z
NouveauPointOrigine\x = *PositionInitiale\x
NouveauPointOrigine\y = *PositionInitiale\y
NouveauPointOrigine\z = *PositionInitiale\z
;On se replace un peu avant le point de d'intersection calculé dans TestCollision()
If InfosCollision\DistanceLaPlusCourte > DistanceTresFaible
V\x = *Vitesse\x
V\y = *Vitesse\y
V\z = *Vitesse\z
LongueurVecteur(@V, InfosCollision\DistanceLaPlusCourte - 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)
InfosCollision\PointIntersection\x - DistanceTresFaible * V\x
InfosCollision\PointIntersection\y - DistanceTresFaible * V\y
InfosCollision\PointIntersection\z - DistanceTresFaible * V\z
EndIf
;Determine le plan de glissement
PlanDeGlissement\Origine\x = InfosCollision\PointIntersection\x
PlanDeGlissement\Origine\y = InfosCollision\PointIntersection\y
PlanDeGlissement\Origine\z = InfosCollision\PointIntersection\z
PlanDeGlissement\Normale\x = NouveauPointOrigine\x - InfosCollision\PointIntersection\x
PlanDeGlissement\Normale\y = NouveauPointOrigine\y - InfosCollision\PointIntersection\y
PlanDeGlissement\Normale\z = NouveauPointOrigine\z - InfosCollision\PointIntersection\z
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
NouveauPointDestination\x = PointDestination\x - Longueur1 * PlanDeGlissement\Normale\x
NouveauPointDestination\y = PointDestination\y - Longueur1 * PlanDeGlissement\Normale\y
NouveauPointDestination\z = PointDestination\z - Longueur1 * PlanDeGlissement\Normale\z
;Calcul la nouvelle vitesse (le long du plan de glissement)
NouvelleVitesse\x = NouveauPointDestination\x - InfosCollision\PointIntersection\x
NouvelleVitesse\y = NouveauPointDestination\y - InfosCollision\PointIntersection\y
NouvelleVitesse\z = NouveauPointDestination\z - InfosCollision\PointIntersection\z
;Inutile de reboucler si la nouvelle vitesse est faible
If Longueur(@NouvelleVitesse) <= DistanceTresFaible
*PositionFinale\x = NouveauPointOrigine\x
*PositionFinale\y = NouveauPointOrigine\y
*PositionFinale\z = NouveauPointOrigine\z
ProcedureReturn
EndIf
NombreDeRebouclage + 1
ReponseCollision(*PositionFinale, @NouveauPointOrigine, @NouvelleVitesse)
EndProcedure
Procedure GestionDeplacement(*InfosCollision.s_Collision)
Protected PositionDansBaseE.Vecteur, VitesseDansBaseE.Vecteur, PositionFinale.Vecteur
;Calcul la position et la vitesse dans la base de l'Ellipsoide
PositionDansBaseE\x = *InfosCollision\PositionDansR3\x / *InfosCollision\RayonEllipsoide\x
PositionDansBaseE\y = *InfosCollision\PositionDansR3\y / *InfosCollision\RayonEllipsoide\y
PositionDansBaseE\z = *InfosCollision\PositionDansR3\z / *InfosCollision\RayonEllipsoide\z
VitesseDansBaseE\x = *InfosCollision\VitesseDansR3\x / *InfosCollision\RayonEllipsoide\x
VitesseDansBaseE\y = *InfosCollision\VitesseDansR3\y / *InfosCollision\RayonEllipsoide\y
VitesseDansBaseE\z = *InfosCollision\VitesseDansR3\z / *InfosCollision\RayonEllipsoide\z
;Gestion du déplacement
NombreDeRebouclage = 0
ReponseCollision(@PositionFinale, @PositionDansBaseE, @VitesseDansBaseE)
;Gestion de la gravité
VitesseDansBaseE\x = gravite\x / *InfosCollision\RayonEllipsoide\x
VitesseDansBaseE\y = gravite\y / *InfosCollision\RayonEllipsoide\y
VitesseDansBaseE\z = gravite\z / *InfosCollision\RayonEllipsoide\z
NombreDeRebouclage = 0
ReponseCollision(@PositionFinale, @PositionFinale, @VitesseDansBaseE)
;Conversion de la position finale dans R3
*InfosCollision\PositionDansR3\x = PositionFinale\x * *InfosCollision\RayonEllipsoide\x
*InfosCollision\PositionDansR3\y = PositionFinale\y * *InfosCollision\RayonEllipsoide\y
*InfosCollision\PositionDansR3\z = PositionFinale\z * *InfosCollision\RayonEllipsoide\z
EndProcedure
LoadTexture(9,"Plafond_U5_01.jpg")
Code : Tout sélectionner
;Ajoute une entity par segment
NoEntity + 1
Delta.f=#Hauteur/1.0
Dx.f=SX/Delta
If Dx<1
dx=1
EndIf
MakeMesh(NoEntity,Dx,SY/Delta)
CreateEntity(NoEntity,MeshID(NoEntity),MaterialID(1+Random(4)))
EntityLocate(NoEntity,PX,#Hauteur/2,PZ)
ScaleEntity(NoEntity,SX,SZ,SY)
RotateEntity(NoEntity, Angle,90,0)
Code : Tout sélectionner
;Ajoute une entity par segment
NoEntity + 1
CreateEntity(NoEntity,MeshID(1),MaterialID(1+Random(4)))
EntityLocate(NoEntity,PX,#Hauteur/2,PZ)
ScaleEntity(NoEntity,SX,SZ,SY)
RotateEntity(NoEntity, Angle,90,0)
Code : Tout sélectionner
;Comtois le 09/12/05
;PB 3.94 et ogre 1.03
;Je me suis grandement inspiré du tutoriel de Fauerby http://www.peroxide.dk
XIncludeFile "VisuMap4DFR.pbi"
;-Initialisation
#ScreenWidth = 800 : #ScreenHeight = 600 : #ScreenDepth = 32
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 PlateForme" ) = 0
MessageRequester( "Erreur" , "Impossible d'ouvrir l'écran " , 0 )
End
EndIf
Add3DArchive("Textures" , #PB_3DArchive_FileSystem)
Add3DArchive("Textures\Skybox.zip", #PB_3DArchive_Zip)
;-Mesh
M3D_CreateMesh(0,#M3D_Cube)
M3D_CreateMesh(1,#M3D_Plain)
M3D_CreateMesh(2,#M3D_Sphere)
;- Textures
LoadTexture(1,"Mur_U3_01.jpg")
LoadTexture(2,"Mur_U3_05.jpg")
LoadTexture(3,"Mur_U3_06.jpg")
LoadTexture(4,"Mur_U3_07.jpg")
LoadTexture(5,"Mur_U3_08.jpg")
LoadTexture(6,"Mur_U3_08.jpg")
LoadTexture(7,"Sol_m_01.jpg")
LoadTexture(8,"Sol_U2_01.jpg")
LoadTexture(9,"Plafond_U5_01.jpg")
;- Material
For i = 1 To 9
CreateMaterial(i, TextureID(i))
Next i
;- Camera
CreateCamera(0, 0, 0 , 100 , 100)
CameraFOV(0,45)
AmbientColor(RGB(215,215,215))
;-Les procédures
Procedure Renum()
ForEach Sommet()
No = Sommet()\No
Sommet()\No = ListIndex(Sommet())
ForEach Segment()
If Segment()\Sommet1 = No
Segment()\Sommet1 = Sommet()\No
ElseIf Segment()\Sommet2 = No
Segment()\Sommet2 = Sommet()\No
EndIf
Next
Next
EndProcedure
Procedure Charge()
If ReadFile(0,"Sommets.hd")=0 : End : EndIf
ClearList(Sommet())
While Eof(0)=0
AddElement(Sommet())
Sommet()\No = ReadLong()
Sommet()\X = ReadLong()
Sommet()\Y = ReadLong()
Wend
CloseFile(0)
ReadFile(0,"Segment.hd")
ClearList(Segment())
While Eof(0)=0
AddElement(Segment())
Segment()\Sommet1 = ReadLong()
Segment()\x1 = ReadLong()
Segment()\Y1 = ReadLong()
Segment()\Sommet2 = ReadLong()
Segment()\x2 = ReadLong()
Segment()\Y2 = ReadLong()
x1 = Segment()\x1
Y1 = Segment()\Y1
x2 = Segment()\x2
Y2 = Segment()\Y2
Segment()\Long = Sqr(Pow(x1-x2,2)+Pow(Y1-Y2,2))
Wend
CloseFile(0)
Renum()
EndProcedure
Procedure AffSegment(Aff)
StartDrawing(ScreenOutput())
If aff
ForEach Segment()
LineXY(Segment()\X1,Segment()\Y1,Segment()\X2,Segment()\Y2,RGB(255,255,255))
Next
Circle(CameraX(0),CameraZ(0),RayonEllipsoide\x-1,RGB(55,55,255))
Else
;Le viseur
DrawingMode(4)
Circle(400,300,16,RGB(255,255,255))
Line(395,300,10,0,RGB(255,255,255))
Line(400,295,0,10,RGB(255,255,255))
EndIf
DrawText("FPS : " + Str(Engine3DFrameRate(#PB_Engine3D_Current)))
StopDrawing()
EndProcedure
Procedure MakePlan()
Protected p2_p1.Vecteur, p3_p1.Vecteur
p2_p1\x = ListTriangle()\P2\x - ListTriangle()\P1\x
p2_p1\y = ListTriangle()\P2\y - ListTriangle()\P1\y
p2_p1\z = ListTriangle()\P2\z - ListTriangle()\P1\z
p3_p1\x = ListTriangle()\P3\x - ListTriangle()\P1\x
p3_p1\y = ListTriangle()\P3\y - ListTriangle()\P1\y
p3_p1\z = ListTriangle()\P3\z - ListTriangle()\P1\z
ProduitVectoriel(@ListTriangle()\Normale,@p2_p1,@p3_p1)
Normalise(@ListTriangle()\Normale)
ListTriangle()\Origine\x = ListTriangle()\P1\x
ListTriangle()\Origine\y = ListTriangle()\P1\y
ListTriangle()\Origine\z = ListTriangle()\P1\z
ListTriangle()\Constante = -(ListTriangle()\Normale\x * ListTriangle()\Origine\x + ListTriangle()\Normale\y * ListTriangle()\Origine\y + ListTriangle()\Normale\z * ListTriangle()\Origine\z)
EndProcedure
Procedure MakeTriangles(*Surface.Face)
;Pour chaque plan , on a deux triangles , voici le premier
AddElement(ListTriangle())
ListTriangle()\P1\x=*Surface\Point[0]\x / RayonEllipsoide\x
ListTriangle()\P1\y=*Surface\Point[0]\y / RayonEllipsoide\y
ListTriangle()\P1\z=*Surface\Point[0]\z / RayonEllipsoide\z
ListTriangle()\P2\x=*Surface\Point[2]\x / RayonEllipsoide\x
ListTriangle()\P2\y=*Surface\Point[2]\y / RayonEllipsoide\y
ListTriangle()\P2\z=*Surface\Point[2]\z / RayonEllipsoide\z
ListTriangle()\P3\x=*Surface\Point[3]\x / RayonEllipsoide\x
ListTriangle()\P3\y=*Surface\Point[3]\y / RayonEllipsoide\y
ListTriangle()\P3\z=*Surface\Point[3]\z / RayonEllipsoide\z
MakePlan()
;Et voici le second
AddElement(ListTriangle())
ListTriangle()\P1\x=*Surface\Point[0]\x / RayonEllipsoide\x
ListTriangle()\P1\y=*Surface\Point[0]\y / RayonEllipsoide\y
ListTriangle()\P1\z=*Surface\Point[0]\z / RayonEllipsoide\z
ListTriangle()\P2\x=*Surface\Point[1]\x / RayonEllipsoide\x
ListTriangle()\P2\y=*Surface\Point[1]\y / RayonEllipsoide\y
ListTriangle()\P2\z=*Surface\Point[1]\z / RayonEllipsoide\z
ListTriangle()\P3\x=*Surface\Point[2]\x / RayonEllipsoide\x
ListTriangle()\P3\y=*Surface\Point[2]\y / RayonEllipsoide\y
ListTriangle()\P3\z=*Surface\Point[2]\z / RayonEllipsoide\z
MakePlan()
EndProcedure
Procedure MakeEntity()
Protected Surface.Face
;Ellipsoide de la caméra
RayonEllipsoide\x = 13.0
RayonEllipsoide\y = 26.0
RayonEllipsoide\z = 13.0
NoEntity = 10 ; Reserve les 10 premières entitys
ForEach Segment()
;Calcul les caractéristiques de l'entity
Adjacent.f = (Segment()\x1 - Segment()\x2)
Oppose.f = (Segment()\Y1 - Segment()\Y2)
Hypothenuse.f = Sqr(Adjacent*Adjacent + Oppose*Oppose)
Angle.f = ACos(Adjacent/Hypothenuse)/0.0174533
If Segment()\Y1 > Segment()\Y2
Angle = 360 - Angle
EndIf
SX.f = (Segment()\Long)
SY.f = #Hauteur
SZ.f = 0
PX.f = ((Segment()\x1 + Segment()\x2) /2.0)
PZ.f = ((Segment()\Y1 + Segment()\Y2) /2.0)
;Ajoute une entity par segment
NoEntity + 1
Delta.f=SY/1.0
Dx.f=SX/Delta
If Dx<1
dx=1
EndIf
MakeMesh(NoEntity,Dx,SY/Delta)
CreateEntity(NoEntity,MeshID(NoEntity),MaterialID(1+Random(4)))
EntityLocate(NoEntity,PX,#Hauteur / 2,PZ)
ScaleEntity(NoEntity,SX,SZ,SY)
RotateEntity(NoEntity, Angle,90,0)
;Pour chaque segment il faut créer deux triangles
Surface\Point[0]\x=Segment()\x1
Surface\Point[0]\y=#Hauteur
Surface\Point[0]\z=Segment()\y1
Surface\Point[1]\x=Segment()\x2
Surface\Point[1]\y=#Hauteur
Surface\Point[1]\z=Segment()\y2
Surface\Point[2]\x=Segment()\x2
Surface\Point[2]\y=0.0
Surface\Point[2]\z=Segment()\y2
Surface\Point[3]\x=Segment()\x1
Surface\Point[3]\y=0.0
Surface\Point[3]\z=Segment()\y1
MakeTriangles(@Surface)
Next
;Ajoute un sol
Surface\Point[0]\x=0.0
Surface\Point[0]\y=0.0
Surface\Point[0]\z=0.0
Surface\Point[1]\x=800.0
Surface\Point[1]\y=0.0
Surface\Point[1]\z=0.0
Surface\Point[2]\x=800.0
Surface\Point[2]\y=0.0
Surface\Point[2]\z=600.0
Surface\Point[3]\x=0.0
Surface\Point[3]\y=0.0
Surface\Point[3]\z=600.0
MakeTriangles(@Surface)
For j = 1 To 6
For i = 1 To 8
NoEntity + 1
CreateEntity(NoEntity,MeshID(1),MaterialID(8))
ScaleEntity(NoEntity, 100, 1, 100)
EntityLocate(NoEntity, 100 * i - 50, 0 , 100 * j - 50)
Next i
Next j
;Un Plafond
For j = 1 To 6
For i = 1 To 8
NoEntity + 1
CreateEntity(NoEntity,MeshID(1),MaterialID(9))
ScaleEntity(NoEntity, 100, 1, 100)
EntityLocate(NoEntity, 100 * i - 50, #Hauteur, 100 * j - 50)
Next i
Next j
;Les escaliers
NbMarche = 8
HauteurEscalier.f = 9.0
LargeurEscalier.f = 53.0
ProfondeurEscalier.f = 32.0
EscalierX.f = 299
EscalierZ.f = 218+40
For i=1 To NbMarche
Surface\Point[0]\x=EscalierX - LargeurEscalier / 2
Surface\Point[0]\y=i * HauteurEscalier
Surface\Point[0]\z=EscalierZ + i * ProfondeurEscalier - ProfondeurEscalier / 2
Surface\Point[1]\x=EscalierX + LargeurEscalier / 2
Surface\Point[1]\y=i * HauteurEscalier
Surface\Point[1]\z=EscalierZ + i * ProfondeurEscalier - ProfondeurEscalier / 2
Surface\Point[2]\x=EscalierX + LargeurEscalier / 2
Surface\Point[2]\y=i * HauteurEscalier
Surface\Point[2]\z=EscalierZ + i * ProfondeurEscalier + ProfondeurEscalier / 2
Surface\Point[3]\x=EscalierX - LargeurEscalier / 2
Surface\Point[3]\y=i * HauteurEscalier
Surface\Point[3]\z=EscalierZ + i * ProfondeurEscalier + ProfondeurEscalier / 2
MakeTriangles(@Surface)
NoEntity + 1
CreateEntity(NoEntity,MeshID(0),MaterialID(7))
ScaleEntity(NoEntity, LargeurEscalier, HauteurEscalier * i, ProfondeurEscalier)
EntityLocate(NoEntity, EscalierX, i * HauteurEscalier - HauteurEscalier*i/2, EscalierZ + i * ProfondeurEscalier)
Next i
;Pour visualiser le tir
SphereI= NoEntity + 1
CreateEntity(SphereI,MeshID(2),MaterialID(7))
ScaleEntity(SphereI, 3, 3, 3)
EndProcedure
;/
;-La boucle principale
;/
Charge()
MakeEntity()
PasX.f=0.0
PasZ.f=0.0
InfosNinja.s_Collision
;Position de déPart
InfosNinja\PositionDansR3\x = 200
InfosNinja\PositionDansR3\y = 26
InfosNinja\PositionDansR3\z = 300
InfosNinja\VitesseDansR3\x = 0.0
InfosNinja\VitesseDansR3\y = 0.0
InfosNinja\VitesseDansR3\z = 0.0
InfosNinja\RayonEllipsoide\x=RayonEllipsoide\x
InfosNinja\RayonEllipsoide\y=RayonEllipsoide\y
InfosNinja\RayonEllipsoide\z=RayonEllipsoide\z
CameraLocate(0,InfosNinja\PositionDansR3\x, InfosNinja\PositionDansR3\y + RayonEllipsoide\y , InfosNinja\PositionDansR3\z)
CameraLookAt(0,InfosNinja\PositionDansR3\x + M3D_Cos(Camera\AngleX) * 80, InfosNinja\PositionDansR3\y + RayonEllipsoide\y ,InfosNinja\PositionDansR3\z - M3D_Sin(Camera\AngleX ) * 80)
Gravite\y=-#CameraSpeed
Gravite\x=0
Gravite\z=0
modeaff=1
MouseX.f
MouseY.f
Repeat
ClearScreen(0, 0, 0)
If ExamineMouse()
MouseX = -(MouseDeltaX()/10)*#CameraSpeed/2
MouseY = -(MouseDeltaY()/10)*#CameraSpeed/2
If MouseButton(1)
Tir=1
EntityLocate(SphereI,InfosNinja\PositionDansR3\x, InfosNinja\PositionDansR3\y, InfosNinja\PositionDansR3\z)
TirA\x=M3D_Cos(Camera\AngleX) * 2
TirA\y=M3D_Sin(Camera\AngleY) * 2
TirA\z=-M3D_Sin(Camera\AngleX) * 2
EndIf
EndIf
If ExamineKeyboard()
If KeyboardReleased(#PB_Key_F1) : Aff2D = 1 - Aff2D : EndIf
; Touches du joueur
Camera\AngleX = M3D_WrapValue( Camera\AngleX + MouseX)
RotateCamera(0,MouseX,0,0)
If MouseY > 0 And Camera\AngleY < 25
Camera\AngleY + MouseY
RotateCamera(0,0,MouseY,0)
ElseIf MouseY < 0 And Camera\AngleY > -25
Camera\AngleY + MouseY
RotateCamera(0,0,MouseY,0)
EndIf
If KeyboardPushed(#PB_Key_Left)
InfosNinja\VitesseDansR3\x + M3D_Cos(Camera\AngleX+90) * #CameraSpeed
InfosNinja\VitesseDansR3\z - M3D_Sin(Camera\AngleX+90) * #CameraSpeed
ElseIf KeyboardPushed(#PB_Key_Right)
InfosNinja\VitesseDansR3\x + M3D_Cos(Camera\AngleX-90) * #CameraSpeed
InfosNinja\VitesseDansR3\z - M3D_Sin(Camera\AngleX-90) * #CameraSpeed
EndIf
If KeyboardPushed(#PB_Key_Up)
InfosNinja\VitesseDansR3\x + M3D_Cos(Camera\AngleX) * #CameraSpeed
InfosNinja\VitesseDansR3\z - M3D_Sin(Camera\AngleX) * #CameraSpeed
ElseIf KeyboardPushed(#PB_Key_Down)
InfosNinja\VitesseDansR3\x + M3D_Cos(Camera\AngleX) * -#CameraSpeed
InfosNinja\VitesseDansR3\z - M3D_Sin(Camera\AngleX) * -#CameraSpeed
EndIf
If KeyboardPushed(#PB_Key_Space)
EndIf
EndIf
If NormeAuCarre(@InfosNinja\VitesseDansR3)>#CameraSpeed * #CameraSpeed
LongueurVecteur(@InfosNinja\VitesseDansR3,#CameraSpeed)
EndIf
GestionDeplacement(@InfosNinja)
CameraLocate(0,InfosNinja\PositionDansR3\x, InfosNinja\PositionDansR3\y, InfosNinja\PositionDansR3\z)
InfosNinja\VitesseDansR3\x = 0.0
InfosNinja\VitesseDansR3\z = 0.0
If tir=1
MoveEntity(SphereI,TirA\x,TirA\y,TirA\z)
EndIf
RenderWorld()
AffSegment(Aff2D)
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
Procedure MakeMesh(No,U,V)
If CreateMesh(No)
*Ptr.Vertex=AllocateMemory(SizeOf(Vertex)*4)
*Mem.Vertex = *Ptr
*Mem\px=-0.5
*Mem\py=0
*Mem\pz=-0.5
*Mem\nx=0
*Mem\ny=1
*Mem\nz=0
*Mem\U=0
*Mem\V=0
*Mem+SizeOf(Vertex)
*Mem\px=-0.5
*Mem\py=0
*Mem\pz=0.5
*Mem\nx=0
*Mem\ny=1
*Mem\nz=0
*Mem\U=0
*Mem\V=V
*Mem+SizeOf(Vertex)
*Mem\px=0.5
*Mem\py=0
*Mem\pz=0.5
*Mem\nx=0
*Mem\ny=1
*Mem\nz=0
*Mem\U=U
*Mem\V=V
*Mem+SizeOf(Vertex)
*Mem\px=0.5
*Mem\py=0
*Mem\pz=-0.5
*Mem\nx=0
*Mem\ny=1
*Mem\nz=0
*Mem\U=U
*Mem\V=0
Flag = #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate
SetMeshData(No,Flag ,*Ptr,4)
SetMeshData(No,#PB_Mesh_face,?IndexPlain,4)
ProcedureReturn *Ptr
Else
ProcedureReturn 0
EndIf
EndProcedure
DataSection
IndexPlain:
Data.w 0,1,2
Data.w 2,3,0
Data.w 2,1,0
Data.w 0,3,2
EndDataSection
Ben, je peux bricoler en C, en C++ déjà beaucoup moins, et alors les sources de Quakecomtois a écrit :Tiens toi qui bricole en C ou C++ , tu ne pourrais pas jeter un oeil dans les sources de Quake3 pour récupérer la gestion des collisions BSP et nous en faire une petite lib ?? ou quelqu'un d'autre , je ne suis pas contrariant
Code : Tout sélectionner
ForEach ListTriangle()
TestCollision(@InfosCollision)
Next
Code : Tout sélectionner
;ForEach ListTriangle()
TestCollision(@InfosCollision)
;Next
Structures encapsulées ? lesquelles ? tu peux être plus précis sur le point qui te bloque ?Polo a écrit :comptois, je vais faire mon chieur, mais est ce que tu pourrais m'expliquer ce que tu fais pour obtenir les réponses de la collision ? Ton code est assez barbare, avec toutes ces structures encapsulées