Torque3D Documentation / _generateds / T3DTransform.cpp

T3DTransform.cpp

Engine/source/T3D/sceneComponent/T3DTransform.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "T3DTransform.h"
 25#include "math/mPoint.h"
 26#include "math/mQuat.h"
 27
 28//---------------------------------------------------------
 29// T3DTransform
 30//---------------------------------------------------------
 31
 32void Transform3D::setParentTransform(Transform3D * parent)
 33{
 34   if (_parentTransform == parent)
 35      return;
 36   _flags |= Transform3D::ParentDirty;
 37   _parentTransform = parent;
 38   if (_dirtyListener != NULL)
 39      _dirtyListener->onTransformDirty();
 40}
 41
 42bool Transform3D::hasObjectScale() const
 43{
 44   if (hasLocalScale())
 45      return true;
 46
 47   // check all parent transforms except last for scale
 48   Transform3D * walk = _parentTransform;
 49   while (walk != NULL && walk->_parentTransform != NULL)
 50   {
 51      if (walk->hasLocalScale())
 52         return true;
 53      walk = walk->getParentTransform();
 54   }
 55   return false;
 56}
 57
 58bool Transform3D::hasWorldScale() const
 59{
 60   if (hasLocalScale())
 61      return true;
 62
 63   // check all parent transforms for scale
 64   Transform3D * walk = _parentTransform;
 65   while (walk != NULL)
 66   {
 67      if (walk->hasLocalScale())
 68         return true;
 69      walk = walk->getParentTransform();
 70   }
 71   return false;
 72}
 73
 74void Transform3D::setWorldMatrix(const MatrixF & world)
 75{
 76   if (_parentTransform != NULL)
 77   {
 78      MatrixF parentMatrix;
 79      _parentTransform->getWorldMatrix(parentMatrix, true);
 80      MatrixF parentMatrixInv = parentMatrix;
 81      parentMatrixInv.inverse();
 82      MatrixF localMat;
 83      localMat = parentMatrixInv * world;
 84      setLocalMatrix(localMat);
 85   }
 86   else
 87      setLocalMatrix(world);
 88}
 89
 90void Transform3D::setObjectMatrix(const MatrixF & objMatrix)
 91{
 92   if (_parentTransform != NULL)
 93   {
 94      MatrixF parentMatrix;
 95      _parentTransform->getObjectMatrix(parentMatrix, true);
 96      MatrixF parentMatrixInv = parentMatrix;
 97      parentMatrixInv.inverse();
 98      MatrixF localMat;
 99      localMat = parentMatrixInv * objMatrix;
100      setLocalMatrix(localMat);
101   }
102   else
103      setLocalMatrix(objMatrix);
104}
105
106bool Transform3D::isChildOf(Transform3D * parent, bool recursive) const
107{
108   if (_parentTransform != NULL)
109   {
110      if (_parentTransform == parent)
111         return true;
112      else if (recursive)
113         return _parentTransform->isChildOf(parent, true);
114      else
115         return false;
116   }
117   else
118   {
119      return false;
120   }
121}
122
123//---------------------------------------------------------
124// Transform3DInPlace
125//---------------------------------------------------------
126
127Point3F Transform3DInPlace::getPosition() const
128{
129   return _position; 
130}
131
132void Transform3DInPlace::setPosition(const Point3F & position)
133{
134   _position = position;
135   _flags |= Transform3D::LocalPositionDirty;
136   if (_dirtyListener != NULL)
137      _dirtyListener->onTransformDirty();
138}
139
140QuatF Transform3DInPlace::getRotation() const
141{ 
142   return _rotation; 
143}
144
145void Transform3DInPlace::setRotation(const QuatF & rotation)
146{
147   _rotation = rotation;
148   _flags |= Transform3D::LocalRotationDirty;
149   if (_dirtyListener != NULL)
150      _dirtyListener->onTransformDirty();
151}
152
153Point3F Transform3DInPlace::getScale() const
154{ 
155   return _scale;
156}
157
158void Transform3DInPlace::setScale(const Point3F & scale)
159{
160   _scale = scale;
161   _flags |= Transform3D::LocalScaleDirty;
162   if (_dirtyListener != NULL)
163      _dirtyListener->onTransformDirty();
164}
165
166void Transform3DInPlace::getWorldMatrix(MatrixF & worldMat, bool includeLocalScale) const
167{
168   if (_parentTransform == NULL)
169      getLocalMatrix(worldMat, includeLocalScale);
170   else
171   {
172      MatrixF localMat, parentMat;
173      getLocalMatrix(localMat, includeLocalScale);
174      _parentTransform->getWorldMatrix(parentMat, true);
175      worldMat = parentMat * localMat;
176   }
177}
178
179void Transform3DInPlace::getObjectMatrix(MatrixF & objectMat, bool includeLocalScale) const
180{
181   if (_parentTransform == NULL)
182      objectMat = MatrixF::smIdentity;
183   else if (_parentTransform->getParentTransform() == NULL)
184      getLocalMatrix(objectMat, includeLocalScale);
185   else
186   {
187      MatrixF localMat, parentMat;
188      getLocalMatrix(localMat, includeLocalScale);
189      _parentTransform->getObjectMatrix(parentMat, true);
190      objectMat = parentMat * localMat;
191   }
192}
193
194void Transform3DInPlace::getLocalMatrix(MatrixF & localMat, bool includeLocalScale) const
195{
196   _rotation.setMatrix(&localMat);
197   localMat.setColumn(3,_position);
198   if (includeLocalScale)
199      localMat.scale(_scale);
200}
201
202void Transform3DInPlace::setLocalMatrix(const MatrixF & localMat)
203{
204   _rotation.set(localMat);
205   _position = localMat.getPosition();
206   _scale = localMat.getScale();
207   _flags |= Transform3D::LocalScaleDirty | Transform3D::LocalRotationDirty | Transform3D::LocalPositionDirty;
208   if (_dirtyListener != NULL)
209      _dirtyListener->onTransformDirty();
210}
211
212//---------------------------------------------------------
213// TSTransform3D
214//---------------------------------------------------------
215
216TSTransform3D::TSTransform3D(TSShapeInstance * si, S32 nodeIndex)
217{
218   _shapeInstance = si;
219   _nodeIndex = nodeIndex;
220   AssertFatal(_nodeIndex >= 0 && _nodeIndex < _shapeInstance->mNodeTransforms.size(), "TSTransform3D nodeIndex out of range");
221}
222
223Point3F TSTransform3D::getPosition() const
224{
225   if (!doHandleLocal())
226   {
227      MatrixF mat;
228      return getTSLocal(mat).getPosition();
229   }
230   return _position;
231}
232
233void TSTransform3D::setPosition(const Point3F & position)
234{
235   setHandleLocal(true);
236   _position = position;
237   _flags |= Transform3D::LocalPositionDirty;
238   if (_dirtyListener != NULL)
239      _dirtyListener->onTransformDirty();
240}
241
242QuatF TSTransform3D::getRotation() const
243{
244   if (!doHandleLocal())
245   {
246      MatrixF mat;
247      return QuatF(getTSLocal(mat));
248   }
249   return _rotation;
250}
251void TSTransform3D::setRotation(const QuatF & rotation)
252{
253   setHandleLocal(true);
254   _rotation = rotation;
255   _flags |= Transform3D::LocalRotationDirty;
256   if (_dirtyListener != NULL)
257      _dirtyListener->onTransformDirty();
258}
259
260Point3F TSTransform3D::getScale() const
261{
262   if (!doHandleLocal())
263   {
264      MatrixF mat;
265      return getTSLocal(mat).getScale();
266   }
267   return _scale;
268}
269void TSTransform3D::setScale(const Point3F & scale)
270{
271   setHandleLocal(true);
272   _scale = scale;
273   _flags |= Transform3D::LocalScaleDirty;
274   if (_dirtyListener != NULL)
275      _dirtyListener->onTransformDirty();
276}
277
278void TSTransform3D::getWorldMatrix(MatrixF & worldMat, bool includeLocalScale) const
279{
280   _shapeInstance->animate();
281   if (_parentTransform == NULL)
282   {
283      worldMat = _shapeInstance->mNodeTransforms[_nodeIndex];
284   }
285   else
286   {
287      MatrixF parentMat;
288      _parentTransform->getWorldMatrix(parentMat, true);
289      worldMat = parentMat * _shapeInstance->mNodeTransforms[_nodeIndex];
290   }
291}
292
293void TSTransform3D::getObjectMatrix(MatrixF & objectMat, bool includeLocalScale) const
294{
295   if (_parentTransform == NULL)
296      objectMat = MatrixF::smIdentity;
297   else if (_parentTransform->getParentTransform() == NULL)
298   {
299      _shapeInstance->animate();
300      objectMat = _shapeInstance->mNodeTransforms[_nodeIndex];
301   }
302   else
303   {
304      _shapeInstance->animate();
305
306      MatrixF parentMat;
307      _parentTransform->getObjectMatrix(parentMat, true);
308      objectMat = parentMat * _shapeInstance->mNodeTransforms[_nodeIndex];
309   }
310}
311
312void TSTransform3D::getLocalMatrix(MatrixF & localMat, bool includeLocalScale) const
313{
314   if (doHandleLocal())
315   {
316      _rotation.setMatrix(&localMat);
317      localMat.setPosition(_position);
318      if (includeLocalScale)
319         localMat.scale(_scale);
320   }
321   else
322   {
323      _shapeInstance->animate();
324      localMat = _shapeInstance->mNodeTransforms[_nodeIndex];
325      if (!includeLocalScale && (_flags & Transform3D::LocalHasScale) != Transform3D::None)
326      {
327         // reverse any scale on matrix -- this is a inconvenient, but not a common case
328         Point3F scale = localMat.getScale();
329         scale.x = 1.0f / scale.x;
330         scale.y = 1.0f / scale.y;
331         scale.z = 1.0f / scale.z;
332         localMat.scale(scale);
333      }
334   }
335}
336
337void TSTransform3D::setLocalMatrix(const MatrixF & localMatrix)
338{
339   setHandleLocal(true);
340   _position = localMatrix.getPosition();
341   _rotation.set(localMatrix);
342   _scale = localMatrix.getScale();
343   _flags |= Transform3D::LocalScaleDirty | Transform3D::LocalRotationDirty | Transform3D::LocalPositionDirty;
344   if (_dirtyListener != NULL)
345      _dirtyListener->onTransformDirty();
346}
347
348MatrixF & TSTransform3D::getTSLocal(MatrixF & mat) const
349{
350     _shapeInstance->animate();
351
352      // if node has no parent, easy enough to just grab the matrix of the node
353      int parentIdx = _shapeInstance->getShape()->nodes[_nodeIndex].parentIndex;
354      if (parentIdx < 0)
355      {
356         return _shapeInstance->mNodeTransforms[_nodeIndex];
357      }
358
359      // has parent, local is transform from this node to parent so get local matrix the hard way
360      MatrixF parentMat = _shapeInstance->mNodeTransforms[parentIdx];
361      parentMat.inverse();
362      mat = parentMat * _shapeInstance->mNodeTransforms[_nodeIndex];
363      return mat;
364}
365
366void TSTransform3D::setHandleLocal(bool handleLocal)
367{
368   if (handleLocal == doHandleLocal())
369      return;
370
371   if (handleLocal)
372   {
373      _position = getPosition();
374      _rotation = getRotation();
375      _scale = getScale();
376      _shapeInstance->setNodeAnimationState(_nodeIndex, 0, this);
377   }
378   else
379      _shapeInstance->setNodeAnimationState(_nodeIndex, 0);
380   _flags ^= TSTransform3D::HandleLocal;
381}
382
383void TSTransform3D::setNodeTransform(TSShapeInstance * si, S32 nodeIndex, MatrixF & localTransform)
384{
385   AssertFatal(si == _shapeInstance,"TSTransform3D hooked up to wrong shape.");
386   getLocalMatrix(localTransform, true);
387}
388