Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
52 #include <OpenFlipper/BasePlugin/PluginFunctions.hh>
53 #include <ObjectTypes/Skeleton/Helper/SkeletonTransform.hh>
54 #include <ACG/Geometry/Algorithms.hh>
55
56 //------------------------------------------------------------------------------
57
61 void SkeletonEditingPlugin::setDescriptions() {
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
318 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(obj);
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
595 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(obj);
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
639 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(obj);
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
682 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(obj);
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
726 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(obj);
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
759 int SkeletonEditingPlugin::animationCount(int _objectId) {
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
770 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(obj);
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
797 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(obj);
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
820 int SkeletonEditingPlugin::activeAnimation(int _objectId) {
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
831 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(obj);
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
847 int SkeletonEditingPlugin::activeFrame(int _objectId) {
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
857 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(obj);
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
884 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(obj);
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
928 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(obj);
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
949 FrameAnimationT<ACG::Vec3d>* animation = new FrameAnimationT<ACG::Vec3d> (
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 //------------------------------------------------------------------------------
AnimationHandle::isValid
bool isValid() const
Returns true if the handle is valid.
Definition: AnimationHandle.hh:64
PoseT::setGlobalMatrix
void setGlobalMatrix(unsigned int _joint, const Matrix &_global, bool _keepGlobalChildPositions=true)
Sets the global coordinate system.
Definition: PoseT.cc:217
PoseT::setGlobalTranslation
void setGlobalTranslation(unsigned int _joint, const Vector &_position, bool _keepGlobalChildPositions=true)
Sets the global translation vector.
Definition: PoseT.cc:255
ACG::Matrix4x4T::is_identity
bool is_identity() const
check if the matrix is the identity ( up to an epsilon )
Definition: Matrix4x4T.hh:220
PluginFunctions::skeletonObject
SkeletonObject * skeletonObject(BaseObjectData *_object)
Cast an BaseObject to a SkeletonObject if possible.
Definition: PluginFunctionsSkeleton.cc:105
UPDATE_GEOMETRY
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
SkeletonEditingPlugin::globalMatrix
Matrix4x4 globalMatrix(int _objectId, int _jointId)
get global matrix of a joint in the active pose
Definition: SkeletonEditingScripting.cc:584
SkeletonEditingPlugin::localMatrix
Matrix4x4 localMatrix(int _objectId, int _jointId)
get local matrix of a joint in the active pose
Definition: SkeletonEditingScripting.cc:628
SkeletonEditingPlugin::globalTranslation
Vector globalTranslation(int _objectId, int _jointId)
get global translation of a joint in the active pose
Definition: SkeletonEditingScripting.cc:671
LOGERR
Definition: LoggingInterface.hh:107
BaseObjectData
Definition: BaseObjectData.hh:105
SkeletonT::addJoint
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
RPCInterface::functionExists
virtual void functionExists(QString _pluginName, QString _functionName, bool &_exists)
Definition: RPCInterface.hh:93
SkeletonEditingPlugin::setDescriptions
void setDescriptions()
Set Descriptions for Scripting Slots.
Definition: SkeletonEditingScripting.cc:61
UPDATE_ALL
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
PluginFunctions::getObject
bool getObject(int _identifier, BSplineCurveObject *&_object)
Definition: PluginFunctionsBSplineCurve.cc:75
SkeletonT::pose
Pose * pose(const AnimationHandle &_hAni)
Returns a pointer to the pose with the given animation handle.
Definition: SkeletonT.cc:741
SkeletonTransform
Skeleton transformation class.
Definition: SkeletonTransform.hh:64
SkeletonEditingPlugin::addAnimation
void addAnimation(int _objectId, QString _name, int _frames)
add animation
Definition: SkeletonEditingScripting.cc:917
Matrix4x4
ACG::Matrix4x4d Matrix4x4
Standard Type for a 4x4 Matrix used for scripting.
Definition: DataTypes.hh:194
PoseT::localTranslation
Vector localTranslation(unsigned int _joint)
Returns the local translation vector.
Definition: PoseT.cc:145
SkeletonT::referencePose
Pose * referencePose()
Returns a pointer to the reference pose.
Definition: SkeletonT.cc:761
JointT::child
Joint * child(size_t _index)
Returns the child joint with the given index.
Definition: JointT.cc:217
SkeletonT::animation
Animation * animation(std::string _name)
Returns a pointer to the animation to the given name.
Definition: SkeletonT.cc:858
SkeletonObject
Definition: SkeletonObject.hh:82
PoseT
A general pose, used to store the frames of the animation.
Definition: PoseT.hh:68
AnimationHandle::animationIndex
unsigned int animationIndex() const
Returns the animation index (zero based)
Definition: AnimationHandle.hh:66
SkeletonT::joint
Joint * joint(const unsigned int &_index)
Returns the joint with the given index.
Definition: SkeletonT.cc:642
SkeletonT::removeJoint
void removeJoint(typename SkeletonT< PointT >::Joint *_pJoint)
Remove the given joint from the tree.
Definition: SkeletonT.cc:538
ACG::GLMatrixT< double >
Vector
ACG::Vec3d Vector
Standard Type for 3d Vector used for scripting.
Definition: DataTypes.hh:187
PoseT::localMatrix
const Matrix & localMatrix(unsigned int _joint) const
Returns the local matrix for the given joint.
Definition: PoseT.cc:110
FrameAnimationT::pose
Pose * pose(unsigned int _iFrame)
Returns a pointer to the pose stored in the given frame.
Definition: FrameAnimationT.cc:151
JointT::parent
Joint * parent()
Returns the parent joint.
Definition: JointT.cc:162
OpenMesh::VectorT
Definition: Vector11T.hh:83
SkeletonT::animationCount
unsigned int animationCount()
Returns the number of animations stored in this skeleton.
Definition: SkeletonT.cc:971
RPC::callFunction
QScriptValue callFunction(QString _plugin, QString _functionName, std::vector< QScriptValue > _parameters)
Call a function provided by a plugin getting multiple parameters.
Definition: RPCWrappers.cc:63
ACG::GLMatrixT::rotate
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
Definition: GLMatrixT.cc:161
SkeletonT
Definition: JointT.hh:56
PoseT::globalTranslation
Vector globalTranslation(unsigned int _joint)
Returns the global translation vector.
Definition: PoseT.cc:233
AnimationHandle::frame
unsigned int frame() const
Returns the selected frame (zero based)
Definition: AnimationHandle.hh:69
UPDATE_TOPOLOGY
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(1)<< 3)
Topology updated.
SkeletonEditingPlugin::splitBone
void splitBone(int _objectId, int _tailJoint)
insert a joint in the middle of a bone given by its (unique) tailJoint
Definition: SkeletonEditingScripting.cc:152
ACG::Matrix4x4T::identity
void identity()
setup an identity matrix
Definition: Matrix4x4T.cc:256
PoseT::setLocalMatrix
void setLocalMatrix(unsigned int _joint, const Matrix &_local, bool _keepLocalChildPositions=true)
Sets the local coordinate system.
Definition: PoseT.cc:126
JointT::id
unsigned int id()
returns the joint id
Definition: JointT.cc:103
AnimationHandle
A handle used to refer to an animation or to a specific frame in an animation.
Definition: AnimationHandle.hh:56
SkeletonEditingPlugin::animationCount
int animationCount(int _objectId)
get the number of animations
Definition: SkeletonEditingScripting.cc:759
SkeletonEditingPlugin::setActivePose
void setActivePose(int _objectId, int _animationIndex, int _frame)
set active pose
Definition: SkeletonEditingScripting.cc:873
JointT::size
size_t size()
Returns the number of children.
Definition: JointT.cc:203
SkeletonEditingPlugin::transformJoint
void transformJoint(int _objectId, int _jointId, Matrix4x4 _matrix)
transform joint with given matrix
Definition: SkeletonEditingScripting.cc:306
AnimationT< ACG::Vec3d >
PluginFunctions.hh
PoseT::globalMatrix
const Matrix & globalMatrix(unsigned int _joint) const
Returns the global matrix for the given joint.
Definition: PoseT.cc:199
SkeletonEditingPlugin::localTranslation
Vector localTranslation(int _objectId, int _jointId)
get local translation of a joint in the active pose
Definition: SkeletonEditingScripting.cc:715
SkeletonEditingPlugin::activeFrame
int activeFrame(int _objectId)
get active frame
Definition: SkeletonEditingScripting.cc:847
SkeletonTransform::transformJoint
void transformJoint(Skeleton::Joint *_joint, Matrix4x4 _matrix, bool _keepChildPositions=true)
apply a transformation to a joint in the refPose
Definition: SkeletonTransform.cc:192
SkeletonTransform::rotateJoint
void rotateJoint(Skeleton::Joint *_joint, Skeleton::Pose *_pose, Matrix4x4 _rotation, bool _applyToWholeAnimation=true)
rotate a joint in an arbitrary Pose
Definition: SkeletonTransform.cc:291
PluginFunctions::skeleton
Skeleton * skeleton(BaseObjectData *_object)
Get a skeleton from an object.
Definition: PluginFunctionsSkeleton.cc:86
JointT
Represents a single joint in the skeleton.
Definition: JointT.hh:66
SkeletonTransform::translateJoint
void translateJoint(Skeleton::Joint *_joint, ACG::Vec3d _translation, bool _keepChildPositions=true)
apply a translation to a joint in the refPose
Definition: SkeletonTransform.cc:271
JointT::setParent
void setParent(Joint *_newParent, SkeletonT< PointT > &_skeleton)
access parent of the joint
Definition: JointT.cc:128
ACG::Matrix4x4T< double >
SkeletonObject::skeletonNode
ACG::SceneGraph::SkeletonNodeT< Skeleton > * skeletonNode()
Returns the skeleton scenegraph node.
Definition: SkeletonObject.cc:218
FrameAnimationT
Definition: FrameAnimationT.hh:56
SkeletonEditingPlugin::frameCount
int frameCount(int _objectId, int _animationIndex)
get the number of frames
Definition: SkeletonEditingScripting.cc:786
SkeletonEditingPlugin::addJoint
void addJoint(int _objectId, int _parent, Vector _position)
add joint to the skeleton
Definition: SkeletonEditingScripting.cc:224
SkeletonEditingPlugin::activeAnimation
int activeAnimation(int _objectId)
get active animation
Definition: SkeletonEditingScripting.cc:820
FrameAnimationT::frameCount
unsigned int frameCount()
Returns the number of frames stored in this pose.
Definition: FrameAnimationT.cc:161