3DTrianglecollision

Share your advanced PureBasic knowledge/code with the community.
DarkDragon
Addict
Addict
Posts: 2345
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

3DTrianglecollision

Post by DarkDragon »

Hello,

This code isn't commented, but you can use it through the procedures and structures:

Code: Select all

IncludeFile "C:\Programme\PureBASIC\Examples\Sources - Advanced\OpenGL Cube\OpenGL.pbi"

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 = 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

If OpenWindow(0, 0, 0, #WindowWidth, #WindowHeight, #WindowFlags, "Trianglecollision by DarkDragon")

SetWindowCallback(@MyWindowCallback())

hWnd = WindowID(0)
pfd.PIXELFORMATDESCRIPTOR   ;OpenGL starten
hDC = GetDC_(hWnd)
pfd\nSize        = SizeOf(PIXELFORMATDESCRIPTOR)
pfd\nVersion     = 1
pfd\dwFlags      = #PFD_SUPPORT_OPENGL | #PFD_DOUBLEBUFFER | #PFD_DRAW_TO_WINDOW
pfd\iLayerType   = #PFD_MAIN_PLANE
pfd\iPixelType   = #PFD_TYPE_RGBA
pfd\cColorBits   = 24
pfd\cDepthBits   = 32
pixformat = ChoosePixelFormat_(hDC, pfd)
SetPixelFormat_(hDC, pixformat, pfd)
hrc = wglCreateContext_(hDC)
wglMakeCurrent_(hDC, hrc)

SwapBuffers_(hDC)

glEnable_(#GL_DEPTH_TEST)

Vec(0)\X = -0.225
Vec(0)\Y = 0.5
Vec(0)\Z = 0.0

Vec(1)\X = -0.225
Vec(1)\Y = -0.5
Vec(1)\Z = 0.5

Vec(2)\X = -0.225
Vec(2)\Y = -0.5
Vec(2)\Z = -0.5

Line3D(0)\X = -0.5
Line3D(1)\X = 0.5

Line3D(1)\Z = 0.5

vNormal.Point3D
vNormal\X = 1.0

vIntersection.Point3D
vIntersection\X = -0.225

Repeat
  Collision = IntersectedPolygon(@Vec(0), @Vec(1), @Vec(2), @Line3D(0), @Line3D(1), @vNormal.Point3D)
  OGLSetCamera(45.0, 0.0, -0.125, -2.0, 1.0, 0.0, 0.0, 0.1, 50.0)
  glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
  glLoadIdentity_()
  glBegin_(#GL_LINES)
  If Collision = 0
  glColor3f_(0.0, 1.0, 0.0)
  Else
  glColor3f_(1.0, 1.0, 0.0)
  EndIf
  glVertex3f_(Line3D(0)\X, Line3D(0)\Y, Line3D(0)\Z)
  glVertex3f_(Line3D(1)\X, Line3D(1)\Y, Line3D(1)\Z)
  glEnd_()
  glLoadIdentity_()
  glBegin_(#GL_TRIANGLES)
    glNormal3f_(vNormal\X, vNormal\Y, vNormal\Z)
    glColor4f_(0.0, 0.0, 1.0, 1.0)
    glVertex3f_(Vec(0)\X, Vec(0)\Y, Vec(0)\Z)
    glColor4f_(1.0, 0.0, 0.0, 1.0)
    glVertex3f_(Vec(1)\X, Vec(1)\Y, Vec(1)\Z)
    glColor4f_(1.0, 1.0, 0.0, 1.0)
    glVertex3f_(Vec(2)\X, Vec(2)\Y, Vec(2)\Z)
  glEnd_()
  SwapBuffers_(hDC)
  Event = WindowEvent()
  If Event = #WM_KEYDOWN
    Select EventwParam()
      Case #VK_PRIOR
        Vec(0)\Y + 0.05
        Vec(1)\Y + 0.05
        Vec(2)\Y + 0.05
      Case #VK_NEXT
        Vec(0)\Y - 0.05
        Vec(1)\Y - 0.05
        Vec(2)\Y - 0.05
      Case #VK_DOWN
        Vec(0)\Z + 0.05
        Vec(1)\Z + 0.05
        Vec(2)\Z + 0.05
      Case #VK_UP
        Vec(0)\Z - 0.05
        Vec(1)\Z - 0.05
        Vec(2)\Z - 0.05
      Case #VK_LEFT
        Vec(0)\X - 0.05
        Vec(1)\X - 0.05
        Vec(2)\X - 0.05
      Case #VK_RIGHT
        Vec(0)\X + 0.05
        Vec(1)\X + 0.05
        Vec(2)\X + 0.05
    EndSelect
  EndIf
  Delay(5)
Until Event = #PB_Event_CloseWindow
End
EndIf
PS: I'll try to include it in my Zap3DEngine :wink:

[EDIT]
I have forgotten the OGLSetCamera Procedure, so now it works fine ;)

[EDIT2]
You should have the glWrapper librarie.
bye,
Daniel
deadmoap
User
User
Posts: 79
Joined: Sun Feb 22, 2004 11:45 pm
Location: Riverdale, Utah
Contact:

Post by deadmoap »

Grrrr it's giving me the same error that I got with my OpenGL code. It says incorrect number of parameters in this function:

gluPerspective_(FOV, WindowWidth()/WindowHeight(), Near.f, Far.f)

I tried adding zeros in the parameters until I didn't get an error. Apparently, it takes 8. But every reference I've looked at says it only takes 4.
User avatar
tinman
PureBasic Expert
PureBasic Expert
Posts: 1102
Joined: Sat Apr 26, 2003 4:56 pm
Location: Level 5 of Robot Hell
Contact:

Post by tinman »

It looks in the above code that there are two underscores on gluPerspective__(). Perhaps this is from a user library, which takes floats and then calls the real gluPerspective_() using doubles?

Where did you put the zeros in your own code? Maybe they need to go into every second parameter rather than, e.g. the four at the end?
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
Post Reply