//TODO: should only refer to our scene graph nodes, and rely on global transforms only void SaveXformSample(SceneNodePtr node, AbcG::OXformSchema & schema,AbcG::XformSample & sample, double time, bool xformCache, bool globalSpace, bool flattenHierarchy) { // check if we are exporting in global space if(globalSpace) { if(schema.getNumSamples() > 0) return; // store identity matrix sample.setTranslation(Imath::V3d(0.0,0.0,0.0)); sample.setRotation(Imath::V3d(1.0,0.0,0.0),0.0); sample.setScale(Imath::V3d(1.0,1.0,1.0)); // save the sample schema.set(sample); return; } // check if the transform is animated //if(schema.getNumSamples() > 0) //{ // X3DObject parent(kineState.GetParent3DObject()); // if(!isRefAnimated(kineState.GetParent3DObject().GetRef(),xformCache)) // return; //} if(flattenHierarchy){//a hack needed to handle namespace xforms sample.setMatrix(node->getGlobalTransDouble(time)); } else{ Imath::M44d parentGlobalTransInv = node->parent->getGlobalTransDouble(time).invert(); Imath::M44d transform = node->getGlobalTransDouble(time) * parentGlobalTransInv; sample.setMatrix(transform); } //KinematicState kineState(kineStateRef); //CTransformation globalTransform = kineState.GetTransform(time); //CTransformation transform; //if(flattenHierarchy){ // transform = globalTransform; //} //else{ // KinematicState parentKineState(parentKineStateRef); // CMatrix4 parentGlobalTransform4 = parentKineState.GetTransform(time).GetMatrix4(); // CMatrix4 transform4 = globalTransform.GetMatrix4(); // parentGlobalTransform4.InvertInPlace(); // transform4.MulInPlace(parentGlobalTransform4); // transform.SetMatrix4(transform4); //} //// store the transform //CVector3 trans = transform.GetTranslation(); //CVector3 axis; //double angle = transform.GetRotationAxisAngle(axis); //CVector3 scale = transform.GetScaling(); //sample.setTranslation(Imath::V3d(trans.GetX(),trans.GetY(),trans.GetZ())); //sample.setRotation(Imath::V3d(axis.GetX(),axis.GetY(),axis.GetZ()),RadiansToDegrees(angle)); //sample.setScale(Imath::V3d(scale.GetX(),scale.GetY(),scale.GetZ())); //ESS_LOG_WARNING("time: "<<time<<" trans: ("<<trans.GetX()<<", "<<trans.GetY()<<", "<<trans.GetZ()<<") angle: "<<angle<<" axis: ("<<axis.GetX()<<", "<<axis.GetY()<<", "<<axis.GetZ()); // save the sample schema.set(sample); }
//we have to save out all mesh encountered on the current frame of this object immediately, because //the pointers will no longer be valid when the object is evaluated at a new time void AlembicPoints::saveCurrentFrameMeshes() { ESS_PROFILE_FUNC(); for(int i=0; i<mMeshesToSaveForCurrentFrame.size(); i++){ //TODO: save immediately instead accumulating in a vector meshInfo* mi = mMeshesToSaveForCurrentFrame[i]; if(mi->pMesh){ Mesh* pMesh = mi->pMesh; //mi->pMesh = NULL;//each mesh only needs to be saved once //Matrix3 worldTrans; //worldTrans.IdentityMatrix(); CommonOptions options; options.SetOption("exportNormals", mJob->GetOption("exportNormals")); options.SetOption("exportMaterialIds", mJob->GetOption("exportMaterialIds")); //gather the mesh data mi->meshTM.IdentityMatrix(); IntermediatePolyMesh3DSMax finalPolyMesh; { ESS_PROFILE_SCOPE("AlembicPoints::saveCurrentFrameMeshes - finalPolyMesh.Save"); Imath::M44f transform44f; ConvertMaxMatrixToAlembicMatrix( mi->meshTM, transform44f ); SceneNodeMaxParticlesPtr inputSceneNode(new SceneNodeMaxParticles(pMesh, NULL, mi->nMatId)); finalPolyMesh.Save(inputSceneNode, transform44f, options, 0.0); } AbcG::OPolyMeshSchema::Sample meshSample; AbcG::OPolyMeshSchema meshSchema; { ESS_PROFILE_SCOPE("AlembicPoints::saveCurrentFrameMeshes - save xforms, bbox, geo, topo"); //save out the mesh xForm //std::string xformName = mi->name + "Xfo"; AbcG::OXform xform(mJob->GetArchive().getTop(), mi->name, GetCurrentJob()->GetAnimatedTs()); AbcG::OXformSchema& xformSchema = xform.getSchema();//mi->xformSchema; std::string meshName = mi->name + "Shape"; AbcG::OPolyMesh mesh(xform, meshName, GetCurrentJob()->GetAnimatedTs()); meshSchema = mesh.getSchema(); AbcG::XformSample xformSample; Matrix3 alembicMatrix; alembicMatrix.IdentityMatrix(); alembicMatrix.SetTrans(Point3(-10000.0f, -10000.0f, -10000.0f)); Abc::M44d iMatrix; ConvertMaxMatrixToAlembicMatrix(alembicMatrix, iMatrix); xformSample.setMatrix(iMatrix); xformSchema.set(xformSample); //update the archive bounding box Abc::Box3d bbox; bbox.min = finalPolyMesh.bbox.min * iMatrix; bbox.max = finalPolyMesh.bbox.max * iMatrix; mJob->GetArchiveBBox().extendBy(bbox); //save out the mesh data meshSample.setPositions(Abc::P3fArraySample(finalPolyMesh.posVec)); meshSample.setSelfBounds(finalPolyMesh.bbox); meshSchema.getChildBoundsProperty().set(finalPolyMesh.bbox); meshSample.setFaceCounts(Abc::Int32ArraySample(finalPolyMesh.mFaceCountVec)); meshSample.setFaceIndices(Abc::Int32ArraySample(finalPolyMesh.mFaceIndicesVec)); } if(mJob->GetOption("validateMeshTopology")){ ESS_PROFILE_SCOPE("AlembicPoints::saveCurrentFrameMeshes - validateMeshTopology"); mJob->mMeshErrors += validateAlembicMeshTopo(finalPolyMesh.mFaceCountVec, finalPolyMesh.mFaceIndicesVec, mi->name); } if(mJob->GetOption("exportNormals")){ ESS_PROFILE_SCOPE("AlembicPoints::saveCurrentFrameMeshes - exportNormals"); AbcG::ON3fGeomParam::Sample normalSample; normalSample.setScope(AbcG::kFacevaryingScope); normalSample.setVals(Abc::N3fArraySample(finalPolyMesh.mIndexedNormals.values)); normalSample.setIndices(Abc::UInt32ArraySample(finalPolyMesh.mIndexedNormals.indices)); meshSample.setNormals(normalSample); } if(mJob->GetOption("exportMaterialIds")){ ESS_PROFILE_SCOPE("AlembicPoints::saveCurrentFrameMeshes - exportMaterialIds"); Abc::OUInt32ArrayProperty mMatIdProperty = Abc::OUInt32ArrayProperty(meshSchema, ".materialids", meshSchema.getMetaData(), mJob->GetAnimatedTs()); mMatIdProperty.set(Abc::UInt32ArraySample(finalPolyMesh.mMatIdIndexVec)); for ( facesetmap_it it=finalPolyMesh.mFaceSets.begin(); it != finalPolyMesh.mFaceSets.end(); it++) { std::stringstream nameStream; int nMaterialId = it->first+1; nameStream<<it->second.name<<"_"<<nMaterialId; std::vector<Abc::int32_t>& faceSetVec = it->second.faceIds; AbcG::OFaceSet faceSet = meshSchema.createFaceSet(nameStream.str()); AbcG::OFaceSetSchema::Sample faceSetSample(Abc::Int32ArraySample(&faceSetVec.front(), faceSetVec.size())); faceSet.getSchema().set(faceSetSample); } } if(mJob->GetOption("exportUVs")){ //TODO... } { ESS_PROFILE_SCOPE("AlembicPoints::saveCurrentFrameMeshes meshSchema.set"); meshSchema.set(meshSample); } if(mi->bNeedDelete){ delete mi->pMesh; mi->bNeedDelete = FALSE; } mi->pMesh = NULL; } } mMeshesToSaveForCurrentFrame.clear(); }