float AI_Car_Experimental::RayCastDistance( MATHVECTOR <float, 3> direction, float max_length){ btVector3 pos = car->GetCarDynamics().GetPosition(); btVector3 dir = car->GetCarDynamics().LocalToWorld(ToBulletVector(direction)); dir -= pos; COLLISION_CONTACT contact; car->GetDynamicsWorld()->castRay( pos, dir, max_length, &car->GetCarDynamics().getCollisionObject(), contact ); float depth = contact.GetDepth(); float dist = std::min(max_length, depth); #ifdef VISUALIZE_AI_DEBUG MATHVECTOR<float, 3> pos_start(ToMathVector<float>(pos)); MATHVECTOR<float, 3> pos_end = pos_start + (ToMathVector<float>(dir) * dist); AddLinePoint(raycastshape, pos_start); AddLinePoint(raycastshape, pos_end); #endif return dist; }
void FollowCamera::update(Real time, const PosInfo& posIn, PosInfo* posOut, COLLISION_WORLD* world, bool bounce) { if (!ca || !posOut) return; /// input from car posInfoIn Vector3 posGoal = posIn.pos; Quaternion orientGoal = posIn.rot; /// output saved back to car posInfoOut Quaternion camRotFinal; const static Quaternion qO = Quaternion(Degree(180),Vector3::UNIT_Z) * Quaternion(Degree(-90),Vector3::UNIT_Y), qR = Quaternion(Degree(90),Vector3(0,1,0)); Quaternion orient = orientGoal * qO; Vector3 ofs = orient * ca->mOffset, goalLook = posGoal + ofs; first = iFirst < 2; ///par few first frames after reset if (iFirst < 10) // after reset { ++iFirst; mDistReduce = 0.f; mATilt = 0.f; } /// Camera Tilt from terrain/road slope under car //------------------------------------------------------------------------------------------- const float // params . . . Rdist = 1.f, // dist from car to ray (front or back) HupCar = 1.5f, // car up dir dist - for pipes - so pos stays inside pipe Habove = 1.5f, // up axis dist, above car - for very high terrain angles HMaxDepth = 12.f; // how far down can the ray goes const static Radian r0(0.f), angMin = Degree(10.f), // below this angle, tilt has no effect - terrain bumps maxDiff = Degree(1.4f); // max diff of tilt - no sudden jumps const float smoothSpeed = 14.f; // how fast to apply tilt change bool bUseTilt = ca->mType == CAM_ExtAng || ca->mType == CAM_Follow; Radian tilt(0.f); if (pSet->cam_tilt && bUseTilt) { // car pos Vector3 carUp = posIn.pos - HupCar * posIn.carY; MATHVECTOR<float,3> pos(carUp.x, -carUp.z, carUp.y + Habove); // to vdr/blt const static MATHVECTOR<float,3> dir(0,0,-1); // cast rays down // car rot, yaw angle Quaternion q = posIn.rot * Quaternion(Degree(90),Vector3(0,1,0)); float angCarY = q.getYaw().valueRadians() + PI_d/2.f; float ax = cosf(angCarY)*Rdist, ay = sinf(angCarY)*Rdist; //LogO("pos: "+fToStr(pos[0],2,4)+" "+fToStr(pos[1],2,4)+" a: "+fToStr(angCarY,2,4)+" dir: "+fToStr(ax,2,4)+" "+fToStr(ay,2,4)); // cast 2 rays - 2 times, average 2 angles COLLISION_CONTACT ct0,ct1,ct20,ct21; MATHVECTOR<float,3> ofs(ax*0.5f,ay*0.5f,0),ofs2(ax,ay,0); world->CastRay(pos+ofs, dir, HMaxDepth,chassis, ct0, 0,0, true, true); world->CastRay(pos-ofs, dir, HMaxDepth,chassis, ct1, 0,0, true, true); world->CastRay(pos+ofs2,dir, HMaxDepth,chassis, ct20, 0,0, true, true); world->CastRay(pos-ofs2,dir, HMaxDepth,chassis, ct21, 0,0, true, true); #ifdef CAM_TILT_DBG MATHVECTOR<float,3> v; v = pos+ofs; posHit[0] = Vector3(v[0],v[2]- ct0.GetDepth(), -v[1]); v = pos-ofs; posHit[1] = Vector3(v[0],v[2]- ct1.GetDepth(), -v[1]); v = pos+ofs2; posHit[2] = Vector3(v[0],v[2]- ct20.GetDepth(),-v[1]); v = pos-ofs2; posHit[3] = Vector3(v[0],v[2]- ct21.GetDepth(),-v[1]); #endif if (ct0.GetColObj() && ct1.GetColObj() && ct20.GetColObj() && ct21.GetColObj() ) tilt = (GetAngle(Rdist, ct1.GetDepth() - ct0.GetDepth()) + GetAngle(2.f*Rdist, ct21.GetDepth() - ct20.GetDepth())) * 0.5f; //else LogO(String("no hit: ")+(ct0.col?"1":"0")+(ct1.col?" 1":" 0")); //if (tilt < angMin && tilt > -angMin) tilt = 0.f; if (tilt < r0 && tilt >-angMin) { Radian d = tilt-angMin; tilt = std::min(r0, tilt + d*d*5.f); } if (tilt > r0 && tilt < angMin) { Radian d =-angMin-tilt; tilt = std::max(r0, tilt - d*d*5.f); } //LogO("a "+fToStr(angCarY,3,5)+" d "+fToStr(ct0.GetDepth(),3,5)+" "+fToStr(ct1.GetDepth(),3,5)+" t "+fToStr(tilt.valueDegrees(),3,5)); } // smooth tilt angle mATilt += std::min(maxDiff, std::max(-maxDiff, tilt - mATilt)) * time * smoothSpeed; //------------------------------------------------------------------------------------------- if (ca->mType == CAM_Car) /* 3 Car - car pos & rot full */ { camPosFinal = goalLook; camRotFinal = orient; posOut->camPos = camPosFinal; // save result in out posInfo posOut->camRot = camRotFinal; return; } if (ca->mType == CAM_Follow) ofs = ca->mOffset; Vector3 pos,goalPos; pos = camPosFinal - ofs; goalPos = posGoal; Vector3 xyz; if (ca->mType != CAM_Arena) { Real x,y,z,xz; // pitch & yaw to direction vector Real ap = bUseTilt ? (ca->mPitch.valueRadians() + mATilt.valueRadians()) : ca->mPitch.valueRadians(), ay = ca->mYaw.valueRadians(); y = sin(ap), xz = cos(ap); x = sin(ay) * xz, z = cos(ay) * xz; xyz = Vector3(x,y,z); xyz *= ca->mDist; } bool manualOrient = false; switch (ca->mType) { case CAM_Arena: /* 2 Arena - free pos & rot */ goalPos = ca->mOffset - ofs; break; case CAM_Free: /* 1 Free - free rot, pos from car */ goalPos += xyz; break; case CAM_Follow: /* 0 Follow - car rotY & pos from behind car, smooth */ { Quaternion orient = orientGoal * qR; orient.FromAngleAxis(orient.getYaw(), Vector3::UNIT_Y); goalPos += orient * xyz; } break; case CAM_ExtAng: /* 4 Extended Angle - car in center, angle smooth */ { Quaternion orient = orientGoal * qR; Quaternion ory; ory.FromAngleAxis(orient.getYaw(), Vector3::UNIT_Y); if (first) { qq = ory; } else qq = orient.Slerp(ca->mSpeed * time, qq, ory, true); // smooth dist from vel #if 0 { if (first) { mPosNodeOld = posGoal; } Real vel = (posGoal - mPosNodeOld).length() / std::max(0.002f, std::min(0.1f, time)); mPosNodeOld = posGoal; if (first) mVel = 0.f; else mVel += (vel - mVel) * time * 8.f; //par- vel smooth speed if (!first) xyz *= 1.f + std::min(100.f, mVel) * 0.01f; //par- vel dist factor } #endif Quaternion qy = Quaternion(ca->mYaw,Vector3(0,1,0)); goalPos += qq * (xyz + ca->mOffset); camPosFinal = goalPos; camRotFinal = qq * qy * Quaternion(Degree(-ca->mPitch - mATilt), Vector3(1,0,0)); manualOrient = true; } break; } if (!manualOrient) // if !CAM_ExtAng { float dtmul = ca->mSpeed == 0 ? 1.0f : ca->mSpeed * time; if (ca->mType == CAM_Arena) { Vector3 Pos(0,0,0), goalPos = ca->mOffset; Pos = camPosFinal; //read last state (smooth) Pos += (goalPos - Pos) * dtmul; mAPitch += (ca->mPitch - mAPitch) * dtmul; mAYaw += (ca->mYaw - mAYaw) * dtmul; if (first) { Pos = goalPos; mAPitch = ca->mPitch; mAYaw = ca->mYaw; } camPosFinal = Pos; camRotFinal = Quaternion(Degree(mAYaw),Vector3(0,1,0)) * Quaternion(Degree(mAPitch),Vector3(1,0,0)); manualOrient = true; } else { if (first) pos = goalPos; Vector3 addPos,addLook; addPos = (goalPos - pos).normalisedCopy() * (goalPos - pos).length() * dtmul; if (addPos.squaredLength() > (goalPos - pos).squaredLength()) addPos = goalPos - pos; pos += addPos; camPosFinal = pos + ofs; goalLook = posGoal + ofs; if (first) { mLook = goalLook; } addLook = (goalLook - mLook) * dtmul;//Rot; mLook += addLook; } } //camLookFinal = mLook; if (!manualOrient) // CAM_Free or CAM_Follow { Vector3 zdir = camPosFinal - mLook; zdir.normalise(); Vector3 xVec = Vector3::UNIT_Y.crossProduct(zdir); xVec.normalise(); Vector3 yVec = zdir.crossProduct(xVec); yVec.normalise(); Quaternion q; q.FromAxes(xVec, yVec, zdir); camRotFinal = q; } // cast ray from car to camera, reduce dist if hit //------------------------------------------------------------------------------------------- Vector3 pp = camPosFinal; if (bounce) pp += posIn.camOfs * ca->mOfsMul * gPar.camBncScale * pSet->cam_bnc_mul; Vector3 p = posGoal; p.y += 1.f; //up //Vector3 d = camRotFinal * Vector3::UNIT_Z; d.normalise(); Vector3 d = pp - p; d.normalise(); if (!first && ca->mType != CAM_Arena) { MATHVECTOR<float,3> pos1(p.x,-p.z,p.y), dir(d.x,-d.z,d.y); //dir = dir.Normalize(); COLLISION_CONTACT ct; float maxLen = (p - pp).length(); //cam near world->CastRay(pos1, dir, maxLen,chassis, ct, 0,0, true, true, true/*+*/); //dbgLen = -maxLen; if (ct.GetColObj()) { float len = ct.GetDepth(); //dbgLen = len; len -= 0.2f + ct.GetNormal()[2]; ///par normal up, flat terrain, move closer if (len < maxLen) { Real dist = maxLen - len; if (dist > mDistReduce) mDistReduce = dist; } } } // save result in out posInfo posOut->camPos = mDistReduce > 0.0001f ? (pp - d * mDistReduce) : pp; posOut->camRot = camRotFinal; // smooth, back to normal dist if (mDistReduce > 0.f) mDistReduce -= time * 10.f; }
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; }
void FollowCamera::update( Real time ) { if (!mGoalNode || !ca || !mCamera) return; Vector3 posGoal = mGoalNode ? mGoalNode->getPosition() : Vector3::UNIT_Y; Quaternion orientGoal = mGoalNode ? mGoalNode->getOrientation() : Quaternion::IDENTITY; const static Quaternion qO = Quaternion(Degree(180),Vector3::UNIT_Z) * Quaternion(Degree(-90),Vector3::UNIT_Y), qR = Quaternion(Degree(90),Vector3(0,1,0)); Quaternion orient = orientGoal * qO; Vector3 ofs = orient * ca->mOffset, goalLook = posGoal + ofs; if (ca->mType == CAM_Car) /* 3 Car - car pos & rot full */ { mCamera->setPosition( goalLook ); mCamera->setOrientation( orient ); updInfo(time); return; } if (ca->mType == CAM_Follow) ofs = ca->mOffset; Vector3 pos,goalPos; pos = mCamera->getPosition() - ofs; goalPos = posGoal; Vector3 xyz; if (ca->mType != CAM_Arena) { Real x,y,z,xz; // pitch & yaw to direction vector Real ap = ca->mPitch.valueRadians(), ay = ca->mYaw.valueRadians(); y = sin(ap), xz = cos(ap); x = sin(ay) * xz, z = cos(ay) * xz; xyz = Vector3(x,y,z); xyz *= ca->mDist; } bool manualOrient = false; switch (ca->mType) { case CAM_Arena: /* 2 Arena - free pos & rot */ goalPos = ca->mOffset - ofs; break; case CAM_Free: /* 1 Free - free rot, pos from car */ goalPos += xyz; break; case CAM_Follow: /* 0 Follow - car rotY & pos from behind car, smooth */ { Quaternion orient = orientGoal * qR; orient.FromAngleAxis(orient.getYaw(), Vector3::UNIT_Y); goalPos += orient * xyz; } break; case CAM_ExtAng: /* 4 Extended Angle - car in center, angle smooth */ { Quaternion orient = orientGoal * qR; Quaternion ory; ory.FromAngleAxis(orient.getYaw(), Vector3::UNIT_Y); if (first) { qq = ory; first = false; } else qq = orient.Slerp(ca->mSpeed * time, qq, ory, true); // smooth dist from vel if (0) { if (first) { mPosNodeOld = posGoal; } Real vel = (posGoal - mPosNodeOld).length() / std::max(0.001f, std::min(0.1f, time)); mPosNodeOld = posGoal; if (first) mVel = 0.f; else mVel += (vel - mVel) * time * 8.f; // par vel smooth speed if (!first) xyz *= 1.f + std::min(100.f, mVel) * 0.01f; // par vel dist factor } Quaternion qy = Quaternion(ca->mYaw,Vector3(0,1,0)); goalPos += qq * (xyz + ca->mOffset); mCamera->setPosition( goalPos ); mCamera->setOrientation( qq * qy * Quaternion(Degree(-ca->mPitch),Vector3(1,0,0)) ); manualOrient = true; } break; } if (!manualOrient) // if !CAM_ExtAng { float dtmul = ca->mSpeed == 0 ? 1.0f : ca->mSpeed * time; if (ca->mType == CAM_Arena) { Vector3 Pos(0,0,0), goalPos = ca->mOffset; Pos = mCamera->getPosition(); Pos += (goalPos - Pos) * dtmul; static Radian pitch(0), yaw(0); pitch += (ca->mPitch - pitch) * dtmul; yaw += (ca->mYaw - yaw) * dtmul; if (first) { Pos = goalPos; pitch = ca->mPitch; yaw = ca->mYaw; first = false; } mCamera->setPosition( Pos ); mCamera->setOrientation(Quaternion::IDENTITY); mCamera->pitch(pitch); mCamera->yaw(yaw); manualOrient = true; } else { if (first) pos = goalPos; Vector3 addPos,addLook; addPos = (goalPos - pos).normalisedCopy() * (goalPos - pos).length() * dtmul; if (addPos.squaredLength() > (goalPos - pos).squaredLength()) addPos = goalPos - pos; pos += addPos; mCamera->setPosition( pos + ofs ); if (mGoalNode) goalLook = posGoal + ofs; if (first) { mLook = goalLook; first = false; } addLook = (goalLook - mLook) * dtmul;//Rot; mLook += addLook; } } /// cast ray from car to camera, to prevent objects blocking the camera's sight #ifdef CAM_BLT // update sphere pos btVector3 carPos = BtOgre::Convert::toBullet(posGoal); state->setWorldTransform( btTransform(btQuaternion(0,0,0,1), carPos )); // calculate origin & direction of the ray, convert to vdrift coordinates MATHVECTOR<float,3> origin; origin.Set( carPos.x(), carPos.y(), carPos.z() ); MATHVECTOR<float,3> direction; btVector3 dir = BtOgre::Convert::toBullet(mCamera->getPosition()-posGoal); direction.Set(dir.x(), dir.y(), dir.z()); Real distance = (mCamera->getPosition()-posGoal ).length(); int pOnRoad; // shoot our ray COLLISION_CONTACT contact; mWorld->CastRay( origin, direction, distance, body, contact, &pOnRoad ); if (contact.col != NULL) { LogO("Collision occured"); // collision occured - update cam pos mCamera->setPosition( BtOgre::Convert::toOgre( btVector3(contact.GetPosition()[0], contact.GetPosition()[1], contact.GetPosition()[2]) ) ); } #endif moveAboveTerrain(); if (!manualOrient) mCamera->lookAt( mLook ); updInfo(time); }
//-------------------------------------------------------------------------------------------------------------------------------- // 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; }