diff --git a/Engine/source/T3D/guiObjectView.cpp b/Engine/source/T3D/guiObjectView.cpp index b22d68a296..114e26ac22 100644 --- a/Engine/source/T3D/guiObjectView.cpp +++ b/Engine/source/T3D/guiObjectView.cpp @@ -565,7 +565,7 @@ void GuiObjectView::renderWorld( const RectI& updateRect ) if( mMountedModelInstance && mMountNode != -1 ) { GFX->pushWorldMatrix(); - GFX->multWorld(mModelInstance->mNodeTransforms[ mMountNode ] ); + GFX->multWorld(*(mModelInstance->mNodeTransforms[mMountNode])); GFX->multWorld( mMountTransform ); mMountedModelInstance->render( rdata ); diff --git a/Engine/source/T3D/physics/physicsDebris.cpp b/Engine/source/T3D/physics/physicsDebris.cpp index 79b8183e04..a069b04a62 100644 --- a/Engine/source/T3D/physics/physicsDebris.cpp +++ b/Engine/source/T3D/physics/physicsDebris.cpp @@ -522,7 +522,7 @@ void PhysicsDebris::interpolateTick( F32 dt ) return; const MatrixF &objectXfm = getRenderWorldTransform(); - Vector &nodeXfms = mShapeInstance->mNodeTransforms; + Vector &nodeXfms = *(mShapeInstance->mNodeTransforms.refGlobal()); MatrixF globalXfm; MatrixF tempXfm; diff --git a/Engine/source/T3D/player.cpp b/Engine/source/T3D/player.cpp index 34da962e6d..851517817f 100644 --- a/Engine/source/T3D/player.cpp +++ b/Engine/source/T3D/player.cpp @@ -5599,9 +5599,9 @@ void Player::getEyeTransform(MatrixF* mat) if (imageIndex >= 0) { // Get the image's eye node's position relative to the eye mount node - MatrixF mountTransform = image->shapeInstance[shapeIndex]->mNodeTransforms[data->eyeMountNode[shapeIndex]]; + MatrixF mountTransform = *(image->shapeInstance[shapeIndex]->mNodeTransforms[data->eyeMountNode[shapeIndex]]); Point3F eyeMountNodePos = mountTransform.getPosition(); - mountTransform = image->shapeInstance[shapeIndex]->mNodeTransforms[data->eyeNode[shapeIndex]]; + mountTransform = *(image->shapeInstance[shapeIndex]->mNodeTransforms[data->eyeNode[shapeIndex]]); Point3F eyeNodePos = mountTransform.getPosition() - eyeMountNodePos; // Now transform to the image's eye node (position only) @@ -5647,7 +5647,7 @@ void Player::getEyeBaseTransform(MatrixF* mat, bool includeBank) MatrixF eyeMat(true); if (mDataBlock->eyeNode != -1) { - sp = mShapeInstance->mNodeTransforms[mDataBlock->eyeNode]; + sp = *(mShapeInstance->mNodeTransforms[mDataBlock->eyeNode]); } else { @@ -5679,9 +5679,9 @@ void Player::getRenderEyeTransform(MatrixF* mat) if ( data.useEyeNode && isFirstPerson() && data.eyeMountNode[shapeIndex] != -1 && data.eyeNode[shapeIndex] != -1 ) { // Get the eye node's position relative to the eye mount node - MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]; + MatrixF mountTransform = *(image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]); Point3F eyeMountNodePos = mountTransform.getPosition(); - mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeNode[shapeIndex]]; + mountTransform = *(image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeNode[shapeIndex]]); Point3F eyeNodePos = mountTransform.getPosition() - eyeMountNodePos; // Now transform to the image's eye node (position only) @@ -5727,7 +5727,7 @@ void Player::getRenderEyeBaseTransform(MatrixF* mat, bool includeBank) MatrixF eyeMat(true); if (mDataBlock->eyeNode != -1) { - sp = mShapeInstance->mNodeTransforms[mDataBlock->eyeNode]; + sp = *(mShapeInstance->mNodeTransforms[mDataBlock->eyeNode]); } else { @@ -5877,7 +5877,7 @@ void Player::renderMountedImage( U32 imageSlot, TSRenderState &rstate, SceneRend { MatrixF nmat; getRenderEyeBaseTransform(&nmat, mDataBlock->mountedImagesBank); - MatrixF offsetMat = image.shapeInstance[imageShapeIndex]->mNodeTransforms[data.eyeMountNode[imageShapeIndex]]; + MatrixF offsetMat = *(image.shapeInstance[imageShapeIndex]->mNodeTransforms[data.eyeMountNode[imageShapeIndex]]); offsetMat.affineInverse(); world.mul(nmat,offsetMat); } diff --git a/Engine/source/T3D/rigidShape.cpp b/Engine/source/T3D/rigidShape.cpp index cfdd8258f4..4ad3392ba4 100644 --- a/Engine/source/T3D/rigidShape.cpp +++ b/Engine/source/T3D/rigidShape.cpp @@ -982,7 +982,7 @@ void RigidShape::getCameraTransform(F32* pos,MatrixF* mat) Point3F osp,sp; if (mDataBlock->cameraNode != -1) { - mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3,&osp); + osp = mShapeInstance->mNodeTransforms.getPosition(mDataBlock->cameraNode); getRenderTransform().mulP(osp,&sp); } else diff --git a/Engine/source/T3D/sfx/sfx3DWorld.cpp b/Engine/source/T3D/sfx/sfx3DWorld.cpp index 4fe3e64ccb..ae517e7d03 100644 --- a/Engine/source/T3D/sfx/sfx3DWorld.cpp +++ b/Engine/source/T3D/sfx/sfx3DWorld.cpp @@ -114,7 +114,7 @@ void SFX3DObject::getEarTransform( MatrixF& transform ) const if ( earNode != -1 && earNode != datablock->eyeNode ) { transform = shape->getTransform(); - transform *= shapeInstance->mNodeTransforms[ earNode ]; + transform *= *(shapeInstance->mNodeTransforms[ earNode ]); } else { diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index dad23da0a8..a22c083cd5 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -2029,7 +2029,7 @@ void ShapeBase::getNodeTransform(const char* nodeName, MatrixF* outMat) const Point3F& scale = getScale(); if (nodeIDx != -1) { - nodeTransform = mShapeInstance->mNodeTransforms[nodeIDx]; + nodeTransform = *(mShapeInstance->mNodeTransforms[nodeIDx]); nodeTransform.mul(xfm); } // The position of the mount point needs to be scaled. @@ -2066,7 +2066,7 @@ void ShapeBase::getEyeBaseTransform(MatrixF* mat, bool includeBank) // Returns eye to world space transform S32 eyeNode = mDataBlock->eyeNode; if (eyeNode != -1) - mat->mul(getTransform(), mShapeInstance->mNodeTransforms[eyeNode]); + mat->mul(getTransform(), *(mShapeInstance->mNodeTransforms[eyeNode])); else *mat = getTransform(); } @@ -2081,7 +2081,7 @@ void ShapeBase::getRenderEyeBaseTransform(MatrixF* mat, bool includeBank) // Returns eye to world space transform S32 eyeNode = mDataBlock->eyeNode; if (eyeNode != -1) - mat->mul(getRenderTransform(), mShapeInstance->mNodeTransforms[eyeNode]); + mat->mul(getRenderTransform(), *(mShapeInstance->mNodeTransforms[eyeNode])); else *mat = getRenderTransform(); } @@ -2116,7 +2116,7 @@ void ShapeBase::getCameraTransform(F32* pos,MatrixF* mat) // Use the camera node's pos. Point3F osp,sp; if (mDataBlock->cameraNode != -1) { - mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3,&osp); + osp = mShapeInstance->mNodeTransforms.getPosition(mDataBlock->cameraNode); // Scale the camera position before applying the transform const Point3F& scale = getScale(); @@ -2195,7 +2195,7 @@ void ShapeBase::getNodeTransform(const char* nodeName, const MatrixF& xfm, Matri const Point3F& scale = getScale(); if (nodeIDx != -1) { - nodeTransform = mShapeInstance->mNodeTransforms[nodeIDx]; + nodeTransform = *(mShapeInstance->mNodeTransforms[nodeIDx]); nodeTransform.mul(xfm); } // The position of the mount point needs to be scaled. @@ -3550,7 +3550,7 @@ void ShapeBaseConvex::findNodeTransform() const TSShape::Object* obj = &shape->objects[i]; if (obj->numMeshes && detail->objectDetailNum < obj->numMeshes) { - nodeTransform = &si->mNodeTransforms[obj->nodeIndex]; + nodeTransform = si->mNodeTransforms[obj->nodeIndex]; return; } } diff --git a/Engine/source/T3D/shapeImage.cpp b/Engine/source/T3D/shapeImage.cpp index f1ea8022f2..d66715ceb6 100644 --- a/Engine/source/T3D/shapeImage.cpp +++ b/Engine/source/T3D/shapeImage.cpp @@ -1869,7 +1869,7 @@ void ShapeBase::getMountTransform( S32 index, const MatrixF &xfm, MatrixF *outMa if ( index >= 0 && index < SceneObject::NumMountPoints) { S32 ni = mDataBlock->mountPointNode[index]; if (ni != -1) { - MatrixF mountTransform = mShapeInstance->mNodeTransforms[ni]; + MatrixF mountTransform = *(mShapeInstance->mNodeTransforms[ni]); mountTransform.mul( xfm ); const Point3F& scale = getScale(); @@ -1903,7 +1903,7 @@ void ShapeBase::getImageTransform(U32 imageSlot,MatrixF* mat) getEyeBaseTransform(&nmat, mDataBlock->mountedImagesBank); - MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]; + MatrixF mountTransform = *(image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]); mat->mul(nmat, mountTransform); } @@ -1931,7 +1931,7 @@ void ShapeBase::getImageTransform(U32 imageSlot,S32 node,MatrixF* mat) ShapeBaseImageData& data = *image.dataBlock; U32 shapeIndex = getImageShapeIndex(image); - MatrixF nmat = image.shapeInstance[shapeIndex]->mNodeTransforms[node]; + MatrixF nmat = *(image.shapeInstance[shapeIndex]->mNodeTransforms[node]); MatrixF mmat; if (data.useEyeNode && isFirstPerson() && data.eyeMountNode[shapeIndex] != -1) @@ -1942,7 +1942,7 @@ void ShapeBase::getImageTransform(U32 imageSlot,S32 node,MatrixF* mat) MatrixF emat; getEyeBaseTransform(&emat, mDataBlock->mountedImagesBank); - MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]; + MatrixF mountTransform = *(image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]); mountTransform.affineInverse(); mmat.mul(emat, mountTransform); @@ -1993,7 +1993,7 @@ void ShapeBase::getRenderMountTransform( F32 delta, S32 mountPoint, const Matrix if ( mountPoint >= 0 && mountPoint < SceneObject::NumMountPoints) { S32 ni = mDataBlock->mountPointNode[mountPoint]; if (ni != -1) { - MatrixF mountTransform = mShapeInstance->mNodeTransforms[ni]; + MatrixF mountTransform = *(mShapeInstance->mNodeTransforms[ni]); mountTransform.mul( xfm ); const Point3F& scale = getScale(); @@ -2027,7 +2027,7 @@ void ShapeBase::getRenderImageTransform( U32 imageSlot, MatrixF* mat, bool noEye if ( data.useEyeNode && isFirstPerson() && data.eyeMountNode[shapeIndex] != -1 ) { getRenderEyeBaseTransform(&nmat, mDataBlock->mountedImagesBank); - MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]; + MatrixF mountTransform = *(image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]); mat->mul(nmat, mountTransform); } @@ -2057,7 +2057,7 @@ void ShapeBase::getRenderImageTransform(U32 imageSlot,S32 node,MatrixF* mat) ShapeBaseImageData& data = *image.dataBlock; U32 shapeIndex = getImageShapeIndex(image); - MatrixF nmat = image.shapeInstance[shapeIndex]->mNodeTransforms[node]; + MatrixF nmat = *(image.shapeInstance[shapeIndex]->mNodeTransforms[node]); MatrixF mmat; if ( data.useEyeNode && isFirstPerson() && data.eyeMountNode[shapeIndex] != -1 ) @@ -2065,7 +2065,7 @@ void ShapeBase::getRenderImageTransform(U32 imageSlot,S32 node,MatrixF* mat) MatrixF emat; getRenderEyeBaseTransform(&emat, mDataBlock->mountedImagesBank); - MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]; + MatrixF mountTransform = *(image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]); mountTransform.affineInverse(); mmat.mul(emat, mountTransform); diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 022cffa93b..ccdfd4ff3f 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -1871,7 +1871,7 @@ void TSStatic::getNodeTransform(const char *nodeName, const MatrixF &xfm, Matrix const Point3F& scale = getScale(); if (nodeIDx != -1) { - nodeTransform = mShapeInstance->mNodeTransforms[nodeIDx]; + nodeTransform = *(mShapeInstance->mNodeTransforms[nodeIDx]); nodeTransform.mul(xfm); } // The position of the mount point needs to be scaled. diff --git a/Engine/source/T3D/turret/aiTurretShape.cpp b/Engine/source/T3D/turret/aiTurretShape.cpp index cdf192b2d0..2ac9320a72 100644 --- a/Engine/source/T3D/turret/aiTurretShape.cpp +++ b/Engine/source/T3D/turret/aiTurretShape.cpp @@ -872,7 +872,7 @@ void AITurretShape::_trackTarget(F32 dt) if (node != -1) { // Get the current position of our node - MatrixF* nodeTrans = &mShapeInstance->mNodeTransforms[node]; + MatrixF* nodeTrans = mShapeInstance->mNodeTransforms[node]; Point3F currentPos; nodeTrans->getColumn(3, ¤tPos); diff --git a/Engine/source/T3D/turret/turretShape.cpp b/Engine/source/T3D/turret/turretShape.cpp index 52cd198e62..e3828527e7 100644 --- a/Engine/source/T3D/turret/turretShape.cpp +++ b/Engine/source/T3D/turret/turretShape.cpp @@ -765,7 +765,7 @@ bool TurretShape::getNodeTransform(S32 node, MatrixF& mat) if (node == -1) return false; - MatrixF nodeTransform = mShapeInstance->mNodeTransforms[node]; + MatrixF nodeTransform = *(mShapeInstance->mNodeTransforms[node]); const Point3F& scale = getScale(); // The position of the node needs to be scaled. @@ -806,7 +806,7 @@ void TurretShape::_updateNodes(const Point3F& rot) S32 node = mDataBlock->headingNode; if (node != -1) { - MatrixF* mat = &mShapeInstance->mNodeTransforms[node]; + MatrixF* mat = mShapeInstance->mNodeTransforms[node]; Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node]; Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node]; @@ -820,7 +820,7 @@ void TurretShape::_updateNodes(const Point3F& rot) node = mDataBlock->pitchNode; if (node != -1) { - MatrixF* mat = &mShapeInstance->mNodeTransforms[node]; + MatrixF* mat = mShapeInstance->mNodeTransforms[node]; Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node]; Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node]; @@ -836,7 +836,7 @@ void TurretShape::_updateNodes(const Point3F& rot) node = mDataBlock->pitchNodes[i]; if (node != -1) { - MatrixF* mat = &mShapeInstance->mNodeTransforms[node]; + MatrixF* mat = mShapeInstance->mNodeTransforms[node]; Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node]; Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node]; @@ -849,7 +849,7 @@ void TurretShape::_updateNodes(const Point3F& rot) node = mDataBlock->headingNodes[i]; if (node != -1) { - MatrixF* mat = &mShapeInstance->mNodeTransforms[node]; + MatrixF* mat = mShapeInstance->mNodeTransforms[node]; Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node]; Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node]; @@ -999,7 +999,7 @@ void TurretShape::getCameraTransform(F32* pos,MatrixF* mat) Point3F osp,sp; if (mDataBlock->cameraNode != -1) { - mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3,&osp); + osp = mShapeInstance->mNodeTransforms.getPosition(mDataBlock->cameraNode); getRenderTransform().mulP(osp,&sp); } else @@ -1141,7 +1141,7 @@ void TurretShape::getWeaponMountTransform( S32 index, const MatrixF &xfm, Matrix if ( index >= 0 && index < ShapeBase::MaxMountedImages) { S32 ni = mDataBlock->weaponMountNode[index]; if (ni != -1) { - MatrixF mountTransform = mShapeInstance->mNodeTransforms[ni]; + MatrixF mountTransform = *(mShapeInstance->mNodeTransforms[ni]); mountTransform.mul( xfm ); const Point3F& scale = getScale(); @@ -1166,7 +1166,7 @@ void TurretShape::getRenderWeaponMountTransform( F32 delta, S32 mountPoint, cons if ( mountPoint >= 0 && mountPoint < ShapeBase::MaxMountedImages) { S32 ni = mDataBlock->weaponMountNode[mountPoint]; if (ni != -1) { - MatrixF mountTransform = mShapeInstance->mNodeTransforms[ni]; + MatrixF mountTransform = *(mShapeInstance->mNodeTransforms[ni]); mountTransform.mul( xfm ); const Point3F& scale = getScale(); @@ -1244,7 +1244,7 @@ void TurretShape::getImageTransform(U32 imageSlot,S32 node,MatrixF* mat) ShapeBaseImageData& data = *image.dataBlock; U32 shapeIndex = getImageShapeIndex(image); - MatrixF nmat = image.shapeInstance[shapeIndex]->mNodeTransforms[node]; + MatrixF nmat = *(image.shapeInstance[shapeIndex]->mNodeTransforms[node]); MatrixF mmat; if (data.useEyeNode && isFirstPerson() && data.eyeMountNode[shapeIndex] != -1) @@ -1255,7 +1255,7 @@ void TurretShape::getImageTransform(U32 imageSlot,S32 node,MatrixF* mat) MatrixF emat; getEyeBaseTransform(&emat, mDataBlock->mountedImagesBank); - MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]; + MatrixF mountTransform = *(image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]); mountTransform.affineInverse(); mmat.mul(emat, mountTransform); @@ -1295,7 +1295,7 @@ void TurretShape::getRenderImageTransform(U32 imageSlot,S32 node,MatrixF* mat) ShapeBaseImageData& data = *image.dataBlock; U32 shapeIndex = getImageShapeIndex(image); - MatrixF nmat = image.shapeInstance[shapeIndex]->mNodeTransforms[node]; + MatrixF nmat = *(image.shapeInstance[shapeIndex]->mNodeTransforms[node]); MatrixF mmat; if ( data.useEyeNode && isFirstPerson() && data.eyeMountNode[shapeIndex] != -1 ) @@ -1303,7 +1303,7 @@ void TurretShape::getRenderImageTransform(U32 imageSlot,S32 node,MatrixF* mat) MatrixF emat; getRenderEyeBaseTransform(&emat, mDataBlock->mountedImagesBank); - MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]; + MatrixF mountTransform = *(image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]]); mountTransform.affineInverse(); mmat.mul(emat, mountTransform); diff --git a/Engine/source/T3D/vehicles/flyingVehicle.cpp b/Engine/source/T3D/vehicles/flyingVehicle.cpp index 179d6a4ca8..33378d9f31 100644 --- a/Engine/source/T3D/vehicles/flyingVehicle.cpp +++ b/Engine/source/T3D/vehicles/flyingVehicle.cpp @@ -752,7 +752,7 @@ void FlyingVehicle::updateEmitter(bool active,F32 dt,ParticleEmitterData *emitte MatrixF mat; Point3F pos,axis; mat.mul(getRenderTransform(), - mShapeInstance->mNodeTransforms[mDataBlock->jetNode[j]]); + *(mShapeInstance->mNodeTransforms[mDataBlock->jetNode[j]])); mat.getColumn(1,&axis); mat.getColumn(3,&pos); mJetEmitter[j]->emitParticles(pos,true,axis,getVelocity(),(U32)(dt * 1000)); diff --git a/Engine/source/T3D/vehicles/hoverVehicle.cpp b/Engine/source/T3D/vehicles/hoverVehicle.cpp index 1eb108ce86..973b1f4f44 100644 --- a/Engine/source/T3D/vehicles/hoverVehicle.cpp +++ b/Engine/source/T3D/vehicles/hoverVehicle.cpp @@ -960,7 +960,7 @@ void HoverVehicle::updateEmitter(bool active,F32 dt,ParticleEmitterData *emitter MatrixF mat; Point3F pos,axis; mat.mul(getRenderTransform(), - mShapeInstance->mNodeTransforms[mDataBlock->jetNode[j]]); + *(mShapeInstance->mNodeTransforms[mDataBlock->jetNode[j]])); mat.getColumn(1,&axis); mat.getColumn(3,&pos); mJetEmitter[j]->emitParticles(pos,true,axis,getVelocity(),(U32)(dt * 1000.0f)); diff --git a/Engine/source/T3D/vehicles/vehicle.cpp b/Engine/source/T3D/vehicles/vehicle.cpp index a1e4a426ae..6bc9cb2497 100644 --- a/Engine/source/T3D/vehicles/vehicle.cpp +++ b/Engine/source/T3D/vehicles/vehicle.cpp @@ -675,7 +675,7 @@ void Vehicle::getCameraTransform(F32* pos, MatrixF* mat) Point3F osp, sp; if (mDataBlock->cameraNode != -1) { - mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3, &osp); + osp = mShapeInstance->mNodeTransforms.getPosition(mDataBlock->cameraNode); getRenderTransform().mulP(osp, &sp); } else diff --git a/Engine/source/T3D/vehicles/wheeledVehicle.cpp b/Engine/source/T3D/vehicles/wheeledVehicle.cpp index 7771fb39df..ff9b19abe8 100644 --- a/Engine/source/T3D/vehicles/wheeledVehicle.cpp +++ b/Engine/source/T3D/vehicles/wheeledVehicle.cpp @@ -375,18 +375,18 @@ bool WheeledVehicleData::preload(bool server, String &errorStr) dSprintf(buff,sizeof(buff),"spring%d",i); wp->springSequence = mShape->findSequence(buff); if (wp->springSequence == -1) - si->mNodeTransforms[wp->springNode].getColumn(3, &wp->pos); + wp->pos = si->mNodeTransforms.getPosition(wp->springNode); else { si->setSequence(thread,wp->springSequence,0); si->animate(); - si->mNodeTransforms[wp->springNode].getColumn(3, &wp->pos); + wp->pos = si->mNodeTransforms.getPosition(wp->springNode); // Determin the length of the animation so we can scale it // according the actual wheel position. Point3F downPos; si->setSequence(thread,wp->springSequence,1); si->animate(); - si->mNodeTransforms[wp->springNode].getColumn(3, &downPos); + downPos = si->mNodeTransforms.getPosition(wp->springNode); wp->springLength = wp->pos.z - downPos.z; if (!wp->springLength) wp->springSequence = -1; diff --git a/Engine/source/afx/afxConstraint.cpp b/Engine/source/afx/afxConstraint.cpp index 5f8997938c..81688772d4 100644 --- a/Engine/source/afx/afxConstraint.cpp +++ b/Engine/source/afx/afxConstraint.cpp @@ -1727,7 +1727,7 @@ void afxShapeNodeConstraint::sample(F32 dt, U32 elapsed_ms, const Point3F* cam_p { mLast_xfm = mShape->getRenderTransform(); mLast_xfm.scale(mShape->getScale()); - mLast_xfm.mul(mShape->getShapeInstance()->mNodeTransforms[mShape_node_ID]); + mLast_xfm.mul(*(mShape->getShapeInstance()->mNodeTransforms[mShape_node_ID])); mLast_pos = mLast_xfm.getPosition(); } } @@ -2031,7 +2031,7 @@ bool afxEffectNodeConstraint::getPosition(Point3F& pos, F32 hist) Point3F scale; mEffect->getUpdatedScale(scale); - MatrixF gag = ts_shape_inst->mNodeTransforms[mEffect_node_ID]; + MatrixF gag = *(ts_shape_inst->mNodeTransforms[mEffect_node_ID]); gag.setPosition( gag.getPosition()*scale ); MatrixF xfm; @@ -2065,7 +2065,7 @@ bool afxEffectNodeConstraint::getTransform(MatrixF& xfm, F32 hist) Point3F scale; mEffect->getUpdatedScale(scale); - MatrixF gag = ts_shape_inst->mNodeTransforms[mEffect_node_ID]; + MatrixF gag = *(ts_shape_inst->mNodeTransforms[mEffect_node_ID]); gag.setPosition( gag.getPosition()*scale ); xfm.mul(mLast_xfm, gag); diff --git a/Engine/source/afx/afxMagicMissile.cpp b/Engine/source/afx/afxMagicMissile.cpp index e797c2dc1b..5aa900c12b 100644 --- a/Engine/source/afx/afxMagicMissile.cpp +++ b/Engine/source/afx/afxMagicMissile.cpp @@ -1927,7 +1927,7 @@ void afxMagicMissile::get_launch_data(Point3F& pos, Point3F& vel) MatrixF node_xfm = launch_cons_obj->getRenderTransform(); node_xfm.scale(launch_cons_obj->getScale()); if (node_ID >= 0) - node_xfm.mul(shape_inst->mNodeTransforms[node_ID]); + node_xfm.mul(shape_inst->mNodeTransforms.copyLocal(node_ID)); VectorF node_offset = mDataBlock->launch_node_offset; node_xfm.mulV(node_offset); diff --git a/Engine/source/afx/xm/afxXM_PivotNodeOffset.cpp b/Engine/source/afx/xm/afxXM_PivotNodeOffset.cpp index 6401c7c790..3b9984b35f 100644 --- a/Engine/source/afx/xm/afxXM_PivotNodeOffset.cpp +++ b/Engine/source/afx/xm/afxXM_PivotNodeOffset.cpp @@ -164,7 +164,7 @@ void afxXM_PivotNodeOffset::updateParams(F32 dt, F32 elapsed, afxXM_Params& para TSShapeInstance* ts_shape_inst = fx_wrapper->getTSShapeInstance(); if (ts_shape_inst) { - const MatrixF& pivot_xfm = ts_shape_inst->mNodeTransforms[node_ID]; + const MatrixF& pivot_xfm = *(ts_shape_inst->mNodeTransforms[node_ID]); pivot_offset = -pivot_xfm.getPosition(); offset_calculated = true; } diff --git a/Engine/source/gui/editor/guiShapeEdPreview.cpp b/Engine/source/gui/editor/guiShapeEdPreview.cpp index e19138004b..51333237a1 100644 --- a/Engine/source/gui/editor/guiShapeEdPreview.cpp +++ b/Engine/source/gui/editor/guiShapeEdPreview.cpp @@ -927,7 +927,7 @@ void GuiShapeEdPreview::exportToCollada( const String& path ) MatrixF mat( true ); if ( mount->mNode != -1 ) { - mat = mModel->mNodeTransforms[ mount->mNode ]; + mat = *(mModel->mNodeTransforms[ mount->mNode ]); mat *= mount->mTransform; } @@ -1067,8 +1067,8 @@ void GuiShapeEdPreview::handleMouseDragged(const GuiEvent& event, GizmoMode mode // Update node transform if ( mSelectedNode != -1 ) { - Point3F pos = mModel->mNodeTransforms[mSelectedNode].getPosition() + mGizmo->getOffset(); - mModel->mNodeTransforms[mSelectedNode].setPosition( pos ); + Point3F pos = mModel->mNodeTransforms.getPosition(mSelectedNode) + mGizmo->getOffset(); + mModel->mNodeTransforms.setPosition(mSelectedNode, pos ); } break; @@ -1077,7 +1077,7 @@ void GuiShapeEdPreview::handleMouseDragged(const GuiEvent& event, GizmoMode mode if ( mSelectedNode != -1 ) { EulerF rot = mGizmo->getDeltaRot(); - mModel->mNodeTransforms[mSelectedNode].mul( MatrixF( rot ) ); + mModel->mNodeTransforms.setRotation(mSelectedNode, rot ); } break; default: @@ -1086,8 +1086,8 @@ void GuiShapeEdPreview::handleMouseDragged(const GuiEvent& event, GizmoMode mode // Notify the change in node transform const char* name = mModel->getShape()->getNodeName(mSelectedNode).c_str(); - const Point3F pos = mModel->mNodeTransforms[mSelectedNode].getPosition(); - AngAxisF aa(mModel->mNodeTransforms[mSelectedNode]); + const Point3F pos = mModel->mNodeTransforms.getPosition(mSelectedNode); + AngAxisF aa(*(mModel->mNodeTransforms[mSelectedNode])); char buffer[256]; dSprintf(buffer, sizeof(buffer), "%g %g %g %g %g %g %g", pos.x, pos.y, pos.z, aa.axis.x, aa.axis.y, aa.axis.z, aa.angle); @@ -1147,7 +1147,7 @@ void GuiShapeEdPreview::updateProjectedNodePoints() { // Project the 3D node position to get the 2D screen coordinates for ( S32 i = 0; i < mModel->mNodeTransforms.size(); i++) - project( mModel->mNodeTransforms[i].getPosition(), &mProjectedNodes[i] ); + project( mModel->mNodeTransforms.getPosition(i), &mProjectedNodes[i] ); } } @@ -1232,7 +1232,7 @@ void GuiShapeEdPreview::computeSceneBounds(Box3F& bounds) //We probably don't have any actual meshes in this model, so compute using the bones if we have them for (S32 i = 0; i < mModel->getShape()->nodes.size(); i++) { - Point3F nodePos = mModel->mNodeTransforms[i].getPosition(); + Point3F nodePos = mModel->mNodeTransforms.getPosition(i); bounds.extend(nodePos); } @@ -1480,7 +1480,7 @@ void GuiShapeEdPreview::renderWorld(const RectI &updateRect) if ( mount->mNode != -1 ) { - GFX->multWorld( mModel->mNodeTransforms[ mount->mNode ] ); + GFX->multWorld( *(mModel->mNodeTransforms[ mount->mNode ]) ); GFX->multWorld( mount->mTransform ); } @@ -1520,7 +1520,7 @@ void GuiShapeEdPreview::renderWorld(const RectI &updateRect) { GFX->pushWorldMatrix(); if ( obj.nodeIndex != -1 ) - GFX->multWorld( mModel->mNodeTransforms[ obj.nodeIndex ] ); + GFX->multWorld( *(mModel->mNodeTransforms[ obj.nodeIndex ]) ); const Box3F& bounds = mesh->getBounds(); GFXStateBlockDesc desc; @@ -1646,8 +1646,8 @@ void GuiShapeEdPreview::renderNodes() const const TSShape::Node& node = mModel->getShape()->nodes[i]; if (node.parentIndex >= 0) { - Point3F start(mModel->mNodeTransforms[i].getPosition()); - Point3F end(mModel->mNodeTransforms[node.parentIndex].getPosition()); + Point3F start(mModel->mNodeTransforms.getPosition(i)); + Point3F end(mModel->mNodeTransforms.getPosition(node.parentIndex)); PrimBuild::vertex3f( start.x, start.y, start.z ); PrimBuild::vertex3f( end.x, end.y, end.z ); @@ -1675,7 +1675,7 @@ void GuiShapeEdPreview::renderNodes() const { renderNodeAxes( mSelectedNode, LinearColorF::GREEN ); - const MatrixF& nodeMat = mModel->mNodeTransforms[mSelectedNode]; + const MatrixF& nodeMat = *(mModel->mNodeTransforms[mSelectedNode]); mGizmo->set( nodeMat, nodeMat.getPosition(), Point3F::One); mGizmo->renderGizmo( smCamMatrix ); } @@ -1697,7 +1697,7 @@ void GuiShapeEdPreview::renderNodeAxes(S32 index, const LinearColorF& nodeColor) F32 scale = mOrbitDist / 60; GFX->pushWorldMatrix(); - GFX->multWorld( mModel->mNodeTransforms[index] ); + GFX->multWorld( *(mModel->mNodeTransforms[index] )); const ColorI color = LinearColorF(nodeColor).toColorI(); GFX->getDrawUtil()->drawCube( desc, xAxis * scale, Point3F::Zero, color ); GFX->getDrawUtil()->drawCube( desc, yAxis * scale, Point3F::Zero, color ); diff --git a/Engine/source/math/mMatrix.h b/Engine/source/math/mMatrix.h index 47787acc58..daccaefa7f 100644 --- a/Engine/source/math/mMatrix.h +++ b/Engine/source/math/mMatrix.h @@ -52,7 +52,6 @@ #endif #ifndef USE_TEMPLATE_MATRIX - /// 4x4 Matrix Class /// /// This runs at F32 precision. diff --git a/Engine/source/math/mPoint2.h b/Engine/source/math/mPoint2.h index 6019bf92ec..4a1c779a18 100644 --- a/Engine/source/math/mPoint2.h +++ b/Engine/source/math/mPoint2.h @@ -919,6 +919,27 @@ inline F64 mCross(const Point2F &p0, const Point2F &p1, const Point2F &pt2) } +inline Point2F mMin2D(const Point2F& a, const Point2F& b) +{ + Point2F temp; + temp.x = (a.x < b.x) ? a.x : b.x; + temp.y = (a.y < b.y) ? a.y : b.y; + return temp; +} + +inline Point2F mMax2D(const Point2F& a, const Point2F& b) +{ + Point2F temp; + temp.x = (a.x > b.x) ? a.x : b.x; + temp.y = (a.y > b.y) ? a.y : b.y; + return temp; +} + +inline Point2F mClamp2D(const Point2F& val, const Point2F& low, const Point2F& high) +{ + return mMax2D(mMin2D(val, high), low); +} + namespace DictHash { /// Generates a 32bit hash from a Point2I. diff --git a/Engine/source/math/mPoint3.h b/Engine/source/math/mPoint3.h index c1bb729233..9eecfc4dc5 100644 --- a/Engine/source/math/mPoint3.h +++ b/Engine/source/math/mPoint3.h @@ -1055,6 +1055,29 @@ inline Point3F mReflect( const Point3F &v, const Point3F &n ) return v - 2 * n * mDot( v, n ); } +inline Point3F mMin3D(const Point3F& a, const Point3F& b) +{ + Point3F temp; + temp.x = (a.x < b.x) ? a.x : b.x; + temp.y = (a.y < b.y) ? a.y : b.y; + temp.x = (a.z < b.z) ? a.z : b.z; + return temp; +} + +inline Point3F mMax3D(const Point3F& a, const Point3F& b) +{ + Point3F temp; + temp.x = (a.x > b.x) ? a.x : b.x; + temp.y = (a.y > b.y) ? a.y : b.y; + temp.x = (a.z > b.z) ? a.z : b.z; + return temp; +} + +inline Point3F mClamp3D(const Point3F& val, const Point3F& low, const Point3F& high) +{ + return mMax3D(mMin3D(val, high), low); +} + /// Returns a perpendicular vector to the unit length input vector. extern Point3F mPerp( const Point3F &normal ); diff --git a/Engine/source/math/util/TransformVec2D.cpp b/Engine/source/math/util/TransformVec2D.cpp new file mode 100644 index 0000000000..fba68193d1 --- /dev/null +++ b/Engine/source/math/util/TransformVec2D.cpp @@ -0,0 +1,85 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "console/engineAPI.h" +#include "math/mTransform.h" +#include "math/util/TransformVec2D.h" + +IMPLEMENT_CONOBJECT(TransformVec2D); +ConsoleDocClass(TransformVec2D, "Relational Vector. 2D space"); + +DefineEngineMethod(TransformVec2D, push, void, (S32 inRootID, String inTransform), , "") +{ + Box2DF box; + object->push(inRootID, box.fromString(inTransform)); +} + +DefineEngineMethod(TransformVec2D, dumpVals, void, (), , "") +{ + for (U32 i = 0; i < object->refLocal()->size(); i++) + { + Con::printf("local[%i]: %s", i, object->local(i)->toString().c_str()); + Con::printf("global[%i]: %s", i, object->global(i)->toString().c_str()); + Con::printf("\n"); + } +} + +DefineEngineMethod(TransformVec2D, getTransform, String, (S32 id, bool global), (0, false), "") +{ + Box2DF* space = (global) ? object->global(id) : object->local(id); + return space->toString(); +} + +DefineEngineMethod(TransformVec2D, getPosition, Point2F, (S32 id, bool global), (0, false), "") +{ + Box2DF* space = (global) ? object->global(id) : object->local(id); + return space->point; +} + +DefineEngineMethod(TransformVec2D, getRotation, F32, (S32 id, bool global), (0, false), "") +{ + Box2DF* space = (global) ? object->global(id) : object->local(id); + return space->rot; +} + +DefineEngineMethod(TransformVec2D, getScale, Point2F, (S32 id, bool global), (0, false), "") +{ + Box2DF* space = (global) ? object->global(id) : object->local(id); + return space->extent; +} + +DefineEngineMethod(TransformVec2D, setConstraint2DString, void, (S32 id, const char* constraintString), (0, ""), "") +{ + Constraint2D constraint; + object->setConstraint(id, constraint.fromString(constraintString)); +} + + +DefineEngineMethod(TransformVec2D, setConstraint2D, void, (S32 id, Point2F inPosMin, Point2F inPosMax, F32 inRotMin, F32 inRotMax, Point2F inScaleMin, Point2F inScaleMax), , "") +{ + Constraint2D constraint; + object->setConstraint(id, Constraint2D(inPosMin, inPosMax, inRotMin, inRotMax, inScaleMin, inScaleMax)); +} + +DefineEngineMethod(TransformVec2D, getConstraint2D, const char*, (S32 id), , "") +{ + return object->getConstraint(id)->toString().c_str(); +} diff --git a/Engine/source/math/util/TransformVec2D.h b/Engine/source/math/util/TransformVec2D.h new file mode 100644 index 0000000000..165745f15f --- /dev/null +++ b/Engine/source/math/util/TransformVec2D.h @@ -0,0 +1,253 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _TransformVec2D_H_ +#define _TransformVec2D_H_ +#include "math/util/relationVec.h" + +class Box2DF : public RectF +{ +private: + typedef RectF Parent; +public: + F32 rot; + Box2DF() : RectF(0.0f,0.0f,1.0f,1.0f), rot(0.0f) {}; + Box2DF(F32 inrot) : RectF(0.0f, 0.0f, 1.0f, 1.0f), rot(inrot) {}; + Box2DF(RectF inrect) : RectF(inrect), rot(0.0f) {}; + Box2DF(RectF inrect, F32 inrot) : RectF(inrect), rot(inrot) {}; + Box2DF(const Point2F& in_rMin, const Point2F& in_rExtent) : RectF(in_rMin, in_rExtent), rot(0.0f) {}; + Box2DF(const Point2F& in_rMin, const Point2F& in_rExtent, F32 inrot) : RectF(in_rMin, in_rExtent), rot(inrot) {}; + Box2DF(const F32 in_left, const F32 in_top, const F32 in_width, const F32 in_height) : RectF(in_left, in_top, in_width, in_height), rot(0.0f) {}; + Box2DF(const F32 in_left, const F32 in_top, const F32 in_width, const F32 in_height, F32 inrot) : RectF(in_left, in_top, in_width, in_height), rot(inrot) {}; + Box2DF& mul(const Box2DF& origin); ///< M * a -> M + Box2DF& mul(const Box2DF& origin, const Box2DF& local); ///< a * b -> M + String toString(); + Box2DF fromString(String inString); +}; + +inline Box2DF& Box2DF::mul(const Box2DF& origin) +{ + // get incomming angle + float s = mSin(origin.rot); + float c = mCos(origin.rot); + + // translate point back to origin: + point -= origin.point; + + // rotate point + Point2F rotPoint = Point2F(point.x * c - point.y * s, point.x * s + point.y * c); + + // translate point back: + extent * origin.extent; + point = rotPoint + origin.point * extent; + return (*this); +} + +inline Box2DF& Box2DF::mul(const Box2DF& origin, const Box2DF& local) +{ + // get incomming angle + float s = mSin(origin.rot + local.rot); + float c = mCos(origin.rot + local.rot); + + // translate point back to origin: + Point2F relPoint = local.point - origin.point; + + // rotate point + Point2F rotPoint = Point2F(local.point.x * c - local.point.y * s, local.point.x * s + local.point.y * c); + + // translate point back: + Point2F relScale = local.extent * origin.extent; + relPoint = rotPoint + local.point* relScale; + Box2DF newBox = Box2DF(relPoint, relScale, origin.rot * local.rot); + return (*this); +} + +inline String Box2DF::toString() +{ + return String::ToString("%g %g &g &g %g", point.x, point.y, extent.x, extent.y, rot ); +} + +inline Box2DF Box2DF::fromString(String inString) +{ + Box2DF outVal; + Vector elements; + inString.split(" ", elements); + U32 i = 0; + outVal.point.x = dAtof(elements[i++].c_str()); + outVal.point.y = dAtof(elements[i++].c_str()); + outVal.extent.y = dAtof(elements[i++].c_str()); + outVal.extent.y = dAtof(elements[i++].c_str()); + outVal.rot = dAtof(elements[i++].c_str()); + return outVal; +} + +typedef Constraint Constraint2D; //pos xy + rotation +typedef RelationVec RelationVec2D; + +template<> inline String Constraint2D::toString() +{ + String retval = String::ToString("%g %g", mPosRanges[MinPos].x, mPosRanges[MinPos].y); + retval += String::ToString(" %g %g", mPosRanges[MaxPos].x, mPosRanges[MaxPos].y); + retval += String::ToString(" %g", mRotRanges[MinRot]); + retval += String::ToString(" %g", mRotRanges[MaxRot]); + retval += String::ToString(" %g %g", mPosRanges[MinScale].x, mPosRanges[MinScale].y); + retval += String::ToString(" %g %g", mPosRanges[MaxScale].x, mPosRanges[MaxScale].y); + return retval; +}; + +template<> inline Constraint2D Constraint2D::fromString(String inString) +{ + Constraint2D outVal; + Vector elements; + inString.split(" ", elements); + + //check to ensure we have PosDimensions*MaxPosTypes+RotDimensions*MaxRotTypes + AssertWarn(elements.size() == (3*MaxPosTypes+MaxRotTypes), avar("fromString got %d entries, expected %d", elements.size(), (3*MaxPosTypes+MaxRotTypes))); + + U32 i = 0; + Box2DF posRange; + posRange = Box2DF(dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str())); + outVal.setPosRange(posRange.point,posRange.extent); + + F32 rotRange[2]; + rotRange[0] = dAtof(elements[i++].c_str()); + rotRange[1] = dAtof(elements[i++].c_str()); + outVal.setRotRange(rotRange); + + Point2F scaleRange[2]; + scaleRange[0] = Point2F(dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str())); + scaleRange[1] = Point2F(dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str())); + outVal.setScaleRange(scaleRange); + + return outVal; +}; + +template<> inline void RelationVec2D::toGLobal() +{ + //first, allocate a copy of local size for global space + if (mGlobal.size() < mLocal.size()) + mGlobal.setSize(mLocal.size()); + + //next, itterate throughout the vector, multiplying matricies down the root/branch chains to shift those to worldspace + for (U32 id = 0; id < mLocal.size(); id++) + { + Box2DF curMat = copyLocal(id); + RelationNode* node = relation(id); + + // multiply transforms... + if (node->mRoot < 0) + setGlobal(id, curMat); + else + { + curMat.mul(copyGlobal(node->mRoot), copyLocal(id)); + setGlobal(id, curMat); + } + } + mCachedResult = true; +}; + +template<> inline void RelationVec2D::setPosition(S32 id, Point2F pos) +{ + mLocal[id].point.x = pos.x; + mLocal[id].point.y = pos.y; + mCachedResult = false; +}; + +template<> inline void RelationVec2D::setRotation(S32 id, F32 rot) +{ + mLocal[id].rot = rot; + mCachedResult = false; +}; + +template<> inline void RelationVec2D::setScale(S32 id, Point2F scale) +{ + mLocal[id].extent = scale; + mCachedResult = false; +}; + +template<> inline Point2F RelationVec2D::getPosition(S32 id) +{ + return global(id)->point; +}; + +template<> inline F32 RelationVec2D::getRotation(S32 id) +{ + return global(id)->rot; +}; + +template<> inline Point2F RelationVec2D::getScale(S32 id) +{ + return global(id)->extent; +}; + +template<> inline void RelationVec2D::translate(S32 id, Point2F posDelta) +{ + Point2F endPos = mClamp2D(mLocal[id].point + posDelta, getConstraint(id)->getPosRange().min, getConstraint(id)->getPosRange().max); + mLocal[id].point = endPos; + mCachedResult = false; +}; + +template<> inline void RelationVec2D::scale(S32 id, Point2F scaleDelta) +{ + Point2F endcale = mClamp2D(mLocal[id].extent * scaleDelta, getConstraint(id)->getScaleRange().min, getConstraint(id)->getScaleRange().max); + mLocal[id].extent = endcale; + mCachedResult = false; +}; + +template<> inline void RelationVec2D::rotate(S32 id, U32 axis, F32 radianDelta) +{ + F32 endRot = mClampF(mLocal[id].rot + radianDelta, getConstraint(id)->getRotRange().min, getConstraint(id)->getRotRange().max); + mLocal[id].rot = endRot; + mCachedResult = false; +}; + +template<> inline void RelationVec2D::orbit(S32 id, U32 axis, F32 radianDelta) +{ + F32 endRot = mClampF(mLocal[id].rot + radianDelta, getConstraint(id)->getRotRange().min, getConstraint(id)->getRotRange().max); + Box2DF temp = Box2DF(mLocal[id].point, mLocal[id].extent, endRot); + mLocal[id].mul(temp); + mCachedResult = false; +}; + +class TransformVec2D : public RelationVec2D, public SimObject +{ + typedef SimObject Parent; +public: + + //type specific I/O + void setTransform(S32 id, Box2DF trans) + { + setLocal(id, trans); + setCached(false); + }; + + void constrain(S32 id) + { + translate(id, Point2F(0, 0)); + rotate(id, 0, 0); + scale(id, Point2F(1, 1)); + setCached(false); + }; + + TransformVec2D() {}; + DECLARE_CONOBJECT(TransformVec2D); +}; +#endif diff --git a/Engine/source/math/util/TransformVec3D.cpp b/Engine/source/math/util/TransformVec3D.cpp new file mode 100644 index 0000000000..d1fc644fcd --- /dev/null +++ b/Engine/source/math/util/TransformVec3D.cpp @@ -0,0 +1,119 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "console/engineAPI.h" +#include "math/mTransform.h" +#include "math/util/TransformVec3D.h" + +IMPLEMENT_CONOBJECT(TransformVec3D); +ConsoleDocClass(TransformVec3D, "Relational Vector 3D space"); + +void testTransformVec3D() +{ + RelationVec3D tMat; + tMat.push(-1, MatrixF()); + MatrixF* localMatPtr = tMat.local(0); + localMatPtr->add(MatrixF::Identity); + MatrixF* globalMatPtr = tMat.global(0); + //expected: global is an identity matrix + localMatPtr->dumpMatrix("local"); + globalMatPtr->dumpMatrix("global"); + + localMatPtr->setPosition(Point3F(10, 0, 0)); + tMat.toGLobal(); + localMatPtr->dumpMatrix("local"); + globalMatPtr->dumpMatrix("global"); + +} + + +DefineEngineFunction(testTransformVec3D, void, (), , + "testTransformVec3D\n" + "@ingroup Math") +{ + testTransformVec3D(); +} + +DefineEngineMethod(TransformVec3D, push, void, (S32 inRootID, TransformF inTransform), , "") +{ + object->push(inRootID, inTransform.getMatrix()); +} + +DefineEngineMethod(TransformVec3D, dumpVals, void, (), , "") +{ + for (U32 i = 0; i < object->refLocal()->size(); i++) + { + object->local(i)->dumpMatrix((String("matL[") + String::ToString(i) + String("]")).c_str()); + object->global(i)->dumpMatrix((String("matG[") + String::ToString(i) + String("]")).c_str()); + Con::printf("\n"); + } +} + +DefineEngineMethod(TransformVec3D, getTransform, TransformF, (S32 id, bool global), (0, false), "") +{ + MatrixF* space = (global) ? object->global(id) : object->local(id); + return TransformF(*space); +} + +DefineEngineMethod(TransformVec3D, getPosition, Point3F, (S32 id, bool global), (0, false), "") +{ + MatrixF* space = (global) ? object->global(id) : object->local(id); + return space->getPosition(); +} + +DefineEngineMethod(TransformVec3D, getRotation, AngAxisF, (S32 id, bool global), (0, false), "") +{ + MatrixF* space = (global) ? object->global(id) : object->local(id); + AngAxisF aa(*space); + aa.axis.normalize(); + return aa; +} + +DefineEngineMethod(TransformVec3D, getScale, Point3F, (S32 id, bool global), (0, false), "") +{ + MatrixF* space = (global) ? object->global(id) : object->local(id); + return space->getScale(); +} + +DefineEngineMethod(TransformVec3D, getEuler, EulerF, (S32 id, bool global), (0, false), "") +{ + MatrixF* space = (global) ? object->global(id) : object->local(id); + return space->toEuler(); +} + + +DefineEngineMethod(TransformVec3D, setConstraint3DString, void, (S32 id, const char* constraintString), (0, ""), "") +{ + Constraint3D constraint; + object->setConstraint(id, constraint.fromString(constraintString)); +} + + +DefineEngineMethod(TransformVec3D, setConstraint3D, void, (S32 id, Point3F inPosMin, Point3F inPosMax, Point3F inRotMin, Point3F inRotMax, Point3F inScaleMin, Point3F inScaleMax),, "") +{ + Constraint3D constraint; + object->setConstraint(id, Constraint3D(inPosMin, inPosMax, inRotMin, inRotMax, inScaleMin, inScaleMax)); +} + +DefineEngineMethod(TransformVec3D, getConstraint3D, const char*, (S32 id),, "") +{ + return object->getConstraint(id)->toString().c_str(); +} diff --git a/Engine/source/math/util/TransformVec3D.h b/Engine/source/math/util/TransformVec3D.h new file mode 100644 index 0000000000..c5125bfed4 --- /dev/null +++ b/Engine/source/math/util/TransformVec3D.h @@ -0,0 +1,233 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#ifndef _TransformVec3D_H_ +#define _TransformVec3D_H_ +#include "math/util/relationVec.h" + +typedef Constraint Constraint3D; +typedef RelationVec RelationVec3D; + +template<> inline String Constraint3D::toString() +{ + String retval = String::ToString("%g %g %g", mPosRanges[MinPos].x, mPosRanges[MinPos].y, mPosRanges[MinPos].z); + retval += String::ToString(" %g %g %g", mPosRanges[MaxPos].x, mPosRanges[MaxPos].y, mPosRanges[MaxPos].z); + retval += String::ToString(" %g %g %g", mRotRanges[MinRot].x, mRotRanges[MinRot].y, mRotRanges[MinRot].z); + retval += String::ToString(" %g %g %g", mRotRanges[MaxRot].x, mRotRanges[MaxRot].y, mRotRanges[MaxRot].z); + retval += String::ToString(" %g %g %g", mPosRanges[MinScale].x, mPosRanges[MinScale].y, mPosRanges[MinScale].z); + retval += String::ToString(" %g %g %g", mPosRanges[MaxScale].x, mPosRanges[MaxScale].y, mPosRanges[MaxScale].z); + return retval; +}; + +template<> inline Constraint3D Constraint3D::fromString(String inString) +{ + Constraint3D outVal; + Vector elements; + inString.split(" ", elements); + + //check to ensure we have PosDimensions*MaxPosTypes+RotDimensions*MaxRotTypes + AssertWarn(elements.size() == (3*MaxPosTypes+3*MaxRotTypes), avar("fromString got %d entries, expected %d", elements.size(), (3*MaxPosTypes+3*MaxRotTypes))); + + U32 i = 0; + Point3F posRange[2]; + posRange[0] = Point3F(dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str())); + posRange[1] = Point3F(dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str())); + outVal.setPosRange(posRange); + + Point3F rotRange[2]; + rotRange[0] = Point3F(dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str())); + rotRange[1] = Point3F(dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str())); + outVal.setRotRange(rotRange); + + Point3F scaleRange[2]; + scaleRange[0] = Point3F(dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str())); + scaleRange[1] = Point3F(dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str()), dAtof(elements[i++].c_str())); + outVal.setScaleRange(scaleRange); + + return outVal; +}; + + +template<> inline void RelationVec3D::toGLobal() +{ + //first, allocate a copy of local size for global space + if (mGlobal.size() < mLocal.size()) + mGlobal.setSize(mLocal.size()); + + //next, itterate throughout the vector, multiplying matricies down the root/branch chains to shift those to worldspace + for (U32 id = 0; id < mLocal.size(); id++) + { + MatrixF curMat = copyLocal(id); + RelationNode* node = relation(id); + + // multiply transforms... + if (node->mRoot < 0) + setGlobal(id, curMat); + else + { + curMat.mul(copyGlobal(node->mRoot), copyLocal(id)); + setGlobal(id, curMat); + } + } + mCachedResult = true; +}; + +template<> inline void RelationVec3D::setPosition(S32 id, Point3F pos) +{ + mLocal[id].setPosition(pos); + mCachedResult = false; +}; + +template<> inline void RelationVec3D::setRotation(S32 id, Point3F rot) +{ + Point3F pos = mLocal[id].getPosition(); + mLocal[id].set(rot, pos); + mCachedResult = false; +}; + +template<> inline void RelationVec3D::setScale(S32 id, Point3F scale) +{ + mLocal[id].normalize(); + mLocal[id].scale(scale); + mCachedResult = false; +}; + +template<> inline Point3F RelationVec3D::getPosition(S32 id) +{ + return global(id)->getPosition(); +}; +template<> inline Point3F RelationVec3D::getRotation(S32 id) +{ + return global(id)->getForwardVector(); +}; +template<> inline Point3F RelationVec3D::getScale(S32 id) +{ + return global(id)->getScale(); +}; + +template<> inline void RelationVec3D::translate(S32 id, Point3F posDelta) +{ + Point3F endPos = mClamp3D(mLocal[id].getPosition() + posDelta, getConstraint(id)->getPosRange().min, getConstraint(id)->getPosRange().max); + mLocal[id].setPosition(endPos); + mCachedResult = false; +}; + +template<> inline void RelationVec3D::scale(S32 id, Point3F scaleDelta) +{ + Point3F endcale = mClamp3D(mLocal[id].getScale() * scaleDelta, getConstraint(id)->getScaleRange().min, getConstraint(id)->getScaleRange().max); + mLocal[id].normalize(); + mLocal[id].scale(endcale); + mCachedResult = false; +}; + +template<> inline void RelationVec3D::rotate(S32 id, U32 axis, F32 radianDelta) +{ + Point3F pos = mLocal[id].getPosition(); + Point3F scale = mLocal[id].getScale(); + VectorF curVec; + VectorF delta; + + switch (axis) + { + case 0: + { + curVec = mLocal[id].getRightVector(); + delta = VectorF(radianDelta, 0, 0); + }break; + case 1: + { + curVec = mLocal[id].getForwardVector(); + delta = VectorF(0, radianDelta, 0); + + }break; + case 2: + { + curVec = mLocal[id].getUpVector(); + delta = VectorF(0, 0, radianDelta); + + }break; + default://bad axis + return; + } + Point3F endRot = mClamp3D(curVec + delta, getConstraint(id)->getRotRange().min, getConstraint(id)->getRotRange().max); + mLocal[id].set(endRot, pos); + mLocal[id].scale(scale); + mCachedResult = false; +}; + +template<> inline void RelationVec3D::orbit(S32 id, U32 axis, F32 radianDelta) +{ + VectorF curVec; + VectorF delta; + + switch (axis) + { + case 0: + { + curVec = mLocal[id].getRightVector(); + delta = VectorF(radianDelta, 0, 0); + }break; + case 1: + { + curVec = mLocal[id].getForwardVector(); + delta = VectorF(0, radianDelta, 0); + + }break; + case 2: + { + curVec = mLocal[id].getUpVector(); + delta = VectorF(0, 0, radianDelta); + + }break; + default://bad axis + return; + } + Point3F endRot = mClamp3D(curVec + delta, getConstraint(id)->getRotRange().min, getConstraint(id)->getRotRange().max); + MatrixF temp = MatrixF(endRot); + mLocal[id].mul(temp); + mCachedResult = false; +}; + +class TransformVec3D : public RelationVec3D, public SimObject +{ + typedef SimObject Parent; +public: + + //type specific I/O + void setTransform(S32 id, AngAxisF trans) + { + MatrixF mat; + trans.setMatrix(&mat); + setLocal(id, mat); + setCached(false); + }; + void constrain(S32 id) + { + translate(id, Point3F(0, 0, 0)); + rotate(id,0,0); + scale(id, Point3F(1, 1, 1)); + setCached(false); + }; + + TransformVec3D() {}; + DECLARE_CONOBJECT(TransformVec3D); +}; +#endif diff --git a/Engine/source/math/util/constraints.h b/Engine/source/math/util/constraints.h new file mode 100644 index 0000000000..5174b718a5 --- /dev/null +++ b/Engine/source/math/util/constraints.h @@ -0,0 +1,104 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _CONSTRAINTS_H_ +#define _CONSTRAINTS_H_ +template class Constraint +{ +public: + enum posRangeType + { + MinPos = 0, + MaxPos, + MinScale, + MaxScale, + MaxPosTypes + }; + + enum rotRangeType + { + MinRot, + MaxRot, + MaxRotTypes + }; + + struct PosRange + { + PosDimensions min; + PosDimensions max; + PosRange(PosDimensions inMin, PosDimensions inMax) :min(inMin),max(inMax) {}; + }; + + struct RotRange + { + RotDimensions min; + RotDimensions max; + RotRange(RotDimensions inMin, RotDimensions inMax) :min(inMin), max(inMax) {}; + }; + + PosDimensions mPosRanges[MaxPosTypes]; + RotDimensions mRotRanges[MaxRotTypes]; + void setPosRange(PosDimensions min, PosDimensions max) { mPosRanges[MinPos] = min; mPosRanges[MaxPos] = max; }; + void setPosRange(PosDimensions inPos[2]) { mPosRanges[MinPos] = inPos[0]; mPosRanges[MaxPos] = inPos[1]; }; + + void setRotRange(RotDimensions min, RotDimensions max) { mRotRanges[MinRot] = min; mRotRanges[MinRot] = max; }; + void setRotRange(RotDimensions inRot[2]) { mRotRanges[MinRot] = inRot[0]; mRotRanges[MinRot] = inRot[1]; }; + + void setScaleRange(PosDimensions min, PosDimensions max) { mPosRanges[MinScale] = min; mPosRanges[MaxScale] = max; }; + void setScaleRange(PosDimensions inScale[2]) { mPosRanges[MinScale] = inScale[0]; mPosRanges[MaxScale] = inScale[1]; }; + + PosRange getPosRange() { return PosRange(mPosRanges[MinPos], mPosRanges[MaxPos]); } + RotRange getRotRange() { return RotRange(mRotRanges[MinRot], mRotRanges[MaxRot]); } + PosRange getScaleRange() { return PosRange(mPosRanges[MinScale], mPosRanges[MaxScale]); } + + Constraint(PosDimensions inPosRanges[MaxPosTypes], RotDimensions inRotRanges[MaxPosTypes]) + { + *mPosRanges = *inPosRanges; + *mRotRanges = *inRotRanges; + } + Constraint(PosDimensions inPos[2], RotDimensions inRot[2], PosDimensions inScale[2]) + { + setPosRange(inPos); + setRotRange(inRot); + setScaleRange(inScale); + } + Constraint(PosDimensions minPos, PosDimensions maxPos, RotDimensions minRot, RotDimensions maxRot, PosDimensions minScale, PosDimensions maxScale) + { + setPosRange(minPos, maxPos); + setRotRange(minRot, maxRot); + setScaleRange(minScale, maxScale); + } + + String toString() + { + return String("not implemented"); + } + + Constraint fromString(String inString) + { + return Constraint(); + } + + Constraint() = default; +private: +}; +#endif diff --git a/Engine/source/math/util/relationVec.h b/Engine/source/math/util/relationVec.h new file mode 100644 index 0000000000..e7208bba7a --- /dev/null +++ b/Engine/source/math/util/relationVec.h @@ -0,0 +1,125 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _RELATIONVEC_H_ +#define _RELATIONVEC_H_ + +#ifndef _MATHUTILS_H_ +#include "math/mathUtils.h" +#endif + +#ifndef _CONSTRAINTS_H_ +#include "math/util/constraints.h" +#endif + +struct RelationNode +{ + S32 mRoot = -1; + Vector mBranch; + RelationNode(S32 root = -1) : mRoot(root) {}; +}; + +template class RelationVec +{ +public: + //initializers + RelationVec() { } + RelationVec(Transform inTransform) {} + //add/remove/vector manipulation + S32 size() { return mLocal.size(); } + void setSize(U32 sz) + { + S32 oldSize = mLocal.size(); + mLocal.setSize(sz); + mGlobal.setSize(sz); + mRelation.setSize(sz); + mConstraints.setSize(sz); + for (S32 fillin = oldSize; fillin < sz; fillin++) + { + mLocal[fillin] = Transform(true); + mCachedResult = false; + } + } + void push(S32 rootId, Transform inMat) + { + mLocal.push_back(inMat); + mRelation.push_back(RelationNode(rootId)); + if (rootId > -1) mRelation[rootId].mBranch.push_back(mLocal.size() - 1); + setCached(false); //if we've added to the RelationVec, the cache is no longer valid + } + RelationNode* relation(S32 id) { return &mRelation[id]; }; + void setRelation(S32 id, S32 parent) { mRelation[id] = parent; }; + void setLocal(S32 id, Transform to) { mLocal[id] = to; mCachedResult = false; } + void setGlobal(S32 id, Transform to) { mGlobal[id] = to; } + //reference the raw vectors in thier entrieties + Vector* refLocal() { return &mLocal; }; + Vector* refGlobal() { toGLobal(); return &mGlobal; }; + Vector* refRelation() { return &mRelation; }; + //get pointers to individual elements + Transform* local(S32 id) { return &mLocal[id]; }; + Transform* global(S32 id, bool recalc = false) { if (recalc || !isCached()) toGLobal(); return &mGlobal[id]; } + Transform* operator[](int id) { return global(id); } + void toGLobal() { mCachedResult = true; }; + //for those cases where you *must* take the performance hit and do a copy + Transform copyLocal(S32 id) { return mLocal[id]; }; + Transform copyGlobal(S32 id) { return mGlobal[id]; }; + void setCached(bool cached) { mCachedResult = cached; }; + bool isCached() { return mCachedResult; }; + //base math + void setPosition(S32 id, PosDimensions pos) { mCachedResult = false; }; + void setRotation(S32 id, RotDimensions rot) { mCachedResult = false; }; + void setScale(S32 id, PosDimensions trans) { mCachedResult = false; }; + PosDimensions getPosition(S32 id) { return PosDimensions(); }; + RotDimensions getRotation(S32 id) { return RotDimensions(); }; + PosDimensions getScale(S32 id) { return PosDimensions(); }; + //incremental math + void translate(S32 id, PosDimensions pos) { mCachedResult = false; }; + void rotate(S32 id, U32 axis, F32 radians) { mCachedResult = false; }; + void orbit(S32 id, U32 axis, F32 radians) { mCachedResult = false; }; + void scale(S32 id, PosDimensions rot) { mCachedResult = false; }; + //constraints + Vector>* refConstraints() { return &mConstraints; }; + void setConstraint(S32 id, Constraint ranges) + { + //first, allocate a copy of local size for global space + if (mConstraints.size() < mLocal.size()) + mConstraints.setSize(mLocal.size()); + mConstraints[id] = ranges; + setCached(false); + }; + Constraint* getConstraint(S32 id) { return &mConstraints[id]; }; +#ifdef TORQUE_DEBUG_GUARD + inline void setFileAssociation(const char* file, const U32 line) { mFileAssociation = file; mLineAssociation = line; } +#endif +private: + Vector mLocal; + Vector mGlobal; + Vector mRelation; + Vector> mConstraints; + bool mCachedResult = false; +#ifdef TORQUE_DEBUG_GUARD + const char* mFileAssociation = ""; + U32 mLineAssociation = 0; +#endif +}; + +#endif diff --git a/Engine/source/ts/tsAnimate.cpp b/Engine/source/ts/tsAnimate.cpp index ef88d1eb8a..ca8a02953f 100644 --- a/Engine/source/ts/tsAnimate.cpp +++ b/Engine/source/ts/tsAnimate.cpp @@ -199,7 +199,7 @@ void TSShapeInstance::animateNodes(S32 ss) if (!mHandsOffNodes.test(i)) TSTransform::setMatrix(smNodeCurrentRotations[i],smNodeCurrentTranslations[i],&smNodeLocalTransforms[i]); else - smNodeLocalTransforms[i] = mNodeTransforms[i]; // in case mNodeTransform was changed externally + smNodeLocalTransforms[i] = mNodeTransforms.copyLocal(i); // in case mNodeTransform was changed externally } // add scale onto transforms @@ -238,11 +238,10 @@ void TSShapeInstance::animateNodes(S32 ss) for (i=a; inodes[i].parentIndex; - if (parentIdx < 0) - mNodeTransforms[i] = smNodeLocalTransforms[i]; - else - mNodeTransforms[i].mul(mNodeTransforms[parentIdx],smNodeLocalTransforms[i]); + mNodeTransforms.setLocal(i, smNodeLocalTransforms[i]); + mNodeTransforms.setRelation(i, parentIdx); } + mNodeTransforms.toGLobal(); } void TSShapeInstance::handleDefaultScale(S32 a, S32 b, TSIntegerSet & scaleBeenSet) diff --git a/Engine/source/ts/tsShapeInstance.cpp b/Engine/source/ts/tsShapeInstance.cpp index f757fdbbcf..ab63c6e568 100644 --- a/Engine/source/ts/tsShapeInstance.cpp +++ b/Engine/source/ts/tsShapeInstance.cpp @@ -218,7 +218,7 @@ void TSShapeInstance::initMeshObjects() MeshObjectInstance * objInst = &mMeshObjects[i]; // hook up the object to it's node and transforms. - objInst->mTransforms = &mNodeTransforms; + objInst->mTransforms = mNodeTransforms.refGlobal(); objInst->nodeIndex = obj->nodeIndex; // set up list of meshes @@ -400,7 +400,7 @@ void TSShapeInstance::renderDebugNodes() desc.setZReadWrite( false, false ); for ( U32 i = 0; i < mNodeTransforms.size(); i++ ) - drawUtil->drawTransform( desc, mNodeTransforms[i], NULL, NULL ); + drawUtil->drawTransform( desc, *(mNodeTransforms[i]), NULL, NULL ); } void TSShapeInstance::listMeshes( const String &state ) const diff --git a/Engine/source/ts/tsShapeInstance.h b/Engine/source/ts/tsShapeInstance.h index 78ed5e641d..2ea315bfaf 100644 --- a/Engine/source/ts/tsShapeInstance.h +++ b/Engine/source/ts/tsShapeInstance.h @@ -49,7 +49,9 @@ #ifndef _TSMATERIALLIST_H_ #include "ts/tsMaterialList.h" #endif - +#ifndef _TransformVec3D_H_ +#include "math/util/TransformVec3D.h" +#endif class RenderItem; class TSThread; class ConvexFeature; @@ -218,7 +220,7 @@ class TSShapeInstance Vector mMeshObjects; /// storage space for node transforms - Vector mNodeTransforms; + RelationVec3D mNodeTransforms; /// @name Reference Transform Vectors /// unused until first transition