Ogre collision detection, accurate to the object mesh Triangle Surface
(19:14:27)
Reprinted
Tags:Miscellaneous |
Category: MSN migration |
The final project of our course is a three-dimensional game of mosquito-sucking blood. Because the volume of mosquitoes is small, and mosquitoes need to fly in 3D scenarios. Therefore, the regular model detection for the box is insufficient. For example, there is a desk lamp in the scenario. From the perspective of the model's surrounding box, the desk lamp is a cuboid. If we use this method for collision detection, as a result, mosquitoes cannot fly through the arch bridge hole formed by the long arc trunk of the lamp, even though it does not seem to have hit the lamp. This is unacceptable in reality. I have tried several methods: one is to use a few rays starting from a mosquito pointing to each direction to detect a collision, and the other is to use a sphere to enclose a mosquito, then, the number of objects in the sphere is checked to detect the collision. However, the final failure is due to the fact that these collisions can only detect the point of intersection with the model surrounding box. It seems that you must find a better solution. Fortunately, I found a third-party open-source library called Minimal ogre collision . You can find the region on http://www.ogre3d.org/wiki/index.php/minimal_ogre_collision. I decided to pick out the core piece of code and explain it in detail.// Ray, X-ray. Result: intersection of the model surface. Target: intersection object. closest_distance: distance from the closest intersection. querymask: bool collisiontools :: raycast (const ogre: Ray & ray, ogre: vector3 & result, ogre: movableobject * & target, float & closest_distance, const ogre: uint32 querymask)
{
Target = NULL; // Test whether the ray is valid
If (mrayscenequery! = NULL)
{
// Create a ray Query Mrayscenequery-> setray (Ray );
Mrayscenequery-> setsortbydistance (true); // the query results are sorted by distance.
Mrayscenequery-> setquerymask (querymask); // sets the mask.
// Execute Query
If (mrayscenequery-> execute (). Size () <= 0)
{ Return (false );
}
}
Else
{
// Log_error <"cannot raycast without rayscenequery instance" <endlog;
Return (false );
} // Note: here we have obtained a series of models detected by the box.
// We need to find the first intersecting object.
// This means that we do not have to detect the following objects, which greatly saves time.
// But unfortunately, we have to traverse every object's triangle. It sounds so painful and we have to endure it.
//
// The minimum initialization distance is-1.
Closest_distance =-1.0f;
Ogre: vector3 closest_result;
Ogre: rayscenequeryresult & query_result = mrayscenequery-> getlastresults (); // retrieve the query result because it was not saved before.
For (size_t qr_idx = 0; qr_idx <query_result.size (); qr_idx ++)
{
// If the next collision object is far behind this, of course we should ignore it. If (closest_distance >=0.0f )&&
(Closest_distance <query_result [qr_idx]. Distance ))
{
Break;
} // We only care about collision as an object. If (query_result [qr_idx]. movable! = NULL) &&
(Query_result [qr_idx]. movable-> getmovabletype (). Compare ("entity") = 0 ))
{
// Obtain the collided object Ogre: movableobject * pentity = static_cast <ogre: movableobject *> (query_result [qr_idx]. movable ); // The vertex is the vertex, and the index is the index. Don't worry. Let's look down.
Size_t vertex_count;
Size_t index_count;
Ogre: vector3 * vertices;
Ogre: uint32 * indices; // The following function gets detailed information about the model.
Getmeshinformation (Ogre: entity *) pentity)-> getmesh (), vertex_count, vertices, index_count, indices,
Pentity-> getparentnode ()-> _ getderivedposition (),
Pentity-> getparentnode ()-> _ getderivedorientation (),
Pentity-> getparentnode ()-> _ getderivedscale ()); // Once again, find the intersection of each triangle and record the latest vertex. Bool new_closest_found = false;
For (size_t I = 0; I <index_count; I + = 3)
{
// The following function calculates the intersection of a ray and a triangle, returns a pair, "whether or not intersection, distance from intersection"
STD: pair <bool, ogre: Real> hit = ogre: Math: intersects (Ray, vertices [indices [I],
Vertices [indices [I + 1], vertices [indices [I + 2], true, false); // you know why the index is used, the index is the index of the vertex. // If a collision occurs, check whether it is the current minimum distance.
If (hit. First)
{
If (closest_distance <0.0f) |
(Hit. Second <closest_distance ))
{
// Update if yes
Closest_distance = hit. Second;
New_closest_found = true;
}
}
} // Release the memory you just applied for. Of course, this kind of stuff will be written in pairs when you write the application, just as at the same time writing {} Delete [] vertices;
Delete [] indices; // If a new vertex is found, do not forget to update the corresponding information.
If (new_closest_found)
{
Target = pentity;
Closest_result = Ray. getpoint (closest_distance); // calculate the closest vertex, a simple linear equation.
}
}
} // Returned results If (closest_distance> = 0.0f)
{
// Succeeded Result = closest_result;
Return (true );
}
Else
{
// Failed Return (false );
}
}