3D Engine Kollision

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
Lukas-P
Beiträge: 262
Registriert: 07.10.2004 12:03

Beitrag von Lukas-P »

Is die Procedure nicht für OpenGL?
Benutzeravatar
Lukas-P
Beiträge: 262
Registriert: 07.10.2004 12:03

Beitrag von Lukas-P »

Gibt es den noch irgendeine andere Art, wie ich bri ego-Shooter feststellen kann ob ich gerade einen getroffen hab??
traumatic
Beiträge: 478
Registriert: 27.11.2004 15:42

Beitrag von traumatic »

DarkDragon hat geschrieben:Hab ich ja schon. Sogar für ne genaue Kollision:

http://robsite.de/php/pureboard-archiv/ ... php?t=5160
Wahrscheinlich bekomme ich gleich ein "Besserwisser" von links oder rechts,
aber ich habe den Code gerade zum ersten Mal gesehen und hätte nach
kurzem Überfliegen folgenden Optimierungsvorschlag (gerade in Bezug auf
Deinen baldigen Release, DarkDragon ;)) :

Originalcode:

Code: Alles auswählen

Mag.f = Magnitude(vLineDir\X, vLineDir\Y, vLineDir\Z)

vLineDir\X / Mag
vLineDir\Y / Mag
vLineDir\Z / Mag 

Vorschlag:

Code: Alles auswählen

Mag.f = 1/Magnitude(vLineDir\X, vLineDir\Y, vLineDir\Z)

vLineDir\X * Mag
vLineDir\Y * Mag
vLineDir\Z * Mag 
Keine Ahnung, ob PB das schon von sich aus optimiert, ich glaub's aber eher nicht...
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

Lukas-P hat geschrieben:Is die Procedure nicht für OpenGL?
hehe, nein, man kann es für alle 3DSachen nehmen. Nur das grafische ist OpenGL ;) .

@traumatic: in meiner sammlung hab ichs verbessert, auch in meiner Engine.
[Edit] achja@Lukas-P: Es gibt eine Edit funktion ;)
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
Lukas-P
Beiträge: 262
Registriert: 07.10.2004 12:03

Beitrag von Lukas-P »

@Dark Dragon: Kannst du mir das ma erklären :oops:
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

Ok, das ist der Code den du brauchst:

Code: Alles auswählen

Global PI.f
PI.f = ATan(1)*4

#WindowWidth = 500
#WindowHeight = 400
#WindowFlags = #PB_Window_TitleBar | #PB_Window_MaximizeGadget | #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered
Version = 1

Procedure MyWindowCallback(WindowID, Message, wParam, lParam)
  Result = #PB_ProcessPureBasicEvents
  If Message = #WM_SIZE
    glViewport_(0, 0, WindowWidth(), WindowHeight())
    Result = 1
  EndIf
  ProcedureReturn Result
EndProcedure

Structure Point3D
  X.f
  Y.f
  Z.f
EndStructure

Dim Vec.Point3D(2)
Dim Line3D.Point3D(1)

Procedure.f Magnitude(X.f, Y.f, Z.f)
  ProcedureReturn Sqr(X*X + Y*Y + Z*Z)
EndProcedure

Procedure OGLSetCamera(FOV.f, X.f, Y.f, Z.f, AngleX.f, AngleY.f, AngleZ.f, Near.f, Far.f)
  If AngleY <= 0
    AngleY + 360
  ElseIf AngleY > 360
    AngleY - 360
  EndIf
  If AngleX <= 0
    AngleX + 360
  ElseIf AngleX > 360
    AngleX - 360
  EndIf
  If AngleZ <= 0
    AngleZ + 360
  ElseIf AngleZ > 360
    AngleZ - 360
  EndIf
  glMatrixMode_(5889)
  glLoadIdentity_()
  gluPerspective__(FOV, WindowWidth()/WindowHeight(), Near.f, Far.f)
  glRotatef_(AngleX, 1.0, 0.0, 0.0)
  glRotatef_(AngleY, 0.0, 1.0, 0.0)
  glRotatef_(AngleZ, 0.0, 0.0, 1.0)
  glTranslatef_(X, Y, Z)
  glMatrixMode_(5888)
EndProcedure

