void Item::setTransform(const MatrixF& mat) { Point3F pos; mat.getColumn(3,&pos); MatrixF tmat; if (!mRotate) { // Forces all rotation to be around the z axis VectorF vec; mat.getColumn(1,&vec); tmat.set(EulerF(0,0,-mAtan2(-vec.x,vec.y))); } else tmat.identity(); tmat.setColumn(3,pos); Parent::setTransform(tmat); if (!mStatic) { mAtRest = false; mAtRestCounter = 0; } if ( mPhysicsRep ) mPhysicsRep->setTransform( getTransform() ); setMaskBits(RotationMask | PositionMask | NoWarpMask); }
EulerF MatrixF::toEuler() const { const F32 * mat = m; EulerF r; r.x = mAsin(mat[MatrixF::idx(2,1)]); if(mCos(r.x) != 0.f) { r.y = mAtan2(-mat[MatrixF::idx(2,0)], mat[MatrixF::idx(2,2)]); r.z = mAtan2(-mat[MatrixF::idx(0,1)], mat[MatrixF::idx(1,1)]); } else { r.y = 0.f; r.z = mAtan2(mat[MatrixF::idx(1,0)], mat[MatrixF::idx(0,0)]); } return r; }
void Frustum::scaleFromCenter( F32 scale ) { // Extract the fov and aspect ratio. F32 fovInRadians = mAtan2( (mNearTop - mNearBottom)*mNumTiles/2.0f, mNearDist ) * 2.0f; F32 aspectRatio = (mNearRight - mNearLeft)/(mNearTop - mNearBottom); // Now move the near and far planes out. F32 halfDist = ( mFarDist - mNearDist ) / 2.0f; mNearDist -= halfDist * ( scale - 1.0f ); mFarDist += halfDist * ( scale - 1.0f ); // Setup the new scaled frustum. set( mIsOrtho, fovInRadians, aspectRatio, mNearDist, mFarDist, mTransform ); }
F32 TimeOfDay::_calcAzimuth( F32 lat, F32 dec, F32 mer ) { // Add PI to normalize this from the range of -PI/2 to PI/2 to 0 to 2 * PI; return mAtan2( mSin(mer), mCos(mer) * mSin(lat) - mTan(dec) * mCos(lat) ) + M_PI_F; }
/** * This method calculates the moves for the AI player * * @param movePtr Pointer to move the move list into */ bool AIPlayer::getAIMove(Move *movePtr) { *movePtr = NullMove; // Use the eye as the current position. MatrixF eye; getEyeTransform(&eye); Point3F location = eye.getPosition(); Point3F rotation = getRotation(); // Orient towards the aim point, aim object, or towards // our destination. if (mAimObject || mAimLocationSet || mMoveState != ModeStop) { // Update the aim position if we're aiming for an object if (mAimObject) mAimLocation = mAimObject->getPosition() + mAimOffset; else if (!mAimLocationSet) mAimLocation = mMoveDestination; F32 xDiff = mAimLocation.x - location.x; F32 yDiff = mAimLocation.y - location.y; if (!mIsZero(xDiff) || !mIsZero(yDiff)) { // First do Yaw // use the cur yaw between -Pi and Pi F32 curYaw = rotation.z; while (curYaw > M_2PI_F) curYaw -= M_2PI_F; while (curYaw < -M_2PI_F) curYaw += M_2PI_F; // find the yaw offset F32 newYaw = mAtan2( xDiff, yDiff ); F32 yawDiff = newYaw - curYaw; // make it between 0 and 2PI if( yawDiff < 0.0f ) yawDiff += M_2PI_F; else if( yawDiff >= M_2PI_F ) yawDiff -= M_2PI_F; // now make sure we take the short way around the circle if( yawDiff > M_PI_F ) yawDiff -= M_2PI_F; else if( yawDiff < -M_PI_F ) yawDiff += M_2PI_F; movePtr->yaw = yawDiff; // Next do pitch. if (!mAimObject && !mAimLocationSet) { // Level out if were just looking at our next way point. Point3F headRotation = getHeadRotation(); movePtr->pitch = -headRotation.x; } else { // This should be adjusted to run from the // eye point to the object's center position. Though this // works well enough for now. F32 vertDist = mAimLocation.z - location.z; F32 horzDist = mSqrt(xDiff * xDiff + yDiff * yDiff); F32 newPitch = mAtan2( horzDist, vertDist ) - ( M_PI_F / 2.0f ); if (mFabs(newPitch) > 0.01f) { Point3F headRotation = getHeadRotation(); movePtr->pitch = newPitch - headRotation.x; } } } } else { // Level out if we're not doing anything else Point3F headRotation = getHeadRotation(); movePtr->pitch = -headRotation.x; } // Move towards the destination if (mMoveState != ModeStop) { F32 xDiff = mMoveDestination.x - location.x; F32 yDiff = mMoveDestination.y - location.y; // Check if we should mMove, or if we are 'close enough' if (mFabs(xDiff) < mMoveTolerance && mFabs(yDiff) < mMoveTolerance) { mMoveState = ModeStop; throwCallback("onReachDestination"); } else { // Build move direction in world space if (mIsZero(xDiff)) movePtr->y = (location.y > mMoveDestination.y) ? -1.0f : 1.0f; else if (mIsZero(yDiff)) movePtr->x = (location.x > mMoveDestination.x) ? -1.0f : 1.0f; else if (mFabs(xDiff) > mFabs(yDiff)) { F32 value = mFabs(yDiff / xDiff); movePtr->y = (location.y > mMoveDestination.y) ? -value : value; movePtr->x = (location.x > mMoveDestination.x) ? -1.0f : 1.0f; } else { F32 value = mFabs(xDiff / yDiff); movePtr->x = (location.x > mMoveDestination.x) ? -value : value; movePtr->y = (location.y > mMoveDestination.y) ? -1.0f : 1.0f; } // Rotate the move into object space (this really only needs // a 2D matrix) Point3F newMove; MatrixF moveMatrix; moveMatrix.set(EulerF(0.0f, 0.0f, -(rotation.z + movePtr->yaw))); moveMatrix.mulV( Point3F( movePtr->x, movePtr->y, 0.0f ), &newMove ); movePtr->x = newMove.x; movePtr->y = newMove.y; // Set movement speed. We'll slow down once we get close // to try and stop on the spot... if (mMoveSlowdown) { F32 speed = mMoveSpeed; F32 dist = mSqrt(xDiff*xDiff + yDiff*yDiff); F32 maxDist = 5.0f; if (dist < maxDist) speed *= dist / maxDist; movePtr->x *= speed; movePtr->y *= speed; mMoveState = ModeSlowing; } else { movePtr->x *= mMoveSpeed; movePtr->y *= mMoveSpeed; mMoveState = ModeMove; } if (mMoveStuckTestCountdown > 0) --mMoveStuckTestCountdown; else { // We should check to see if we are stuck... F32 locationDelta = (location - mLastLocation).len(); if (locationDelta < mMoveStuckTolerance && mDamageState == Enabled) { // If we are slowing down, then it's likely that our location delta will be less than // our move stuck tolerance. Because we can be both slowing and stuck // we should TRY to check if we've moved. This could use better detection. if ( mMoveState != ModeSlowing || locationDelta == 0 ) { mMoveState = ModeStuck; throwCallback("onMoveStuck"); } } } } } // Test for target location in sight if it's an object. The LOS is // run from the eye position to the center of the object's bounding, // which is not very accurate. if (mAimObject) { MatrixF eyeMat; getEyeTransform(&eyeMat); eyeMat.getColumn(3,&location); Point3F targetLoc = mAimObject->getBoxCenter(); // This ray ignores non-static shapes. Cast Ray returns true // if it hit something. RayInfo dummy; if (getContainer()->castRay( location, targetLoc, StaticShapeObjectType | StaticObjectType | TerrainObjectType, &dummy)) { if (mTargetInLOS) { throwCallback( "onTargetExitLOS" ); mTargetInLOS = false; } } else if (!mTargetInLOS) { throwCallback( "onTargetEnterLOS" ); mTargetInLOS = true; } } // Replicate the trigger state into the move so that // triggers can be controlled from scripts. for( int i = 0; i < MaxTriggerKeys; i++ ) movePtr->trigger[i] = getImageTriggerState(i); mLastLocation = location; return true; }
/** * This method calculates the moves for the AI player * * @param movePtr Pointer to move the move list into */ bool AIPlayer::getAIMove(Move *movePtr) { *movePtr = NullMove; // Use the eye as the current position. MatrixF eye; getEyeTransform(&eye); Point3F location = eye.getPosition(); Point3F rotation = getRotation(); #ifdef TORQUE_NAVIGATION_ENABLED if(mDamageState == Enabled) { if(mMoveState != ModeStop) updateNavMesh(); if(!mFollowData.object.isNull()) { if(mPathData.path.isNull()) { if((getPosition() - mFollowData.object->getPosition()).len() > mFollowData.radius) followObject(mFollowData.object, mFollowData.radius); } else { if((mPathData.path->mTo - mFollowData.object->getPosition()).len() > mFollowData.radius) repath(); else if((getPosition() - mFollowData.object->getPosition()).len() < mFollowData.radius) { clearPath(); mMoveState = ModeStop; throwCallback("onTargetInRange"); } else if((getPosition() - mFollowData.object->getPosition()).len() < mAttackRadius) { throwCallback("onTargetInFiringRange"); } } } } #endif // TORQUE_NAVIGATION_ENABLED // Orient towards the aim point, aim object, or towards // our destination. if (mAimObject || mAimLocationSet || mMoveState != ModeStop) { // Update the aim position if we're aiming for an object if (mAimObject) mAimLocation = mAimObject->getPosition() + mAimOffset; else if (!mAimLocationSet) mAimLocation = mMoveDestination; F32 xDiff = mAimLocation.x - location.x; F32 yDiff = mAimLocation.y - location.y; if (!mIsZero(xDiff) || !mIsZero(yDiff)) { // First do Yaw // use the cur yaw between -Pi and Pi F32 curYaw = rotation.z; while (curYaw > M_2PI_F) curYaw -= M_2PI_F; while (curYaw < -M_2PI_F) curYaw += M_2PI_F; // find the yaw offset F32 newYaw = mAtan2( xDiff, yDiff ); F32 yawDiff = newYaw - curYaw; // make it between 0 and 2PI if( yawDiff < 0.0f ) yawDiff += M_2PI_F; else if( yawDiff >= M_2PI_F ) yawDiff -= M_2PI_F; // now make sure we take the short way around the circle if( yawDiff > M_PI_F ) yawDiff -= M_2PI_F; else if( yawDiff < -M_PI_F ) yawDiff += M_2PI_F; movePtr->yaw = yawDiff; // Next do pitch. if (!mAimObject && !mAimLocationSet) { // Level out if were just looking at our next way point. Point3F headRotation = getHeadRotation(); movePtr->pitch = -headRotation.x; } else { // This should be adjusted to run from the // eye point to the object's center position. Though this // works well enough for now. F32 vertDist = mAimLocation.z - location.z; F32 horzDist = mSqrt(xDiff * xDiff + yDiff * yDiff); F32 newPitch = mAtan2( horzDist, vertDist ) - ( M_PI_F / 2.0f ); if (mFabs(newPitch) > 0.01f) { Point3F headRotation = getHeadRotation(); movePtr->pitch = newPitch - headRotation.x; } } } } else { // Level out if we're not doing anything else Point3F headRotation = getHeadRotation(); movePtr->pitch = -headRotation.x; } // Move towards the destination if (mMoveState != ModeStop) { F32 xDiff = mMoveDestination.x - location.x; F32 yDiff = mMoveDestination.y - location.y; // Check if we should mMove, or if we are 'close enough' if (mFabs(xDiff) < mMoveTolerance && mFabs(yDiff) < mMoveTolerance) { mMoveState = ModeStop; onReachDestination(); } else { // Build move direction in world space if (mIsZero(xDiff)) movePtr->y = (location.y > mMoveDestination.y) ? -1.0f : 1.0f; else if (mIsZero(yDiff)) movePtr->x = (location.x > mMoveDestination.x) ? -1.0f : 1.0f; else if (mFabs(xDiff) > mFabs(yDiff)) { F32 value = mFabs(yDiff / xDiff); movePtr->y = (location.y > mMoveDestination.y) ? -value : value; movePtr->x = (location.x > mMoveDestination.x) ? -1.0f : 1.0f; } else { F32 value = mFabs(xDiff / yDiff); movePtr->x = (location.x > mMoveDestination.x) ? -value : value; movePtr->y = (location.y > mMoveDestination.y) ? -1.0f : 1.0f; } // Rotate the move into object space (this really only needs // a 2D matrix) Point3F newMove; MatrixF moveMatrix; moveMatrix.set(EulerF(0.0f, 0.0f, -(rotation.z + movePtr->yaw))); moveMatrix.mulV( Point3F( movePtr->x, movePtr->y, 0.0f ), &newMove ); movePtr->x = newMove.x; movePtr->y = newMove.y; // Set movement speed. We'll slow down once we get close // to try and stop on the spot... if (mMoveSlowdown) { F32 speed = mMoveSpeed; F32 dist = mSqrt(xDiff*xDiff + yDiff*yDiff); F32 maxDist = mMoveTolerance*2; if (dist < maxDist) speed *= dist / maxDist; movePtr->x *= speed; movePtr->y *= speed; mMoveState = ModeSlowing; } else { movePtr->x *= mMoveSpeed; movePtr->y *= mMoveSpeed; mMoveState = ModeMove; } if (mMoveStuckTestCountdown > 0) --mMoveStuckTestCountdown; else { // We should check to see if we are stuck... F32 locationDelta = (location - mLastLocation).len(); if (locationDelta < mMoveStuckTolerance && mDamageState == Enabled) { // If we are slowing down, then it's likely that our location delta will be less than // our move stuck tolerance. Because we can be both slowing and stuck // we should TRY to check if we've moved. This could use better detection. if ( mMoveState != ModeSlowing || locationDelta == 0 ) { mMoveState = ModeStuck; onStuck(); } } } } } // Test for target location in sight if it's an object. The LOS is // run from the eye position to the center of the object's bounding, // which is not very accurate. if (mAimObject) { if (checkInLos(mAimObject.getPointer())) { if (!mTargetInLOS) { throwCallback( "onTargetEnterLOS" ); mTargetInLOS = true; } } else if (mTargetInLOS) { throwCallback( "onTargetExitLOS" ); mTargetInLOS = false; } } Pose desiredPose = mPose; if ( mSwimming ) desiredPose = SwimPose; else if ( mAiPose == 1 && canCrouch() ) desiredPose = CrouchPose; else if ( mAiPose == 2 && canProne() ) desiredPose = PronePose; else if ( mAiPose == 3 && canSprint() ) desiredPose = SprintPose; else if ( canStand() ) desiredPose = StandPose; setPose( desiredPose ); // Replicate the trigger state into the move so that // triggers can be controlled from scripts. for( U32 i = 0; i < MaxTriggerKeys; i++ ) movePtr->trigger[ i ] = getImageTriggerState( i ); #ifdef TORQUE_NAVIGATION_ENABLED if(mJump == Now) { movePtr->trigger[2] = true; mJump = None; } else if(mJump == Ledge) { // If we're not touching the ground, jump! RayInfo info; if(!getContainer()->castRay(getPosition(), getPosition() - Point3F(0, 0, 0.4f), StaticShapeObjectType, &info)) { movePtr->trigger[2] = true; mJump = None; } } #endif // TORQUE_NAVIGATION_ENABLED mLastLocation = location; return true; }
void DecalManager::_generateWindingOrder( const Point3F &cornerPoint, Vector<Point3F> *sortPoints ) { // This block of code is used to find // the winding order for the points in our quad. // First, choose an arbitrary corner point. // We'll use the "lowerRight" point. Point3F relPoint( 0, 0, 0 ); // See comment below about radius. //F32 radius = 0; F32 theta = 0; Vector<Point4F> tmpPoints; for ( U32 i = 0; i < (*sortPoints).size(); i++ ) { const Point3F &pnt = (*sortPoints)[i]; relPoint = cornerPoint - pnt; // Get the radius (r^2 = x^2 + y^2). // This is commented because for a quad // you typically can't have the same values // for theta, which is the caveat which would // require sorting by the radius. //radius = mSqrt( (relPoint.x * relPoint.x) + (relPoint.y * relPoint.y) ); // Get the theta value for the // interval -PI, PI. // This algorithm for determining the // theta value is defined by // | arctan( y / x ) if x > 0 // | arctan( y / x ) if x < 0 and y >= 0 // theta = | arctan( y / x ) if x < 0 and y < 0 // | PI / 2 if x = 0 and y > 0 // | -( PI / 2 ) if x = 0 and y < 0 if ( relPoint.x > 0.0f ) theta = mAtan2( relPoint.y, relPoint.x ); else if ( relPoint.x < 0.0f ) { if ( relPoint.y >= 0.0f ) theta = mAtan2( relPoint.y, relPoint.x ) + M_PI_F; else if ( relPoint.y < 0.0f ) theta = mAtan2( relPoint.y, relPoint.x ) - M_PI_F; } else if ( relPoint.x == 0.0f ) { if ( relPoint.y > 0.0f ) theta = M_PI_F / 2.0f; else if ( relPoint.y < 0.0f ) theta = -(M_PI_F / 2.0f); } tmpPoints.push_back( Point4F( pnt.x, pnt.y, pnt.z, theta ) ); } dQsort( tmpPoints.address(), tmpPoints.size(), sizeof( Point4F ), cmpQuadPointTheta ); for ( U32 i = 0; i < tmpPoints.size(); i++ ) { const Point4F &tmpPoint = tmpPoints[i]; (*sortPoints)[i].set( tmpPoint.x, tmpPoint.y, tmpPoint.z ); } }
void WaterObject::setShaderParams( SceneRenderState *state, BaseMatInstance *mat, const WaterMatParams ¶mHandles ) { MaterialParameters* matParams = mat->getMaterialParameters(); matParams->setSafe( paramHandles.mElapsedTimeSC, (F32)Sim::getCurrentTime() / 1000.0f ); // set vertex shader constants //----------------------------------- Point2F reflectTexSize( mPlaneReflector.reflectTex.getWidth(), mPlaneReflector.reflectTex.getHeight() ); matParams->setSafe( paramHandles.mReflectTexSizeSC, reflectTexSize ); static AlignedArray<Point2F> mConstArray( MAX_WAVES, sizeof( Point4F ) ); // Ripples... for ( U32 i = 0; i < MAX_WAVES; i++ ) mConstArray[i].set( -mRippleDir[i].x, -mRippleDir[i].y ); matParams->setSafe( paramHandles.mRippleDirSC, mConstArray ); Point3F rippleSpeed( mRippleSpeed[0], mRippleSpeed[1], mRippleSpeed[2] ); matParams->setSafe( paramHandles.mRippleSpeedSC, rippleSpeed ); Point4F rippleMagnitude( mRippleMagnitude[0], mRippleMagnitude[1], mRippleMagnitude[2], mOverallRippleMagnitude ); matParams->setSafe( paramHandles.mRippleMagnitudeSC, rippleMagnitude ); for ( U32 i = 0; i < MAX_WAVES; i++ ) { Point2F texScale = mRippleTexScale[i]; if ( texScale.x > 0.0 ) texScale.x = 1.0 / texScale.x; if ( texScale.y > 0.0 ) texScale.y = 1.0 / texScale.y; mConstArray[i].set( texScale.x, texScale.y ); } matParams->setSafe(paramHandles.mRippleTexScaleSC, mConstArray); static AlignedArray<Point4F> mConstArray4F( 3, sizeof( Point4F ) ); F32 angle, cosine, sine; for ( U32 i = 0; i < MAX_WAVES; i++ ) { angle = mAtan2( mRippleDir[i].x, -mRippleDir[i].y ); cosine = mCos( angle ); sine = mSin( angle ); mConstArray4F[i].set( cosine, sine, -sine, cosine ); matParams->setSafe( paramHandles.mRippleMatSC, mConstArray4F ); } // Waves... for ( U32 i = 0; i < MAX_WAVES; i++ ) mConstArray[i].set( -mWaveDir[i].x, -mWaveDir[i].y ); matParams->setSafe( paramHandles.mWaveDirSC, mConstArray ); for ( U32 i = 0; i < MAX_WAVES; i++ ) mConstArray[i].set( mWaveSpeed[i], mWaveMagnitude[i] * mOverallWaveMagnitude ); matParams->setSafe( paramHandles.mWaveDataSC, mConstArray ); // Foam... Point4F foamDir( mFoamDir[0].x, mFoamDir[0].y, mFoamDir[1].x, mFoamDir[1].y ); matParams->setSafe( paramHandles.mFoamDirSC, foamDir ); Point2F foamSpeed( mFoamSpeed[0], mFoamSpeed[1] ); matParams->setSafe( paramHandles.mFoamSpeedSC, foamSpeed ); //Point3F rippleMagnitude( mRippleMagnitude[0] * mOverallRippleMagnitude, // mRippleMagnitude[1] * mOverallRippleMagnitude, // mRippleMagnitude[2] * mOverallRippleMagnitude ); //matParams->setSafe( paramHandles.mRippleMagnitudeSC, rippleMagnitude ); Point4F foamTexScale( mFoamTexScale[0].x, mFoamTexScale[0].y, mFoamTexScale[1].x, mFoamTexScale[1].y ); for ( U32 i = 0; i < 4; i++ ) { if ( foamTexScale[i] > 0.0f ) foamTexScale[i] = 1.0 / foamTexScale[i]; } matParams->setSafe(paramHandles.mFoamTexScaleSC, foamTexScale); // Other vert params... matParams->setSafe( paramHandles.mUndulateMaxDistSC, mUndulateMaxDist ); // set pixel shader constants //----------------------------------- Point2F fogParams( mWaterFogData.density, mWaterFogData.densityOffset ); matParams->setSafe(paramHandles.mFogParamsSC, fogParams ); matParams->setSafe(paramHandles.mFarPlaneDistSC, (F32)state->getFarPlane() ); Point2F wetnessParams( mWaterFogData.wetDepth, mWaterFogData.wetDarkening ); matParams->setSafe(paramHandles.mWetnessParamsSC, wetnessParams ); Point3F distortionParams( mDistortStartDist, mDistortEndDist, mDistortFullDepth ); matParams->setSafe(paramHandles.mDistortionParamsSC, distortionParams ); LightInfo *sun = LIGHTMGR->getSpecialLight(LightManager::slSunLightType); const ColorF &sunlight = state->getAmbientLightColor(); Point3F ambientColor = mEmissive ? Point3F::One : sunlight; matParams->setSafe(paramHandles.mAmbientColorSC, ambientColor ); matParams->setSafe(paramHandles.mLightDirSC, sun->getDirection() ); Point4F foamParams( mOverallFoamOpacity, mFoamMaxDepth, mFoamAmbientLerp, mFoamRippleInfluence ); matParams->setSafe(paramHandles.mFoamParamsSC, foamParams ); Point4F miscParams( mFresnelBias, mFresnelPower, mClarity, mMiscParamW ); matParams->setSafe( paramHandles.mMiscParamsSC, miscParams ); Point4F specularParams( mSpecularColor.red, mSpecularColor.green, mSpecularColor.blue, mSpecularPower ); if ( !mEmissive ) { const ColorF &sunColor = sun->getColor(); F32 brightness = sun->getBrightness(); specularParams.x *= sunColor.red * brightness; specularParams.y *= sunColor.green * brightness; specularParams.z *= sunColor.blue * brightness; } matParams->setSafe( paramHandles.mSpecularParamsSC, specularParams ); matParams->setSafe( paramHandles.mDepthGradMaxSC, mDepthGradientMax ); matParams->setSafe( paramHandles.mReflectivitySC, mReflectivity ); }
//----------------------------------------------------------------------------- // // VActorPhysicsController::postTickUpdate( pDelta ); // // ... // //----------------------------------------------------------------------------- void VActorPhysicsController::postTickUpdate( const F32 &pDelta ) { switch( mControlState ) { case k_PathControlState : { AssertFatal( isPathing(), "VActorPhysicsController::postTickUpdate() - Invalid Path State." ); // Fetch Mount Transform. MatrixF transform; mMountedPath->getMountTransform( mObject->getMountNode(), getTransform(), &transform ); // Fetch Mount Position. const Point3F &mountPosition = transform.getPosition(); // Update X & Y Position. Point3F position = getPosition(); position.x = mountPosition.x; position.y = mountPosition.y; // In Water? bool underWater = false; if ( isInWater() ) { // Fetch Body of Water. WaterObject *waterBody = getWaterObject(); // Fetch Surface Position. const F32 &waterSurfacePosition = waterBody->getSurfaceHeight( Point2F( position.x, position.y ) ); // Fetch Submersion Position. const F32 sumbersionPosition = waterSurfacePosition - ( mObject->getWorldBox().len_z() * mObject->getDataBlock()->getSumbergeCoverage() ); // Choose a Z Value. // Note: This is done so that the Actor will either path under the // water, or it will swim along the water's surface. position.z = getMin( mountPosition.z, sumbersionPosition ); // Under Water? underWater = ( position.z < sumbersionPosition ); } // Under Water? if ( !underWater ) { // Fetch Y Column. VectorF forwardVector; transform.getColumn( 1, &forwardVector ); // Determine Angle. const F32 &angle = -mAtan2( -forwardVector.x, forwardVector.y ); // Reset Transform. transform.set( EulerF( 0.f, 0.f, angle ) ); // In the air? if ( !isOnGround() ) { // Apply z-axis force. position.z += ( getVelocity().z * pDelta ); } } // Update Transform. transform.setPosition( position ); // Apply Update. setTransform( transform ); } break; default : { // Fetch Transform. MatrixF transform = getTransform(); // Determine the Post-Tick Position. Point3F postTickPosition = getPosition() + ( getVelocity() * pDelta ); // Set the Post Tick Position. transform.setPosition( postTickPosition ); // Apply the Transform. setTransform( transform ); } break; } // Push Delta. mInterpController.pushDelta( getTransform() ); }
/** * This method gets the move list for an object, in the case * of the AI, it actually calculates the moves, and then * sends them down the pipe. * * @param movePtr Pointer to move the move list into * @param numMoves Number of moves in the move list */ U32 AIClient::getMoveList( Move **movePtr,U32 *numMoves ) { //initialize the move structure and return pointers mMove = NullMove; *movePtr = &mMove; *numMoves = 1; // Check if we got a player mPlayer = NULL; mPlayer = dynamic_cast<Player *>( getControlObject() ); // We got a something controling us? if( !mPlayer ) return 1; // What is The Matrix? MatrixF moveMatrix; moveMatrix.set( EulerF( 0, 0, 0 ) ); moveMatrix.setColumn( 3, Point3F( 0, 0, 0 ) ); moveMatrix.transpose(); // Position / rotation variables F32 curYaw, curPitch; F32 newYaw, newPitch; F32 xDiff, yDiff; F32 moveSpeed = mMoveSpeed; switch( mMoveMode ) { case ModeStop: return 1; // Stop means no action break; case ModeStuck: // Fall through, so we still try to move case ModeMove: // Get my location MatrixF const& myTransform = mPlayer->getTransform(); myTransform.getColumn( 3, &mLocation ); // Set rotation variables Point3F rotation = mPlayer->getRotation(); Point3F headRotation = mPlayer->getHeadRotation(); curYaw = rotation.z; curPitch = headRotation.x; xDiff = mAimLocation.x - mLocation.x; yDiff = mAimLocation.y - mLocation.y; // first do Yaw if( !mIsZero( xDiff ) || !mIsZero( yDiff ) ) { // use the cur yaw between -Pi and Pi while( curYaw > M_2PI_F ) curYaw -= M_2PI_F; while( curYaw < -M_2PI_F ) curYaw += M_2PI_F; // find the new yaw newYaw = mAtan2( xDiff, yDiff ); // find the yaw diff F32 yawDiff = newYaw - curYaw; // make it between 0 and 2PI if( yawDiff < 0.0f ) yawDiff += M_2PI_F; else if( yawDiff >= M_2PI_F ) yawDiff -= M_2PI_F; // now make sure we take the short way around the circle if( yawDiff > M_2PI_F ) yawDiff -= M_2PI_F; else if( yawDiff < -M_2PI_F ) yawDiff += M_2PI_F; mMove.yaw = yawDiff; // set up the movement matrix moveMatrix.set( EulerF( 0.0f, 0.0f, newYaw ) ); } else moveMatrix.set( EulerF( 0.0f, 0.0f, curYaw ) ); // next do pitch F32 horzDist = Point2F( mAimLocation.x, mAimLocation.y ).len(); if( !mIsZero( horzDist ) ) { //we shoot from the gun, not the eye... F32 vertDist = mAimLocation.z; newPitch = mAtan2( horzDist, vertDist ) - ( M_2PI_F / 2.0f ); F32 pitchDiff = newPitch - curPitch; mMove.pitch = pitchDiff; } // finally, mMove towards mMoveDestination xDiff = mMoveDestination.x - mLocation.x; yDiff = mMoveDestination.y - mLocation.y; // Check if we should mMove, or if we are 'close enough' if( ( ( mFabs( xDiff ) > mMoveTolerance ) || ( mFabs( yDiff ) > mMoveTolerance ) ) && ( !mIsZero( mMoveSpeed ) ) ) { if( mIsZero( xDiff ) ) mMove.y = ( mLocation.y > mMoveDestination.y ? -moveSpeed : moveSpeed ); else if( mIsZero( yDiff ) ) mMove.x = ( mLocation.x > mMoveDestination.x ? -moveSpeed : moveSpeed ); else if( mFabs( xDiff ) > mFabs( yDiff ) ) { F32 value = mFabs( yDiff / xDiff ) * mMoveSpeed; mMove.y = ( mLocation.y > mMoveDestination.y ? -value : value ); mMove.x = ( mLocation.x > mMoveDestination.x ? -moveSpeed : moveSpeed ); } else { F32 value = mFabs( xDiff / yDiff ) * mMoveSpeed; mMove.x = ( mLocation.x > mMoveDestination.x ? -value : value ); mMove.y = ( mLocation.y > mMoveDestination.y ? -moveSpeed : moveSpeed ); } //now multiply the mMove vector by the transpose of the object rotation matrix moveMatrix.transpose(); Point3F newMove; moveMatrix.mulP( Point3F( mMove.x, mMove.y, 0.0f ), &newMove ); //and sub the result back in the mMove structure mMove.x = newMove.x; mMove.y = newMove.y; // We should check to see if we are stuck... if( mLocation.x == mLastLocation.x && mLocation.y == mLastLocation.y && mLocation.z == mLastLocation.z ) { // We're stuck...probably setMoveMode( ModeStuck ); } else setMoveMode( ModeMove ); } else { // Ok, we are close enough, lets stop // setMoveMode( ModeStop ); // DON'T use this, it'll throw the wrong callback mMoveMode = ModeStop; throwCallback( "onReachDestination" ); // Callback } break; } // Test for target location in sight RayInfo dummy; Point3F targetLoc = mMoveDestination; // Change this if( mPlayer ) { if( !mPlayer->getContainer()->castRay( mLocation, targetLoc, StaticShapeObjectType | StaticObjectType | TerrainObjectType, &dummy ) ) { if( !mTargetInLOS ) throwCallback( "onTargetEnterLOS" ); } else { if( mTargetInLOS ) throwCallback( "onTargetExitLOS" ); } } // Copy over the trigger status for( int i = 0; i < MaxTriggerKeys; i++ ) { mMove.trigger[i] = mTriggers[i]; mTriggers[i] = false; } return 1; }
bool afxEA_ZodiacPlane::ea_update(F32 dt) { if (!pzode) { // create and register effect pzode = new afxZodiacPlane(); pzode->onNewDataBlock(zode_data, false); if (!pzode->registerObject()) { delete pzode; pzode = 0; Con::errorf("afxEA_ZodiacPlane::ea_update() -- effect failed to register."); return false; } deleteNotify(pzode); ///pzode->setSequenceRateFactor(datablock->rate_factor/prop_time_factor); ///pzode->setSortPriority(datablock->sort_priority); } if (pzode) { //ColorF zode_color = zode_data->color; ColorF zode_color = updated_color; if (live_color_factor > 0.0) zode_color.interpolate(zode_color, live_color, live_color_factor); if (do_fades) { if (zode_data->blend_flags == afxZodiacDefs::BLEND_SUBTRACTIVE) zode_color *= fade_value*live_fade_factor; else zode_color.alpha *= fade_value*live_fade_factor; } // scale and grow zode //F32 zode_radius = zode_data->radius_xy*updated_scale.x + life_elapsed*zode_data->growth_rate; F32 zode_radius = zode_data->radius_xy + life_elapsed*zode_data->growth_rate; // zode is growing if (life_elapsed < zode_data->grow_in_time) { F32 t = life_elapsed/zode_data->grow_in_time; zode_radius = afxEase::eq(t, 0.001f, zode_radius, 0.2f, 0.8f); } // zode is shrinking else if (full_lifetime - life_elapsed < zode_data->shrink_out_time) { F32 t = (full_lifetime - life_elapsed)/zode_data->shrink_out_time; zode_radius = afxEase::eq(t, 0.001f, zode_radius, 0.0f, 0.9f); } zode_radius *= live_scale_factor; if (zode_data->respect_ori_cons && !zode_data->use_full_xfm) { VectorF shape_vec; updated_xfm.getColumn(1, &shape_vec); shape_vec.normalize(); F32 ang; switch (zode_data->face_dir) { case afxZodiacPlaneData::FACES_FORWARD: case afxZodiacPlaneData::FACES_BACK: ang = mAtan2(shape_vec.x, shape_vec.z); break; case afxZodiacPlaneData::FACES_RIGHT: case afxZodiacPlaneData::FACES_LEFT: ang = mAtan2(shape_vec.y, shape_vec.z); break; case afxZodiacPlaneData::FACES_UP: case afxZodiacPlaneData::FACES_DOWN: default: ang = mAtan2(shape_vec.x, shape_vec.y); break; } if (ang < 0.0f) ang += M_2PI_F; switch (zode_data->face_dir) { case afxZodiacPlaneData::FACES_DOWN: case afxZodiacPlaneData::FACES_BACK: case afxZodiacPlaneData::FACES_LEFT: ang = -ang; break; } zode_angle_offset = mRadToDeg(ang); } F32 zode_angle = zode_data->calcRotationAngle(life_elapsed, datablock->rate_factor/prop_time_factor); zode_angle = mFmod(zode_angle + zode_angle_offset, 360.0f); aa_rot.angle = mDegToRad(zode_angle); MatrixF spin_xfm; aa_rot.setMatrix(&spin_xfm); // set color, radius pzode->setColor(zode_color); pzode->setRadius(zode_radius); if (zode_data->use_full_xfm) { updated_xfm.mul(spin_xfm); pzode->setTransform(updated_xfm); } else pzode->setTransform(spin_xfm); pzode->setPosition(updated_pos); pzode->setScale(updated_scale); } return true; }