changed: gcc8 base update
[opensg.git] / Source / System / FileIO / Collada / OSGColladaController.cpp
blob8c57d3bf9478f700dddb7c160afbce022efc9201
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2009 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 #if __GNUC__ >= 4 || __GNUC_MINOR__ >=3
40 #pragma GCC diagnostic ignored "-Wold-style-cast"
41 #endif
43 #include "OSGColladaController.h"
45 #ifdef OSG_WITH_COLLADA
47 #include "OSGColladaLog.h"
48 #include "OSGColladaGlobal.h"
49 #include "OSGColladaInstanceController.h"
50 #include "OSGColladaSource.h"
51 #include "OSGColladaNode.h"
52 #include "OSGGroup.h"
53 #include "OSGTransform.h"
54 #include "OSGSkinnedGeometry.h"
55 #include "OSGSkeletonJoint.h"
56 #include "OSGNameAttachment.h"
57 #include "OSGFieldContainerUtils.h"
59 #include "OSGTypedGeoVectorProperty.h"
61 #include <dom/domController.h>
62 #include <dom/domGeometry.h>
64 #include <set>
66 OSG_BEGIN_NAMESPACE
68 ColladaInstInfoTransitPtr
69 ColladaController::ColladaControllerInstInfo::create(
70 ColladaNode *colInstParent, ColladaInstanceController *colInst,
71 Node *parentN )
73 return ColladaInstInfoTransitPtr(
74 new ColladaControllerInstInfo(colInstParent, colInst, parentN));
77 void
78 ColladaController::ColladaControllerInstInfo::process(void)
80 Node *ctrlInstN = dynamic_cast<Node *>(
81 getColInst()->getTargetElem()->createInstance(this));
83 getParentNode()->addChild(ctrlInstN);
86 ColladaController::ColladaControllerInstInfo::ColladaControllerInstInfo(
87 ColladaNode *colInstParent, ColladaInstanceController *colInst,
88 Node *parentN )
90 : Inherited(colInstParent, colInst)
91 , _parentN (parentN )
95 ColladaController::ColladaControllerInstInfo::~ColladaControllerInstInfo(void)
99 // ===========================================================================
101 ColladaElementRegistrationHelper ColladaController::_regHelper(
102 &ColladaController::create, "controller");
105 ColladaElementTransitPtr
106 ColladaController::create(daeElement *elem, ColladaGlobal *global)
108 return ColladaElementTransitPtr(new ColladaController(elem, global));
111 void
112 ColladaController::read(ColladaElement *colElemParent)
114 domControllerRef ctrl = getDOMElementAs<domController>();
115 domSkinRef skin = ctrl->getSkin();
117 OSG_COLLADA_LOG(("ColladaController::read id [%s]\n", ctrl->getId()));
119 if(skin == NULL)
121 SWARNING << "ColladaController::read: No <skin>" << std::endl;
122 return;
125 readSkin(skin);
128 Node *
129 ColladaController::createInstance(ColladaInstInfo *colInstInfo)
131 typedef ColladaInstanceController::MaterialMap ColMaterialMap;
132 typedef ColladaInstanceController::MaterialMapConstIt ColMaterialMapConstIt;
134 domControllerRef ctrl = getDOMElementAs<domController>();
136 OSG_COLLADA_LOG(("ColladaController::createInstance id [%s]\n",
137 ctrl->getId()));
139 domSkinRef skin = ctrl->getSkin();
140 NodeUnrecPtr groupN = makeCoredNode<Group>();
141 ColladaInstanceControllerRefPtr colInstCtrl =
142 dynamic_cast<ColladaInstanceController *>(colInstInfo->getColInst());
144 if(getGlobal()->getOptions()->getCreateNameAttachments() == true &&
145 ctrl->getName() != NULL )
147 setName(groupN, ctrl->getName());
150 // create Skeleton
152 // find all joints and store them in jointStore
153 JointInfoStore jointStore;
154 JointIdMap jointIdMap;
155 resolveJoints(skin, colInstCtrl, jointStore, jointIdMap);
156 remapJointIds(skin, colInstCtrl, jointStore, jointIdMap);
158 // create SkinnedGeometry
160 const ColMaterialMap &matMap = colInstCtrl->getMaterialMap();
162 // iterate over all parts of geometry
163 GeoStoreIt gsIt = _geoStore.begin();
164 GeoStoreIt gsEnd = _geoStore.end ();
166 for(; gsIt != gsEnd; ++gsIt)
168 OSG_ASSERT(gsIt->_propStore.size() == gsIt->_indexStore.size());
170 // find the material associated with the geometry's material symbol
171 ColMaterialMapConstIt mmIt = matMap.find(gsIt->_matSymbol);
172 std::string matTarget;
174 if(mmIt != matMap.end())
176 matTarget = mmIt->second->getTarget();
179 // can't reuse SkinnedGeometry, it may be instantiated with
180 // a different Skeleton
182 // create new geometry
183 SkinnedGeometryUnrecPtr geo = SkinnedGeometry::create();
185 getGlobal()->getStatCollector()->getElem(
186 ColladaGlobal::statNGeometryCreated)->inc();
188 geo->setLengths(gsIt->_lengths);
189 geo->setTypes (gsIt->_types );
191 Inherited::handleBindMaterial(*gsIt, geo, colInstCtrl);
193 geo->setSkeleton (_skeleton );
194 geo->setBindShapeMatrix(_matBindShape );
195 geo->setRenderMode (SkinnedGeometry::RMSkinnedGPU);
197 PropStoreConstIt psIt = (*gsIt)._propStore .begin();
198 PropStoreConstIt psEnd = (*gsIt)._propStore .end ();
200 for(; psIt != psEnd; ++psIt)
202 if((*psIt)._semantic == "JOINT_INDEX")
204 for(UInt16 i = 0; i < geo->getMFProperties()->size(); ++i)
206 if((*psIt)._prop == geo->getProperty(i))
208 geo->setJointIndexProperty(i);
209 break;
214 if((*psIt)._semantic == "JOINT_WEIGHT")
216 for(UInt16 i = 0; i < geo->getMFProperties()->size(); ++i)
218 if((*psIt)._prop == geo->getProperty(i))
220 geo->setJointWeightProperty(i);
221 break;
228 NodeUnrecPtr geoN = makeNodeFor(geo);
230 groupN->addChild(geoN);
233 // store the generated group node
234 editInstStore().push_back(groupN);
236 return groupN;
239 ColladaController::ColladaController(daeElement *elem, ColladaGlobal *global)
240 : Inherited (elem, global)
241 , _matBindShape()
242 , _skeleton (NULL)
246 ColladaController::~ColladaController(void)
250 void
251 ColladaController::readSkin(domSkin *skin)
253 daeURI geoURI = skin->getSource();
254 domGeometryRef geo = daeSafeCast<domGeometry>(geoURI.getElement());
256 if(geo == NULL)
258 SWARNING << "ColladaController::readSkin: Could not resolve source "
259 << "URI [" << geoURI.str() << "] to a <geometry>"
260 << std::endl;
261 return;
264 domMeshRef mesh = geo->getMesh();
266 if(mesh == NULL)
268 SWARNING << "ColladaController::readSkin: No <mesh> in <geometry>"
269 << std::endl;
270 return;
273 Inherited::readMesh(mesh);
275 readBindShapeMatrix(skin);
277 Inherited::readSources(skin->getSource_array());
279 // evaluate <vertex_weights>
280 domSkin::domVertex_weightsRef vweights = skin->getVertex_weights();
281 const domInputLocalOffset_Array &inputs = vweights->getInput_array();
283 UInt32 jointIdx = UInt32(inputs.getCount());
284 ColladaSourceRefPtr weightSrc = NULL;
286 for(UInt32 i = 0; i < inputs.getCount(); ++i)
288 std::string semantic = inputs[i]->getSemantic();
289 std::string sourceId = inputs[i]->getSource ().id();
290 UInt32 offset = inputs[i]->getOffset ();
292 SourceMapConstIt smIt = _sourceMap.find(sourceId);
294 if(smIt == _sourceMap.end())
296 SWARNING << "ColladaController::readSkin: Could not find "
297 << "<source> with id [" << sourceId << "] used by "
298 << "<input> [" << i << "] with semantic ["
299 << semantic << "]. Ignored." << std::endl;
300 continue;
303 if(semantic == "JOINT")
305 // which item of the index tuples in <v> hold the joint
306 jointIdx = offset;
308 else if(semantic == "WEIGHT")
310 weightSrc = smIt->second;
314 // test if the file has the "usual" form, and only handle that
315 // this means there is an <input> with semantic "JOINT" and
316 // one with semantic "WEIGHT"
317 if(jointIdx < inputs.getCount() && weightSrc != NULL &&
318 inputs.getCount() == 2 )
320 GeoVec4fPropertyUnrecPtr jIndexProp = GeoVec4fProperty::create();
321 GeoVec4fPropertyUnrecPtr jWeightProp = GeoVec4fProperty::create();
323 GeoVec4fProperty::StoredFieldType *jIndexPropF =
324 jIndexProp ->editFieldPtr();
325 GeoVec4fProperty::StoredFieldType *jWeightPropF =
326 jWeightProp->editFieldPtr();
328 const domListOfUInts &vcount = vweights->getVcount()->getValue();
329 const domListOfInts &v = vweights->getV ()->getValue();
331 UInt32 vIdx = 0;
333 for(UInt32 i = 0; i < vcount.getCount(); ++i)
335 Vec4f jIndex;
336 Vec4f jWeight;
338 if(vcount[i] > 4)
340 SWARNING << "ColladaController::readSkin: Vertex [" << i
341 << "] has [" << vcount[i] << "] > 4 weights."
342 << std::endl;
345 UInt32 j;
347 // the current vertex i is influenced by vcount[i] many joints
348 for(j = 0; j < osgMin<UInt32>(4, vcount[i]); ++j)
350 jIndex [j] = v[vIdx];
351 jWeight[j] = weightSrc->getFloatValue(v[vIdx + 1]);
353 vIdx += 2;
356 #if 0
357 OSG_COLLADA_LOG(("ColladaController::readSkin: vert [%d] "
358 "jIndex [%f %f %f %f] jWeight [%f %f %f %f]\n",
359 i, jIndex[0], jIndex[1], jIndex[2], jIndex[3],
360 jWeight[0], jWeight[1], jWeight[2], jWeight[3]));
361 #endif
363 jIndexPropF ->push_back(jIndex );
364 jWeightPropF->push_back(jWeight);
366 // skip joint/weight indices we can not store (if any)
367 for(j = osgMin<UInt32>(4, vcount[i]); j < vcount[i]; ++j)
369 vIdx += 2;
373 OSG_COLLADA_LOG(("ColladaController::readSkin: "
374 "jIndexProp.size() [%" PRIUSize "] "
375 "jWeightProp.size() [%" PRIUSize "]\n",
376 jIndexProp->size(),
377 jWeightProp->size()));
379 // add jIndexProp and jWeightProp to geoInfos
380 GeoStore::iterator gsIt = _geoStore.begin();
381 GeoStore::iterator gsEnd = _geoStore.end ();
383 for(UInt32 i = 0; gsIt != gsEnd; ++gsIt, ++i)
385 // add joint index property
386 UInt16 propSlot = Inherited::findFreePropertyIndex(i);
387 gsIt->_propStore.resize (
388 osgMax<UInt16>(UInt16(gsIt->_propStore .size()), propSlot + 1), PropInfo());
389 gsIt->_indexStore.resize(
390 osgMax<UInt16>(UInt16(gsIt->_indexStore.size()), propSlot + 1), NULL );
392 gsIt->_propStore [propSlot]._prop = jIndexProp;
393 gsIt->_propStore [propSlot]._semantic = "JOINT_INDEX";
394 gsIt->_propStore [propSlot]._set = 0;
395 gsIt->_indexStore[propSlot] = gsIt->_indexStore[0];
397 // add weight property
398 propSlot = Inherited::findFreePropertyIndex(i);
399 gsIt->_propStore.resize (
400 osgMax<UInt16>(UInt16(gsIt->_propStore .size()), propSlot + 1), PropInfo());
401 gsIt->_indexStore.resize(
402 osgMax<UInt16>(UInt16(gsIt->_indexStore.size()), propSlot + 1), NULL );
404 gsIt->_propStore [propSlot]._prop = jWeightProp;
405 gsIt->_propStore [propSlot]._semantic = "JOINT_WEIGHT";
406 gsIt->_propStore [propSlot]._set = 0;
407 gsIt->_indexStore[propSlot] = gsIt->_indexStore[0];
410 else
412 SWARNING << "ColladaController::readSkin: Can only handle "
413 << "<vertex_weights> with JOINT and WEIGHT <input>s."
414 << std::endl;
418 void
419 ColladaController::readBindShapeMatrix(domSkin *skin)
421 domSkin::domBind_shape_matrixRef bsMat = skin->getBind_shape_matrix();
423 if(bsMat != NULL)
425 _matBindShape.setValue(bsMat->getValue()[ 0], bsMat->getValue()[ 1],
426 bsMat->getValue()[ 2], bsMat->getValue()[ 3],
427 bsMat->getValue()[ 4], bsMat->getValue()[ 5],
428 bsMat->getValue()[ 6], bsMat->getValue()[ 7],
429 bsMat->getValue()[ 8], bsMat->getValue()[ 9],
430 bsMat->getValue()[10], bsMat->getValue()[11],
431 bsMat->getValue()[12], bsMat->getValue()[13],
432 bsMat->getValue()[14], bsMat->getValue()[15] );
434 else
436 _matBindShape.setIdentity();
439 if(_matBindShape.equals(Matrix::identity(), Eps) == true)
440 return;
442 #if 0
443 // transform the properties by the bind shape matrix
445 Matrix matBindShapeIT(_matBindShape);
446 matBindShapeIT.invert ();
447 matBindShapeIT.transpose();
449 typedef std::set<GeoVectorProperty *> PropertySet;
450 PropertySet xformedProps;
452 GeoStore::iterator gsIt = _geoStore.begin();
453 GeoStore::iterator gsEnd = _geoStore.end ();
455 for(; gsIt != gsEnd; ++gsIt)
457 PropStoreIt psIt = gsIt->_propStore.begin();
458 PropStoreIt psEnd = gsIt->_propStore.end ();
460 for(; psIt != psEnd; ++psIt)
462 if(psIt->_prop == NULL)
463 continue;
465 // only transform once
466 if(xformedProps.count(psIt->_prop) > 0)
467 continue;
469 if(psIt->_semantic == "POSITION")
471 for(UInt32 i = 0; i < psIt->_prop->size(); ++i)
473 Pnt4f pnt;
475 psIt->_prop->getValue(pnt, i);
476 _matBindShape.mult(pnt, pnt);
477 psIt->_prop->setValue(pnt, i);
480 OSG_COLLADA_LOG(("ColladaController::readBindShapeMatrix: "
481 "Transformed property with semantic [%s]\n",
482 psIt->_semantic.c_str()));
484 else if(psIt->_semantic == "NORMAL")
486 for(UInt32 i = 0; i < psIt->_prop->size(); ++i)
488 Vec4f vec;
490 psIt->_prop->getValue(vec, i);
491 matBindShapeIT.mult(vec, vec);
492 psIt->_prop->setValue(vec, i);
495 OSG_COLLADA_LOG(("ColladaController::readBindShapeMatrix: "
496 "Transformed property with semantic [%s]\n",
497 psIt->_semantic.c_str()));
499 else
501 OSG_COLLADA_LOG(("ColladaController::readBindShapeMatrix: "
502 "Skipped property with semantic [%s]\n",
503 psIt->_semantic.c_str()));
506 xformedProps.insert(psIt->_prop);
509 #endif
512 void
513 ColladaController::resolveJoints(
514 domSkin *skin, ColladaInstanceController *colInstCtrl,
515 JointInfoStore &jointStore, JointIdMap &jointIdMap )
517 domControllerRef ctrl = getDOMElementAs<domController>();
518 domSkin::domJointsRef joints = skin->getJoints();
520 // find <input>s with handled semantics (JOINT and INV_BIND_MATRIX)
521 // everything else is ignored/warned about
523 ColladaSourceRefPtr jointSrc = NULL;
524 ColladaSourceRefPtr ibmSrc = NULL;
526 const domInputLocal_Array &jointInputs = joints->getInput_array();
528 for(UInt32 i = 0; i < jointInputs.getCount(); ++i)
530 std::string semantic = jointInputs[i]->getSemantic();
531 std::string sourceId = jointInputs[i]->getSource ().id();
533 SourceMapConstIt smIt = _sourceMap.find(sourceId);
535 if(smIt == _sourceMap.end())
537 SWARNING << "ColladaController::resolveJoints: Could not find "
538 << "<source> with id [" << sourceId << "] used by "
539 << "<input> [" << i << "] with semantic ["
540 << semantic << "]. Ignored." << std::endl;
541 continue;
544 if(semantic == "JOINT")
546 jointSrc = smIt->second;
548 else if(semantic == "INV_BIND_MATRIX")
550 ibmSrc = smIt->second;
552 else
554 SWARNING << "ColladaController::resolveJoints: Unknown semantic ["
555 << semantic << "] on <input> [" << i << "]"
556 << std::endl;
560 _skeleton = NULL;
562 // resolve joint names to <node>s and fill jointStore
564 if(jointSrc != NULL && ibmSrc != NULL)
566 const ColladaSource::NameStore &jointNames =
567 jointSrc->getNameStore ();
568 const ColladaSource::MatrixStore &invBindMats =
569 ibmSrc ->getMatrixStore();
571 OSG_ASSERT(jointNames.size() == invBindMats.size());
573 for(UInt32 i = 0; i < jointNames.size(); ++i)
575 JointInfo jointInfo;
576 // joint names are relative to the <skeleton> tags in the
577 // <instance_controller> element
579 domNode *jointNode = colInstCtrl->findJointNode(jointNames[i]);
581 if(jointNode == NULL)
583 SWARNING << "ColladaController::resolveJoints: Could not "
584 << "find <node> for joint name ["
585 << jointNames[i] << "] - <controller> ["
586 << (ctrl->getId() != NULL ? ctrl->getId() : "")
587 << "]. Ignored." << std::endl;
588 continue;
591 if(jointNode->getType() != NODETYPE_JOINT)
593 SWARNING << "ColladaController::resolveJoints: <node> for "
594 << "joint name [" << jointNames[i] << "] does not "
595 << "have node type JOINT. Ignored." << std::endl;
596 continue;
599 ColladaNode *colJointNode = getUserDataAs<ColladaNode>(jointNode);
600 OSG_ASSERT(colJointNode != NULL);
602 // store skeleton and ensure all joints belong to the same one
603 if(_skeleton != NULL)
605 if(_skeleton != colJointNode->getSkeleton())
607 SWARNING << "ColladaController::resolveJoints: joint ["
608 << i << "] name [" << jointNames[i]
609 << "] belongs to differente skeleton. Ignoring."
610 << std::endl;
611 continue;
614 else
616 _skeleton = colJointNode->getSkeleton();
619 if(colJointNode->getInstStore().size() > 1)
621 SWARNING << "ColladaController::resolveJoints: joint ["
622 << i << "] name [" << jointNames[i]
623 << "] has multiple instances. Using instance 0."
624 << std::endl;
627 SkeletonJoint *joint = dynamic_cast<SkeletonJoint *>(
628 colJointNode->getBottomNode(0)->getCore());
630 if(joint->getInvBindMatrix().equals(Matrix::identity(), Eps) == true)
632 joint->setInvBindMatrix(invBindMats[i]);
634 else if(joint->getInvBindMatrix().equals(invBindMats[i], Eps) == false)
636 SWARNING << "ColladaController::resolveJoints: joint ["
637 << i << "] name [" << jointNames[i]
638 << "] already has a different inv bind matrix."
639 << std::endl;
642 jointInfo.jointNode = jointNode;
643 jointInfo.colJointNode = colJointNode;
644 jointInfo.jointId = joint->getJointId();
645 jointInfo.invBindMatrix = invBindMats[i];
647 jointStore.push_back(jointInfo);
649 // remember joint id mapping
650 jointIdMap.push_back(joint->getJointId());
652 OSG_COLLADA_LOG(("ColladaController::resolveJoints: Resolved "
653 "joint [%d] name [%s] jointId [%d]\n",
654 i, jointNames[i].c_str(), joint->getJointId() ));
657 else
659 SWARNING << "ColladaController::resolveJoints: Can only handle "
660 << "<joints> with JOINT and INV_BIND_MATRIX <input>s."
661 << std::endl;
665 void
666 ColladaController::remapJointIds(
667 domSkin *skin,
668 ColladaInstanceController *colInstCtrl,
669 const JointInfoStore &jointStore,
670 const JointIdMap &jointIdMap )
672 typedef std::set<GeoVectorProperty *> PropertySet;
673 PropertySet mappedProps;
675 GeoStore::iterator gsIt = _geoStore.begin();
676 GeoStore::iterator gsEnd = _geoStore.end ();
678 for(; gsIt != gsEnd; ++gsIt)
680 PropStoreIt psIt = gsIt->_propStore.begin();
681 PropStoreIt psEnd = gsIt->_propStore.end ();
683 for(; psIt != psEnd; ++psIt)
685 if(psIt->_prop == NULL)
686 continue;
688 if(mappedProps.count(psIt->_prop) > 0)
689 continue;
691 if(psIt->_semantic != "JOINT_INDEX")
692 continue;
694 GeoVec4fPropertyUnrecPtr jIndexProp =
695 dynamic_pointer_cast<GeoVec4fProperty>(psIt->_prop);
697 GeoVec4fProperty::StoredFieldType *jIndexPropF =
698 jIndexProp->editFieldPtr();
700 for(UInt32 i = 0; i < jIndexPropF->size(); ++i)
702 Vec4f jIdx = (*jIndexPropF)[i];
704 jIdx[0] = jointIdMap[UInt32(jIdx[0])];
705 jIdx[1] = jointIdMap[UInt32(jIdx[1])];
706 jIdx[2] = jointIdMap[UInt32(jIdx[2])];
707 jIdx[3] = jointIdMap[UInt32(jIdx[3])];
709 (*jIndexPropF)[i] = jIdx;
712 mappedProps.insert(jIndexProp);
717 Int32
718 ColladaController::findJoint(
719 const JointInfoStore &jointStore, domNode *joint)
721 Int32 retVal = -1;
722 JointInfoStoreConstIt jIt = jointStore.begin();
723 JointInfoStoreConstIt jEnd = jointStore.end ();
725 for(Int32 i = 0; jIt != jEnd; ++jIt, ++i)
727 if(jIt->jointNode == joint)
729 retVal = i;
730 break;
734 return retVal;
737 OSG_END_NAMESPACE
739 #endif // OSG_WITH_COLLADA