Procedure.l Normal(*Pos1.Point3D, *Pos2.Point3D, *Pos3.Point3D, *vNormal.Point3D)
  vVector1.Point3D
  vVector1\X = *Pos1\X - *Pos2\X
  vVector1\Y = *Pos1\Y - *Pos2\Y
  vVector1\Z = *Pos1\Z - *Pos2\Z
  vVector2.Point3D
  vVector2\X = *Pos1\X - *Pos3\X
  vVector2\Y = *Pos1\Y - *Pos3\Y
  vVector2\Z = *Pos1\Z - *Pos3\Z

  *vNormal\X = ((vVector1\Y * vVector2\Z) - (vVector1\Z * vVector2\Y))
  *vNormal\Y = ((vVector1\Z * vVector2\X) - (vVector1\X * vVector2\Z))
  *vNormal\Z = ((vVector1\X * vVector2\Y) - (vVector1\Y * vVector2\X))

  Magnitude.f = Magnitude(*vNormal\X, *vNormal\Y, *vNormal\Z)

  *vNormal\X / Magnitude
  *vNormal\Y / Magnitude
  *vNormal\Z / Magnitude
EndProcedure

Procedure.f PlaneDistance(*vNormal.Point3D, *Point.Point3D)
  distance.f = 0
  distance = - ((*vNormal\X * *Point\X) + (*vNormal\Y * *Point\Y) + (*vNormal\Z * *Point\Z))
  ProcedureReturn distance.f
EndProcedure

Procedure IntersectedPlane(*LPos1.Point3D, *LPos2.Point3D, *TPos1.Point3D, *TPos2.Point3D, *TPos3.Point3D, *vNormal.Point3D)
  distance1.f=0
  distance2.f=0

  originDistance.f = PlaneDistance(*vNormal.Point3D, *TPos1.Point3D)

  distance1 = ((*vNormal\X * *LPos1\X) + (*vNormal\Y * *LPos1\Y) + (*vNormal\Z * *LPos1\Z)) + originDistance
  distance2 = ((*vNormal\X * *LPos2\X) + (*vNormal\Y * *LPos2\Y) + (*vNormal\Z * *LPos2\Z)) + originDistance
  If distance1 * distance2 >= 0
    ProcedureReturn 0
  Else
    ProcedureReturn 1
  EndIf
EndProcedure

Procedure.f Dot(*vVector1.Point3D, *vVector2.Point3D)
  ProcedureReturn ((*vVector1\x * *vVector2\x) + (*vVector1\y * *vVector2\y) + (*vVector1\z * *vVector2\z))
EndProcedure

Procedure Isnan(Num.f)
  If StrF(Num, 6) = "-1.#IND00"
    ProcedureReturn 1
  EndIf
EndProcedure

Procedure.f AngleBetweenVectors(*Vector1.Point3D, *Vector2.Point3D)
  dotProduct.f = Dot(*Vector1, *Vector2)   

  vectorsMagnitude.f = Magnitude(*Vector1\X, *Vector1\Y, *Vector1\Z) * Magnitude(*Vector2\X, *Vector2\Y, *Vector2\Z)

  angle.f = ACos(dotProduct / vectorsMagnitude)

  If Isnan(angle.f)
    ProcedureReturn 0
  Else
    ProcedureReturn angle
  EndIf
EndProcedure

Procedure InsidePolygon(*vIntersection.Point3D, *TPos1.Point3D, *TPos2.Point3D, *TPos3.Point3D)
  vA.Point3D
  vB.Point3D
  Angle.f = 0.0
  MATCH_FACTOR.f = 0.9999

  vA\X = *TPos1\X - *vIntersection\X
  vA\Y = *TPos1\Y - *vIntersection\Y
  vA\Z = *TPos1\Z - *vIntersection\Z

  vB\X = *TPos2\X - *vIntersection\X
  vB\Y = *TPos2\Y - *vIntersection\Y
  vB\Z = *TPos2\Z - *vIntersection\Z

  Angle + AngleBetweenVectors(@vA, @vB)

  vA\X = *TPos2\X - *vIntersection\X
  vA\Y = *TPos2\Y - *vIntersection\Y
  vA\Z = *TPos2\Z - *vIntersection\Z

  vB\X = *TPos3\X - *vIntersection\X
  vB\Y = *TPos3\Y - *vIntersection\Y
  vB\Z = *TPos3\Z - *vIntersection\Z

  Angle + AngleBetweenVectors(@vA, @vB)

  vA\X = *TPos3\X - *vIntersection\X
  vA\Y = *TPos3\Y - *vIntersection\Y
  vA\Z = *TPos3\Z - *vIntersection\Z

  vB\X = *TPos1\X - *vIntersection\X
  vB\Y = *TPos1\Y - *vIntersection\Y
  vB\Z = *TPos1\Z - *vIntersection\Z

  Angle + AngleBetweenVectors(@vA, @vB)

  If Angle >= (MATCH_FACTOR * (2.0 * PI))
    ProcedureReturn 1
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure IntersectionPoint(*vNormal.Point3D, *LPos1.Point3D, *LPos2.Point3D, distance.f)
  vPoint.Point3D
  vLineDir.Point3D

  Numerator.f = 0.0
  Denominator.f = 0.0
  dist.f = 0.0

  vLineDir\X = *LPos2\X - *LPos1\X
  vLineDir\Y = *LPos2\Y - *LPos1\Y
  vLineDir\Z = *LPos2\Z - *LPos1\Z

  Mag.f = 1/Magnitude(vLineDir\X, vLineDir\Y, vLineDir\Z)

  vLineDir\X * Mag
  vLineDir\Y * Mag
  vLineDir\Z * Mag

  Numerator = - (*vNormal\X * *LPos1\X + *vNormal\Y * *LPos1\Y + *vNormal\Z * *LPos1\Z + distance)
  Denominator = Dot(*vNormal, @vLineDir)

  If Denominator = 0.0
    ProcedureReturn *LPos1
  EndIf

  dist = Numerator / Denominator

  vPoint\X = (*LPos1\X + (vLineDir\X * dist))
  vPoint\Y = (*LPos1\Y + (vLineDir\y * dist))
  vPoint\Z = (*LPos1\Z + (vLineDir\z * dist))

  ProcedureReturn @vPoint
