// 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; }
//-------------------------------------------------------------------------------------------------------------------------------- // Ray ///------------------------------------------------------------------------------------------------------------------------------- bool COLLISION_WORLD::CastRay( const MATHVECTOR<float,3> & origin, const MATHVECTOR<float,3> & direction, const float length, const btCollisionObject * caster, COLLISION_CONTACT & contact, //out CARDYNAMICS* cd, int w, //out pCarDyn, nWheel bool ignoreCars, bool camTilt, bool camDist) const { btVector3 from = ToBulletVector(origin); btVector3 to = ToBulletVector(origin + direction * length); MyRayResultCallback res(from, to, caster, ignoreCars, camTilt, camDist); // data to set MATHVECTOR<float,3> pos, norm; float dist; const TRACKSURFACE * surf = TRACKSURFACE::None(); btCollisionObject * col = NULL; const BEZIER * bzr = NULL; world->rayTest(from, to, res); bool geometryHit = res.hasHit(); if (geometryHit) { pos = ToMathVector<float>(res.m_hitPointWorld); norm = ToMathVector<float>(res.m_hitNormalWorld); dist = res.m_closestHitFraction * length; col = res.m_collisionObject; const TerData& td = pApp->scn->sc->td; if (col->isStaticObject() /*&& (c->getCollisionFlags() & btCollisionObject::CF_NO_CONTACT_RESPONSE == 0)*/) { long long ptrU = (long long)col->getCollisionShape()->getUserPointer(), su = ptrU & 0xFF00, mtr = ptrU & 0xFF; //void* /// set surface, basing on shape type ----------------- if (ptrU) switch (su) { case SU_Road: // road { int id = td.layerRoad.surfId; // Road[mtr]. surf = &pApp->pGame->surfaces[id]; if (cd) { cd->iWhOnRoad[w] = 1; cd->whRoadMtr[w] = mtr; cd->whTerMtr[w] = 0; } } break; case SU_Pipe: // pipe { int id = td.layerRoad.surfId; surf = &pApp->pGame->surfaces[id]; if (cd) { cd->iWhOnRoad[w] = 2; cd->whRoadMtr[w] = mtr+30; cd->whTerMtr[w] = 0; } } break; case SU_Terrain: // Terrain get surface from blendmap mtr { int t = pApp->blendMapSize; float tws = td.fTerWorldSize; int mx = (pos[0] + 0.5*tws)/tws*t; mx = std::max(0,std::min(t-1, mx)); int my = (pos[1] + 0.5*tws)/tws*t; my = std::max(0,std::min(t-1, t-1-my)); int mtr = pApp->blendMtr[my*t + mx]; int id = td.layersAll[td.layers[mtr]].surfId; surf = &pApp->pGame->surfaces[id]; if (cd) // mtr 0 = not on terrain { cd->iWhOnRoad[w] = 0; cd->whRoadMtr[w] = 60; cd->whTerMtr[w] = mtr + 1; } } break; //case SU_RoadWall: //case SU_RoadColumn: //case SU_Vegetation: case SU_Border: //case SU_ObjectStatic: //case SU_ObjectDynamic: default: { int id = td.layerRoad.surfId; surf = &pApp->pGame->surfaces[id]; if (cd) { cd->iWhOnRoad[w] = 0; cd->whRoadMtr[w] = 80; cd->whTerMtr[w] = 0; } } break; } else //if (ptrU == 0) { int id = td.layersAll[0].surfId; //0 only 1st surf = &pApp->pGame->surfaces[id]; if (cd) { cd->iWhOnRoad[w] = 0; cd->whRoadMtr[w] = 0; cd->whTerMtr[w] = 1; } /*void * ptr = col->getUserPointer(); if (ptr != NULL) { const TRACK_OBJECT * const obj = reinterpret_cast <const TRACK_OBJECT * const> (ptr); assert(obj); surf = obj->GetSurface(); } else // track geometry { int shapeId = res.m_shapeId; //assert(shapeId >= 0 && shapeId < trackSurface.size()); if (shapeId >= trackSurface.size() || shapeId < 0) shapeId = 0; //crash hf- if (trackSurface.size() > 0) surf = 0;//trackSurface[shapeId]; }*/ } } // track bezierpatch collision if (track != NULL) { MATHVECTOR<float,3> bs_pos(origin[1], origin[2], origin[0]); //bezierspace MATHVECTOR<float,3> bs_dir(direction[1], direction[2], direction[0]); MATHVECTOR<float,3> colpos, colnorm; const BEZIER * colpatch = NULL; bool bezierHit = track->CastRay(bs_pos, bs_dir, length, colpos, colpatch, colnorm); if (bezierHit) { pos = MATHVECTOR<float,3> (colpos[2], colpos[0], colpos[1]); norm = MATHVECTOR<float,3> (colnorm[2], colnorm[0], colnorm[1]); dist = (colpos - bs_pos).Magnitude(); //surf = 0;//track->GetRoadSurface(); bzr = colpatch; col = NULL; int id = td.layerRoad.surfId; surf = &pApp->pGame->surfaces[id]; if (cd) { cd->iWhOnRoad[w] = 1; cd->whRoadMtr[w] = 0; cd->whTerMtr[w] = 0; } } } contact.Set(pos, norm, dist, surf, bzr, col); return true; } // should only happen on vehicle rollover contact.Set(origin + direction * length, -direction, length, surf, bzr, col); return false; }