// performs simple maneuvers void CBE_Floater::AttackManeuver(CCopyEntity* pCopyEnt, SBE_EnemyExtraData *pExtraData) { float& rfSensoringInterval = pCopyEnt->f1; Vector3& rvDesiredDirection = pCopyEnt->v1; float& rfCurrentManeuverTime = pExtraData->fCurrentManeuverTime; float& rfTotalManeuverTime = pExtraData->fTotalManeuverTime; Vector3& rvManeuverDir = pExtraData->vManeuverDirection; float fSqDistToPlayer = pExtraData->fLastCheckedSqDistToPlayer; ApplyFriction( pCopyEnt, 1.8f ); // evasive maneuver if( 0.20f < rfCurrentManeuverTime - rfTotalManeuverTime || rvManeuverDir == Vector3(0,0,0) ) { rfCurrentManeuverTime = 0; rfTotalManeuverTime = 0.7f + 0.5f * (float)rand() / (float)RAND_MAX; // set up a new direction rvManeuverDir += pCopyEnt->GetRightDirection() * ( 3.0f * (float)rand()/(float)RAND_MAX - 1.5f ) + pCopyEnt->GetUpDirection() * ( 3.0f * (float)rand()/(float)RAND_MAX - 1.5f ) + pCopyEnt->GetDirection() * ( 1.6f * (float)rand()/(float)RAND_MAX - 0.8f ); if( 36.0f < fSqDistToPlayer ) // if over 6m away from player rvManeuverDir += rvDesiredDirection * fSqDistToPlayer / 50.0f; // move toward the player Vec3Normalize( rvManeuverDir, rvManeuverDir ); } else rfCurrentManeuverTime += m_pStage->GetFrameTime(); if( 0.5f < rfTotalManeuverTime - rfCurrentManeuverTime ) { // float fWishSpeed = 12.0f; float fWishSpeed = 10.0f * m_fMobility; Accelerate( pCopyEnt, rvManeuverDir, fWishSpeed, 4.0f ); } if( rfSensoringInterval == 0 ) { // check if there is an obstacle in the direction to which the entity is heading STrace tr; tr.bvType = BVTYPE_AABB; tr.aabb = this->m_aabb; tr.pSourceEntity = pCopyEnt; tr.vStart = pCopyEnt->GetWorldPosition(); tr.vGoal = pCopyEnt->GetWorldPosition() + pCopyEnt->vVelocity * 1.2f; tr.SetAABB(); m_pStage->ClipTrace(tr); // since the entity is heading for some obstacle, correct the velocity to avoid it if( tr.fFraction < 1.0f ) { pCopyEnt->vVelocity += tr.plane.normal * (1.0f - tr.fFraction ) * 3.0f; // m_pStage->GetFrameTime(); } } SlideMove( pCopyEnt ); }
void CBE_Floater::SearchManeuver(CCopyEntity* pCopyEnt, SBE_EnemyExtraData *pExtraData) { Vector3& rvDesiredDirection = pCopyEnt->v1; Vector3& rvTargetPosition = pExtraData->vTargetPosition; float& rfSensoringInterval2 = pExtraData->fSensoringInterval2; float& rfCurrentManeuverTime = pExtraData->fCurrentManeuverTime; float& rfTotalManeuverTime = pExtraData->fTotalManeuverTime; Vector3& rvManeuverDir = pExtraData->vManeuverDirection; float fWishSpeed = 6.0f; const float frametime = m_pStage->GetFrameTime(); // if( pCopyEnt->vVelocity == Vector3(0,0,0) ) // return; ApplyFriction( pCopyEnt, 1.5f ); if( m_iRandomSearchManeuver != 0 ) { Vector3 vFromCurrentPosToDest = rvTargetPosition - pCopyEnt->GetWorldPosition(); float fDist = Vec3LengthSq( vFromCurrentPosToDest ); if( 0.20f < rfCurrentManeuverTime - rfTotalManeuverTime || rvManeuverDir == Vector3(0,0,0) || fDist < 0.2f ) { rfCurrentManeuverTime = 0; rfTotalManeuverTime = 1.0f + 0.6f * (float)rand() / (float)RAND_MAX; // set up a target locaion rvTargetPosition = pExtraData->vOriginalPosition + Vector3(1,0,0) * ( 12.0f * (float)rand()/(float)RAND_MAX - 6.0f ) + Vector3(0,1,0) * ( 6.0f * (float)rand()/(float)RAND_MAX - 3.0f ) + Vector3(0,0,1) * ( 12.0f * (float)rand()/(float)RAND_MAX - 6.0f ) + pCopyEnt->GetDirection() * 2.5f; Vec3Normalize( rvManeuverDir, rvManeuverDir ); } else rfCurrentManeuverTime += frametime; if( 0.16f < rfSensoringInterval2 ) { rfSensoringInterval2 = 0.0f; Vec3Normalize( rvManeuverDir, vFromCurrentPosToDest ); } else rfSensoringInterval2 += frametime; if( 0.1f < rfTotalManeuverTime - rfCurrentManeuverTime ) { float fWishSpeed = 4.5f; Accelerate( pCopyEnt, rvManeuverDir, fWishSpeed, 2.0f ); } UpdateDesiredYawAndPitch(pCopyEnt, rvManeuverDir); AimAlong(pCopyEnt, rvManeuverDir); } SlideMove( pCopyEnt ); }
/* ===================== idPhysics_Monster::StepMove move start into the delta direction the velocity is clipped conform any collisions ===================== */ monsterMoveResult_t idPhysics_Monster::StepMove(idVec3 &start, idVec3 &velocity, const idVec3 &delta) { trace_t tr; idVec3 up, down, noStepPos, noStepVel, stepPos, stepVel; monsterMoveResult_t result1, result2; float stepdist; float nostepdist; if (delta == vec3_origin) { return MM_OK; } // try to move without stepping up noStepPos = start; noStepVel = velocity; result1 = SlideMove(noStepPos, noStepVel, delta); if (result1 == MM_OK) { velocity = noStepVel; if (gravityNormal == vec3_zero) { start = noStepPos; return MM_OK; } // try to step down so that we walk down slopes and stairs at a normal rate down = noStepPos + gravityNormal * maxStepHeight; gameLocal.clip.Translation(tr, noStepPos, down, clipModel, clipModel->GetAxis(), clipMask, self); if (tr.fraction < 1.0f) { start = tr.endpos; return MM_STEPPED; } else { start = noStepPos; return MM_OK; } } if (blockingEntity && blockingEntity->IsType(idActor::Type)) { // try to step down in case walking into an actor while going down steps down = noStepPos + gravityNormal * maxStepHeight; gameLocal.clip.Translation(tr, noStepPos, down, clipModel, clipModel->GetAxis(), clipMask, self); start = tr.endpos; velocity = noStepVel; return MM_BLOCKED; } if (gravityNormal == vec3_zero) { return result1; } // try to step up up = start - gravityNormal * maxStepHeight; gameLocal.clip.Translation(tr, start, up, clipModel, clipModel->GetAxis(), clipMask, self); if (tr.fraction == 0.0f) { start = noStepPos; velocity = noStepVel; return result1; } // try to move at the stepped up position stepPos = tr.endpos; stepVel = velocity; result2 = SlideMove(stepPos, stepVel, delta); if (result2 == MM_BLOCKED) { start = noStepPos; velocity = noStepVel; return result1; } // step down again down = stepPos + gravityNormal * maxStepHeight; gameLocal.clip.Translation(tr, stepPos, down, clipModel, clipModel->GetAxis(), clipMask, self); stepPos = tr.endpos; // if the move is further without stepping up, or the slope is too steap, don't step up nostepdist = (noStepPos - start).LengthSqr(); stepdist = (stepPos - start).LengthSqr(); if ((nostepdist >= stepdist) || ((tr.c.normal * -gravityNormal) < minFloorCosine)) { start = noStepPos; velocity = noStepVel; return MM_SLIDING; } start = stepPos; velocity = stepVel; return MM_STEPPED; }
/* ===================== idPhysics_Monster::StepMove move start into the delta direction the velocity is clipped conform any collisions ===================== */ monsterMoveResult_t idPhysics_Monster::StepMove( idVec3 &start, idVec3 &velocity, const idVec3 &delta ) { trace_t tr; idVec3 up, down, noStepPos, noStepVel, stepPos, stepVel; monsterMoveResult_t result1, result2; float stepdist; float nostepdist; if( delta == vec3_origin ) { return MM_OK; } // try to move without stepping up noStepPos = start; noStepVel = velocity; result1 = SlideMove( noStepPos, noStepVel, delta ); if( result1 == MM_OK ) { velocity = noStepVel; if( gravityNormal == vec3_zero ) { start = noStepPos; return MM_OK; } // try to step down so that we walk down slopes and stairs at a normal rate down = noStepPos + gravityNormal * maxStepHeight; gameLocal.clip.Translation( tr, noStepPos, down, clipModel, clipModel->GetAxis(), clipMask, self ); if( tr.fraction < 1.0f ) { start = tr.endpos; return MM_STEPPED; } else { start = noStepPos; return MM_OK; } } if( blockingEntity && blockingEntity->IsType( idActor::Type ) ) { // try to step down in case walking into an actor while going down steps down = noStepPos + gravityNormal * maxStepHeight; gameLocal.clip.Translation( tr, noStepPos, down, clipModel, clipModel->GetAxis(), clipMask, self ); start = tr.endpos; velocity = noStepVel; return MM_BLOCKED; } if( gravityNormal == vec3_zero ) { return result1; } // try to step up up = start - gravityNormal * maxStepHeight; gameLocal.clip.Translation( tr, start, up, clipModel, clipModel->GetAxis(), clipMask, self ); //gameRenderWorld->DebugArrow(colorRed, start, up, 2, 5000); if( tr.fraction == 0.0f ) { start = noStepPos; velocity = noStepVel; return result1; } // try to move at the stepped up position stepPos = tr.endpos; stepVel = velocity; result2 = SlideMove( stepPos, stepVel, delta ); if( result2 == MM_BLOCKED ) { start = noStepPos; velocity = noStepVel; return result1; } // step down again down = stepPos + gravityNormal * maxStepHeight; gameLocal.clip.Translation( tr, stepPos, down, clipModel, clipModel->GetAxis(), clipMask, self ); //gameRenderWorld->DebugArrow(colorGreen, stepPos, down, 2, 5000); //gameRenderWorld->DebugArrow(colorBlue, tr.c.point, tr.c.point + 5 * tr.c.normal, 2, 5000); float projection = tr.c.normal * -gravityNormal; // greebo: We have collided with a steep slope in front of us if( projection < minFloorCosine && projection > 0.06f ) { // greebo: Set the endposition a bit more upwards than necessary to prevent gravity from pulling us down immediately again stepPos = tr.endpos - gravityNormal * stepUpIncrease; } else { // No slope, just use the step position stepPos = tr.endpos; } // if the move is further without stepping up, or the slope is too steep, don't step up nostepdist = ( noStepPos - start ).LengthSqr(); stepdist = ( stepPos - start ).LengthSqr(); // Use the position that brought us the largest forward movement if( nostepdist >= stepdist ) { start = noStepPos; velocity = noStepVel; return MM_SLIDING; } start = stepPos; velocity = stepVel; return MM_STEPPED; }
void OvrSceneView::UpdateViewMatrix(const VrFrame vrFrame ) { // Experiments with position tracking const bool useHeadModel = !AllowPositionTracking || ( ( vrFrame.Input.buttonState & ( BUTTON_A | BUTTON_X ) ) == 0 ); // Delta time in seconds since last frame. const float dt = vrFrame.DeltaSeconds; const float yawSpeed = 1.5f; Vector3f GamepadMove; // Allow up / down movement if there is no floor collision model if ( vrFrame.Input.buttonState & BUTTON_RIGHT_TRIGGER ) { FootPos.y -= vrFrame.Input.sticks[0][1] * dt * MoveSpeed; } else { GamepadMove.z = vrFrame.Input.sticks[0][1]; } GamepadMove.x = vrFrame.Input.sticks[0][0]; // Turn based on the look stick // Because this can be predicted ahead by async TimeWarp, we apply // the yaw from the previous frame's controls, trading a frame of // latency on stick controls to avoid a bounce-back. YawOffset -= YawVelocity * dt; if ( !( vrFrame.OvrStatus & ovrStatus_OrientationTracked ) ) { PitchOffset -= yawSpeed * vrFrame.Input.sticks[1][1] * dt; YawVelocity = yawSpeed * vrFrame.Input.sticks[1][0]; } else { YawVelocity = 0.0f; } // We extract Yaw, Pitch, Roll instead of directly using the orientation // to allow "additional" yaw manipulation with mouse/controller. const Quatf quat = vrFrame.PoseState.Pose.Orientation; quat.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>( &EyeYaw, &EyePitch, &EyeRoll ); EyeYaw += YawOffset; // If the sensor isn't plugged in, allow right stick up/down // to adjust pitch, which can be useful for debugging. Never // do this when head tracking if ( !( vrFrame.OvrStatus & ovrStatus_OrientationTracked ) ) { EyePitch += PitchOffset; } // Perform player movement. if ( GamepadMove.LengthSq() > 0.0f ) { const Matrix4f yawRotate = Matrix4f::RotationY( EyeYaw ); const Vector3f orientationVector = yawRotate.Transform( GamepadMove ); // Don't let move get too crazy fast const float moveDistance = OVR::Alg::Min<float>( MoveSpeed * (float)dt, 1.0f ); if ( WorldModel.Definition ) { FootPos = SlideMove( FootPos, ViewParms.EyeHeight, orientationVector, moveDistance, WorldModel.Definition->Collisions, WorldModel.Definition->GroundCollisions ); } else { // no scene loaded, walk without any collisions CollisionModel collisionModel; CollisionModel groundCollisionModel; FootPos = SlideMove( FootPos, ViewParms.EyeHeight, orientationVector, moveDistance, collisionModel, groundCollisionModel ); } } // Rotate and position View Camera, using YawPitchRoll in BodyFrame coordinates. Matrix4f rollPitchYaw = Matrix4f::RotationY( EyeYaw ) * Matrix4f::RotationX( EyePitch ) * Matrix4f::RotationZ( EyeRoll ); const Vector3f up = rollPitchYaw.Transform( UpVector ); const Vector3f forward = rollPitchYaw.Transform( ForwardVector ); const Vector3f right = rollPitchYaw.Transform( RightVector ); // Have sensorFusion zero the integration when not using it, so the // first frame is correct. if ( vrFrame.Input.buttonPressed & (BUTTON_A | BUTTON_X) ) { LatchedHeadModelOffset = LastHeadModelOffset; } // Calculate the shiftedEyePos ShiftedEyePos = CenterEyePos(); Vector3f headModelOffset = HeadModelOffset( EyeRoll, EyePitch, EyeYaw, ViewParms.HeadModelDepth, ViewParms.HeadModelHeight ); if ( useHeadModel ) { ShiftedEyePos += headModelOffset; } headModelOffset += forward * ImuToEyeCenter.z; headModelOffset += right * ImuToEyeCenter.x; LastHeadModelOffset = headModelOffset; if ( !useHeadModel ) { // Use position tracking from the sensor system, which is in absolute // coordinates without the YawOffset ShiftedEyePos += Matrix4f::RotationY( YawOffset ).Transform( vrFrame.PoseState.Pose.Position ); ShiftedEyePos -= forward * ImuToEyeCenter.z; ShiftedEyePos -= right * ImuToEyeCenter.x; ShiftedEyePos += LatchedHeadModelOffset; } ViewMatrix = Matrix4f::LookAtRH( ShiftedEyePos, ShiftedEyePos + forward, up ); }
/* ================ rvPhysics_Particle::Evaluate Evaluate the impulse based rigid body physics. When a collision occurs an impulse is applied at the moment of impact but the remaining time after the collision is ignored. ================ */ bool rvPhysics_Particle::Evaluate( int timeStepMSec, int endTimeMSec ) { particlePState_t next; float timeStep; float upspeed; timeStep = MS2SEC( timeStepMSec ); // if bound to a master if ( hasMaster ) { idVec3 masterOrigin; idMat3 masterAxis; idVec3 oldOrigin; oldOrigin = current.origin; self->GetMasterPosition( masterOrigin, masterAxis ); current.origin = masterOrigin + current.localOrigin * masterAxis; // RAVEN BEGIN // ddynerman: multiple clip worlds clipModel->Link( self, clipModel->GetId(), current.origin, current.localAxis * masterAxis ); // RAVEN END trace_t tr; gameLocal.Translation( self, tr, oldOrigin, current.origin, clipModel, clipModel->GetAxis(), clipMask, self ); if ( tr.fraction < 1.0f ) { self->Collide ( tr, current.origin - oldOrigin ); } DebugDraw(); return true; } // if the body is at rest if ( current.atRest >= 0 || timeStep <= 0.0f ) { DebugDraw(); return false; } // if putting the body to rest if ( dropToFloor ) { DropToFloorAndRest(); return true; } clipModel->Unlink(); // Determine if currently on the ground CheckGround ( ); // Determine the current upward velocity if ( gravityNormal != vec3_zero ) { upspeed = -( current.velocity * gravityNormal ); } else { upspeed = current.velocity.z; } // If not on the ground, or moving upwards, or bouncing and moving toward gravity then do a straight // forward slide move and gravity. if ( !current.onGround || upspeed > 1.0f || (bouncyness > 0.0f && upspeed < -PRT_BOUNCESTOP && !current.inWater) ) { // Force ground off when moving upward if ( upspeed > 0.0f ) { current.onGround = false; } SlideMove( current.origin, current.velocity, current.velocity * timeStep ); if ( current.onGround && upspeed < PRT_BOUNCESTOP ) { current.velocity -= ( current.velocity * gravityNormal ) * gravityNormal; } else { current.velocity += (gravityVector * timeStep); } } else { idVec3 delta; // Slow down due to friction ApplyFriction ( timeStep ); delta = current.velocity * timeStep; current.velocity -= ( current.velocity * gravityNormal ) * gravityNormal; if ( delta == vec3_origin ) { PutToRest( ); } else { SlideMove( current.origin, current.velocity, delta ); } } // update the position of the clip model // RAVEN BEGIN // ddynerman: multiple clip worlds clipModel->Link( self, clipModel->GetId(), current.origin, clipModel->GetAxis() ); // RAVEN END DebugDraw(); // get all the ground contacts EvaluateContacts(); current.pushVelocity.Zero(); if ( IsOutsideWorld() ) { gameLocal.Warning( "clip model outside world bounds for entity '%s' at (%s)", self->name.c_str(), current.origin.ToString(0) ); PutToRest(); } return true; }
void OvrSceneView::Frame( const VrFrame & vrFrame, const ovrHeadModelParms & headModelParms_, const long long supressModelsWithClientId_ ) { HeadModelParms = headModelParms_; SupressModelsWithClientId = supressModelsWithClientId_; CurrentTracking = vrFrame.Tracking; // Delta time in seconds since last frame. const float dt = vrFrame.DeltaSeconds; const float angleSpeed = 1.5f; // // Player view angles // // Turn based on the look stick // Because this can be predicted ahead by async TimeWarp, we apply // the yaw from the previous frame's controls, trading a frame of // latency on stick controls to avoid a bounce-back. StickYaw -= YawVelocity * dt; YawVelocity = angleSpeed * vrFrame.Input.sticks[1][0]; // Only if there is no head tracking, allow right stick up/down to adjust pitch, // which can be useful for debugging without having to dock the device. if ( ( vrFrame.Tracking.Status & VRAPI_TRACKING_STATUS_ORIENTATION_TRACKED ) == 0 ) { StickPitch -= angleSpeed * vrFrame.Input.sticks[1][1] * dt; } else { StickPitch = 0.0f; } // We extract Yaw, Pitch, Roll instead of directly using the orientation // to allow "additional" yaw manipulation with mouse/controller and scene offsets. const Quatf quat = vrFrame.Tracking.HeadPose.Pose.Orientation; quat.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>( &EyeYaw, &EyePitch, &EyeRoll ); // Yaw is modified by both joystick and application-set scene yaw. // Pitch is only modified by joystick when no head tracking sensor is active. EyeYaw += StickYaw + SceneYaw; EyePitch += StickPitch; // // Player movement // // Allow up / down movement if there is no floor collision model or in 'free move' mode. const bool upDown = ( WorldModel.Definition == NULL || FreeMove ) && ( ( vrFrame.Input.buttonState & BUTTON_RIGHT_TRIGGER ) != 0 ); const Vector3f gamepadMove( vrFrame.Input.sticks[0][0], upDown ? -vrFrame.Input.sticks[0][1] : 0.0f, upDown ? 0.0f : vrFrame.Input.sticks[0][1] ); // Perform player movement if there is input. if ( gamepadMove.LengthSq() > 0.0f ) { const Matrix4f yawRotate = Matrix4f::RotationY( EyeYaw ); const Vector3f orientationVector = yawRotate.Transform( gamepadMove ); // Don't let move get too crazy fast const float moveDistance = OVR::Alg::Min<float>( MoveSpeed * (float)dt, 1.0f ); if ( WorldModel.Definition != NULL && !FreeMove ) { FootPos = SlideMove( FootPos, HeadModelParms.EyeHeight, orientationVector, moveDistance, WorldModel.Definition->Collisions, WorldModel.Definition->GroundCollisions ); } else { // no scene loaded, walk without any collisions ModelCollision collisionModel; ModelCollision groundCollisionModel; FootPos = SlideMove( FootPos, HeadModelParms.EyeHeight, orientationVector, moveDistance, collisionModel, groundCollisionModel ); } } // // Center eye transform // UpdateCenterEye(); // // Model animations // if ( !Paused ) { for ( int i = 0; i < Models.GetSizeI(); i++ ) { if ( Models[i] != NULL ) { Models[i]->AnimateJoints( static_cast<float>( vrFrame.PredictedDisplayTimeInSeconds ) ); } } } // External systems can add surfaces to this list before drawing. EmitSurfaces.Resize( 0 ); }