void GameSession::SimulateFreeElems(MR_SimulationTime pTimeToSimulate) { Level *mCurrentLevel = track->GetLevel(); // Do the simulation int lRoomIndex; // Interaction objects collection // Simulate element by element for(lRoomIndex = -1; lRoomIndex < mCurrentLevel->GetRoomCount(); lRoomIndex++) { // Simulate FreeElements MR_FreeElementHandle lElementHandle = mCurrentLevel->GetFirstFreeElement(lRoomIndex); while(lElementHandle != NULL) { MR_FreeElementHandle lNext = Level::GetNextFreeElement(lElementHandle); SimulateOneFreeElem(pTimeToSimulate, lElementHandle, lRoomIndex); lElementHandle = lNext; } } mCurrentLevel->FlushPermElementPosCache(); }
void GameSession::ComputeShapeContactEffects(int pCurrentRoom, FreeElement *pActor, const RoomContactSpec &pLastSpec, MR_FastArrayBase<int> *pVisitedRooms, int pMaxDepth, MR_SimulationTime pDuration) { Level *mCurrentLevel = track->GetLevel(); int lCounter; ContactSpec lSpec; const ShapeInterface *lActorShape = pActor->GetGivingContactEffectShape(); BOOL lValidDirection = FALSE; MR_Angle lDirectionAngle = 0; pVisitedRooms->Add(pCurrentRoom); // Compute contact with features // Not correctly done. If a collision is detected, only the floor of the // feature is assumed to be touched (directio is ok but wrong elementis selected int lNbFeatures = mCurrentLevel->GetFeatureCount(pCurrentRoom); for(lCounter = 0; lCounter < lNbFeatures; lCounter++) { int lFeatureId = mCurrentLevel->GetFeature(pCurrentRoom, lCounter); if(mCurrentLevel->GetFeatureContact(lFeatureId, lActorShape, lSpec)) { SurfaceElement *lFloor = mCurrentLevel->GetFeatureTopElement(lFeatureId); // Ok Compute the directiion of the collision if(lSpec.mZMax <= lActorShape->ZMin()) { lValidDirection = FALSE; } else if(lSpec.mZMin >= lActorShape->ZMax()) { lValidDirection = FALSE; } else { lValidDirection = mCurrentLevel->GetFeatureContactOrientation(lFeatureId, lActorShape, lDirectionAngle); } // const ContactEffectList* lActorEffectList = pActor->GetEffectList(); const ContactEffectList *lObstacleEffectList = lFloor->GetEffectList(); // Apply feature effects to the actor pActor->ApplyEffects(lObstacleEffectList, mSimulationTime, pDuration, lValidDirection, lDirectionAngle, lSpec.mZMin, lSpec.mZMax, *track); // Apply actor effects to the feature // if( lValidDirection ) //{ // lDirectionAngle = MR_NORMALIZE_ANGLE( lDirectionAngle+MR_PI ); // lFloor->ApplyEffects( lActorEffectList, mSimulationTime, pDuration, lValidDirection, lDirectionAngle ); //} } } // Compute interaction with room actors MR_FreeElementHandle lObstacleHandle = mCurrentLevel->GetFirstFreeElement(pCurrentRoom); while(lObstacleHandle != NULL) { FreeElement *lObstacleElem = Level::GetFreeElement(lObstacleHandle); if(lObstacleElem != pActor) { if(DetectActorContact(lActorShape, lObstacleElem->GetReceivingContactEffectShape(), lSpec)) { // Ok Compute the directiion of the collision if(lSpec.mZMax <= lActorShape->ZMin()) { lValidDirection = FALSE; } else if(lSpec.mZMin >= lActorShape->ZMax()) { lValidDirection = FALSE; } else { lValidDirection = GetActorForceLongitude(lActorShape, lObstacleElem->GetReceivingContactEffectShape(), lDirectionAngle); } const ContactEffectList *lActorEffectList = pActor->GetEffectList(); const ContactEffectList *lObstacleEffectList = lObstacleElem->GetEffectList(); // Apply feature effects to the actor pActor->ApplyEffects(lObstacleEffectList, mSimulationTime, pDuration, lValidDirection, lDirectionAngle, lSpec.mZMin, lSpec.mZMax, *track); // Apply actor effects to the feature lDirectionAngle = MR_NORMALIZE_ANGLE(lDirectionAngle + MR_PI); lObstacleElem->ApplyEffects(lActorEffectList, mSimulationTime, pDuration, lValidDirection, lDirectionAngle, lSpec.mZMin, lSpec.mZMax, *track); } } lObstacleHandle = Level::GetNextFreeElement(lObstacleHandle); } // Compute interaction with touched walls // at the same time compute interaction with other rooms for(lCounter = 0; lCounter < pLastSpec.mNbWallContact; lCounter++) { // Verify that the wall is a wall on all its height MR_Int32 lContactTop = lActorShape->ZMax(); MR_Int32 lContactBottom = lActorShape->ZMin(); int lNeighbor = mCurrentLevel->GetNeighbor(pCurrentRoom, pLastSpec.mWallContact[lCounter]); if(lNeighbor != -1) { if(!pVisitedRooms->Contains(lNeighbor)) { RoomContactSpec cspec; // Recursively call this function mCurrentLevel->GetRoomContact(lNeighbor, lActorShape, cspec); if((cspec.mDistanceFromFloor < 0) || (cspec.mDistanceFromCeiling < 0)) { lNeighbor = -1; } else { ComputeShapeContactEffects(lNeighbor, pActor, cspec, pVisitedRooms, pMaxDepth - 1, pDuration); } } } if(lNeighbor == -1) { // Apply the effect of the wall if(mCurrentLevel->GetRoomWallContactOrientation(pCurrentRoom, pLastSpec.mWallContact[lCounter], lActorShape, lDirectionAngle)) { SurfaceElement *lWall = mCurrentLevel->GetRoomWallElement(pCurrentRoom, static_cast<size_t>(pLastSpec.mWallContact[static_cast<size_t>(lCounter)])); // const ContactEffectList* lActorEffectList = pActor->GetEffectList(); const ContactEffectList *lWallEffectList = lWall->GetEffectList(); // Apply feature effects to the actor pActor->ApplyEffects(lWallEffectList, mSimulationTime, pDuration, TRUE, lDirectionAngle, lContactBottom, lContactTop, *track); // Apply actor effects to the feature // lDirectionAngle = MR_NORMALIZE_ANGLE( lDirectionAngle+MR_PI ); // lWall->ApplyEffects( lActorEffectList, mSimulationTime, pDuration, TRUE, lDirectionAngle ); } } } }