void convertRotation(const F32 inRotMat[3][3], MatrixF& outRotation) { // Set rotation. We need to convert from sixense coordinates to // Torque coordinates. The conversion is: // // Sixense Torque // a b c a b c a -c b // d e f --> -g -h -i --> -g i -h // g h i d e f d -f e outRotation.setColumn(0, Point4F( inRotMat[0][0], -inRotMat[0][2], inRotMat[0][1], 0.0f)); outRotation.setColumn(1, Point4F(-inRotMat[2][0], inRotMat[2][2], -inRotMat[2][1], 0.0f)); outRotation.setColumn(2, Point4F( inRotMat[1][0], -inRotMat[1][2], inRotMat[1][1], 0.0f)); outRotation.setPosition(Point3F::Zero); }
void WorldEditorSelection::offset( const Point3F& offset, F32 gridSnap ) { for( iterator iter = begin(); iter != end(); ++ iter ) { SceneObject* obj = dynamic_cast<SceneObject*>( *iter ); if( !obj ) continue; MatrixF mat = obj->getTransform(); Point3F wPos; mat.getColumn(3, &wPos); // adjust wPos += offset; if( gridSnap != 0.f ) { wPos.x -= mFmod( wPos.x, gridSnap ); wPos.y -= mFmod( wPos.y, gridSnap ); wPos.z -= mFmod( wPos.z, gridSnap ); } mat.setColumn(3, wPos); obj->setTransform(mat); } mCentroidValid = false; }
void RigidBody::setRenderPosition(const Point3F& pos, const QuatF& rot) { MatrixF mat; rot.setMatrix(&mat); mat.setColumn(3,pos); setRenderTransform(mat); }
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); }
void SceneObject::setPosition(const Point3F &pos) { AssertFatal( !mIsNaN( pos ), "SceneObject::setPosition() - The position is NaN!" ); MatrixF xform = mObjToWorld; xform.setColumn(3, pos); setTransform(xform); }
void convertPointableRotation(const Leap::Pointable& pointable, MatrixF& outRotation) { // We need to convert from Motion coordinates to // Torque coordinates. The conversion is: // // Motion Torque // a b c a b c a -c b // d e f --> -g -h -i --> -g i -h // g h i d e f d -f e Leap::Vector pointableFront = -pointable.direction(); Leap::Vector pointableRight = Leap::Vector::up().cross(pointableFront); Leap::Vector pointableUp = pointableFront.cross(pointableRight); outRotation.setColumn(0, Point4F( pointableRight.x, -pointableRight.z, pointableRight.y, 0.0f)); outRotation.setColumn(1, Point4F( -pointableFront.x, pointableFront.z, -pointableFront.y, 0.0f)); outRotation.setColumn(2, Point4F( pointableUp.x, -pointableUp.z, pointableUp.y, 0.0f)); outRotation.setPosition(Point3F::Zero); }
void Etherform::setRenderPosition(const Point3F& pos, const Point3F& rot, F32 dt) { MatrixF xRot, zRot; xRot.set(EulerF(rot.x, 0, 0)); zRot.set(EulerF(0, 0, rot.z)); MatrixF temp; temp.mul(zRot, xRot); temp.setColumn(3, pos); Parent::setRenderTransform(temp); }
void Item::interpolateTick(F32 dt) { Parent::interpolateTick(dt); // Client side interpolation Point3F pos = delta.pos + delta.posVec * dt; MatrixF mat = mRenderObjToWorld; mat.setColumn(3,pos); setRenderTransform(mat); delta.dt = dt; }
void convertHandRotation(const Leap::Hand& hand, MatrixF& outRotation) { // We need to convert from Motion coordinates to // Torque coordinates. The conversion is: // // Motion Torque // a b c a b c a -c b // d e f --> -g -h -i --> -g i -h // g h i d e f d -f e const Leap::Vector& handToFingers = hand.direction(); Leap::Vector handFront = -handToFingers; const Leap::Vector& handDown = hand.palmNormal(); Leap::Vector handUp = -handDown; Leap::Vector handRight = handUp.cross(handFront); outRotation.setColumn(0, Point4F( handRight.x, -handRight.z, handRight.y, 0.0f)); outRotation.setColumn(1, Point4F( -handFront.x, handFront.z, -handFront.y, 0.0f)); outRotation.setColumn(2, Point4F( handUp.x, -handUp.z, handUp.y, 0.0f)); outRotation.setPosition(Point3F::Zero); }
MatrixF PlaneReflector::getFrustumClipProj( MatrixF &modelview ) { static MatrixF rotMat(EulerF( static_cast<F32>(M_PI / 2.f), 0.0, 0.0)); static MatrixF invRotMat(EulerF( -static_cast<F32>(M_PI / 2.f), 0.0, 0.0)); MatrixF revModelview = modelview; revModelview = rotMat * revModelview; // add rotation to modelview because it needs to be removed from projection // rotate clip plane into modelview space Point4F clipPlane; Point3F pnt = refplane * -(refplane.d + 0.0 ); Point3F norm = refplane; revModelview.mulP( pnt ); revModelview.mulV( norm ); norm.normalize(); clipPlane.set( norm.x, norm.y, norm.z, -mDot( pnt, norm ) ); // Manipulate projection matrix //------------------------------------------------------------------------ MatrixF proj = GFX->getProjectionMatrix(); proj.mul( invRotMat ); // reverse rotation imposed by Torque proj.transpose(); // switch to row-major order // Calculate the clip-space corner point opposite the clipping plane // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and // transform it into camera space by multiplying it // by the inverse of the projection matrix Vector4F q; q.x = sgn(clipPlane.x) / proj(0,0); q.y = sgn(clipPlane.y) / proj(1,1); q.z = -1.0F; q.w = ( 1.0F - proj(2,2) ) / proj(3,2); F32 a = 1.0 / (clipPlane.x * q.x + clipPlane.y * q.y + clipPlane.z * q.z + clipPlane.w * q.w); Vector4F c = clipPlane * a; // CodeReview [ags 1/23/08] Come up with a better way to deal with this. if(GFX->getAdapterType() == OpenGL) c.z += 1.0f; // Replace the third column of the projection matrix proj.setColumn( 2, c ); proj.transpose(); // convert back to column major order proj.mul( rotMat ); // restore Torque rotation return proj; }
void GFXGLDevice::setClipRect( const RectI &inRect ) { AssertFatal(mCurrentRT.isValid(), "GFXGLDevice::setClipRect - must have a render target set to do any rendering operations!"); // Clip the rect against the renderable size. Point2I size = mCurrentRT->getSize(); RectI maxRect(Point2I(0,0), size); mClip = inRect; mClip.intersect(maxRect); // Create projection matrix. See http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/ortho.html const F32 left = mClip.point.x; const F32 right = mClip.point.x + mClip.extent.x; const F32 bottom = mClip.extent.y; const F32 top = 0.0f; const F32 nearPlane = 0.0f; const F32 farPlane = 1.0f; const F32 tx = -(right + left)/(right - left); const F32 ty = -(top + bottom)/(top - bottom); const F32 tz = -(farPlane + nearPlane)/(farPlane - nearPlane); static Point4F pt; pt.set(2.0f / (right - left), 0.0f, 0.0f, 0.0f); mProjectionMatrix.setColumn(0, pt); pt.set(0.0f, 2.0f/(top - bottom), 0.0f, 0.0f); mProjectionMatrix.setColumn(1, pt); pt.set(0.0f, 0.0f, -2.0f/(farPlane - nearPlane), 0.0f); mProjectionMatrix.setColumn(2, pt); pt.set(tx, ty, tz, 1.0f); mProjectionMatrix.setColumn(3, pt); // Translate projection matrix. static MatrixF translate(true); pt.set(0.0f, -mClip.point.y, 0.0f, 1.0f); translate.setColumn(3, pt); mProjectionMatrix *= translate; setMatrix(GFXMatrixProjection, mProjectionMatrix); MatrixF mTempMatrix(true); setViewMatrix( mTempMatrix ); setWorldMatrix( mTempMatrix ); // Set the viewport to the clip rect RectI viewport(mClip.point.x, mClip.point.y, mClip.extent.x, mClip.extent.y); setViewport(viewport); }
void Item::processTick(const Move* move) { Parent::processTick(move); // if (mCollisionObject && !--mCollisionTimeout) mCollisionObject = 0; // Warp to catch up to server if (delta.warpTicks > 0) { delta.warpTicks--; // Set new pos. MatrixF mat = mObjToWorld; mat.getColumn(3,&delta.pos); delta.pos += delta.warpOffset; mat.setColumn(3,delta.pos); Parent::setTransform(mat); // Backstepping delta.posVec.x = -delta.warpOffset.x; delta.posVec.y = -delta.warpOffset.y; delta.posVec.z = -delta.warpOffset.z; } else { if (isServerObject() && mAtRest && (mStatic == false && mDataBlock->sticky == false)) { if (++mAtRestCounter > csmAtRestTimer) { mAtRest = false; mAtRestCounter = 0; setMaskBits(PositionMask); } } if (!mStatic && !mAtRest && isHidden() == false) { updateVelocity(TickSec); updateWorkingCollisionSet(isGhost() ? sClientCollisionMask : sServerCollisionMask, TickSec); updatePos(isGhost() ? sClientCollisionMask : sServerCollisionMask, TickSec); } else { // Need to clear out last updatePos or warp interpolation delta.posVec.set(0,0,0); } } }
bool Item::buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F&, const SphereF&) { if ( context == PLC_Decal ) return false; // Collision with the item is always against the item's object // space bounding box axis aligned in world space. Point3F pos; mObjToWorld.getColumn(3,&pos); IMat.setColumn(3,pos); polyList->setTransform(&IMat, mObjScale); polyList->setObject(this); polyList->addBox(mObjBox); return true; }
void RigidBody::processTick(const Move* move) { Parent::processTick(move); if (mPhysShape) { // Save current interpolation /* MatrixF curTr = getRenderTransform(); mDelta.posVec = curTr.getPosition(); mDelta.rot[0].set(curTr); */ mDelta.posVec = mPhysPosition; mDelta.rot[0] = mPhysRotation; mPhysPosition = mPhysShape->getPosition(); mPhysRotation = mPhysShape->getRotation(); mForce = mPhysShape->getForce(); mTorque = mPhysShape->getTorque(); mLinVelocity = mPhysShape->getLinVelocity(); mAngVelocity = mPhysShape->getAngVelocity(); mDelta.pos = mPhysPosition; mDelta.posVec -= mDelta.pos; mDelta.rot[1] = mPhysRotation; // Update container database //setPosition(mDelta.pos, mDelta.rot[1]); MatrixF mat; mDelta.rot[1].setMatrix(&mat); mat.setColumn(3,mDelta.pos); Parent::setTransform(mat); } /* Con::printf("ProcessTick s:%d vel: %f %f %f momentum: %f %f %f ",isServerObject(),mLinVelocity.x,mLinVelocity.y,mLinVelocity.z, mForce.x, mForce.y, mForce.z); */ setMaskBits(PositionMask); updateContainer(); }
void fxShapeReplicator::CreateShapes(void) { F32 HypX, HypY; F32 Angle; U32 RelocationRetry; Point3F ShapePosition; Point3F ShapeStart; Point3F ShapeEnd; Point3F ShapeScale; EulerF ShapeRotation; QuatF QRotation; bool CollisionResult; RayInfo RayEvent; TSShape* pShape; // Don't create shapes if we are hiding replications. if (mFieldData.mHideReplications) return; // Cannot continue without shapes! if (dStrcmp(mFieldData.mShapeFile, "") == 0) return; // Check that we can position somewhere! if (!( mFieldData.mAllowOnTerrain || mFieldData.mAllowStatics || mFieldData.mAllowOnWater)) { // Problem ... Con::warnf(ConsoleLogEntry::General, "[%s] - Could not place object, All alloweds are off!", getName()); // Return here. return; } // Check Shapes. AssertFatal(mCurrentShapeCount==0,"Shapes already present, this should not be possible!") // Check that we have a shape... if (!mFieldData.mShapeFile) return; // Set Seed. RandomGen.setSeed(mFieldData.mSeed); // Set shape vector. mReplicatedShapes.clear(); // Add shapes. for (U32 idx = 0; idx < mFieldData.mShapeCount; idx++) { fxShapeReplicatedStatic* fxStatic; // Create our static shape. fxStatic = new fxShapeReplicatedStatic(); // Set the 'shapeName' field. fxStatic->setField("shapeName", mFieldData.mShapeFile); // Is this Replicator on the Server? if (isServerObject()) // Yes, so stop it from Ghosting. (Hack, Hack, Hack!) fxStatic->touchNetFlags(Ghostable, false); else // No, so flag as ghost object. (Another damn Hack!) fxStatic->touchNetFlags(IsGhost, true); // Register the Object. if (!fxStatic->registerObject()) { // Problem ... Con::warnf(ConsoleLogEntry::General, "[%s] - Could not load shape file '%s'!", getName(), mFieldData.mShapeFile); // Destroy Shape. delete fxStatic; // Destroy existing hapes. DestroyShapes(); // Quit. return; } // Get Allocated Shape. pShape = fxStatic->getShape(); // Reset Relocation Retry. RelocationRetry = mFieldData.mShapeRetries; // Find it a home ... do { // Get the Replicator Position. ShapePosition = getPosition(); // Calculate a random offset HypX = RandomGen.randF(mFieldData.mInnerRadiusX, mFieldData.mOuterRadiusX); HypY = RandomGen.randF(mFieldData.mInnerRadiusY, mFieldData.mOuterRadiusY); Angle = RandomGen.randF(0, (F32)M_2PI); // Calcualte the new position. ShapePosition.x += HypX * mCos(Angle); ShapePosition.y += HypY * mSin(Angle); // Initialise RayCast Search Start/End Positions. ShapeStart = ShapeEnd = ShapePosition; ShapeStart.z = 2000.f; ShapeEnd.z= -2000.f; // Is this the Server? if (isServerObject()) // Perform Ray Cast Collision on Server Terrain. CollisionResult = gServerContainer.castRay(ShapeStart, ShapeEnd, FXREPLICATOR_COLLISION_MASK, &RayEvent); else // Perform Ray Cast Collision on Client Terrain. CollisionResult = gClientContainer.castRay( ShapeStart, ShapeEnd, FXREPLICATOR_COLLISION_MASK, &RayEvent); // Did we hit anything? if (CollisionResult) { // For now, let's pretend we didn't get a collision. CollisionResult = false; // Yes, so get it's type. U32 CollisionType = RayEvent.object->getTypeMask(); // Check Illegal Placements. if (((CollisionType & TerrainObjectType) && !mFieldData.mAllowOnTerrain) || ((CollisionType & StaticShapeObjectType) && !mFieldData.mAllowStatics) || ((CollisionType & WaterObjectType) && !mFieldData.mAllowOnWater) ) continue; // If we collided with water and are not allowing on the water surface then let's find the // terrain underneath and pass this on as the original collision else fail. // // NOTE:- We need to do this on the server/client as appropriate. if ((CollisionType & WaterObjectType) && !mFieldData.mAllowWaterSurface) { // Is this the Server? if (isServerObject()) { // Yes, so do it on the server container. if (!gServerContainer.castRay( ShapeStart, ShapeEnd, FXREPLICATOR_NOWATER_COLLISION_MASK, &RayEvent)) continue; } else { // No, so do it on the client container. if (!gClientContainer.castRay( ShapeStart, ShapeEnd, FXREPLICATOR_NOWATER_COLLISION_MASK, &RayEvent)) continue; } } // We passed with flying colours so carry on. CollisionResult = true; } // Invalidate if we are below Allowed Terrain Angle. if (RayEvent.normal.z < mSin(mDegToRad(90.0f-mFieldData.mAllowedTerrainSlope))) CollisionResult = false; // Wait until we get a collision. } while(!CollisionResult && --RelocationRetry); // Check for Relocation Problem. if (RelocationRetry > 0) { // Adjust Impact point. RayEvent.point.z += mFieldData.mOffsetZ; // Set New Position. ShapePosition = RayEvent.point; } else { // Warning. Con::warnf(ConsoleLogEntry::General, "[%s] - Could not find satisfactory position for shape '%s' on %s!", getName(), mFieldData.mShapeFile,isServerObject()?"Server":"Client"); // Unregister Object. fxStatic->unregisterObject(); // Destroy Shape. delete fxStatic; // Skip to next. continue; } // Get Shape Transform. MatrixF XForm = fxStatic->getTransform(); // Are we aligning to Terrain? if (mFieldData.mAlignToTerrain) { // Yes, so set rotation to Terrain Impact Normal. ShapeRotation = RayEvent.normal * mFieldData.mTerrainAlignment; } else { // No, so choose a new Rotation (in Radians). ShapeRotation.set( mDegToRad(RandomGen.randF(mFieldData.mShapeRotateMin.x, mFieldData.mShapeRotateMax.x)), mDegToRad(RandomGen.randF(mFieldData.mShapeRotateMin.y, mFieldData.mShapeRotateMax.y)), mDegToRad(RandomGen.randF(mFieldData.mShapeRotateMin.z, mFieldData.mShapeRotateMax.z))); } // Set Quaternion Roation. QRotation.set(ShapeRotation); // Set Transform Rotation. QRotation.setMatrix(&XForm); // Set Position. XForm.setColumn(3, ShapePosition); // Set Shape Position / Rotation. fxStatic->setTransform(XForm); // Choose a new Scale. ShapeScale.set( RandomGen.randF(mFieldData.mShapeScaleMin.x, mFieldData.mShapeScaleMax.x), RandomGen.randF(mFieldData.mShapeScaleMin.y, mFieldData.mShapeScaleMax.y), RandomGen.randF(mFieldData.mShapeScaleMin.z, mFieldData.mShapeScaleMax.z)); // Set Shape Scale. fxStatic->setScale(ShapeScale); // Lock it. fxStatic->setLocked(true); // Store Shape in Replicated Shapes Vector. //mReplicatedShapes[mCurrentShapeCount++] = fxStatic; mReplicatedShapes.push_back(fxStatic); } mCurrentShapeCount = mReplicatedShapes.size(); // Take first Timestamp. mLastRenderTime = Platform::getVirtualMilliseconds(); }
void EditTSCtrl::renderCameraAxis() { GFXDEBUGEVENT_SCOPE( Editor_renderCameraAxis, ColorI::WHITE ); static MatrixF sRotMat(EulerF( (M_PI_F / -2.0f), 0.0f, 0.0f)); MatrixF camMat = mLastCameraQuery.cameraMatrix; camMat.mul(sRotMat); camMat.inverse(); MatrixF axis; axis.setColumn(0, Point3F(1, 0, 0)); axis.setColumn(1, Point3F(0, 0, 1)); axis.setColumn(2, Point3F(0, -1, 0)); axis.mul(camMat); Point3F forwardVec, upVec, rightVec; axis.getColumn( 2, &forwardVec ); axis.getColumn( 1, &upVec ); axis.getColumn( 0, &rightVec ); Point2I pos = getPosition(); F32 offsetx = pos.x + 20.0; F32 offsety = pos.y + getExtent().y - 42.0; // Take the status bar into account F32 scale = 15.0; // Generate correct drawing order ColorI c1(255,0,0); ColorI c2(0,255,0); ColorI c3(0,0,255); ColorI tc; Point3F *p1, *p2, *p3, *tp; p1 = &rightVec; p2 = &upVec; p3 = &forwardVec; if(p3->y > p2->y) { tp = p2; tc = c2; p2 = p3; c2 = c3; p3 = tp; c3 = tc; } if(p2->y > p1->y) { tp = p1; tc = c1; p1 = p2; c1 = c2; p2 = tp; c2 = tc; } PrimBuild::begin( GFXLineList, 6 ); //*** Axis 1 PrimBuild::color(c1); PrimBuild::vertex3f(offsetx, offsety, 0); PrimBuild::vertex3f(offsetx+p1->x*scale, offsety-p1->z*scale, 0); //*** Axis 2 PrimBuild::color(c2); PrimBuild::vertex3f(offsetx, offsety, 0); PrimBuild::vertex3f(offsetx+p2->x*scale, offsety-p2->z*scale, 0); //*** Axis 3 PrimBuild::color(c3); PrimBuild::vertex3f(offsetx, offsety, 0); PrimBuild::vertex3f(offsetx+p3->x*scale, offsety-p3->z*scale, 0); PrimBuild::end(); }
void Item::updatePos(const U32 /*mask*/, const F32 dt) { // Try and move Point3F pos; mObjToWorld.getColumn(3,&pos); delta.posVec = pos; bool contact = false; bool nonStatic = false; bool stickyNotify = false; CollisionList collisionList; F32 time = dt; static Polyhedron sBoxPolyhedron; static ExtrudedPolyList sExtrudedPolyList; static EarlyOutPolyList sEarlyOutPolyList; MatrixF collisionMatrix(true); Point3F end = pos + mVelocity * time; U32 mask = isServerObject() ? sServerCollisionMask : sClientCollisionMask; // Part of our speed problem here is that we don't track contact surfaces, like we do // with the player. In order to handle the most common and performance impacting // instance of this problem, we'll use a ray cast to detect any contact surfaces below // us. This won't be perfect, but it only needs to catch a few of these to make a // big difference. We'll cast from the top center of the bounding box at the tick's // beginning to the bottom center of the box at the end. Point3F startCast((mObjBox.minExtents.x + mObjBox.maxExtents.x) * 0.5, (mObjBox.minExtents.y + mObjBox.maxExtents.y) * 0.5, mObjBox.maxExtents.z); Point3F endCast((mObjBox.minExtents.x + mObjBox.maxExtents.x) * 0.5, (mObjBox.minExtents.y + mObjBox.maxExtents.y) * 0.5, mObjBox.minExtents.z); collisionMatrix.setColumn(3, pos); collisionMatrix.mulP(startCast); collisionMatrix.setColumn(3, end); collisionMatrix.mulP(endCast); RayInfo rinfo; bool doToughCollision = true; disableCollision(); if (mCollisionObject) mCollisionObject->disableCollision(); if (getContainer()->castRay(startCast, endCast, mask, &rinfo)) { F32 bd = -mDot(mVelocity, rinfo.normal); if (bd >= 0.0) { // Contact! if (mDataBlock->sticky && rinfo.object->getTypeMask() & (STATIC_COLLISION_TYPEMASK)) { mVelocity.set(0, 0, 0); mAtRest = true; mAtRestCounter = 0; stickyNotify = true; mStickyCollisionPos = rinfo.point; mStickyCollisionNormal = rinfo.normal; doToughCollision = false;; } else { // Subtract out velocity into surface and friction VectorF fv = mVelocity + rinfo.normal * bd; F32 fvl = fv.len(); if (fvl) { F32 ff = bd * mDataBlock->friction; if (ff < fvl) { fv *= ff / fvl; fvl = ff; } } bd *= 1 + mDataBlock->elasticity; VectorF dv = rinfo.normal * (bd + 0.002); mVelocity += dv; mVelocity -= fv; // Keep track of what we hit contact = true; U32 typeMask = rinfo.object->getTypeMask(); if (!(typeMask & StaticObjectType)) nonStatic = true; if (isServerObject() && (typeMask & ShapeBaseObjectType)) { ShapeBase* col = static_cast<ShapeBase*>(rinfo.object); queueCollision(col,mVelocity - col->getVelocity()); } } } } enableCollision(); if (mCollisionObject) mCollisionObject->enableCollision(); if (doToughCollision) { U32 count; for (count = 0; count < 3; count++) { // Build list from convex states here... end = pos + mVelocity * time; collisionMatrix.setColumn(3, end); Box3F wBox = getObjBox(); collisionMatrix.mul(wBox); Box3F testBox = wBox; Point3F oldMin = testBox.minExtents; Point3F oldMax = testBox.maxExtents; testBox.minExtents.setMin(oldMin + (mVelocity * time)); testBox.maxExtents.setMin(oldMax + (mVelocity * time)); sEarlyOutPolyList.clear(); sEarlyOutPolyList.mNormal.set(0,0,0); sEarlyOutPolyList.mPlaneList.setSize(6); sEarlyOutPolyList.mPlaneList[0].set(wBox.minExtents,VectorF(-1,0,0)); sEarlyOutPolyList.mPlaneList[1].set(wBox.maxExtents,VectorF(0,1,0)); sEarlyOutPolyList.mPlaneList[2].set(wBox.maxExtents,VectorF(1,0,0)); sEarlyOutPolyList.mPlaneList[3].set(wBox.minExtents,VectorF(0,-1,0)); sEarlyOutPolyList.mPlaneList[4].set(wBox.minExtents,VectorF(0,0,-1)); sEarlyOutPolyList.mPlaneList[5].set(wBox.maxExtents,VectorF(0,0,1)); CollisionWorkingList& eorList = mConvex.getWorkingList(); CollisionWorkingList* eopList = eorList.wLink.mNext; while (eopList != &eorList) { if ((eopList->mConvex->getObject()->getTypeMask() & mask) != 0) { Box3F convexBox = eopList->mConvex->getBoundingBox(); if (testBox.isOverlapped(convexBox)) { eopList->mConvex->getPolyList(&sEarlyOutPolyList); if (sEarlyOutPolyList.isEmpty() == false) break; } } eopList = eopList->wLink.mNext; } if (sEarlyOutPolyList.isEmpty()) { pos = end; break; } collisionMatrix.setColumn(3, pos); sBoxPolyhedron.buildBox(collisionMatrix, mObjBox, true); // Build extruded polyList... VectorF vector = end - pos; sExtrudedPolyList.extrude(sBoxPolyhedron, vector); sExtrudedPolyList.setVelocity(mVelocity); sExtrudedPolyList.setCollisionList(&collisionList); CollisionWorkingList& rList = mConvex.getWorkingList(); CollisionWorkingList* pList = rList.wLink.mNext; while (pList != &rList) { if ((pList->mConvex->getObject()->getTypeMask() & mask) != 0) { Box3F convexBox = pList->mConvex->getBoundingBox(); if (testBox.isOverlapped(convexBox)) { pList->mConvex->getPolyList(&sExtrudedPolyList); } } pList = pList->wLink.mNext; } if (collisionList.getTime() < 1.0) { // Set to collision point F32 dt = time * collisionList.getTime(); pos += mVelocity * dt; time -= dt; // Pick the most resistant surface F32 bd = 0; const Collision* collision = 0; for (int c = 0; c < collisionList.getCount(); c++) { const Collision &cp = collisionList[c]; F32 dot = -mDot(mVelocity,cp.normal); if (dot > bd) { bd = dot; collision = &cp; } } if (collision && mDataBlock->sticky && collision->object->getTypeMask() & (STATIC_COLLISION_TYPEMASK)) { mVelocity.set(0, 0, 0); mAtRest = true; mAtRestCounter = 0; stickyNotify = true; mStickyCollisionPos = collision->point; mStickyCollisionNormal = collision->normal; break; } else { // Subtract out velocity into surface and friction if (collision) { VectorF fv = mVelocity + collision->normal * bd; F32 fvl = fv.len(); if (fvl) { F32 ff = bd * mDataBlock->friction; if (ff < fvl) { fv *= ff / fvl; fvl = ff; } } bd *= 1 + mDataBlock->elasticity; VectorF dv = collision->normal * (bd + 0.002); mVelocity += dv; mVelocity -= fv; // Keep track of what we hit contact = true; U32 typeMask = collision->object->getTypeMask(); if (!(typeMask & StaticObjectType)) nonStatic = true; if (isServerObject() && (typeMask & ShapeBaseObjectType)) { ShapeBase* col = static_cast<ShapeBase*>(collision->object); queueCollision(col,mVelocity - col->getVelocity()); } } } } else { pos = end; break; } } if (count == 3) { // Couldn't move... mVelocity.set(0, 0, 0); } } // If on the client, calculate delta for backstepping if (isGhost()) { delta.pos = pos; delta.posVec -= pos; delta.dt = 1; } // Update transform MatrixF mat = mObjToWorld; mat.setColumn(3,pos); Parent::setTransform(mat); enableCollision(); if (mCollisionObject) mCollisionObject->enableCollision(); updateContainer(); if ( mPhysicsRep ) mPhysicsRep->setTransform( mat ); // if (contact) { // Check for rest condition if (!nonStatic && mVelocity.len() < sAtRestVelocity) { mVelocity.x = mVelocity.y = mVelocity.z = 0; mAtRest = true; mAtRestCounter = 0; } // Only update the client if we hit a non-static shape or // if this is our final rest pos. if (nonStatic || mAtRest) setMaskBits(PositionMask); } // Collision callbacks. These need to be processed whether we hit // anything or not. if (!isGhost()) { SimObjectPtr<Item> safePtr(this); if (stickyNotify) { notifyCollision(); if(bool(safePtr)) onStickyCollision_callback( getIdString() ); } else notifyCollision(); // water if(bool(safePtr)) { if(!mInLiquid && mWaterCoverage != 0.0f) { mInLiquid = true; if ( !isGhost() ) mDataBlock->onEnterLiquid_callback( this, mWaterCoverage, mLiquidType.c_str() ); } else if(mInLiquid && mWaterCoverage == 0.0f) { mInLiquid = false; if ( !isGhost() ) mDataBlock->onLeaveLiquid_callback( this, mLiquidType.c_str() ); } } } }
void Item::unpackUpdate(NetConnection *connection, BitStream *stream) { Parent::unpackUpdate(connection,stream); // InitialUpdateMask if (stream->readFlag()) { mRotate = stream->readFlag(); mStatic = stream->readFlag(); if (stream->readFlag()) mathRead(*stream, &mObjScale); else mObjScale.set(1, 1, 1); } // ThrowSrcMask && mCollisionObject if (stream->readFlag()) { S32 gIndex = stream->readInt(NetConnection::GhostIdBitSize); setCollisionTimeout(static_cast<ShapeBase*>(connection->resolveGhost(gIndex))); } MatrixF mat = mObjToWorld; // RotationMask && !mRotate if (stream->readFlag()) { // Assumes rotation is about the Z axis AngAxisF aa; aa.axis.set(0.0f, 0.0f, stream->readFlag() ? -1.0f : 1.0f); stream->read(&aa.angle); aa.setMatrix(&mat); Point3F pos; mObjToWorld.getColumn(3,&pos); mat.setColumn(3,pos); } // PositionMask if (stream->readFlag()) { Point3F pos; mathRead(*stream, &pos); F32 speed = mVelocity.len(); if ((mAtRest = stream->readFlag()) == true) mVelocity.set(0.0f, 0.0f, 0.0f); else mathRead(*stream, &mVelocity); if (stream->readFlag() && isProperlyAdded()) { // Determin number of ticks to warp based on the average // of the client and server velocities. delta.warpOffset = pos - delta.pos; F32 as = (speed + mVelocity.len()) * 0.5f * TickSec; F32 dt = (as > 0.00001f) ? delta.warpOffset.len() / as: sMaxWarpTicks; delta.warpTicks = (S32)((dt > sMinWarpTicks)? getMax(mFloor(dt + 0.5f), 1.0f): 0.0f); if (delta.warpTicks) { // Setup the warp to start on the next tick, only the // object's position is warped. if (delta.warpTicks > sMaxWarpTicks) delta.warpTicks = sMaxWarpTicks; delta.warpOffset /= (F32)delta.warpTicks; } else { // Going to skip the warp, server and client are real close. // Adjust the frame interpolation to move smoothly to the // new position within the current tick. Point3F cp = delta.pos + delta.posVec * delta.dt; VectorF vec = delta.pos - cp; F32 vl = vec.len(); if (vl) { F32 s = delta.posVec.len() / vl; delta.posVec = (cp - pos) * s; } delta.pos = pos; mat.setColumn(3,pos); } } else { // Set the item to the server position delta.warpTicks = 0; delta.posVec.set(0,0,0); delta.pos = pos; delta.dt = 0; mat.setColumn(3,pos); } } Parent::setTransform(mat); }
void TurretShape::_updateNodes(const Point3F& rot) { EulerF xRot(rot.x, 0.0f, 0.0f); EulerF zRot(0.0f, 0.0f, rot.z); // Set heading S32 node = mDataBlock->headingNode; if (node != -1) { MatrixF* mat = &mShapeInstance->mNodeTransforms[node]; Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node]; Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node]; QuatF qrot(zRot); qrot *= defaultRot.getQuatF(); qrot.setMatrix( mat ); mat->setColumn(3, defaultPos); } // Set pitch node = mDataBlock->pitchNode; if (node != -1) { MatrixF* mat = &mShapeInstance->mNodeTransforms[node]; Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node]; Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node]; QuatF qrot(xRot); qrot *= defaultRot.getQuatF(); qrot.setMatrix( mat ); mat->setColumn(3, defaultPos); } // Now the mirror direction nodes, if any for (U32 i=0; i<TurretShapeData::NumMirrorDirectionNodes; ++i) { node = mDataBlock->pitchNodes[i]; if (node != -1) { MatrixF* mat = &mShapeInstance->mNodeTransforms[node]; Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node]; Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node]; QuatF qrot(xRot); qrot *= defaultRot.getQuatF(); qrot.setMatrix( mat ); mat->setColumn(3, defaultPos); } node = mDataBlock->headingNodes[i]; if (node != -1) { MatrixF* mat = &mShapeInstance->mNodeTransforms[node]; Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node]; Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node]; QuatF qrot(zRot); qrot *= defaultRot.getQuatF(); qrot.setMatrix( mat ); mat->setColumn(3, defaultPos); } } mShapeInstance->setDirty(TSShapeInstance::TransformDirty); }
/** * 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; }
void WorldEditorSelection::rotate(const EulerF & rot, const Point3F & center) { // single selections will rotate around own axis, multiple about world if(size() == 1) { SceneObject* object = dynamic_cast< SceneObject* >( at( 0 ) ); if( object ) { MatrixF mat = object->getTransform(); Point3F pos; mat.getColumn(3, &pos); // get offset in obj space Point3F offset = pos - center; MatrixF wMat = object->getWorldTransform(); wMat.mulV(offset); // MatrixF transform(EulerF(0,0,0), -offset); transform.mul(MatrixF(rot)); transform.mul(MatrixF(EulerF(0,0,0), offset)); mat.mul(transform); object->setTransform(mat); } } else { for( iterator iter = begin(); iter != end(); ++ iter ) { SceneObject* object = dynamic_cast< SceneObject* >( *iter ); if( !object ) continue; MatrixF mat = object->getTransform(); Point3F pos; mat.getColumn(3, &pos); // get offset in obj space Point3F offset = pos - center; MatrixF transform(rot); Point3F wOffset; transform.mulV(offset, &wOffset); MatrixF wMat = object->getWorldTransform(); wMat.mulV(offset); // transform.set(EulerF(0,0,0), -offset); mat.setColumn(3, Point3F(0,0,0)); wMat.setColumn(3, Point3F(0,0,0)); transform.mul(wMat); transform.mul(MatrixF(rot)); transform.mul(mat); mat.mul(transform); mat.normalize(); mat.setColumn(3, wOffset + center); object->setTransform(mat); } } mCentroidValid = false; }
void DualParaboloidLightShadowMap::_render( RenderPassManager* renderPass, const SceneRenderState *diffuseState ) { PROFILE_SCOPE(DualParaboloidLightShadowMap_render); const ShadowMapParams *p = mLight->getExtended<ShadowMapParams>(); const LightMapParams *lmParams = mLight->getExtended<LightMapParams>(); const bool bUseLightmappedGeometry = lmParams ? !lmParams->representedInLightmap || lmParams->includeLightmappedGeometryInShadow : true; const U32 texSize = getBestTexSize( 2 ); if ( mShadowMapTex.isNull() || mTexSize != texSize ) { mTexSize = texSize; mShadowMapTex.set( mTexSize * 2, mTexSize, ShadowMapFormat, &ShadowMapProfile, "DualParaboloidLightShadowMap" ); mShadowMapDepth = _getDepthTarget( mShadowMapTex->getWidth(), mShadowMapTex->getHeight() ); } GFXFrustumSaver frustSaver; GFXTransformSaver saver; // Set and Clear target GFX->pushActiveRenderTarget(); mTarget->attachTexture(GFXTextureTarget::Color0, mShadowMapTex); mTarget->attachTexture( GFXTextureTarget::DepthStencil, mShadowMapDepth ); GFX->setActiveRenderTarget(mTarget); GFX->clear(GFXClearTarget | GFXClearStencil | GFXClearZBuffer, ColorI::WHITE, 1.0f, 0); const bool bUseSinglePassDPM = (p->shadowType == ShadowType_DualParaboloidSinglePass); // Set up matrix and visible distance mWorldToLightProj = mLight->getTransform(); mWorldToLightProj.inverse(); const F32 &lightRadius = mLight->getRange().x; const F32 paraboloidNearPlane = 0.01f; const F32 renderPosOffset = 0.01f; // Alter for creation of scene state if this is a single pass map if(bUseSinglePassDPM) { VectorF camDir; MatrixF temp = mLight->getTransform(); temp.getColumn(1, &camDir); temp.setPosition(mLight->getPosition() - camDir * (lightRadius + renderPosOffset)); temp.inverse(); GFX->setWorldMatrix(temp); GFX->setOrtho(-lightRadius, lightRadius, -lightRadius, lightRadius, paraboloidNearPlane, 2.0f * lightRadius, true); } else { VectorF camDir; MatrixF temp = mLight->getTransform(); temp.getColumn(1, &camDir); temp.setPosition(mLight->getPosition() - camDir * renderPosOffset); temp.inverse(); GFX->setWorldMatrix(temp); GFX->setOrtho(-lightRadius, lightRadius, -lightRadius, lightRadius, paraboloidNearPlane, lightRadius, true); } SceneManager* sceneManager = diffuseState->getSceneManager(); // Front map render { SceneRenderState frontMapRenderState ( sceneManager, SPT_Shadow, SceneCameraState::fromGFXWithViewport( diffuseState->getViewport() ), renderPass ); frontMapRenderState.getMaterialDelegate().bind( this, &LightShadowMap::getShadowMaterial ); frontMapRenderState.renderNonLightmappedMeshes( true ); frontMapRenderState.renderLightmappedMeshes( bUseLightmappedGeometry ); frontMapRenderState.setDiffuseCameraTransform( diffuseState->getCameraTransform() ); frontMapRenderState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() ); if(bUseSinglePassDPM) { GFX->setWorldMatrix(mWorldToLightProj); frontMapRenderState.getRenderPass()->getMatrixSet().setSceneView(mWorldToLightProj); GFX->setOrtho(-lightRadius, lightRadius, -lightRadius, lightRadius, paraboloidNearPlane, lightRadius, true); } GFXDEBUGEVENT_SCOPE( DualParaboloidLightShadowMap_Render_FrontFacingParaboloid, ColorI::RED ); mShadowMapScale.set(0.5f, 1.0f); mShadowMapOffset.set(-0.5f, 0.0f); sceneManager->renderSceneNoLights( &frontMapRenderState, SHADOW_TYPEMASK ); _debugRender( &frontMapRenderState ); } // Back map render if(!bUseSinglePassDPM) { GFXDEBUGEVENT_SCOPE( DualParaboloidLightShadowMap_Render_BackFacingParaboloid, ColorI::RED ); mShadowMapScale.set(0.5f, 1.0f); mShadowMapOffset.set(0.5f, 0.0f); // Invert direction on camera matrix VectorF right, forward; MatrixF temp = mLight->getTransform(); temp.getColumn( 1, &forward ); temp.getColumn( 0, &right ); forward *= -1.0f; right *= -1.0f; temp.setColumn( 1, forward ); temp.setColumn( 0, right ); temp.setPosition(mLight->getPosition() - forward * -renderPosOffset); temp.inverse(); GFX->setWorldMatrix(temp); // Create an inverted scene state for the back-map SceneRenderState backMapRenderState ( sceneManager, SPT_Shadow, SceneCameraState::fromGFXWithViewport( diffuseState->getViewport() ), renderPass ); backMapRenderState.getMaterialDelegate().bind( this, &LightShadowMap::getShadowMaterial ); backMapRenderState.renderNonLightmappedMeshes( true ); backMapRenderState.renderLightmappedMeshes( bUseLightmappedGeometry ); backMapRenderState.setDiffuseCameraTransform( diffuseState->getCameraTransform() ); backMapRenderState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() ); backMapRenderState.getRenderPass()->getMatrixSet().setSceneView(temp); // Draw scene sceneManager->renderSceneNoLights( &backMapRenderState ); _debugRender( &backMapRenderState ); } mTarget->resolve(); GFX->popActiveRenderTarget(); }