void PxSingleActor::interpolateTick( F32 delta ) { Point3F interpPos; QuatF interpRot; // Interpolate the position based on the delta. interpPos.interpolate( mNextPos, mLastPos, delta ); // Interpolate the rotation based on the delta. interpRot.interpolate( mNextRot, mLastRot, delta ); // Set up the interpolated transform. MatrixF interpMat; // Set the interpolated position and rotation. interpRot.setMatrix( &interpMat ); interpMat.setPosition( interpPos ); // Set the transform to the interpolated transform. Parent::setTransform( interpMat ); }
void RigidBody::interpolateTick(F32 dt) { Parent::interpolateTick(dt); //setRenderPosition(mDelta.pos, mDelta.rot[1]); if(dt == 0.0f) { setRenderPosition(mDelta.pos, mDelta.rot[1]); } else { QuatF rot; rot.interpolate(mDelta.rot[1], mDelta.rot[0], dt); Point3F pos = mDelta.pos + mDelta.posVec * dt; setRenderPosition(pos,rot); } mDelta.dt = dt; }
//----------------------------------------------------------------------------- void CameraSpline::value(F32 t, CameraSpline::Knot *result, bool skip_rotation) { // Do some easing in and out for t. if(!gBuilding) { F32 oldT = t; if(oldT < 0.5f) { t = 0.5f - (mSin( (0.5 - oldT) * M_PI ) / 2.f); } if((F32(size()) - 1.5f) > 0.f && oldT - (F32(size()) - 1.5f) > 0.f) { oldT -= (F32(size()) - 1.5f); t = (F32(size()) - 1.5f) + (mCos( (0.5f - oldT) * F32(M_PI) ) / 2.f); } } // Verify that t is in range [0 >= t > size] // AssertFatal(t >= 0.0f && t < (F32)size(), "t out of range"); Knot *p1 = getKnot((S32)mFloor(t)); Knot *p2 = next(p1); F32 i = t - mFloor(t); // adjust t to 0 to 1 on p1-p2 interval if (p1->mPath == Knot::SPLINE) { Knot *p0 = (p1->mType == Knot::KINK) ? p1 : prev(p1); Knot *p3 = (p2->mType == Knot::KINK) ? p2 : next(p2); result->mPosition.x = mCatmullrom(i, p0->mPosition.x, p1->mPosition.x, p2->mPosition.x, p3->mPosition.x); result->mPosition.y = mCatmullrom(i, p0->mPosition.y, p1->mPosition.y, p2->mPosition.y, p3->mPosition.y); result->mPosition.z = mCatmullrom(i, p0->mPosition.z, p1->mPosition.z, p2->mPosition.z, p3->mPosition.z); } else { // Linear result->mPosition.interpolate(p1->mPosition, p2->mPosition, i); } if (skip_rotation) return; buildTimeMap(); // find the two knots to interpolate rotation and velocity through since some // knots are only positional S32 start = (S32)mFloor(t); S32 end = (p2 == p1) ? start : (start + 1); while (p1->mType == Knot::POSITION_ONLY && p1 != front()) { p1 = prev(p1); start--; } while (p2->mType == Knot::POSITION_ONLY && p2 != back()) { p2 = next(p2); end++; } if (start == end) { result->mRotation = p1->mRotation; result->mSpeed = p1->mSpeed; } else { F32 c = getDistance(t); F32 d1 = getDistance((F32)start); F32 d2 = getDistance((F32)end); if (d1 == d2) { result->mRotation = p2->mRotation; result->mSpeed = p2->mSpeed; } else { i = (c-d1)/(d2-d1); if(p1->mPath == Knot::SPLINE) { Knot *p0 = (p1->mType == Knot::KINK) ? p1 : prev(p1); Knot *p3 = (p2->mType == Knot::KINK) ? p2 : next(p2); F32 q,w,e; q = mCatmullrom(i, 0, 1, 1, 1); w = mCatmullrom(i, 0, 0, 0, 1); e = mCatmullrom(i, 0, 0, 1, 1); QuatF a; a.interpolate(p0->mRotation, p1->mRotation, q); QuatF b; b.interpolate(p2->mRotation, p3->mRotation, w); result->mRotation.interpolate(a, b, e); result->mSpeed = mCatmullrom(i, p0->mSpeed, p1->mSpeed, p2->mSpeed, p3->mSpeed); } else { result->mRotation.interpolate(p1->mRotation, p2->mRotation, i); result->mSpeed = (p1->mSpeed * (1.0f-i)) + (p2->mSpeed * i); } } } }
void SFXEmitter::_renderCone( F32 radialIncrements, F32 sweepIncrements, F32 pointDistance, F32 startAngle, F32 stopAngle, F32 startVolume, F32 stopVolume, const ColorI& color ) { if( startAngle == stopAngle ) return; const F32 startAngleRadians = mDegToRad( startAngle ); const F32 stopAngleRadians = mDegToRad( stopAngle ); const F32 radialIncrementsRadians = mDegToRad( radialIncrements ); // Unit quaternions representing the start and end angle so we // can interpolate between the two without flipping. QuatF rotateZStart( EulerF( 0.f, 0.f, startAngleRadians / 2.f ) ); QuatF rotateZEnd( EulerF( 0.f, 0.f, stopAngleRadians / 2.f ) ); // Do an angular sweep on one side of our XY disc. Since we do a full 360 radial sweep // around Y for each angle, we only need to sweep over one side. const F32 increment = 1.f / ( ( ( startAngle / 2.f ) - ( stopAngle / 2.f ) ) / sweepIncrements ); for( F32 t = 0.f; t < 1.0f; t += increment ) { // Quaternion to rotate point into place on XY disc. QuatF rotateZ; rotateZ.interpolate( rotateZStart, rotateZEnd, t ); // Quaternion to rotate one position around Y axis. Used for radial sweep. QuatF rotateYOne( EulerF( 0.f, radialIncrementsRadians, 0.f ) ); // Do a radial sweep each step along the distance axis. For each step, volume is // the same for any point on the sweep circle. for( F32 y = pointDistance; y <= mDescription.mMaxDistance; y += pointDistance ) { ColorI c = color; // Compute volume at current point. First off, find the interpolated volume // in the cone. Only for the outer cone will this actually result in // interpolation. For the remaining angles, the cone volume is constant. F32 volume = mLerp( startVolume, stopVolume, t ); if( volume == 0.f ) c.alpha = 0; else { // Apply distance attenuation. F32 attenuatedVolume = SFXDistanceAttenuation( SFX->getDistanceModel(), mDescription.mMinDistance, mDescription.mMaxDistance, y, volume, SFX->getRolloffFactor() ); //RDTODO // Fade alpha according to how much volume we // have left at the current point. c.alpha = F32( c.alpha ) * ( attenuatedVolume / 1.f ); } PrimBuild::color( c ); // Create points by doing a full 360 degree radial sweep around Y. Point3F p( 0.f, y, 0.f ); rotateZ.mulP( p, &p ); for( F32 radialAngle = 0.f; radialAngle < 360.f; radialAngle += radialIncrements ) { PrimBuild::vertex3f( p.x, p.y, p.z ); rotateYOne.mulP( p, &p ); } } } }
void RigidBody::unpackUpdate(NetConnection *con, BitStream *stream) { //Con::printf("RigidBody::unpackUpdate: %p isServer :%d tick: %d",this,isServerObject(),isServerObject()? gServerProcessList.getTotalTicks():gClientProcessList.getTotalTicks()); Parent::unpackUpdate(con,stream); // Initial update if (stream->readFlag()) { if (stream->readFlag()) { mHasServerPhysic = true; PhysShape* serverShape = NULL; stream->readBits(8*sizeof(serverShape),&serverShape); mPhysShape = serverShape; } else { MatrixF tr; mathRead(*stream,&tr); setTransform(tr); } mDelta.dt = 0; } if (stream->readFlag()) return; if (!mHasServerPhysic && !mDataBlock->mOnlyOnClient && stream->readFlag()) { // Read in new position and momentum values if (!mPhysShape) createPhysShape(); { mPhysShape->unpack(stream); mPhysPosition = mPhysShape->getPosition(); mPhysRotation = mPhysShape->getRotation(); mForce = mPhysShape->getForce(); mTorque = mPhysShape->getTorque(); mLinVelocity = mPhysShape->getLinVelocity(); mAngVelocity = mPhysShape->getAngVelocity(); } /* Con::printf("Unpack vel: %f %f %f momentum: %f %f %f ",mLinVelocity.x,mLinVelocity.y,mLinVelocity.z, mForce.x, mForce.y, mForce.z);*/ if (mDelta.dt > 0.f) { Point3F curPos = mDelta.pos + mDelta.posVec * mDelta.dt; QuatF curRotate; curRotate.interpolate(mDelta.rot[1],mDelta.rot[0],mDelta.dt); mDelta.pos = mPhysPosition; mDelta.posVec = (curPos - mDelta.pos) / mDelta.dt; mDelta.rot[0] = curRotate; mDelta.rot[1] = mPhysRotation; } else { //Con::printf("Unpack pos dt0:"); mDelta.pos = mPhysPosition; mDelta.posVec.set(0,0,0); mDelta.rot[1] = mDelta.rot[0] = mPhysRotation; } } }