EndProcedure

Procedure IntersectedPolygon(*TPos1.Point3D, *TPos2.Point3D, *TPos3.Point3D, *LPos1.Point3D, *LPos2.Point3D, *vNormal.Point3D)
  originDistance.f = PlaneDistance(*vNormal.Point3D, *TPos1.Point3D)
  If IntersectedPlane(*LPos1.Point3D, *LPos2.Point3D, *TPos1.Point3D, *TPos2.Point3D, *TPos3.Point3D, *vNormal.Point3D) = 0
    ProcedureReturn 0
  EndIf
  CopyMemory(IntersectionPoint(*vNormal.Point3D, *LPos1.Point3D, *LPos2.Point3D, originDistance), @vIntersection.Point3D, SizeOf(Point3D))
  If InsidePolygon(@vIntersection, *TPos1.Point3D, *TPos2.Point3D, *TPos3.Point3D) = 1
    ProcedureReturn 1
  EndIf
EndProcedure 
Den fügst du am anfang deines Codes ein.
Vorraussetzung für das ganze ist natürlich, dass du weißt wie das Modelformat von Ogre aufgebaut ist oder du erstellst deine Meshes durch DataSection und EndDataSection.

Dann liest du die ganze Sache in einen Array mit der Struktur Point3D. Doch du solltest nicht alles in den selben array speichern. Die Normalen , Texturpositionen und die Dreiecke getrennt ;) .
Dann gehst du bei jeder Bewegung durch, ob das sich Bewegende Objekt mit den anderen Objekten der Welt kollidiert. Wenn ja, dann bewegst du es einfach nicht. Wenn nein, dann bewegst du es. Eine Box-kollision sollte aber zuerst mal stattfinden.

Hier einmal 2 Prozeduren:

Code: Alles auswählen

Procedure SphereCollision(X1.f, Y1.f, Z1.f, Size1.f, X2.f, Y2.f, Z2.f, Size2.f) ;Size ist der Radius
   If Sqr((X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2)+(Z1-Z2)*(Z1-Z2)) <= Size1+Size2
      Result = 1
   Else
      Result = 0
   EndIf
   ProcedureReturn Result
EndProcedure

Procedure BoxCollision(X1.f, Y1.f, Z1.f, SizeX1.f, SizeY1.f, SizeZ1.f, X2.f, Y2.f, Z2.f, SizeX2.f, SizeY2.f, SizeZ2.f) ;Size ist der Radius der einzelnen Objekte
   If Sqr((X1-X2)*(X1-X2)) <= SizeX1+SizeX2 And Sqr((Y1-Y2)*(Y1-Y2)) <= SizeY1+SizeY2 And Sqr((Z1-Z2)*(Z1-Z2)) <= SizeZ1+SizeZ2
      Result = 1
   Else
      Result = 0
   EndIf
   ProcedureReturn Result
EndProcedure

Debug "Sollte 1 ergeben:"
Debug "Sphere: "+Str(SphereCollision(0.0, 0.0, 0.0, 1.5, 0.0, 0.0, 2.0, 1.0))
Debug "Box: "+Str(BoxCollision(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.5, 1.0, 1.0))

Debug "Sollte 0 ergeben:"
Debug "Sphere: "+Str(SphereCollision(0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 2.0, 1.0))
Debug "Box: "+Str(BoxCollision(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 2.0, 0.0, 0.0, 0.5, 1.0, 1.0)) 
Achja: kann das mal bitte ein Moderator ins richtige Forum verschieben?
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Antworten