Properly fix driving no physical objects to enable smoothing (e.g.

volcano in both directions).
This commit is contained in:
hiker 2017-04-18 23:07:24 +10:00
parent 76491d13ec
commit c23873da37
6 changed files with 83 additions and 37 deletions

View File

@ -981,17 +981,17 @@ void btKart::debugDraw(btIDebugDraw* debugDrawer)
if (n > -1)
{
const TriangleMesh &tm = Track::getCurrentTrack()->getTriangleMesh();
btVector3 *p1, *p2, *p3;
btVector3 p1, p2, p3;
tm.getTriangle(n, &p1, &p2, &p3);
const btVector3 *n1, *n2, *n3;
btVector3 n1, n2, n3;
tm.getNormals(n, &n1, &n2, &n3);
// Draw the normals at the vertices
debugDrawer->drawLine(*p1, *p1 + *n1, white);
debugDrawer->drawLine(*p2, *p2 + *n2, white);
debugDrawer->drawLine(*p3, *p3 + *n3, white);
debugDrawer->drawLine(p1, p1 + n1, white);
debugDrawer->drawLine(p2, p2 + n2, white);
debugDrawer->drawLine(p3, p3 + n3, white);
// Also draw the triangle in white, it can make it easier
// to identify which triangle a wheel is on
debugDrawer->drawTriangle(*p1, *p2, *p3, white, 1.0f);
debugDrawer->drawTriangle(p1, p2, p3, white, 1.0f);
}
} // for i < getNumWheels

View File

