// grab the current mesh and setup the polygon sets void Mesh::SetMesh(const MDagPath &dPath) { MObjectArray fPolygonSets; MObjectArray fPolygonComponents; MDagPath dagPath(dPath); polySets.clear(); MFnMesh fMesh = MFnMesh(dagPath); //Have to make the path include the shape below it so that //we can determine if the underlying shape node is instanced. //By default, dag paths only include transform nodes. dagPath.extendToShape(); //If the shape is instanced then we need to determine which instance this path refers to. int instanceNum = 0; if (dagPath.isInstanced()) instanceNum = dagPath.instanceNumber(); //Get the connected sets and members - these will be used to determine texturing of different faces if (!fMesh.getConnectedSetsAndMembers(instanceNum, fPolygonSets, fPolygonComponents, true)) { MGlobal::displayError("MFnMesh::getConnectedSetsAndMembers"); return; } unsigned int setCount = fPolygonSets.length(); if (setCount > 1) setCount--; for (unsigned int i=0; i < setCount; i++) polySets.push_back(PolygonSet(dagPath, fPolygonComponents[i], fPolygonSets[i])); }
MStatus liqAttachPrefAttribute::redoIt() { MFnTypedAttribute tAttr; MStatus status; for ( unsigned i( 0 ); i < objectNames.length(); i++ ) { MSelectionList nodeList; nodeList.add( objectNames[i] ); MObject depNodeObj; nodeList.getDependNode( 0, depNodeObj ); MDagPath dagNode; nodeList.getDagPath( 0, dagNode ); MFnDependencyNode depNode( depNodeObj ); MObject prefAttr; MString attrName, varName; // make sure the renderer description is up to date liqglo.liquidRenderer.setRenderer(); // build the name of the attribute varName = ( ( exportN && depNodeObj.hasFn( MFn::kMesh ) )? "N":"P" ); attrName = "rman"; attrName += varName; attrName += ( ( liqglo.liquidRenderer.requires__PREF )? "__":"" ); attrName += varName + "ref"; // create the attribute prefAttr = tAttr.create( attrName, attrName, MFnData::kPointArray ); if ( depNodeObj.hasFn( MFn::kNurbsSurface ) ) { MFnNurbsSurface nodeFn( depNodeObj ); MPointArray nodePArray; MItSurfaceCV cvs( dagNode, MObject::kNullObj, liqglo.liquidRenderer.requires_SWAPPED_UVS == false, &status ); while( !cvs.isDone() ) { while( !cvs.isRowDone() ) { MPoint pt = (worldSpace)? cvs.position( MSpace::kWorld ) : cvs.position( MSpace::kObject ); nodePArray.append( pt ); cvs.next(); } cvs.nextRow(); } nodeFn.addAttribute( prefAttr ); MFnPointArrayData pArrayData; MObject prefDefault = pArrayData.create( nodePArray ); MPlug nodePlug( depNodeObj, prefAttr ); nodePlug.setValue( prefDefault ); } else if ( depNodeObj.hasFn( MFn::kNurbsCurve ) ) { // Carsten: added support for PREF on nurbs curves // MFnNurbsCurve nodeFn( depNodeObj ); MPointArray nodePArray; nodeFn.getCVs( nodePArray ); nodeFn.addAttribute( prefAttr ); MFnPointArrayData pArrayData; MObject prefDefault = pArrayData.create( nodePArray ); MPlug nodePlug( depNodeObj, prefAttr ); nodePlug.setValue( prefDefault ); } else if ( depNodeObj.hasFn( MFn::kMesh ) ) { MFnMesh nodeFn( depNodeObj ); // Moritz: modified this line to dim nodePArray -- otherwise // nodePArray.set() in the wile loop below throws an exception // which was why __Pref didn't work MPointArray nodePArray( MFnMesh( depNodeObj ).numVertices() ); unsigned count; nodeFn.addAttribute( prefAttr ); if ( exportN ) { // export Nref unsigned vertex; unsigned normal; unsigned face = 0; unsigned faceVertex = 0; unsigned int numNormals = nodeFn.numNormals(); unsigned int numPoints = nodeFn.numVertices(); MFloatVectorArray normals; MVectorArray normalAttArray; nodeFn.getNormals( normals ); if ( numNormals > numPoints ) { // if we get more than 1 normal per vertex, // force the arraysize to the full facevarying size unsigned faceVaryingCount( 0 ); for ( unsigned pOn( 0 ); pOn < nodeFn.numPolygons(); pOn++ ) faceVaryingCount += nodeFn.polygonVertexCount( pOn ); normalAttArray.setLength( faceVaryingCount ); } else normalAttArray.setLength(normals.length()); for ( MItMeshPolygon polyIt ( depNodeObj ); polyIt.isDone() == false; polyIt.next() ) { count = polyIt.polygonVertexCount(); while ( count > 0 ) { --count; normal = polyIt.normalIndex( count ); vertex = polyIt.vertexIndex( count ); if( numNormals == numPoints ) normalAttArray.set(normals[normal], vertex); else normalAttArray.set(normals[normal], faceVertex); ++faceVertex; } ++face; } MFnVectorArrayData pArrayData; MObject prefDefault = pArrayData.create( normalAttArray ); MPlug nodePlug( depNodeObj, prefAttr ); nodePlug.setValue( prefDefault ); } else { // TODO: do we need to account for the altMeshExport algo that's // used in liquidRibMeshData? // Moritz: no, it's basically the same as the algo below for ( MItMeshPolygon polyIt( dagNode, MObject::kNullObj ); !polyIt.isDone(); polyIt.next()) { count = polyIt.polygonVertexCount(); while ( count > 0 ) { --count; unsigned vertexIndex = polyIt.vertexIndex( count ); MPoint nodePoint = (worldSpace)? polyIt.point( count, MSpace::kWorld ) : polyIt.point( count, MSpace::kObject ); // Moritz: this returns MS::kFailure but seems to work?! nodePArray.set( nodePoint, vertexIndex ); } } MFnPointArrayData pArrayData; MObject prefDefault = pArrayData.create( nodePArray ); MPlug nodePlug( depNodeObj, prefAttr ); nodePlug.setValue( prefDefault ); } } else cerr << "Neither a Nurbs nor a Mesh !!" << endl; } return MS::kSuccess; }
bool CSGSlicer::slice( const Cell& cell, const MeshSlicerInfo& info, MFnMesh& outMesh ) { // copy maya mesh to csg.js model csgjs_model jsModel; MItMeshVertex it(_sourceMesh); while( !it.isDone() ) { csgjs_vertex vtx; // get position MPoint pos = it.position(MSpace::kWorld); vtx.pos = csgjs_vector(static_cast<float>(pos.x), static_cast<float>(pos.y), static_cast<float>(pos.z)); // add position jsModel.vertices.push_back(vtx); it.next(); } MIntArray triangleCounts; MIntArray triangleVertices; MFnMesh(_sourceMesh).getTriangles(triangleCounts, triangleVertices); for( unsigned int i = 0; i < triangleVertices.length(); ++i ) { jsModel.indices.push_back(triangleVertices[i]); } // convert cell into csgjs_model csgjs_model cellModel; int indexOffset = 0; const auto& planePoints = cell.getPlanePoints(); for( const auto& points : planePoints ) { for( const auto& pnt : points ) { csgjs_vertex vtx; vtx.pos = csgjs_vector(pnt.x, pnt.y, pnt.z); cellModel.vertices.push_back(vtx); } const auto& indices = HadanConvexTriangulate(points); for( const auto& idx : indices ) { cellModel.indices.push_back(indexOffset + idx[0]); cellModel.indices.push_back(indexOffset + idx[1]); cellModel.indices.push_back(indexOffset + idx[2]); } indexOffset += static_cast<int>(points.size()); } // perform intersection const csgjs_model result = csgjs_intersection(jsModel, cellModel); // copy back to maya mesh MPointArray pointArray; for( const auto& vtx : result.vertices ) { pointArray.append(MPoint(vtx.pos.x, vtx.pos.y, vtx.pos.z)); } MIntArray faceConnects; for( const auto& idx : result.indices ) { faceConnects.append(idx); } MIntArray faceCounts; for( size_t i = 0; i < result.indices.size() / 3; ++i ) { faceCounts.append(3); } { std::unique_lock<std::mutex> lock(CSGJS_CREATEMESH_MUTEX); outMesh.create(pointArray.length(), faceCounts.length(), pointArray, faceCounts, faceConnects); } return true; }