Post by xenovacivus on Feb 10, 2007 21:35:57 GMT -5
Here's a demo with collision detection and simple physics. It's commented pretty good, but if you have any questions just ask em!
enjoy! ;D
enjoy! ;D
' Simple Collision Detection/Physics demo!
' by Ben Porter
dim i, j
' Structure to hold a polygon and any related polygon collision detection info
struc sPolygon
'Most important part- The vertices!
'I keep things simple and use a max of 5.
dim vert# (5)(2)
dim VertCount
'Now for collision detection stuff.
' The Normal and Scalar define the plane the polygon sits on.
'Normal - normalized vector perpendicular to the polygon.
dim Normal# (2)
'Scalar - distance from the plane the polygon sits on and the origin.
dim Scalar#
' SideNormal & SideScalar - define a plane for each side of the polygon.
' These planes define the limits of the polygon on the main plane.
dim SideNormal# (5)(2)
dim SideScalar# (5)
endStruc
dim sPolygon Poly (10)
dim PolyCount ' to keep track of how many polygons I've got...
' To make the normals work correctly, the points must all be ordered in a
' specific way. I use counter-clockwise when looking at the face of the polygon.
' Floor Polygon
Poly (0).VertCount = 3
Poly (0).Vert# (0) = vec3 (-10, -5, -10)
Poly (0).Vert# (1) = vec3 (-10, -5, 10)
Poly (0).Vert# (2) = vec3 (10, -5, 10)
Poly (0).Vert# (3) = vec3 (10, -5, -10)
' Back Wall
Poly (1).VertCount = 3
Poly (1).Vert# (0) = vec3 (-10, -5, -10)
Poly (1).Vert# (1) = vec3 (10, -5, -10)
Poly (1).Vert# (2) = vec3 (10, 0, -10)
Poly (1).Vert# (3) = vec3 (-10, 0, -10)
' Right Wall
Poly (2).VertCount = 3
Poly (2).Vert# (0) = vec3 (10, -5, -10)
Poly (2).Vert# (1) = vec3 (10, -5, 10)
Poly (2).Vert# (2) = vec3 (10, 0, 10)
Poly (2).Vert# (3) = vec3 (10, 0, -10)
' Front Wall
Poly (3).VertCount = 3
Poly (3).Vert# (0) = vec3 (10, -5, 10)
Poly (3).Vert# (1) = vec3 (-10, -5, 10)
Poly (3).Vert# (2) = vec3 (-10, 0, 10)
Poly (3).Vert# (3) = vec3 (10, 0, 10)
' Left Wall
Poly (4).VertCount = 3
Poly (4).Vert# (0) = vec3 (-10, -5, 10)
Poly (4).Vert# (1) = vec3 (-10, -5, -10)
Poly (4).Vert# (2) = vec3 (-10, 0, -10)
Poly (4).Vert# (3) = vec3 (-10, 0, 10)
' Obstacle
Poly (5).VertCount = 3
Poly (5).vert# (0) = vec3 (0, -5, 2)
Poly (5).vert# (1) = vec3 (10, -5, 2)
Poly (5).vert# (2) = vec3 (10, -1, -5)
Poly (5).vert# (3) = vec3 (0, -1, -5)
' Triangle
Poly (6).VertCount = 2
Poly (6).vert# (0) = vec3 (-10, -4, -10)
Poly (6).vert# (1) = vec3 (-10, -5, -2)
Poly (6).vert# (2) = vec3 (-6, -5, -10)
' Ramp
Poly (7).VertCount = 3
Poly (7).vert# (0) = vec3 (-2, -3, -10)
Poly (7).vert# (1) = vec3 (-8, -3, -10)
Poly (7).vert# (2) = vec3 (-8, -3, -8.5)
Poly (7).vert# (3) = vec3 (-2, -3, -8.5)
' Fun Ramp thing
Poly (8).VertCount = 3
Poly (8).vert# (0) = vec3 (8, -1, -10)
Poly (8).vert# (1) = vec3 (2, -4, -10)
Poly (8).vert# (2) = vec3 (2, -4, -8.5)
Poly (8).vert# (3) = vec3 (8, -1, -8.5)
' Another ramp thing
Poly (9).VertCount = 3
Poly (9).vert# (0) = vec3 (-10, -1, -8.5)
Poly (9).vert# (1) = vec3 (-8, -3, -8.5)
Poly (9).vert# (2) = vec3 (-8, -3, -10)
Poly (9).vert# (3) = vec3 (-10, -1, -10)
PolyCount = 9
for i = 0 to PolyCount
' Calculate the main normal and scalar-
Poly (i).Normal# = Normalize (CrossProduct (Poly (i).vert# (1) - Poly (i).vert# (0), Poly (i).vert# (2) - Poly (i).vert# (0)))
Poly (i).Scalar# = Poly (i).Normal# * Poly (i).vert# (0)
' Now the complicated part. Create a normal and scalar for each edge of the polygon.
' By calculating them as follows, the SideNormals point from an edge to the inside of the polygon.
for j = 0 to Poly (i).VertCount
Poly (i).SideNormal# (j) = Normalize (CrossProduct (Poly (i).vert# (j) - Poly (i).vert# ((j+1)%(Poly (i).VertCount+1)), Poly (i).Normal#))
Poly (i).SideScalar# (j) = Poly (i).SideNormal# (j) * Poly (i).vert# (j)
next
next
glEnable (GL_LIGHTING)
glLightfv(GL_LIGHT1, GL_AMBIENT, vec4 (.5, .2, .2, 1))' light thats always there.
glLightfv(GL_LIGHT1, GL_DIFFUSE, vec4 (0, 1, .2, 1)) ' light coming from a source.
glLightfv(GL_LIGHT1, GL_POSITION,vec4 (0, -10, 0, 10))' where the light source is.
glEnable(GL_LIGHT1)
dim point# (2) ' point to test for collisions!
dim acc# (2), vel# (2), lastPos# (2) ' for realistic looking movement.
dim tempvec1# (2)
dim tempFloat1#
' Collision Detection stuff
dim D_ToPlane#
dim D_ToEdge#
dim I_Edge
TextMode (TEXT_OVERLAID)
while true
cls
glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
glLoadIdentity ()
glTranslatef (0, 0, -20)
glRotatef (35, .7071, .7071, 0)
' Draw all the polygons
for i = 0 to PolyCount
glBegin (GL_TRIANGLE_FAN)
for j = 0 to Poly (i).VertCount
glNormal3fv (Poly (i).Normal#)
glVertex3fv (Poly (i).Vert# (j))
next
glEnd ()
next
' To make it run faster/slower, uncomment the while/wend loop below
'while synctimer (10)
' logically, the velocity is the position - last position.
' It works well, so I'll go with it.
vel# = point# - lastPos#
lastPos# = point#
' acceleration is zero unless a force acts on an object.
' Gravity is a force acting on the Y part of the vector.
acc# = vec3 (0, -.01, 0)
if ScanKeyDown (VK_UP) then acc# = acc# + vec3 (0, 0, -.01) endif
if ScanKeyDown (VK_DOWN) then acc# = acc# + vec3 (0, 0, .01) endif
if ScanKeyDown (VK_LEFT) then acc# = acc# + vec3 (-.01, 0, 0) endif
if ScanKeyDown (VK_RIGHT) then acc# = acc# + vec3 (.01, 0, 0) endif
' Add accelerations onto velocity-
vel# = vel# + acc#
' Create a terminal velocity of .4 unit per frame.
if Length (vel#) >= .25 then
vel# = Normalize (vel#) * .25
endif
point# = point# + vel#
' Check the new point for collisions!
for i = 0 to PolyCount
' First, find the distance from the point to the polygon-
D_ToPlane# = point# * Poly (i).Normal# - Poly (i).Scalar#
' Check if that distnace is less than the radius of the sphere- (radius is .5)
' If the distnace is negative, the point is on the opposite side of a plane.
if D_ToPlane# < .5 and D_ToPlane# >= 0 then
' It's within 1 unit of the front face of the plane the polygon resides on.
' Now check if it's within the edges of the polygon
for j = 0 to Poly (i).VertCount
tempFloat1# = point# * Poly (i).SideNormal# (j) - Poly (i).SideScalar# (j)
if D_ToEdge# > tempFloat1# or j = 0 then
D_ToEdge# = tempFloat1#
I_Edge = j ' save an index to the closest edge for later on
endif
next
' now D_ToEdge# is the distance to the closest edge. If the number is greater than zero,
' the point is within the boundaries of the polygon on the plane. This means collision
' response is simple- just push the point away from the polygon however far it penetrated
' into the polygon.
if D_ToEdge# >=0 then
point# = point# + Poly (i).Normal# * (.5-D_ToPlane#)
else
' If the point is outside the polygon, but still within a radius of the edges, a collision
' with an edge or point could occur. Check for em!
if D_ToEdge# >= -.5 then
' Here's a new way of doing this. Previously, I iterated through all the edges and
' tested the distance from each edge to the point and so forth. This time I'll
' use information I already have, I.E, the distance from the plane and distnace
' from the edge.
tempFloat1# = sqrt (D_ToEdge#*D_ToEdge# + D_ToPlane#*D_ToPlane#)
if tempFloat1# < .5 then
' Actually, this works suprisingly well! Before, I used 25 lines of code,
' full of vector math and in the really old version a bunch of sin stuff.
' Now I've got only one line of code! Granted, it does a lot, but I'll bet
' the collision detection is 5x as fast as the previous method. This does omit
' the corner collision detection, but corner collision detection rarely happens
' and there's no noticable difference from this method. So unless you're making
' a piano simulation, this works fine!
point# = point# + (.5-tempFloat1#)*Normalize (D_ToEdge#*Poly (i).SideNormal# (I_Edge) + D_ToPlane#*Poly (i).Normal#)*.5
endif
endif
endif
endif
next
'wend
glPushMatrix ()
glTranslatef (point# (0), point# (1), point# (2))
for i = 0 to 10
glBegin (GL_QUAD_STRIP)
for j = 0 to 10
tempvec1# (0) = .5 * cos (i * 2*M_PI / 10) * sin (j * M_PI / 10)
tempvec1# (1) = .5 * sin (i * 2*M_PI / 10) * sin (j * M_PI / 10)
tempvec1# (2) = .5 * cos (j * M_PI / 10)
glNormal3fv (tempvec1#)
glVertex3fv (tempvec1#)
i = i + 1
tempvec1# (0) = .5 * cos (i * 2*M_PI / 10) * sin (j * M_PI / 10)
tempvec1# (1) = .5 * sin (i * 2*M_PI / 10) * sin (j * M_PI / 10)
tempvec1# (2) = .5 * cos (j * M_PI / 10)
glNormal3fv (tempvec1#)
glVertex3fv (tempvec1#)
i = i - 1
next
glEnd ()
next
glPopMatrix ()
DrawText ()
SwapBuffers ()
wend