@ -81,9 +81,11 @@ void* btKartRaycaster::castRay(const btVector3& from, const btVector3& to,
// different triangle mesh). TODO: Add a mapping from bullet
// objects back to triangle meshes, so that it's easy to pick up
// the right triangle mesh for smoothing
TriangleMesh::RigidBodyTriangleMesh *rbtm =
dynamic_cast<TriangleMesh::RigidBodyTriangleMesh*>(body);
if(m_smooth_normals &&
rayCallback.getTriangleIndex()>-1 &&
body == Track::getCurrentTrack()->getTriangleMesh().getBody())
rbtm != NULL )
{
#undef DEBUG_NORMALS
#ifdef DEBUG_NORMALS
@ -91,7 +93,7 @@ void* btKartRaycaster::castRay(const btVector3& from, const btVector3& to,
#endif
result.m_triangle_index = rayCallback.getTriangleIndex();
result.m_hitNormalInWorld =
tm.getInterpolatedNormal(rayCallback.getTriangleIndex(),
rbtm->m_triangle_mesh->getInterpolatedNormal(rayCallback.getTriangleIndex(),
result.m_hitPointInWorld);
#ifdef DEBUG_NORMALS
printf("old %f %f %f new %f %f %f\n",

View File

@ -378,7 +378,8 @@ void PhysicalObject::init(const PhysicalObject::Settings& settings)
return;
} // switch node->getType()
std::unique_ptr<TriangleMesh> triangle_mesh(new TriangleMesh());
std::unique_ptr<TriangleMesh>
triangle_mesh(new TriangleMesh(/*can_be_transformed*/true));
for(unsigned int i=0; i<mesh->getMeshBufferCount(); i++)
{
@ -522,7 +523,10 @@ void PhysicalObject::init(const PhysicalObject::Settings& settings)
btRigidBody::btRigidBodyConstructionInfo info(m_mass, m_motion_state,
m_shape, inertia);
m_body = new btRigidBody(info);
if(m_triangle_mesh)
m_body = new TriangleMesh::RigidBodyTriangleMesh(m_triangle_mesh, info);
else
m_body = new btRigidBody(info);
m_user_pointer.set(this);
m_body->setUserPointer(&m_user_pointer);

View File

@ -30,11 +30,12 @@
// -----------------------------------------------------------------------------
/** Constructor: Initialises all data structures with zero.
*/
TriangleMesh::TriangleMesh() : m_mesh()
TriangleMesh::TriangleMesh(bool can_be_transformed) : m_mesh()
{
m_body = NULL;
m_free_body = true;
m_motion_state = NULL;
m_body = NULL;
m_free_body = true;
m_motion_state = NULL;
m_can_be_transformed = can_be_transformed;
// FIXME: on VS in release mode this statement actually overwrites
// part of the data of m_mesh, causing a crash later. Debugging
// shows that apparently m_collision_shape is at the same address
@ -194,7 +195,7 @@ void TriangleMesh::createPhysicalBody(float friction,
info.m_restitution = 0.8f;
info.m_friction = friction;
m_body=new btRigidBody(info);
m_body=new RigidBodyTriangleMesh(this, info);
Physics::getInstance()->addBody(m_body);
m_body->setUserPointer(&m_user_pointer);
@ -239,22 +240,41 @@ void TriangleMesh::removeAll()
btVector3 TriangleMesh::getInterpolatedNormal(unsigned int index,
const btVector3 &position) const
{
btVector3 *p1, *p2, *p3;
getTriangle(index, &p1, &p2, &p3);
const btVector3 *n1, *n2, *n3;
getNormals(index, &n1, &n2, &n3);
btVector3 p1, p2, p3;
btVector3 n1, n2, n3;
if(m_can_be_transformed)
{
btVector3 q1, q2, q3;
getTriangle(index, &q1, &q2, &q3);
const btTransform &tf = m_body->getWorldTransform();
// The triangle verteces must be moved according to the transform of the body
p1 = tf(q1);
p2 = tf(q2);
p3 = tf(q3);
// The normals must be rotated according to the transform of the body
btVector3 m1, m2, m3;
getNormals(index, &m1, &m2, &m3);
n1 = tf.getBasis() * m1;
n2 = tf.getBasis() * m2;
n3 = tf.getBasis() * m3;
}
else
{
getTriangle(index, &p1, &p2, &p3);
getNormals(index, &n1, &n2, &n3);
}
// Compute the Barycentric coordinates of position inside triangle
// p1, p2, p3.
btScalar p1p2p3 = getP1P2P3(index);
float p1p2p3 = getP1P2P3(index);
// Area of BCP
btScalar p2p3p = (*p3 - *p2).cross(position - *p2).length2();
btScalar p2p3p = (p3 - p2).cross(position - p2).length2();
// Area of CAP
btVector3 edge2 = *p3 - *p1;
btScalar p3p1p = edge2.cross(position - *p3).length2();
btVector3 edge2 = p3 - p1;
btScalar p3p1p = edge2.cross(position - p3).length2();
btScalar s = btSqrt(p2p3p / p1p2p3);
btScalar t = btSqrt(p3p1p / p1p2p3);
btScalar w = 1.0f - s - t;
@ -275,7 +295,7 @@ btVector3 TriangleMesh::getInterpolatedNormal(unsigned int index,
}
#endif
return s*(*n1) + t*(*n2) + w*(*n3);
return s*n1 + t*n2 + w*n3;
} // getInterpolatedNormal
// ----------------------------------------------------------------------------

View File

@ -45,12 +45,32 @@ private:
btVector3 dummy1, dummy2;
btDefaultMotionState *m_motion_state;
btCollisionShape *m_collision_shape;
/** The three normals for each triangle. */
AlignedArray<btVector3> m_normals;
/** Pre-compute value used in smoothing. */
AlignedArray<float> m_p1p2p3;
/** If the rigid body can be transformed (which means that normalising
* the normals need to update the vertices and normals used according
* to the current transform of the body. */
bool m_can_be_transformed;
public:
TriangleMesh();
class RigidBodyTriangleMesh : public btRigidBody
{
public:
TriangleMesh *m_triangle_mesh;
RigidBodyTriangleMesh(TriangleMesh *tm,
const btRigidBody::btRigidBodyConstructionInfo &ci)
: btRigidBody(ci),
m_triangle_mesh(tm)
{
} // RigidBodyTriangleMesh
};
TriangleMesh(bool can_be_transformed);
~TriangleMesh();
void addTriangle(const btVector3 &t1, const btVector3 &t2,
const btVector3 &t3, const btVector3 &n1,
@ -96,27 +116,27 @@ public:
/** Returns the points of the 'indx' triangle.
* \param indx Index of the triangle to get.
* \param p1,p2,p3 On return the three points of the triangle. */
void getTriangle(unsigned int indx, btVector3 **p1, btVector3 **p2,
btVector3 **p3) const
void getTriangle(unsigned int indx, btVector3 *p1, btVector3 *p2,
btVector3 *p3) const
{
const IndexedMeshArray &m = m_mesh.getIndexedMeshArray();
btVector3 *p = &(((btVector3*)(m[0].m_vertexBase))[3*indx]);
*p1 = &(p[0]);
*p2 = &(p[1]);
*p3 = &(p[2]);
*p1 = p[0];
*p2 = p[1];
*p3 = p[2];
} // getTriangle
// ------------------------------------------------------------------------
/** Returns the normals of the triangle with the given index.
* \param indx Index of the triangle to get the three normals of.
* \result n1,n2,n3 The three normals. */
void getNormals(unsigned int indx, const btVector3 **n1,
const btVector3 **n2, const btVector3 **n3) const
void getNormals(unsigned int indx, btVector3 *n1,
btVector3 *n2, btVector3 *n3) const
{
assert(indx < m_triangleIndex2Material.size());
unsigned int n = indx*3;
*n1 = &(m_normals[n ]);
*n2 = &(m_normals[n+1]);
*n3 = &(m_normals[n+2]);
*n1 = m_normals[n ];
*n2 = m_normals[n+1];
*n3 = m_normals[n+2];
} // getNormals
// ------------------------------------------------------------------------
/** Returns basically the area of the triangle, which is needed when

View File

@ -1095,8 +1095,8 @@ bool Track::loadMainTrack(const XMLNode &root)
m_challenges.clear();
m_track_mesh = new TriangleMesh();
m_gfx_effect_mesh = new TriangleMesh();
m_track_mesh = new TriangleMesh(/*can_be_transformed*/false);
m_gfx_effect_mesh = new TriangleMesh(/*can_be_transformed*/false);
const XMLNode *track_node = root.getNode("track");
std::string model_name;