#### Archived

This topic is now archived and is closed to further replies.

# Engine Trouble - Collision Detection

This topic is 5640 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I made an engine, unfortunately after I added time to it (I had it as per frame), the collision detection went wacko. If I am travelling at speeds between 3 and 9 meters per second there is a chance that I will fall right through the floor. I can''t find out why. Can some one help. Also, when I stop, I sort of vibrate. All of my functions that are called from these two work fine, but if you want to know what any function does, just ask. For example, you may not know what happens if you set a Vector3D equal to a double. So, I would reply that it sets the length of the vector to that double. Anyways, here are my two functions:
double Character::Collisions(Triangle* TriangleList, unsigned long Time)

{

if(Velocity==0.0)

return 0.0;

Vector3D Movement(Velocity*Time);

const double MoveDist=Movement.Length();

Triangle* Current=TriangleList;

double Coefficient,DistToCollision=-1.0;											// DistToCollision=-1.0 only if no collision has been found

Vector3D PointOfCollision;

while(Current!=NULL)

{

Vector3D planeNormal(Current->Normal());

Vector3D RelativePos(Position-(Current->Vertex[0]));

if(Dot(planeNormal,RelativePos)<0)

planeNormal*=-1;

double PerpDist=Current->Intersect(Position,-planeNormal);

Vector3D IntersectionPoint;

if(PerpDist<=1.0)													// Is the Plane Embedded in the Unit Sphere?

{

Vector3D SphereIntersectPoint(-planeNormal*PerpDist);

IntersectionPoint=Position+SphereIntersectPoint;

}

else

{

Vector3D SphereIntersectPoint(Position-planeNormal);

double CollDist=Current->Intersect(SphereIntersectPoint,Movement);

Vector3D Temp=Movement.unit()*CollDist;							// Temporary vector for velocity to plane collision point

IntersectionPoint=Temp+SphereIntersectPoint;					// So we just add that to the sphere intersection point!

}

double Dist=MoveDist+SMALL;

if(!(Current->Contains(IntersectionPoint)))							// If IntersectionPoint is not within the triangle

{																	// The Intersection Point must be moved

double Temp;

Sphere Point[3]={

Sphere(Current->Vertex[0]),

Sphere(Current->Vertex[1]),

Sphere(Current->Vertex[2])};

for(int K=0; K<3; K++)

{

Temp=Point[K].Intersect(Position,Movement);

if(Temp>=0.0 && Temp<Dist)

{

IntersectionPoint=Current->Vertex[K];

Dist=Temp;

}

}

if(Dist>0.0)

{

Cylinder Edge[3]={

Cylinder(Current->Vertex[0],Current->Vertex[1]),

Cylinder(Current->Vertex[1],Current->Vertex[2]),

Cylinder(Current->Vertex[2],Current->Vertex[0])};

for(int K=0; K<3; K++)

{

Temp=Edge[K].Intersect(Position,Movement);

if(Temp>=0.0 && Temp<Dist)

{

Vector3D CollPoint(Position+(Movement.unit()*Temp));

IntersectionPoint=Edge[K].Axis.ClosestPoint(CollPoint);

Dist=Temp;

}

}

}

if(Dist>MoveDist)

IntersectionPoint=Position-(Movement.unit()*2);

}

else Dist=Sphere(Position).Intersect(IntersectionPoint,-Movement);

//if(Sphere(Position,1.0-SMALL).Contains(IntersectionPoint))

//	MessageBox(NULL,"Embedded Sphere","ERROR",MB_OK|MB_ICONSTOP);

if(Dist>=0.0 && Dist<=MoveDist &&

(DistToCollision==-1.0 || Dist<DistToCollision))

{

DistToCollision=Dist;

Coefficient=Current->Coeff;

PointOfCollision=IntersectionPoint;

}

Current=Current->Next;

}

if (DistToCollision==-1.0)												// If no Collision was found

{																		// We can just

Position+=Movement;													// Move to the destination

return MoveDist;													// And return the distance travelled

}

DistToCollision-=SMALL;													// If the Ellipsoid Slides along the wall, the distance will be Zero, so the Ellipsoid must Hover along the wall

Movement=DistToCollision;												// Set the length of the velocity vector to the distance that the Ellipsoid must move

Position+=Movement;														// Move the Ellipsoid this distance

Movement=MoveDist-DistToCollision;										// Change the Velocity into the remaining distance that must not be moved

Vector3D Destination(Position+Movement);								// The destination point (if there was no collision)

Vector3D SlidePlaneNormal((Position-PointOfCollision).unit());			// The normal vector for the slide plane

double Length=Plane(Position,SlidePlaneNormal).Intersect(Destination,SlidePlaneNormal);

Destination+=SlidePlaneNormal*Length;									// Move the destination onto the slide plane

double ForceNormal=-Dot(SlidePlaneNormal,Velocity)/Time;				// Acceleration caused by the Slide Plane

double ForceFriction=Coefficient*ForceNormal;							// Acceleration that will be caused by friction

Velocity=(Destination-Position)/Time;									// The new Velocity vector without Friction

if(ForceFriction>Velocity.Length())										// If the force of friction is larger than the new Velocity Vector

Velocity=Vector3D(0,0,0);											// There is no velocity

Velocity=Velocity.Length()-(ForceFriction*Time);						// Subtract friction from velocity vector

double DistTravelled=DistToCollision+Collisions(TriangleList,Time);		// The Distance travelled is

return DistTravelled;													// Return the distance travelled

}

