Advertisement

Engine Trouble - Collision Detection

Started by July 02, 2003 04:00 PM
4 comments, last by Nathaniel Hammen 21 years, 7 months ago
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;

	Position/=pseudoRadius;

	Velocity/=pseudoRadius;

	Triangle* List=TriangleList->Scale(pseudoRadius);

	double DistTravelled=Collisions(List,Time);

	Velocity=DistTravelled;

	Velocity*=pseudoRadius;

	Position*=pseudoRadius;

	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...
I am the master of ideas.....If only I could write them down...
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.

Everything is better with Metal.

Advertisement
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...
I am the master of ideas.....If only I could write them down...
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...
I am the master of ideas.....If only I could write them down...
is that on the Y axis? this could be due to the gravity.

Everything is better with Metal.

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...
I am the master of ideas.....If only I could write them down...

This topic is closed to new replies.

Advertisement