void fillMesh(PolygonMesh &mesh, double *verts, int nVerts, double *faceIdxs, int nVertsPerFace, int nFaces) { using namespace mas::mesh; PVertex3dList vtxList; IndexListList faceIdxList; for (int i=0; i<nVerts; i++) { PVertex3d vtx = MeshFactory::createVertex(verts[i*DIM], verts[i*DIM+1], verts[i*DIM+2], i); vtxList.push_back(vtx); } for (int i=0; i<nFaces; i++) { IndexList face; for (int j=0; j<nVertsPerFace; j++) { int vidx = (int)faceIdxs[i*nVertsPerFace+j]-1; face.push_back(vidx); } faceIdxList.push_back(face); } mesh.set(vtxList, faceIdxList); }
XSIPLUGINCALLBACK CStatus Coat3DExport_Execute( CRef& in_ctxt ) { // Unpack the command argument values Context ctxt( in_ctxt ); CValueArray args = ctxt.GetAttribute(L"Arguments"); CString string; // A 3d object with a mesh geometry must be selected Selection selection(app.GetSelection()); bool isPolymesh = true; for(int i =0; i< selection.GetCount(); i++) { X3DObject obj(selection[i]); //app.LogMessage(L"obj.IsA(siPolygonMeshID): " + CString(obj.GetType())); if(obj.GetType() != L"polymsh" ) { isPolymesh = false; break; } } if (selection.GetCount() > 0 && isPolymesh) { gV = 0; gVn = 0; gVt = 0; gVprev = 0; gVnPrev = 0; gVtPrev = 0; // prepare the output text file CString strOut = Get3DCoatParam( L"tempLocation" ).GetValue(); std::ofstream mfw; mfw.open(strOut.GetAsciiString(), std::ios_base::out | std::ios_base::trunc); if (mfw.is_open()) { bar.PutMaximum( selection.GetCount() ); bar.PutStep( 1 ); bar.PutVisible( true ); OutputHeader( mfw); // output the data for (int i=0; i < selection.GetCount(); i++) { gObjCnt = i; gVprev = gV; gVtPrev = gVt; gVnPrev = gVn; X3DObject xobj(selection.GetItem(i)); bar.PutValue(i); bar.PutCaption( L"Exporting " + xobj.GetName()); mfw << "\n"; mfw << "# Hierarchy (from self to top father)\n"; string = L"g " + xobj.GetName() + L"\n"; mfw << string.GetAsciiString(); mfw << "\n"; // Get a geometry accessor from the selected object Primitive prim = xobj.GetActivePrimitive(); PolygonMesh mesh = prim.GetGeometry(); if (!mesh.IsValid()) return CStatus::False; CGeometryAccessor ga = mesh.GetGeometryAccessor(); OutputVertices( mfw, ga, xobj ); if (bar.IsCancelPressed()) return CStatus::False; OutputPolygonComponents( mfw, ga ); if (bar.IsCancelPressed()) return CStatus::False; //bar.Increment(); } } mfw.close(); if(Get3DCoatParam(L"bExpMat").GetValue()) { OutputMaterials(selection ); } bar.PutStatusText( L"import.txt" ); OutputImportTxt(); bar.PutVisible(false); app.LogMessage(L"Export done!"); } else { app.LogMessage(L"Please, select objects!", siWarningMsg); return CStatus::False; } return CStatus::OK; }
XSI::CStatus AlembicSubD::Save(double time) { // store the transform Primitive prim(GetRef(REF_PRIMITIVE)); bool globalSpace = GetJob()->GetOption(L"globalSpace"); // query the global space CTransformation globalXfo; if(globalSpace) globalXfo = KinematicState(GetRef(REF_GLOBAL_TRANS)).GetTransform(time); CTransformation globalRotation; globalRotation.SetRotation(globalXfo.GetRotation()); // store the metadata SaveMetaData(GetRef(REF_NODE),this); // check if the mesh is animated if(mNumSamples > 0) { if(!isRefAnimated(GetRef(REF_PRIMITIVE), false, globalSpace)) return CStatus::OK; } // determine if we are a pure point cache bool purePointCache = (bool)GetJob()->GetOption(L"exportPurePointCache"); // access the mesh PolygonMesh mesh = prim.GetGeometry(time); CVector3Array pos = mesh.GetVertices().GetPositionArray(); LONG vertCount = pos.GetCount(); // prepare the bounding box Abc::Box3d bbox; // allocate the points and normals std::vector<Abc::V3f> posVec(vertCount); for(LONG i=0;i<vertCount;i++) { if(globalSpace) pos[i] = MapObjectPositionToWorldSpace(globalXfo,pos[i]); posVec[i].x = (float)pos[i].GetX(); posVec[i].y = (float)pos[i].GetY(); posVec[i].z = (float)pos[i].GetZ(); bbox.extendBy(posVec[i]); } // allocate the sample for the points if(posVec.size() == 0) { bbox.extendBy(Abc::V3f(0,0,0)); posVec.push_back(Abc::V3f(FLT_MAX,FLT_MAX,FLT_MAX)); } Abc::P3fArraySample posSample(&posVec.front(),posVec.size()); // store the positions && bbox mSubDSample.setPositions(posSample); mSubDSample.setSelfBounds(bbox); customAttributes.exportCustomAttributes(mesh); // abort here if we are just storing points if(purePointCache) { if(mNumSamples == 0) { // store a dummy empty topology mFaceCountVec.push_back(0); mFaceIndicesVec.push_back(0); Abc::Int32ArraySample faceCountSample(&mFaceCountVec.front(),mFaceCountVec.size()); Abc::Int32ArraySample faceIndicesSample(&mFaceIndicesVec.front(),mFaceIndicesVec.size()); mSubDSample.setFaceCounts(faceCountSample); mSubDSample.setFaceIndices(faceIndicesSample); } mSubDSchema.set(mSubDSample); mNumSamples++; return CStatus::OK; } // check if we support changing topology bool dynamicTopology = (bool)GetJob()->GetOption(L"exportDynamicTopology"); CPolygonFaceRefArray faces = mesh.GetPolygons(); LONG faceCount = faces.GetCount(); LONG sampleCount = mesh.GetSamples().GetCount(); // create a sample look table LONG offset = 0; CLongArray sampleLookup(sampleCount); for(LONG i=0;i<faces.GetCount();i++) { PolygonFace face(faces[i]); CLongArray samples = face.GetSamples().GetIndexArray(); for(LONG j=samples.GetCount()-1;j>=0;j--) sampleLookup[offset++] = samples[j]; } // check if we should export the velocities if(dynamicTopology) { ICEAttribute velocitiesAttr = mesh.GetICEAttributeFromName(L"PointVelocity"); if(velocitiesAttr.IsDefined() && velocitiesAttr.IsValid()) { CICEAttributeDataArrayVector3f velocitiesData; velocitiesAttr.GetDataArray(velocitiesData); mVelocitiesVec.resize(vertCount); for(LONG i=0;i<vertCount;i++) { CVector3 vel; vel.PutX(velocitiesData[i].GetX()); vel.PutY(velocitiesData[i].GetY()); vel.PutZ(velocitiesData[i].GetZ()); if(globalSpace) vel = MapObjectPositionToWorldSpace(globalRotation,vel); mVelocitiesVec[i].x = (float)vel.GetX(); mVelocitiesVec[i].y = (float)vel.GetY(); mVelocitiesVec[i].z = (float)vel.GetZ(); } if(mVelocitiesVec.size() == 0) mVelocitiesVec.push_back(Abc::V3f(0,0,0)); Abc::V3fArraySample sample = Abc::V3fArraySample(&mVelocitiesVec.front(),mVelocitiesVec.size()); mSubDSample.setVelocities(sample); } } // if we are the first frame! if(mNumSamples == 0 || dynamicTopology) { // we also need to store the face counts as well as face indices if(mFaceIndicesVec.size() != sampleCount || sampleCount == 0) { mFaceCountVec.resize(faceCount); mFaceIndicesVec.resize(sampleCount); offset = 0; for(LONG i=0;i<faceCount;i++) { PolygonFace face(faces[i]); CLongArray indices = face.GetVertices().GetIndexArray(); mFaceCountVec[i] = indices.GetCount(); for(LONG j=indices.GetCount()-1;j>=0;j--) mFaceIndicesVec[offset++] = indices[j]; } if(mFaceIndicesVec.size() == 0) { mFaceCountVec.push_back(0); mFaceIndicesVec.push_back(0); } Abc::Int32ArraySample faceCountSample(&mFaceCountVec.front(),mFaceCountVec.size()); Abc::Int32ArraySample faceIndicesSample(&mFaceIndicesVec.front(),mFaceIndicesVec.size()); mSubDSample.setFaceCounts(faceCountSample); mSubDSample.setFaceIndices(faceIndicesSample); } // set the subd level Property geomApproxProp; prim.GetParent3DObject().GetPropertyFromName(L"geomapprox",geomApproxProp); mSubDSample.setFaceVaryingInterpolateBoundary(geomApproxProp.GetParameterValue(L"gapproxmordrsl")); // also check if we need to store UV CRefArray clusters = mesh.GetClusters(); if((bool)GetJob()->GetOption(L"exportUVs")) { CGeometryAccessor accessor = mesh.GetGeometryAccessor(siConstructionModeSecondaryShape); CRefArray uvPropRefs = accessor.GetUVs(); // if we now finally found a valid uvprop if(uvPropRefs.GetCount() > 0) { // ok, great, we found UVs, let's set them up if(mNumSamples == 0) { mUvVec.resize(uvPropRefs.GetCount()); if((bool)GetJob()->GetOption(L"indexedUVs")) mUvIndexVec.resize(uvPropRefs.GetCount()); // query the names of all uv properties std::vector<std::string> uvSetNames; for(LONG i=0;i< uvPropRefs.GetCount();i++) uvSetNames.push_back(ClusterProperty(uvPropRefs[i]).GetName().GetAsciiString()); Abc::OStringArrayProperty uvSetNamesProperty = Abc::OStringArrayProperty( mSubDSchema, ".uvSetNames", mSubDSchema.getMetaData(), GetJob()->GetAnimatedTs() ); Abc::StringArraySample uvSetNamesSample(&uvSetNames.front(),uvSetNames.size()); uvSetNamesProperty.set(uvSetNamesSample); } // loop over all uvsets for(LONG uvI=0;uvI<uvPropRefs.GetCount();uvI++) { mUvVec[uvI].resize(sampleCount); CDoubleArray uvValues = ClusterProperty(uvPropRefs[uvI]).GetElements().GetArray(); for(LONG i=0;i<sampleCount;i++) { mUvVec[uvI][i].x = (float)uvValues[sampleLookup[i] * 3 + 0]; mUvVec[uvI][i].y = (float)uvValues[sampleLookup[i] * 3 + 1]; } // now let's sort the normals size_t uvCount = mUvVec[uvI].size(); size_t uvIndexCount = 0; if((bool)GetJob()->GetOption(L"indexedUVs")) { std::map<SortableV2f,size_t> uvMap; std::map<SortableV2f,size_t>::const_iterator it; size_t sortedUVCount = 0; std::vector<Abc::V2f> sortedUVVec; mUvIndexVec[uvI].resize(mUvVec[uvI].size()); sortedUVVec.resize(mUvVec[uvI].size()); // loop over all uvs for(size_t i=0;i<mUvVec[uvI].size();i++) { it = uvMap.find(mUvVec[uvI][i]); if(it != uvMap.end()) mUvIndexVec[uvI][uvIndexCount++] = (Abc::uint32_t)it->second; else { mUvIndexVec[uvI][uvIndexCount++] = (Abc::uint32_t)sortedUVCount; uvMap.insert(std::pair<Abc::V2f,size_t>(mUvVec[uvI][i],(Abc::uint32_t)sortedUVCount)); sortedUVVec[sortedUVCount++] = mUvVec[uvI][i]; } } // use indexed uvs if they use less space mUvVec[uvI] = sortedUVVec; uvCount = sortedUVCount; sortedUVCount = 0; sortedUVVec.clear(); } AbcG::OV2fGeomParam::Sample uvSample(Abc::V2fArraySample(&mUvVec[uvI].front(),uvCount),AbcG::kFacevaryingScope); if(mUvIndexVec.size() > 0 && uvIndexCount > 0) uvSample.setIndices(Abc::UInt32ArraySample(&mUvIndexVec[uvI].front(),uvIndexCount)); if(uvI == 0) { mSubDSample.setUVs(uvSample); } else { // create the uv param if required if(mNumSamples == 0) { CString storedUvSetName = CString(L"uv") + CString(uvI); mUvParams.push_back(AbcG::OV2fGeomParam( mSubDSchema, storedUvSetName.GetAsciiString(), uvIndexCount > 0, AbcG::kFacevaryingScope, 1, GetJob()->GetAnimatedTs())); } mUvParams[uvI-1].set(uvSample); } } // create the uv options if(mUvOptionsVec.size() == 0) { mUvOptionsProperty = Abc::OFloatArrayProperty(mSubDSchema, ".uvOptions", mSubDSchema.getMetaData(), GetJob()->GetAnimatedTs() ); for(LONG uvI=0;uvI<uvPropRefs.GetCount();uvI++) { //ESS_LOG_ERROR( "Cluster Property child name: " << ClusterProperty(uvPropRefs[uvI]).GetFullName().GetAsciiString() ); //ESS_LOG_ERROR( "Cluster Property child type: " << ClusterProperty(uvPropRefs[uvI]).GetType().GetAsciiString() ); ClusterProperty clusterProperty = (ClusterProperty) uvPropRefs[uvI]; bool subdsmooth = false; if( clusterProperty.GetType() == L"uvspace") { subdsmooth = (bool)clusterProperty.GetParameter(L"subdsmooth").GetValue(); // ESS_LOG_ERROR( "subdsmooth: " << subdsmooth ); } CRefArray children = clusterProperty.GetNestedObjects(); bool uWrap = false; bool vWrap = false; for(LONG i=0; i<children.GetCount(); i++) { ProjectItem child(children.GetItem(i)); CString type = child.GetType(); // ESS_LOG_ERROR( " Cluster Property child type: " << type.GetAsciiString() ); if(type == L"uvprojdef") { uWrap = (bool)child.GetParameter(L"wrap_u").GetValue(); vWrap = (bool)child.GetParameter(L"wrap_v").GetValue(); break; } } // uv wrapping mUvOptionsVec.push_back(uWrap ? 1.0f : 0.0f); mUvOptionsVec.push_back(vWrap ? 1.0f : 0.0f); mUvOptionsVec.push_back(subdsmooth ? 1.0f : 0.0f); } mUvOptionsProperty.set(Abc::FloatArraySample(&mUvOptionsVec.front(),mUvOptionsVec.size())); } } } // sweet, now let's have a look at face sets if(GetJob()->GetOption(L"exportFaceSets") && mNumSamples == 0) { for(LONG i=0;i<clusters.GetCount();i++) { Cluster cluster(clusters[i]); if(!cluster.GetType().IsEqualNoCase(L"poly")) continue; CLongArray elements = cluster.GetElements().GetArray(); if(elements.GetCount() == 0) continue; std::string name(cluster.GetName().GetAsciiString()); mFaceSetsVec.push_back(std::vector<Abc::int32_t>()); std::vector<Abc::int32_t> & faceSetVec = mFaceSetsVec.back(); for(LONG j=0;j<elements.GetCount();j++) faceSetVec.push_back(elements[j]); if(faceSetVec.size() > 0) { AbcG::OFaceSet faceSet = mSubDSchema.createFaceSet(name); AbcG::OFaceSetSchema::Sample faceSetSample(Abc::Int32ArraySample(&faceSetVec.front(),faceSetVec.size())); faceSet.getSchema().set(faceSetSample); } } } // save the sample mSubDSchema.set(mSubDSample); // check if we need to export the bindpose if(GetJob()->GetOption(L"exportBindPose") && prim.GetParent3DObject().GetEnvelopes().GetCount() > 0 && mNumSamples == 0) { mBindPoseProperty = Abc::OV3fArrayProperty(mSubDSchema, ".bindpose", mSubDSchema.getMetaData(), GetJob()->GetAnimatedTs()); // store the positions of the modeling stack into here PolygonMesh bindPoseGeo = prim.GetGeometry(time, siConstructionModeModeling); CVector3Array bindPosePos = bindPoseGeo.GetPoints().GetPositionArray(); mBindPoseVec.resize((size_t)bindPosePos.GetCount()); for(LONG i=0;i<bindPosePos.GetCount();i++) { mBindPoseVec[i].x = (float)bindPosePos[i].GetX(); mBindPoseVec[i].y = (float)bindPosePos[i].GetY(); mBindPoseVec[i].z = (float)bindPosePos[i].GetZ(); } Abc::V3fArraySample sample; if(mBindPoseVec.size() > 0) sample = Abc::V3fArraySample(&mBindPoseVec.front(),mBindPoseVec.size()); mBindPoseProperty.set(sample); } } else { mSubDSchema.set(mSubDSample); } mNumSamples++; return CStatus::OK; }
XSIPLUGINCALLBACK CStatus OutputMaterials( Selection& in_sel ) { // prepare the mtl file Project prj = app.GetActiveProject(); Scene scn = prj.GetActiveScene(); CString tmpLocation = Get3DCoatParam( L"tempLocation" ).GetValue(); ULONG npos = tmpLocation.ReverseFindString(L"."); CString substr = tmpLocation.GetSubString(0, npos+1); CString strOut = substr + L"mtl"; //app.LogMessage(L"strOut:" + strOut); std::ofstream matfw; matfw.open(strOut.GetAsciiString(), std::ios_base::out | std::ios_base::trunc); if (matfw.is_open()) { CRefArray tempMats; for(int i=0; i< in_sel.GetCount(); i++) { X3DObject xobj(in_sel.GetItem(i)); // Get a geometry accessor from the selected object Primitive prim = xobj.GetActivePrimitive(); PolygonMesh mesh = prim.GetGeometry(); if (!mesh.IsValid()) return CStatus::False; CGeometryAccessor ga = mesh.GetGeometryAccessor(); // get the material objects used by the mesh CRefArray materials = ga.GetMaterials(); for (LONG n=0; n < materials.GetCount(); n++) { bar.PutStatusText( L"materials" ); Material mat(materials[n]); bool inMats = false; //app.LogMessage(CString(n) +L" : "+ CString(i)+ L" :" + mat.GetName()); for(int m = 0; m < tempMats.GetCount(); m++) { Material tmat(tempMats[m]); if(mat.GetName() == tmat.GetName()) { inMats = true; break; } } //app.LogMessage(CString(inMats)); if(!inMats) { CString string = L"newmtl " + mat.GetName() + L"\n"; matfw << string.GetAsciiString(); Parameter surf = mat.GetParameters().GetItem(L"surface"); Shader lShader(surf.GetSource()); //app.LogMessage(L"shader: " + lShader.GetFullName()); //app.LogMessage(L"shader: " + lShader.GetProgID()); if ( lShader.GetProgID() == L"Softimage.material-phong.1" ) { float r, g, b, a; lShader.GetColorParameterValue(L"ambient", r, g, b, a ); CString ka = L"Ka " + FormatNumber(r) + L" " + FormatNumber(g) + L" " + FormatNumber(b); lShader.GetColorParameterValue(L"diffuse", r, g, b, a ); CString kd = L"Kd " + FormatNumber(r) + L" " + FormatNumber(g) + L" " + FormatNumber(b); lShader.GetColorParameterValue(L"specular", r, g, b, a ); CString ks = L"Ks " + FormatNumber(r) + L" " + FormatNumber(g) + L" " + FormatNumber(b); float ns = lShader.GetParameterValue(L"shiny"); float d = 1.0f; CValue illum = 2; matfw << ka.GetAsciiString(); matfw << "\n"; matfw << kd.GetAsciiString(); matfw << "\n"; matfw << ks.GetAsciiString(); matfw << "\n"; matfw << "Ns "; matfw << FormatNumber(ns).GetAsciiString(); matfw << "\n"; matfw << "d "; matfw << FormatNumber(d).GetAsciiString(); matfw << "\n"; matfw << "illum "; matfw << illum.GetAsText().GetAsciiString(); matfw << "\n"; Parameter diff = lShader.GetParameters().GetItem(L"diffuse"); Shader lImageD(diff.GetSource()); if (lImageD.GetProgID() == L"Softimage.txt2d-image-explicit.1") { Parameter tex = lImageD.GetParameters().GetItem(L"tex"); ImageClip2 lTextureD(tex.GetSource()); //app.LogMessage( L"Found texture shader: " + lTexture.GetFullName() + L", Class: " + lTexture.GetClassIDName() + L", Type: " + lTexture.GetType() ); app.LogMessage(L"texture GetFileName: " + lTextureD.GetFileName()); matfw << "map_Kd "; matfw << lTextureD.GetFileName().GetAsciiString(); matfw << "\n"; } Parameter spec = lShader.GetParameters().GetItem(L"specular"); Shader lImageS(spec.GetSource()); if (lImageS.GetProgID() == L"Softimage.txt2d-image-explicit.1") { Parameter tex = lImageD.GetParameters().GetItem(L"tex"); ImageClip2 lTextureS(tex.GetSource()); //app.LogMessage( L"Found texture shader: " + lTexture.GetFullName() + L", Class: " + lTexture.GetClassIDName() + L", Type: " + lTexture.GetType() ); //app.LogMessage(L"texture GetFileName: " + lTexture.GetFileName()); matfw << "map_Ks "; matfw << lTextureS.GetFileName().GetAsciiString(); matfw << "\n"; } } tempMats.Add(mat); matfw << "\n"; matfw << "\n"; } } } matfw.close(); } return CStatus::OK; }
PolygonMesh<PointType>::PolygonMesh(const PolygonMesh<PointType>& source) :vertices(0),lastVertex(0),faces(0),lastFace(0) { /* Copy all vertices and associate the copies with their originals: */ Misc::HashTable<const Vertex*,Vertex*> vertexMap((source.getNumVertices()*3)/2); for(const Vertex* vPtr=source.vertices;vPtr!=0;vPtr=vPtr->succ) vertexMap.setEntry(typename Misc::HashTable<const Vertex*,Vertex*>::Entry(vPtr,newVertex(*vPtr))); /* Count the number of edges in the source mesh to estimate the needed hash table size: */ const Face* fPtr; int numEdges=0; for(fPtr=source.faces;fPtr!=0;fPtr=fPtr->succ) { const Edge* firstSourceEdge=fPtr->getEdge(); const Edge* fePtr=firstSourceEdge; do { ++numEdges; fePtr=fePtr->getFaceSucc(); } while(fePtr!=firstSourceEdge); } Misc::HashTable<VertexPair,Edge*,VertexPair> companions(numEdges); /* Copy faces one at a time: */ for(fPtr=source.faces;fPtr!=0;fPtr=fPtr->succ) { Face* face=newFace(); /* Copy all edges of the face (don't connect them to other faces yet): */ const Edge* firstSourceEdge=fPtr->getEdge(); const Edge* fePtr=firstSourceEdge; Edge* firstEdge; Edge* lastEdge=0; do { /* Create a new edge: */ Edge* edge=newEdge(); Vertex* vPtr=vertexMap.getEntry(fePtr->getStart()).getDest(); edge->set(vPtr,face,lastEdge,0,0); edge->sharpness=fePtr->sharpness; vPtr->setEdge(edge); if(lastEdge!=0) lastEdge->setFaceSucc(edge); else firstEdge=edge; lastEdge=edge; fePtr=fePtr->getFaceSucc(); } while(fePtr!=firstSourceEdge); lastEdge->setFaceSucc(firstEdge); firstEdge->setFacePred(lastEdge); face->setEdge(firstEdge); /* Now go around the edge loop again to connect the face to its neighbours: */ Edge* edge=firstEdge; do { VertexPair vp(*edge); typename Misc::HashTable<VertexPair,Edge*,VertexPair>::Iterator companionsIt=companions.findEntry(vp); if(companionsIt!=companions.end()) { /* Connect the edge to its companion: */ edge->setOpposite(companionsIt->getDest()); companionsIt->getDest()->setOpposite(edge); } else { /* Add the edge to the companion table: */ companions.setEntry(typename Misc::HashTable<VertexPair,Edge*,VertexPair>::Entry(vp,edge)); } edge=edge->getFaceSucc(); } while(edge!=firstEdge); } }