void Character::Move(Triangle* TriangleList, unsigned long Time)

{

if(keys[VK_LEFT])

Longitude-=0.025;

if(keys[VK_RIGHT])

Longitude+=0.025;

Polar Look(0,Longitude);

if(keys[''W''] || keys[VK_UP])

Look.R+=0.00001;

if(keys[''S''] || keys[VK_DOWN])

Look.R-=0.00001;

Vector2D Movement(Look);

Velocity+=Vector3D(Movement.X,GRAVITY,Movement.Y)*Time;

double DistTravelled=Collisions(List,Time);

Velocity=DistTravelled;

Velocity/=Time;

delete List;

}

Even if you couldn''t help, I still apreciate the effort! -------------------------------------- I am the master of stories..... If only I could just write them down...

##### Share on other sites
I don''t think you need to inverse the normal if the player is under the triangle. That would probably push the player under the terrain.

Apart from that, too much code You gotta debug it yourself. Debugging is a skill. I''d write a small app with only a couple of triangles and a sphere, and test the algo with that. If you set the triangles to known values, and so on, it will be much easier to see what''s going wrong. And draw stuff like normals, points of intersections, velocities, ect... So many things can go bonkers in your algo.

And put the code in classes and split it into more functions! It''s well messy. It would be easier to conceptualise. And there seems to be redundant piece of code there, which doesn''t help.

##### Share on other sites
I figured it out! Or at least part of it...
DistTo Collision is the distance to the collision - 1e-8
So it CAN be negative. I decided to take the absolute value of DistToCollision right before I create DistTravelled, and poof, no more falling through the floor. Unfortunately, there''s a sort of Earthquake kind of thing going on, but maybe if I add 1e-8 to DistToCollision rather than taking the absolute value of it, the Tremors will go away. I''ll test now.

--------------------------------------
I am the master of stories.....
If only I could just write them down...

##### Share on other sites
It didn''t work...
I think this little shaking sickness is due to problems with friction.
Even "stopped" my velocity fluctuates between 0 and 3 meters per second. I don''t know why.

--------------------------------------
I am the master of stories.....
If only I could just write them down...

##### Share on other sites
is that on the Y axis? this could be due to the gravity.

##### Share on other sites
No it wasn''t, but I fixed the problem finally. I had to remove "DistToCollision-=SMALL;" and replace it with "Position+=SlidePlaneNormal*SMALL;" a couple of lines down.
Now my only problem is that stairs are easier to climb at an angle than straight forward. Oh, well.

--------------------------------------
I am the master of stories.....
If only I could just write them down...

1. 1
2. 2
3. 3
Rutin
15
4. 4
5. 5

• 10
• 9
• 9
• 11
• 11
• ### Forum Statistics

• Total Topics
633685
• Total Posts
3013323
×