Seite 2 von 2

Verfasst: 06.12.2004 18:00
von Lukas-P
Is die Procedure nicht für OpenGL?

Verfasst: 06.12.2004 18:18
von Lukas-P
Gibt es den noch irgendeine andere Art, wie ich bri ego-Shooter feststellen kann ob ich gerade einen getroffen hab??

Verfasst: 06.12.2004 18:44
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...

Verfasst: 06.12.2004 19:25
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 ;)

Verfasst: 06.12.2004 20:38
von Lukas-P
@Dark Dragon: Kannst du mir das ma erklären :oops:

Verfasst: 07.12.2004 07:48
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?