bool DynamicsWorld::castRay( const btVector3 & origin, const btVector3 & direction, const btScalar length, const btCollisionObject * caster, COLLISION_CONTACT & contact) const { btVector3 p = origin + direction * length; btVector3 n = -direction; btScalar d = length; int patch_id = -1; const BEZIER * b = 0; const TRACKSURFACE * s = TRACKSURFACE::None(); btCollisionObject * c = 0; MyRayResultCallback ray(origin, p, caster); rayTest(origin, p, ray); // track geometry collision bool geometryHit = ray.hasHit(); if (geometryHit) { p = ray.m_hitPointWorld; n = ray.m_hitNormalWorld; d = ray.m_closestHitFraction * length; c = ray.m_collisionObject; if (c->isStaticObject()) { TRACKSURFACE* tsc = static_cast<TRACKSURFACE*>(c->getUserPointer()); const std::vector<TRACKSURFACE> & surfaces = track->GetSurfaces(); if (tsc >= &surfaces[0] && tsc <= &surfaces[surfaces.size()-1]) { s = tsc; } #ifndef EXTBULLET else if (c->getCollisionShape()->isCompound()) { TRACKSURFACE* tss = static_cast<TRACKSURFACE*>(ray.m_shape->getUserPointer()); if (tss >= &surfaces[0] && tss <= &surfaces[surfaces.size()-1]) { s = tss; } } #endif //std::cerr << "static object without surface" << std::endl; } // track bezierpatch collision if (track) { MATHVECTOR<float, 3> bezierspace_raystart(origin[1], origin[2], origin[0]); MATHVECTOR<float, 3> bezierspace_dir(direction[1], direction[2], direction[0]); MATHVECTOR<float, 3> colpoint; MATHVECTOR<float, 3> colnormal; patch_id = contact.GetPatchId(); if (track->CastRay(bezierspace_raystart, bezierspace_dir, length, patch_id, colpoint, b, colnormal)) { p = btVector3(colpoint[2], colpoint[0], colpoint[1]); n = btVector3(colnormal[2], colnormal[0], colnormal[1]); d = (colpoint - bezierspace_raystart).Magnitude(); } } contact = COLLISION_CONTACT(p, n, d, patch_id, b, s, c); return true; } // should only happen on vehicle rollover contact = COLLISION_CONTACT(p, n, d, patch_id, b, s, c); return false; }
// Ray //------------------------------------------------------------------------------------------------------------------------------- bool COLLISION_WORLD::CastRay( const MATHVECTOR <float, 3> & origin, const MATHVECTOR <float, 3> & direction, const float length, const btCollisionObject * caster, COLLISION_CONTACT & contact, int* pOnRoad) const { btVector3 from = ToBulletVector(origin); btVector3 to = ToBulletVector(origin + direction * length); MyRayResultCallback rayCallback(from, to, caster); MATHVECTOR <float, 3> p, n; float d; const TRACKSURFACE * s = TRACKSURFACE::None(); const BEZIER * b = NULL; btCollisionObject * c = NULL; // track geometry collision world->rayTest(from, to, rayCallback); bool geometryHit = rayCallback.hasHit(); if (geometryHit) { p = ToMathVector<float>(rayCallback.m_hitPointWorld); n = ToMathVector<float>(rayCallback.m_hitNormalWorld); d = rayCallback.m_closestHitFraction * length; c = rayCallback.m_collisionObject; if (c->isStaticObject() /*&& (c->getCollisionFlags() & btCollisionObject::CF_NO_CONTACT_RESPONSE == 0)*/) { void * ptr = c->getCollisionShape()->getUserPointer(); if (ptr == (void*)7777) // road { s = trackSurface[0]; *pOnRoad = 1; } if (ptr == (void*)7788) // pipe { s = trackSurface[0]; *pOnRoad = 2; } else if (ptr == 0) { *pOnRoad = 0; void * ptr = c->getUserPointer(); if (ptr != NULL) { const TRACK_OBJECT * const obj = reinterpret_cast <const TRACK_OBJECT * const> (ptr); assert(obj); s = obj->GetSurface(); } else //track geometry { int shapeId = rayCallback.m_shapeId; //assert(shapeId >= 0 && shapeId < trackSurface.size()); if (shapeId >= trackSurface.size() || shapeId < 0) shapeId = 0; //crash hf- //if (trackSurface.size() > 0) s = trackSurface[shapeId]; } } } // track bezierpatch collision if (track != NULL) { MATHVECTOR <float, 3> bezierspace_raystart(origin[1], origin[2], origin[0]); MATHVECTOR <float, 3> bezierspace_dir(direction[1], direction[2], direction[0]); MATHVECTOR <float, 3> colpoint, colnormal; const BEZIER * colpatch = NULL; bool bezierHit = track->CastRay(bezierspace_raystart, bezierspace_dir, length, colpoint, colpatch, colnormal); if (bezierHit) { p = MATHVECTOR <float, 3> (colpoint[2], colpoint[0], colpoint[1]); n = MATHVECTOR <float, 3> (colnormal[2], colnormal[0], colnormal[1]); d = (colpoint - bezierspace_raystart).Magnitude(); s = track->GetRoadSurface(); b = colpatch; c = NULL; *pOnRoad = 1; } } contact.Set(p, n, d, s, b, c); return true; } // should only happen on vehicle rollover contact.Set(origin + direction * length, -direction, length, s, b, c); return false; }