Developer Documentation
SkeletonEditingScripting.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 #include "SkeletonEditingPlugin.hh"
51 
53 #include <ObjectTypes/Skeleton/Helper/SkeletonTransform.hh>
54 #include <ACG/Geometry/Algorithms.hh>
55 
56 //------------------------------------------------------------------------------
57 
62 
63  emit setSlotDescription("splitBone(int,int)",
64  tr("insert a joint in the middle of a bone."),
65  QString(tr("objectId,jointId")).split(","),
66  QString(tr("ID of an object,ID of tail joint")).split(","));
67 
68  emit
69  setSlotDescription(
70  "addJoint(int,int,Vector)",
71  tr("add a joint to the skeleton."),
72  QString(tr("objectId,jointId,Vector")).split(","),
73  QString(
74  tr(
75  "ID of an object,ID of parent joint,Position for the new joint")).split(
76  ","));
77 
78  emit setSlotDescription("deleteJoint(int,int)",
79  tr("delete a joint from the skeleton."),
80  QString(tr("objectId,jointId")).split(","),
81  QString(tr("ID of an object,ID of a joint")).split(","));
82 
83  emit setSlotDescription(
84  "transformJoint(int,int,Matrix4x4)",
85  tr("transform a joint with a matrix."),
86  QString(tr("objectId,jointId,Matrix")).split(","),
87  QString(tr("ID of an object,ID of a joint,transformation matrix")).split(
88  ","));
89 
90  emit setSlotDescription("globalMatrix(int,int)",
91  tr("get the global matrix of a joint in the active pose."),
92  QString(tr("objectId,jointId")).split(","),
93  QString(tr("ID of an object,ID of a joint")).split(","));
94 
95  emit setSlotDescription("localMatrix(int,int)",
96  tr("get the local matrix of a joint in the active pose."),
97  QString(tr("objectId,jointId")).split(","),
98  QString(tr("ID of an object,ID of a joint")).split(","));
99 
100  emit setSlotDescription("globalTranslation(int,int)",
101  tr("get the global translation of a joint in the active pose."),
102  QString(tr("objectId,jointId")).split(","),
103  QString(tr("ID of an object,ID of a joint")).split(","));
104 
105  emit setSlotDescription("localTranslation(int,int)",
106  tr("get the local translation of a joint in the active pose."),
107  QString(tr("objectId,jointId")).split(","),
108  QString(tr("ID of an object,ID of a joint")).split(","));
109 
110  emit setSlotDescription("animationCount(int)",
111  tr("get the number of animations the skeleton has."),
112  QString(tr("objectId")).split(","),
113  QString(tr("ID of an object")).split(","));
114 
115  emit setSlotDescription("frameCount(int,int)",
116  tr("get the number of frames a given animation has."),
117  QString(tr("objectId,animationIndex")).split(","),
118  QString(tr("ID of an object,Index of an animation")).split(","));
119 
120  emit setSlotDescription("activeAnimation(int)",
121  tr("get the animation which is currently active."),
122  QString(tr("objectId")).split(","),
123  QString(tr("ID of an object")).split(","));
124 
125  emit setSlotDescription("activeFrame(int)",
126  tr("get the frame which is currently active"),
127  QString(tr("objectId")).split(","),
128  QString(tr("ID of an object")).split(","));
129 
130  emit
131  setSlotDescription(
132  "setActivePose(int,int,int)",
133  tr("set the active pose of the skeleton."),
134  QString(tr("objectId,animationIndex,frame")).split(","),
135  QString(tr("ID of an object,Index of an animation,Index of a frame")).split(
136  ","));
137 
138  emit
139  setSlotDescription(
140  "addAnimation(int,QString,int)",
141  tr("add an animation to the skeleton."),
142  QString(tr("objectId,AnimationName,frameCount")).split(","),
143  QString(
144  tr(
145  "ID of an object,name for the animation,number of frames the animation should have")).split(
146  ","));
147 }
148 
149 //------------------------------------------------------------------------------
150 
152 void SkeletonEditingPlugin::splitBone(int _objectId, int _tailJoint) {
153 
154  BaseObjectData* baseObject = 0;
155  PluginFunctions::getObject(_objectId, baseObject);
156 
157  if (baseObject == 0)
158  return;
159 
160  Skeleton* skeleton = PluginFunctions::skeleton(baseObject);
161 
162  if (skeleton == 0)
163  return;
164 
165  Skeleton::Joint* tailJoint = skeleton->joint(_tailJoint);
166 
167  if (tailJoint == 0) {
168  emit log(
169  LOGERR,
170  tr("Cannot split bone. Unable to find joint with id ")
171  + QString::number(_tailJoint));
172  return;
173  }
174 
175  Skeleton::Joint* headJoint = tailJoint->parent();
176 
177  //add the new joint
178  Skeleton::Joint* jointNew = new Skeleton::Joint(headJoint);
179  skeleton->addJoint(headJoint, jointNew);
180  tailJoint->setParent(jointNew, *skeleton);
181 
182  //set position in refPose
183  Skeleton::Pose* refPose = skeleton->referencePose();
184  refPose->setGlobalTranslation(
185  jointNew->id(),
186  0.5 * refPose->globalTranslation(headJoint->id()) + 0.5
187  * refPose->globalTranslation(tailJoint->id()));
188 
189  //set position in animations
190  for (unsigned int a = 0; a < skeleton->animationCount(); a++)
191  if (AnimationHandle(a, 0).isValid()) {
192 
193  AnimationT<ACG::Vec3d> *animation = skeleton->animation(
194  AnimationHandle(a, 0));
195 
196  if (animation != 0) {
197 
198  //set initial joint translation
199  for (int iFrame = 0; iFrame < (int) animation->frameCount(); iFrame++) {
200 
201  PoseT<ACG::Vec3d>* pose = skeleton->pose(AnimationHandle(a, iFrame));
202 
203  pose->setGlobalMatrix(jointNew->id(),
204  pose->globalMatrix(headJoint->id()));
205  pose->setGlobalTranslation(
206  jointNew->id(),
207  0.5 * pose->globalTranslation(headJoint->id()) + 0.5
208  * pose->globalTranslation(tailJoint->id()));
209  }
210  }
211  }
212 
213  emit updatedObject(_objectId, UPDATE_GEOMETRY);
214 
215  emit scriptInfo("splitBone( ObjectId, " + QString::number(_tailJoint) + " )");
216 
217  // Create backup
218  emit createBackup(_objectId, "Split Bone", UPDATE_TOPOLOGY);
219 }
220 
221 //------------------------------------------------------------------------------
222 
224 void SkeletonEditingPlugin::addJoint(int _objectId, int _parent,
225  Vector _position) {
226 
227  BaseObjectData* baseObject = 0;
228  PluginFunctions::getObject(_objectId, baseObject);
229 
230  if (baseObject == 0)
231  return;
232 
233  Skeleton* skeleton = PluginFunctions::skeleton(baseObject);
234 
235  if (skeleton == 0)
236  return;
237 
238  Skeleton::Joint* parent = skeleton->joint(_parent);
239 
240  if (parent == 0) {
241  emit log(
242  LOGERR,
243  tr("Cannot add joint. Unable to find joint with id ")
244  + QString::number(_parent));
245  return;
246  }
247 
248  //add the new joint
249  Skeleton::Joint* jointNew = new Skeleton::Joint(parent);
250  skeleton->addJoint(parent, jointNew);
251 
252  //set the position
253 
254  setJointPosition(PluginFunctions::skeletonObject(baseObject), jointNew,
255  _position);
256  emit updatedObject(_objectId, UPDATE_ALL);
257 
258  emit scriptInfo(
259  "addJoint( ObjectId, " + QString::number(_parent) + ", Vector("
260  + QString::number(_position[0]) + "," + QString::number(_position[1])
261  + "," + QString::number(_position[2]) + ") )");
262 
263  // Create backup
264  emit createBackup(_objectId, "Add Joint", UPDATE_TOPOLOGY);
265 }
266 
267 //------------------------------------------------------------------------------
268 
270 void SkeletonEditingPlugin::deleteJoint(int _objectId, int _jointId) {
271 
272  BaseObjectData* baseObject = 0;
273  PluginFunctions::getObject(_objectId, baseObject);
274 
275  if (baseObject == 0)
276  return;
277 
278  Skeleton* skeleton = PluginFunctions::skeleton(baseObject);
279 
280  if (skeleton == 0)
281  return;
282 
283  Skeleton::Joint* joint = skeleton->joint(_jointId);
284 
285  if (joint == 0) {
286  emit log(
287  LOGERR,
288  tr("Cannot Remove joint. Unable to find joint with id ")
289  + QString::number(_jointId));
290  return;
291  }
292 
293  skeleton->removeJoint(joint);
294 
295  emit scriptInfo("deleteJoint( ObjectId, " + QString::number(_jointId) + " )");
296 
297  // Create backup
298  emit createBackup(_objectId, "Delete Joint", UPDATE_TOPOLOGY);
299 
300  emit updatedObject(_objectId, UPDATE_ALL);
301 }
302 
303 //------------------------------------------------------------------------------
304 
306 void SkeletonEditingPlugin::transformJoint(int _objectId, int _jointId,
307  Matrix4x4 _matrix) {
308 
309  BaseObjectData* obj = 0;
310 
311  PluginFunctions::getObject(_objectId, obj);
312 
313  if (obj == 0) {
314  emit log(LOGERR, tr("Unable to get object"));
315  return;
316  }
317 
319 
320  if (skeletonObj == 0) {
321  emit log(LOGERR, tr("Unable to get skeletonObject"));
322  return;
323  }
324 
325  Skeleton* skeleton = PluginFunctions::skeleton(obj);
326 
327  if (skeleton == 0) {
328  emit log(LOGERR, tr("Unable to get skeleton"));
329  return;
330  }
331 
332  Skeleton::Joint* joint = skeleton->joint(_jointId);
333 
334  if (joint == 0) {
335  emit log(LOGERR, tr("Unable to get joint"));
336  return;
337  }
338 
339  bool recursiveJointTransformation = transformChildJoints_;
340 
341  AnimationHandle handle = skeletonObj->skeletonNode()->activePose();
342 
343  Skeleton::Pose* activePose;
344 
345  if (!handle.isValid()) { // reference pose
346  activePose = skeleton->referencePose();
347  } else { // animation pose
348 
349  activePose = skeleton->animation(handle.animationIndex())->pose(
350  handle.frame());
351 
352  //always transform children otherwise only the local coordsys is rotated
353  recursiveJointTransformation = true;
354 
355  // translation changes the skeleton structure
356  // this is only allowed in refPose therefore delete translation
357  Matrix4x4 mat = _matrix;
358  mat(0, 3) = 0.0;
359  mat(1, 3) = 0.0;
360  mat(2, 3) = 0.0;
361  if (mat.is_identity())
362  _matrix = mat;
363  }
364 
365  SkeletonTransform transformer(*skeleton);
366 
367  if (handle.isValid()) { // animation pose
368 
369  //we are in an animation pose -> only rotation allowed
370  transformer.rotateJoint(joint, activePose, _matrix, transformAllFrames_);
371 
372  //update the skin
373  bool exists = false;
374 
375  emit functionExists("skeletalanimation", "updateSkin()", exists);
376 
377  if (exists)
378  RPC::callFunction("skeletalanimation", "updateSkin");
379 
380  } else { // reference pose
381 
382  // full transformation
383  if (_matrix(0, 0) != 1 || _matrix(1, 1) != 1 || _matrix(2, 2) != 1
384  || _matrix(0, 1) != 0 || _matrix(0, 2) != 0 || _matrix(1, 0) != 0
385  || _matrix(1, 2) != 0 || _matrix(2, 0) != 0 || _matrix(2, 1) != 0) {
386  // apply full transformation
387  transformer.transformJoint(joint, _matrix, !recursiveJointTransformation);
388 
389  } else { // translation only
390 
391  if (_matrix(0, 3) == 0 && _matrix(1, 3) == 0 && _matrix(2, 3) == 0) // no translation
392  return;
393 
394  if (joint->isRoot()) {
395 
396  /*
397  * Change translation of root joint.
398  */
399 
400  transformer.translateJoint(joint, ACG::Vec3d(_matrix(0, 3), _matrix(1, 3), _matrix(2, 3)), !transformChildJoints_);
401 
402  } else {
403 
404  /*
405  * Change translation of non-root joint.
406  *
407  * In these cases, the rotation of the coordinate frame of the parent
408  * joint (unless it is not a branching joint) as well as the
409  * the rotation of the coordinate frame of the current joint have to be
410  * corrected in the following way:
411  *
412  * We compute the rotation of the affected joints' coordinate system
413  * such that the local(!) translation of the respective child
414  * joint remains constant. So, in 2D, consider configuration
415  * A --> B --> C, where C is a child of B is a child of A.
416  * If C has translation (2, 0) and B has translation (3,5), then, after
417  * global translation of B, the coordinate frames of A and B have to be rotated
418  * such that the joint axes remain constant, so B lies on the line (0,0) + x*(3,5)
419  * with respect to A's coordinate system and C lies somewhere on the line (0,0) + y*(2,0)
420  * with respect to B's coordinate system.
421  *
422  */
423 
424  // init params
425  bool parentIsNotBranch = (joint->parent()->size() == 1);
426  bool hasOneChild = (joint->size() == 1);
427  ACG::Vec3d oldParentAxis(0.0, 0.0, 0.0);
428  ACG::Vec3d oldJointAxis(0.0, 0.0, 0.0);
429  ACG::Vec3d transParentAxis(0.0, 0.0, 0.0);
430  ACG::Vec3d transJointAxis(0.0, 0.0, 0.0);
431  ACG::Vec3d parentRotAxis(0.0, 0.0, 0.0);
432  ACG::Vec3d jointRotAxis(0.0, 0.0, 0.0);
433  double parentRotAngle = 0.0;
434  double jointRotAngle = 0.0;
435 
436  // get the original parent axis: parent joint -----> current joint
437  oldParentAxis = activePose->localTranslation(_jointId);
438  // get the original joint axis: current joint -----> child joint
439  if (hasOneChild)
440  oldJointAxis = activePose->localTranslation(joint->child(0)->id());
441 
442  // store the joint axes of all animations before the translation of the current joint
443  // so that the rotations can be calculated for the animation poses
444  std::vector<ACG::Vec3d> oldAnimJoint, oldAnimParent;
445  for (unsigned int a = 0; a < skeleton->animationCount(); ++a) {
446  for (unsigned int iFrame = 0; iFrame < skeleton->animation(a)->frameCount(); iFrame++) {
447  Skeleton::Pose* pose = skeleton->animation(a)->pose(iFrame);
448 
449  if (hasOneChild)
450  oldAnimJoint.push_back(pose->localTranslation(joint->child(0)->id()));
451 
452  oldAnimParent.push_back(pose->localTranslation(_jointId));
453  }
454  }
455 
456  // translate the joint
457  transformer.translateJoint(joint, ACG::Vec3d(_matrix(0, 3), _matrix(1, 3), _matrix(2, 3)), !transformChildJoints_);
458 
459  // get translated parent axis
460  transParentAxis = activePose->localTranslation(_jointId);
461 
462  if (hasOneChild) {
463  // get translated joint axis
464  transJointAxis = activePose->localTranslation(joint->child(0)->id());
465  }
466 
467  // now calculate the rotation that has to occur for a translation of the joint:
468 
469  // get the rotation axis and angle between the old and new parent axis
470  if (!ACG::Geometry::rotationOfTwoVectors<double>(oldParentAxis, transParentAxis, parentRotAxis, parentRotAngle))
471  return;
472 
473  // get rotation axis and angle between old and new joint axis
474  if (hasOneChild) {
475  if (!ACG::Geometry::rotationOfTwoVectors<double>(oldJointAxis, transJointAxis, jointRotAxis, jointRotAngle))
476  return;
477  }
478 
479  if (parentIsNotBranch) {
480  // parent rotation matrix
481  ACG::GLMatrixT<double> parentRotMatrix;
482  parentRotMatrix.identity();
483  parentRotMatrix.rotate(parentRotAngle, parentRotAxis);
484 
485  // apply rotation to parent joint
486  ACG::Matrix4x4d localParent = activePose->localMatrix(joint->parent()->id());
487  localParent *= parentRotMatrix;
488  activePose->setLocalMatrix(joint->parent()->id(), localParent, false);
489  }
490 
491  if (hasOneChild) {
492  // joint rotation matrix
493  ACG::GLMatrixT<double> jointRotMatrix;
494  jointRotMatrix.identity();
495  jointRotMatrix.rotate(jointRotAngle, jointRotAxis);
496 
497  // apply current joint
498  ACG::Matrix4x4d localJoint = activePose->localMatrix(joint->id());
499  localJoint *= jointRotMatrix;
500  activePose->setLocalMatrix(joint->id(), localJoint, false);
501  }
502 
503  // apply rotations to animation
504  std::vector<ACG::Vec3d>::iterator jointIt, parentIt;
505  jointIt = oldAnimJoint.begin();
506  parentIt = oldAnimParent.begin();
507  for (unsigned int a = 0; a < skeleton->animationCount(); ++a) {
508  for (unsigned int iFrame = 0; iFrame < skeleton->animation(a)->frameCount(); iFrame++) {
509  Skeleton::Pose* pose = skeleton->animation(a)->pose(iFrame);
510 
511  // only apply rotation to parent joint if it is not a branch
512  if (parentIsNotBranch) {
513 
514  // get the rotation axis and angle between the old and new parent axis
515  ACG::Vec3d translatedParent = pose->localTranslation(_jointId);
516  ACG::Vec3d parentRotAxis(0.0, 0.0, 0.0);
517  double parentRotAngle = 0.0;
518  if (!ACG::Geometry::rotationOfTwoVectors<double>(*parentIt, translatedParent, parentRotAxis,
519  parentRotAngle))
520  return;
521 
522  // parent rotation matrix
523  ACG::GLMatrixT<double> parentRotMatrix;
524  parentRotMatrix.identity();
525  parentRotMatrix.rotate(parentRotAngle, parentRotAxis);
526 
527  // apply rotation to parent joint
528  ACG::Matrix4x4d parentMat = pose->localMatrix(joint->parent()->id());
529  parentMat *= parentRotMatrix;
530  pose->setLocalMatrix(joint->parent()->id(), parentMat, false);
531 
532  ++parentIt;
533  }
534 
535  if (hasOneChild) {
536  // get rotation axis and angle between old and new joint axis
537  ACG::Vec3d translatedAxis = pose->localTranslation(joint->child(0)->id());
538  ACG::Vec3d jointRotAxis(0.0, 0.0, 0.0);
539  double jointRotAngle = 0.0;
540 
541  if (!ACG::Geometry::rotationOfTwoVectors<double>(*jointIt, translatedAxis, jointRotAxis, jointRotAngle))
542  return;
543 
544  // joint rotation matrix
545  ACG::GLMatrixT<double> jointRotMatrix;
546  jointRotMatrix.identity();
547  jointRotMatrix.rotate(jointRotAngle, jointRotAxis);
548 
549  // apply rotation to current joint
550  ACG::Matrix4x4d localMat = pose->localMatrix(joint->id());
551  localMat *= jointRotMatrix;
552  pose->setLocalMatrix(joint->id(), localMat, false);
553 
554  ++jointIt;
555  }
556  }
557  }
558  }
559  }
560  }
561 
562  emit updatedObject(_objectId, UPDATE_GEOMETRY);
563 
564  QString matString;
565  for (int i = 0; i < 4; i++)
566  for (int j = 0; j < 4; j++)
567  matString += " , " + QString::number(_matrix(i, j));
568 
569  matString = matString.right(matString.length() - 3);
570 
571  emit scriptInfo(
572  "transformJoint( ObjectId, " + QString::number(_jointId) + ", Matrix4x4("
573  + matString + " ) )");
574 
575  // Create backup if there was a change
576  // the backup is only created when the slot is called via scripting (sender == 0)
577  if (!_matrix.is_identity() && (sender() == 0))
578  emit createBackup(_objectId, "Joint Transformation", UPDATE_GEOMETRY);
579 }
580 
581 //------------------------------------------------------------------------------
582 
584 Matrix4x4 SkeletonEditingPlugin::globalMatrix(int _objectId, int _jointId) {
585 
586  BaseObjectData* obj = 0;
587 
588  PluginFunctions::getObject(_objectId, obj);
589 
590  if (obj == 0) {
591  emit log(LOGERR, tr("Unable to get object"));
592  return Matrix4x4();
593  }
594 
596 
597  if (skeletonObj == 0) {
598  emit log(LOGERR, tr("Unable to get skeletonObject"));
599  return Matrix4x4();
600  }
601 
602  Skeleton* skeleton = PluginFunctions::skeleton(obj);
603  Skeleton::Joint* joint = skeleton->joint(_jointId);
604 
605  if (joint == 0) {
606  emit log(LOGERR, tr("Unable to get joint"));
607  return Matrix4x4();
608  }
609 
610  AnimationHandle handle = skeletonObj->skeletonNode()->activePose();
611 
612  Skeleton::Pose* activePose;
613 
614  if (!handle.isValid())
615  activePose = skeleton->referencePose();
616  else
617  activePose = skeleton->animation(handle.animationIndex())->pose(
618  handle.frame());
619 
620  emit
621  scriptInfo("globalMatrix( ObjectId, " + QString::number(_jointId) + " )");
622  return activePose->globalMatrix(joint->id());
623 }
624 
625 //------------------------------------------------------------------------------
626 
628 Matrix4x4 SkeletonEditingPlugin::localMatrix(int _objectId, int _jointId) {
629 
630  BaseObjectData* obj = 0;
631 
632  PluginFunctions::getObject(_objectId, obj);
633 
634  if (obj == 0) {
635  emit log(LOGERR, tr("Unable to get object"));
636  return Matrix4x4();
637  }
638 
640 
641  if (skeletonObj == 0) {
642  emit log(LOGERR, tr("Unable to get skeletonObject"));
643  return Matrix4x4();
644  }
645 
646  Skeleton* skeleton = PluginFunctions::skeleton(obj);
647  Skeleton::Joint* joint = skeleton->joint(_jointId);
648 
649  if (joint == 0) {
650  emit log(LOGERR, tr("Unable to get joint"));
651  return Matrix4x4();
652  }
653 
654  AnimationHandle handle = skeletonObj->skeletonNode()->activePose();
655 
656  Skeleton::Pose* activePose;
657 
658  if (!handle.isValid())
659  activePose = skeleton->referencePose();
660  else
661  activePose = skeleton->animation(handle.animationIndex())->pose(
662  handle.frame());
663 
664  emit scriptInfo("localMatrix( ObjectId, " + QString::number(_jointId) + " )");
665  return activePose->localMatrix(joint->id());
666 }
667 
668 //------------------------------------------------------------------------------
669 
671 Vector SkeletonEditingPlugin::globalTranslation(int _objectId, int _jointId) {
672 
673  BaseObjectData* obj = 0;
674 
675  PluginFunctions::getObject(_objectId, obj);
676 
677  if (obj == 0) {
678  emit log(LOGERR, tr("Unable to get object"));
679  return Vector();
680  }
681 
683 
684  if (skeletonObj == 0) {
685  emit log(LOGERR, tr("Unable to get skeletonObject"));
686  return Vector();
687  }
688 
689  Skeleton* skeleton = PluginFunctions::skeleton(obj);
690  Skeleton::Joint* joint = skeleton->joint(_jointId);
691 
692  if (joint == 0) {
693  emit log(LOGERR, tr("Unable to get joint"));
694  return Vector();
695  }
696 
697  AnimationHandle handle = skeletonObj->skeletonNode()->activePose();
698 
699  Skeleton::Pose* activePose;
700 
701  if (!handle.isValid())
702  activePose = skeleton->referencePose();
703  else
704  activePose = skeleton->animation(handle.animationIndex())->pose(
705  handle.frame());
706 
707  emit scriptInfo(
708  "globalTranslation( ObjectId, " + QString::number(_jointId) + " )");
709  return activePose->globalTranslation(joint->id());
710 }
711 
712 //------------------------------------------------------------------------------
713 
715 Vector SkeletonEditingPlugin::localTranslation(int _objectId, int _jointId) {
716 
717  BaseObjectData* obj = 0;
718 
719  PluginFunctions::getObject(_objectId, obj);
720 
721  if (obj == 0) {
722  emit log(LOGERR, tr("Unable to get object"));
723  return Vector();
724  }
725 
727 
728  if (skeletonObj == 0) {
729  emit log(LOGERR, tr("Unable to get skeletonObject"));
730  return Vector();
731  }
732 
733  Skeleton* skeleton = PluginFunctions::skeleton(obj);
734  Skeleton::Joint* joint = skeleton->joint(_jointId);
735 
736  if (joint == 0) {
737  emit log(LOGERR, tr("Unable to get joint"));
738  return Vector();
739  }
740 
741  AnimationHandle handle = skeletonObj->skeletonNode()->activePose();
742 
743  Skeleton::Pose* activePose;
744 
745  if (!handle.isValid())
746  activePose = skeleton->referencePose();
747  else
748  activePose = skeleton->animation(handle.animationIndex())->pose(
749  handle.frame());
750 
751  emit scriptInfo(
752  "localTranslation( ObjectId, " + QString::number(_jointId) + " )");
753  return activePose->localTranslation(joint->id());
754 }
755 
756 //------------------------------------------------------------------------------
757 
760 
761  BaseObjectData* obj = 0;
762 
763  PluginFunctions::getObject(_objectId, obj);
764 
765  if (obj == 0) {
766  emit log(LOGERR, tr("Unable to get object"));
767  return -1;
768  }
769 
771 
772  if (skeletonObj == 0) {
773  emit log(LOGERR, tr("Unable to get skeletonObject"));
774  return -1;
775  }
776 
777  Skeleton* skeleton = PluginFunctions::skeleton(obj);
778 
779  emit scriptInfo("animationCount( ObjectId )");
780  return skeleton->animationCount();
781 }
782 
783 //------------------------------------------------------------------------------
784 
786 int SkeletonEditingPlugin::frameCount(int _objectId, int _animationIndex) {
787 
788  BaseObjectData* obj = 0;
789 
790  PluginFunctions::getObject(_objectId, obj);
791 
792  if (obj == 0) {
793  emit log(LOGERR, tr("Unable to get object"));
794  return -1;
795  }
796 
798 
799  if (skeletonObj == 0) {
800  emit log(LOGERR, tr("Unable to get skeletonObject"));
801  return -1;
802  }
803 
804  Skeleton* skeleton = PluginFunctions::skeleton(obj);
805 
806  if ((_animationIndex < 0) || (_animationIndex
807  > (int) skeleton->animationCount())) {
808  emit log(LOGERR, tr("Invalid animationIndex"));
809  return -1;
810  }
811 
812  emit scriptInfo(
813  "frameCount( ObjectId, " + QString::number(_animationIndex) + " )");
814  return skeleton->animation(_animationIndex)->frameCount();
815 }
816 
817 //------------------------------------------------------------------------------
818 
821 
822  BaseObjectData* obj = 0;
823 
824  PluginFunctions::getObject(_objectId, obj);
825 
826  if (obj == 0) {
827  emit log(LOGERR, tr("Unable to get object"));
828  return -1;
829  }
830 
832 
833  if (skeletonObj == 0) {
834  emit log(LOGERR, tr("Unable to get skeletonObject"));
835  return -1;
836  }
837 
838  AnimationHandle handle = skeletonObj->skeletonNode()->activePose();
839 
840  emit scriptInfo("activeAnimation( ObjectId )");
841  return handle.animationIndex();
842 }
843 
844 //------------------------------------------------------------------------------
845 
848  BaseObjectData* obj = 0;
849 
850  PluginFunctions::getObject(_objectId, obj);
851 
852  if (obj == 0) {
853  emit log(LOGERR, tr("Unable to get object"));
854  return -1;
855  }
856 
858 
859  if (skeletonObj == 0) {
860  emit log(LOGERR, tr("Unable to get skeletonObject"));
861  return -1;
862  }
863 
864  AnimationHandle handle = skeletonObj->skeletonNode()->activePose();
865 
866  emit scriptInfo("activeFrame( ObjectId )");
867  return handle.frame();
868 }
869 
870 //------------------------------------------------------------------------------
871 
873 void SkeletonEditingPlugin::setActivePose(int _objectId, int _animationIndex,
874  int _frame) {
875  BaseObjectData* obj = 0;
876 
877  PluginFunctions::getObject(_objectId, obj);
878 
879  if (obj == 0) {
880  emit log(LOGERR, tr("Unable to get object"));
881  return;
882  }
883 
885 
886  if (skeletonObj == 0) {
887  emit log(LOGERR, tr("Unable to get skeletonObject"));
888  return;
889  }
890 
891  Skeleton* skeleton = PluginFunctions::skeleton(obj);
892 
893  if ((_animationIndex < 0) || (_animationIndex
894  > (int) skeleton->animationCount())) {
895  emit log(LOGERR, tr("Invalid animationIndex"));
896  return;
897  }
898 
899  if ((_frame < 0) || (_frame
900  > (int) skeleton->animation(_animationIndex)->frameCount())) {
901  emit log(LOGERR, tr("Invalid frame"));
902  return;
903  }
904 
905  skeletonObj->skeletonNode()->setActivePose(
906  AnimationHandle(_animationIndex, _frame));
907  emit updatedObject(_objectId, UPDATE_GEOMETRY);
908 
909  emit scriptInfo(
910  "setActivePose( ObjectId, " + QString::number(_animationIndex) + ", "
911  + QString::number(_frame) + ")");
912 }
913 
914 //------------------------------------------------------------------------------
915 
917 void SkeletonEditingPlugin::addAnimation(int _objectId, QString _name,
918  int _frames) {
919  BaseObjectData* obj = 0;
920 
921  PluginFunctions::getObject(_objectId, obj);
922 
923  if (obj == 0) {
924  emit log(LOGERR, tr("Unable to get object"));
925  return;
926  }
927 
929 
930  if (skeletonObj == 0) {
931  emit log(LOGERR, tr("Unable to get skeletonObject"));
932  return;
933  }
934 
935  Skeleton* skeleton = PluginFunctions::skeleton(obj);
936 
937  if (_frames <= 0) {
938  emit log(LOGERR, tr("Invalid frame count"));
939  return;
940  }
941 
942  std::string stdName = _name.toStdString();
943 
944  if (skeleton->animation(stdName) != 0) {
945  emit log(LOGERR, tr("Animation with this name already exists"));
946  return;
947  }
948 
950  skeleton, _frames);
951  AnimationHandle handle = skeleton->addAnimation(stdName, animation);
952 
953  //init pose to refPose
954  for (unsigned int i = 0; i < skeleton->animation(handle)->frameCount(); i++) {
955  handle.setFrame(i);
956  Skeleton::Pose* pose = skeleton->pose(handle);
957 
958  for (unsigned int j = 0; j < skeleton->jointCount(); j++)
959  pose->setGlobalMatrix(j, skeleton->referencePose()->globalMatrix(j));
960  }
961 
962  emit updatedObject(_objectId, UPDATE_ALL);
963  emit scriptInfo(
964  "addAnimation( ObjectId, " + _name + ", " + QString::number(_frames)
965  + ")");
966 
967  // Create backup
968  emit createBackup(_objectId, "Add Animation", UPDATE_ALL);
969 }
970 
971 //------------------------------------------------------------------------------
Matrix4x4 globalMatrix(int _objectId, int _jointId)
get global matrix of a joint in the active pose
Matrix4x4 localMatrix(int _objectId, int _jointId)
get local matrix of a joint in the active pose
Pose * pose(unsigned int _iFrame)
Returns a pointer to the pose stored in the given frame.
void setGlobalTranslation(unsigned int _joint, const Vector &_position, bool _keepGlobalChildPositions=true)
Sets the global translation vector.
Definition: PoseT.cc:255
unsigned int animationIndex() const
Returns the animation index (zero based)
int frameCount(int _objectId, int _animationIndex)
get the number of frames
Represents a single joint in the skeleton.
Definition: JointT.hh:66
Joint * child(size_t _index)
Returns the child joint with the given index.
Definition: JointT.cc:217
unsigned int frameCount()
Returns the number of frames stored in this pose.
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(1)<< 3)
Topology updated.
virtual void functionExists(QString _pluginName, QString _functionName, bool &_exists)
Definition: RPCInterface.hh:93
bool getObject(int _identifier, BSplineCurveObject *&_object)
Vector globalTranslation(unsigned int _joint)
Returns the global translation vector.
Definition: PoseT.cc:233
void addJoint(int _objectId, int _parent, Vector _position)
add joint to the skeleton
void setParent(Joint *_newParent, SkeletonT< PointT > &_skeleton)
access parent of the joint
Definition: JointT.cc:128
void transformJoint(int _objectId, int _jointId, Matrix4x4 _matrix)
transform joint with given matrix
const Matrix & globalMatrix(unsigned int _joint) const
Returns the global matrix for the given joint.
Definition: PoseT.cc:199
ACG::Matrix4x4d Matrix4x4
Standard Type for a 4x4 Matrix used for scripting.
Definition: DataTypes.hh:194
int activeFrame(int _objectId)
get active frame
Skeleton transformation class.
bool isValid() const
Returns true if the handle is valid.
void setActivePose(int _objectId, int _animationIndex, int _frame)
set active pose
unsigned int id()
returns the joint id
Definition: JointT.cc:103
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
Definition: GLMatrixT.cc:161
A general pose, used to store the frames of the animation.
Definition: PoseT.hh:68
Animation * animation(std::string _name)
Returns a pointer to the animation to the given name.
Definition: SkeletonT.cc:858
void rotateJoint(Skeleton::Joint *_joint, Skeleton::Pose *_pose, Matrix4x4 _rotation, bool _applyToWholeAnimation=true)
rotate a joint in an arbitrary Pose
const Matrix & localMatrix(unsigned int _joint) const
Returns the local matrix for the given joint.
Definition: PoseT.cc:110
A handle used to refer to an animation or to a specific frame in an animation.
bool is_identity() const
check if the matrix is the identity ( up to an epsilon )
Definition: Matrix4x4T.hh:220
void identity()
setup an identity matrix
Definition: Matrix4x4T.cc:256
void addAnimation(int _objectId, QString _name, int _frames)
add animation
Vector localTranslation(unsigned int _joint)
Returns the local translation vector.
Definition: PoseT.cc:145
SkeletonObject * skeletonObject(BaseObjectData *_object)
Cast an BaseObject to a SkeletonObject if possible.
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
void transformJoint(Skeleton::Joint *_joint, Matrix4x4 _matrix, bool _keepChildPositions=true)
apply a transformation to a joint in the refPose
void addJoint(typename SkeletonT< PointT >::Joint *_pParent, typename SkeletonT< PointT >::Joint *_pJoint)
Adds a joint as child of a given parent joint.
Definition: SkeletonT.cc:494
unsigned int animationCount()
Returns the number of animations stored in this skeleton.
Definition: SkeletonT.cc:971
ACG::Vec3d Vector
Standard Type for 3d Vector used for scripting.
Definition: DataTypes.hh:187
Joint * parent()
Returns the parent joint.
Definition: JointT.cc:162
Pose * pose(const AnimationHandle &_hAni)
Returns a pointer to the pose with the given animation handle.
Definition: SkeletonT.cc:741
ACG::SceneGraph::SkeletonNodeT< Skeleton > * skeletonNode()
Returns the skeleton scenegraph node.
Vector localTranslation(int _objectId, int _jointId)
get local translation of a joint in the active pose
Skeleton * skeleton(BaseObjectData *_object)
Get a skeleton from an object.
void setDescriptions()
Set Descriptions for Scripting Slots.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
Vector globalTranslation(int _objectId, int _jointId)
get global translation of a joint in the active pose
Joint * joint(const unsigned int &_index)
Returns the joint with the given index.
Definition: SkeletonT.cc:642
void splitBone(int _objectId, int _tailJoint)
insert a joint in the middle of a bone given by its (unique) tailJoint
size_t size()
Returns the number of children.
Definition: JointT.cc:203
int animationCount(int _objectId)
get the number of animations
void removeJoint(typename SkeletonT< PointT >::Joint *_pJoint)
Remove the given joint from the tree.
Definition: SkeletonT.cc:538
void translateJoint(Skeleton::Joint *_joint, ACG::Vec3d _translation, bool _keepChildPositions=true)
apply a translation to a joint in the refPose
int activeAnimation(int _objectId)
get active animation
QScriptValue callFunction(QString _plugin, QString _functionName, std::vector< QScriptValue > _parameters)
Call a function provided by a plugin getting multiple parameters.
Definition: RPCWrappers.cc:63
void setGlobalMatrix(unsigned int _joint, const Matrix &_global, bool _keepGlobalChildPositions=true)
Sets the global coordinate system.
Definition: PoseT.cc:217
void setLocalMatrix(unsigned int _joint, const Matrix &_local, bool _keepLocalChildPositions=true)
Sets the local coordinate system.
Definition: PoseT.cc:126
Pose * referencePose()
Returns a pointer to the reference pose.
Definition: SkeletonT.cc:761
unsigned int frame() const
Returns the selected frame (zero based)