/*! Push \a srcTrans into \a dstGeo */ void TransformPushGraphOp::pushToGeometry( const Transform *srcTrans, Geometry *dstGeo) { typedef Vec4f VecType; typedef Pnt3f PntType; Matrix mat = srcTrans->getMatrix(); Matrix invMat = mat; invMat[3][0] = invMat[3][1] = invMat[3][2] = 0.f; invMat.invert (); invMat.transpose(); const Geometry::SFLengthsType *sfLen = dstGeo->getSFLengths (); Geometry::MFPropertiesType *mfProp = dstGeo->editMFProperties (); Geometry::MFPropIndicesType *mfInd = dstGeo->editMFPropIndices(); Geometry::MFPropertiesType::const_iterator propIt = mfProp->begin(); Geometry::MFPropertiesType::const_iterator propEnd = mfProp->end (); Geometry::MFPropIndicesType::const_iterator indIt = mfInd ->begin(); Geometry::MFPropIndicesType::const_iterator indEnd = mfInd ->end (); UInt32 propUsed = 0; for(UInt32 i = 0; i < sfLen->getValue()->size(); ++i) propUsed += sfLen->getValue()->getValue<UInt32>(i); for(; propIt != propEnd && indIt != indEnd; ++propIt, ++indIt) { GeoVectorProperty *prop = *propIt; const GeoIntegralProperty *ind = *indIt; if(prop == NULL) continue; if(ind == NULL) { // unindexed if((prop->getUsage() & GeoProperty::UsageObjectSpace) != 0x0000) { // transform with mat for(UInt32 i = 0; i < propUsed; ++i) { PntType pnt = prop->getValue<PntType>(i); mat.multFull(pnt, pnt); prop->setValue(pnt, i); } } else if((prop->getUsage() & GeoProperty::UsageTangentSpace) != 0x0000) { // transform with invMat for(UInt32 i = 0; i < propUsed; ++i) { VecType vec = prop->getValue<VecType>(i); invMat.mult(vec, vec); prop->setValue(vec, i); } } } else { std::set<UInt32> transInd; if((prop->getUsage() & GeoProperty::UsageObjectSpace) != 0x0000) { // transform with mat for(UInt32 i = 0; i < propUsed; ++i) { UInt32 j = ind->getValue(i); if(transInd.find(j) == transInd.end()) { PntType pnt = prop->getValue<PntType>(j); mat.multFull(pnt, pnt); prop->setValue(pnt, j); transInd.insert(j); } } } else if((prop->getUsage() & GeoProperty::UsageTangentSpace) != 0x0000) { // transform with invMat for(UInt32 i = 0; i < propUsed; ++i) { UInt32 j = ind->getValue(i); if(transInd.find(j) == transInd.end()) { VecType vec = prop->getValue<VecType>(j); invMat.mult(vec, vec); prop->setValue(vec, j); transInd.insert(j); } } } } } }
void CPUSkinningAlgorithm::transformGeometry( SkinnedGeometry *skinGeo, Skeleton *skel, CPUSkinningDataAttachment *data) { const SkinnedGeometry::MFPropIndicesType *mfOrigIdx = skinGeo->getMFPropIndices(); const SkinnedGeometry::MFPropertiesType *mfOrigProps = skinGeo->getMFProperties(); SkinnedGeometry::MFPropertiesType *mfProps = data->editMFProperties(); const GeoVec4fProperty *jointIdxProp = dynamic_cast<const GeoVec4fProperty *>( (*mfOrigProps)[skinGeo->getJointIndexProperty()]); const GeoVec4fProperty *jointWeightProp = dynamic_cast<const GeoVec4fProperty *>( (*mfOrigProps)[skinGeo->getJointWeightProperty()]); if(skinGeo->getIndex(skinGeo->getJointIndexProperty ()) != skinGeo->getIndex(skinGeo->getJointWeightProperty()) ) { SWARNING << "CPUSkinningAlgorithm::transformGeometry: " << "Multi indexed geometry not supported!" << std::endl; return; } mfProps->resize(mfOrigProps->size(), NULL); const MFMatrix *mfJointMat = NULL; const MFMatrix *mfJointNormalMat = NULL; // if the geometry has a non-identity bind shape matrix // premultiply joint matrices with bind shape matrix and store in data // attachment if(skinGeo->getBindShapeMatrix().equals(Matrix::identity(), Eps) == false) { mfJointMat = skel->getMFJointMatrices (); MFMatrix *mfJointBindMat = data->editMFJointMatrices(); mfJointBindMat->resize(mfJointMat->size()); for(UInt32 i = 0; i < mfJointMat->size(); ++i) { (*mfJointBindMat)[i] = (*mfJointMat)[i]; (*mfJointBindMat)[i].mult(skinGeo->getBindShapeMatrix()); } mfJointMat = data->getMFJointMatrices(); if(skel->getCalcNormalMatrices() == true) { mfJointNormalMat = skel->getMFJointNormalMatrices (); MFMatrix *mfJointNormalBindMat = data->editMFJointNormalMatrices(); mfJointNormalBindMat->resize(mfJointNormalMat->size()); for(UInt32 i = 0; i < mfJointNormalMat->size(); ++i) { (*mfJointNormalBindMat)[i] = (*mfJointNormalMat)[i]; (*mfJointNormalBindMat)[i].mult(skinGeo->getBindShapeMatrix()); } mfJointNormalMat = data->getMFJointNormalMatrices(); } else { mfJointNormalMat = data->getMFJointMatrices(); } } else { mfJointMat = skel->getMFJointMatrices(); if(skel->getCalcNormalMatrices() == true) { mfJointNormalMat = skel->getMFJointNormalMatrices(); } else { mfJointNormalMat = skel->getMFJointMatrices(); } } // transform all properties for(UInt16 i = 0; i < mfProps->size(); ++i) { // do not transform the vertex joint indices/weights if(i == skinGeo->getJointIndexProperty () || i == skinGeo->getJointWeightProperty() ) { continue; } GeoIntegralProperty *origPropIdx = (*mfOrigIdx )[i]; GeoVectorProperty *origProp = (*mfOrigProps)[i]; GeoVectorProperty *prop = (*mfProps )[i]; if(origProp == NULL) continue; if(prop == NULL) { GeoVectorPropertyUnrecPtr newProp = dynamic_pointer_cast<GeoVectorProperty>(origProp->clone()); mfProps->replace(i, newProp); prop = newProp; } else if(prop->size() != origProp->size()) { prop->resize(origProp->size()); } switch(origProp->getUsage() & GeoProperty::UsageSpaceMask) { case GeoProperty::UsageObjectSpace: { transformObjectSpaceProperty( mfJointMat, jointIdxProp, jointWeightProp, origPropIdx, origProp, prop); } break; case GeoProperty::UsageTangentSpace: { transformTangentSpaceProperty( mfJointNormalMat, jointIdxProp, jointWeightProp, origPropIdx, origProp, prop); } break; default: // only need to transform object/tangent space properties break; } } }