MStatus SelectRingContext1::doRelease( MEvent &event ) { // Get the mouse release position event.getPosition( releaseX, releaseY ); // Didn't select a single point if( abs(pressX - releaseX) > 1 || abs(pressY - releaseY) > 1 ) { MGlobal::displayWarning( "Click on a single edge" ); return MS::kFailure; } // Set the selection surface area int halfClickBoxSize = clickBoxSize / 2; pressX -= halfClickBoxSize; pressY -= halfClickBoxSize; releaseX = pressX + clickBoxSize; releaseY = pressY + clickBoxSize; /* // Record previous selection state prevSelMode = MGlobal::selectionMode(); prevCompMask = MGlobal::componentSelectionMask(); */ // Get the current selection MSelectionList curSel; MGlobal::getActiveSelectionList( curSel ); //MGlobal::displayInfo( MString("Dim: ") + start_x + " " + start_y + " " + last_x + " " + last_y ); // Change to object selection mode MGlobal::setSelectionMode( MGlobal::kSelectObjectMode ); MGlobal::setComponentSelectionMask( MSelectionMask( MSelectionMask::kSelectObjectsMask ) ); // Select the object under the selection area MGlobal::selectFromScreen( pressX, pressY, releaseX, releaseY, MGlobal::kReplaceList); MGlobal::executeCommand( "hilite" ); // Change selection mode to mesh edges MGlobal::setSelectionMode( MGlobal::kSelectComponentMode ); MGlobal::setComponentSelectionMask( MSelectionMask( MSelectionMask::kSelectMeshEdges ) ); // Select the edges MGlobal::selectFromScreen( pressX, pressY, releaseX, releaseY, MGlobal::kReplaceList ); // Get the list of selected edges MSelectionList origEdgesSel; MGlobal::getActiveSelectionList( origEdgesSel ); MSelectionList newEdgesSel; MDagPath dagPath; MObject component; // Only use the first edge in the selection MItSelectionList selIter( origEdgesSel, MFn::kMeshEdgeComponent ); if( !selIter.isDone() ) { selIter.getDagPath( dagPath, component ); MIntArray faces; MItMeshEdge edgeIter( dagPath, component ); MIntArray edgesVisited, facesVisited; int edgeIndex, faceIndex; int prevIndex; unsigned int i; bool finished = false; while( !finished ) { edgeIndex = edgeIter.index(); edgesVisited.append( edgeIndex ); // Create an edge component the current edge MFnSingleIndexedComponent indexedCompFn; MObject newComponent = indexedCompFn.create( MFn::kMeshEdgeComponent ); indexedCompFn.addElement( edgeIndex ); newEdgesSel.add( dagPath, newComponent ); //MGlobal::displayInfo( MString("ADDING: ") + edgeIter.index() ); edgeIter.getConnectedFaces( faces ); faceIndex = faces[0]; if( faces.length() > 1 ) { // Select the face that hasn't already been visited for( i=0; i < facesVisited.length(); i++ ) { if( faceIndex == facesVisited[i] ) { faceIndex = faces[1]; break; } } } //MGlobal::displayInfo( MString("FACE: ") + faceIndex ); facesVisited.append( faceIndex ); MItMeshPolygon polyIter( dagPath ); polyIter.setIndex( faceIndex, prevIndex ); //MGlobal::displayInfo( MString( "faces: " ) + faces[0] + " " + faces[1] ); MIntArray edges; polyIter.getEdges( edges ); // Determine the face-relative index of the current // edge unsigned int edgeFaceIndex = 0; for( i=0; i < edges.length(); i++ ) { if( edges[i] == edgeIter.index() ) { edgeFaceIndex = i; break; } } // Determine the edge that is opposite the current edge edgeIndex = edges[ (edgeFaceIndex + (edges.length() / 2) ) % edges.length() ]; //int index = edgeIter.index(); //MGlobal::displayInfo( MString( "sel edge index: " ) + index + " next edge: " + edgeIndex ); // Set the current edge to the opposite edge edgeIter.setIndex( edgeIndex, prevIndex ); // Determine if the edge has already been visited for( i=0; i < edgesVisited.length(); i++ ) { if( edgeIndex == edgesVisited[i] ) { finished = true; break; } } } } // Set the active selection to the one previous to edge loop selection MGlobal::setActiveSelectionList( curSel, MGlobal::kReplaceList); // Update this selection based on the list adjustment setting MGlobal::selectCommand( newEdgesSel, listAdjust ); return MS::kSuccess; }
MStatus LSystemNode::compute(const MPlug& plug, MDataBlock& data) { MStatus returnStatus; if (plug == outputMesh) { /* Get time */ MDataHandle timeData = data.inputValue( time, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); MTime time = timeData.asTime(); MDataHandle angleData = data.inputValue( angle, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); double angle_value = angleData.asDouble(); MDataHandle stepsData = data.inputValue( steps, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); double steps_value = stepsData.asDouble(); MDataHandle grammarData = data.inputValue( grammar, &returnStatus ); McheckErr(returnStatus, "Error getting time data handle\n"); MString grammar_value = grammarData.asString(); /* Get output object */ MDataHandle outputHandle = data.outputValue(outputMesh, &returnStatus); McheckErr(returnStatus, "ERROR getting polygon data handle\n"); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&returnStatus); McheckErr(returnStatus, "ERROR creating outputData"); MFnMesh myMesh; MPointArray points; MIntArray faceCounts; MIntArray faceConnects; //MString grammar = ("F\\nF->F[+F]F[-F]F"); CylinderMesh *cm; LSystem system; system.loadProgramFromString(grammar_value.asChar()); system.setDefaultAngle(angle_value); system.setDefaultStep(steps_value); std::vector<LSystem::Branch> branches; system.process(time.value(), branches); int k = branches.size(); for(int j = 0; j < branches.size(); j++) { //1. find the position for start and end point of current branch //2. generate a cylinder MPoint start(branches[j].first[0],branches[j].first[1],branches[j].first[2]); MPoint end(branches[j].second[0],branches[j].second[1],branches[j].second[2]); cm = new CylinderMesh(start, end); cm->appendToMesh(points, faceCounts, faceConnects); } MObject newMesh = myMesh.create(points.length(), faceCounts.length(), points, faceCounts, faceConnects, newOutputData, &returnStatus); McheckErr(returnStatus, "ERROR creating new mesh"); outputHandle.set(newOutputData); data.setClean( plug ); } else return MS::kUnknownParameter; return MS::kSuccess; }
// write a normal mesh // MStatus vxCache::writeMesh(const char* filename, MDagPath meshDag, const MObject& meshObj) { struct meshInfo mesh; MString uvset("map1"); MStatus status; MFnMesh meshFn(meshDag, &status ); MItMeshPolygon faceIter( meshDag, MObject::kNullObj, &status ); MItMeshVertex vertIter(meshDag, MObject::kNullObj, &status); MItMeshEdge edgeIter(meshDag, MObject::kNullObj, &status); mesh.numPolygons = meshFn.numPolygons(); mesh.numVertices = meshFn.numVertices(); mesh.numFaceVertices = meshFn.numFaceVertices(); mesh.numUVs = meshFn.numUVs(uvset, &status); mesh.skip_interreflection = mesh.skip_scattering = 0; //if(zWorks::hasNamedAttribute(meshObj, "_prt_ig_intr") == 1) mesh.skip_interreflection = 1; //if(zWorks::hasNamedAttribute(meshObj, "_prt_ig_scat") == 1) mesh.skip_scattering = 1; //zWorks::displayIntParam("N Face", mesh.numPolygons); //zWorks::displayIntParam("N Vertex", mesh.numVertices); //zWorks::displayIntParam("N Facevertex", mesh.numFaceVertices); //zWorks::displayIntParam("N UV", mesh.numUVs); int *fcbuf = new int[mesh.numPolygons]; faceIter.reset(); for( ; !faceIter.isDone(); faceIter.next() ) { fcbuf[ faceIter.index() ] = faceIter.polygonVertexCount(); } int* vertex_id = new int[mesh.numFaceVertices]; int* uv_id = new int[mesh.numFaceVertices]; // output face loop int acc = 0; faceIter.reset(); for( ; !faceIter.isDone(); faceIter.next() ) { MIntArray vexlist; faceIter.getVertices ( vexlist ); for( unsigned int i=0; i < vexlist.length(); i++ ) { vertex_id[acc] = vexlist[i]; faceIter.getUVIndex ( i, uv_id[acc] ); acc++; } } // output vertices MPointArray pArray; if(worldSpace) meshFn.getPoints ( pArray, MSpace::kWorld); else meshFn.getPoints ( pArray, MSpace::kObject ); XYZ *pbuf = new XYZ[pArray.length()]; for( unsigned int i=0; i<pArray.length(); i++) { pbuf[i].x = pArray[i].x; pbuf[i].y = pArray[i].y; pbuf[i].z= pArray[i].z; } //output texture coordinate MFloatArray uArray, vArray; meshFn.getUVs ( uArray, vArray, &uvset ); double* ubuf = new double[mesh.numUVs]; double* vbuf = new double[mesh.numUVs]; for( unsigned int i=0; i<uArray.length(); i++) { ubuf[i] = uArray[i]; vbuf[i] = vArray[i]; } /* XYZ *norbuf = new XYZ[mesh.numVertices]; vertIter.reset(); MVector tnor; for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ ) { if(worldSpace) vertIter.getNormal(tnor, MSpace::kWorld); else vertIter.getNormal(tnor, MSpace::kObject); tnor.normalize(); norbuf[i].x = tnor.x; norbuf[i].y = tnor.y; norbuf[i].z = tnor.z; } MStatus hasAttr; MString sColorSet("set_prt_attr"); meshFn.numColors( sColorSet, &hasAttr ); XYZ *colbuf = new XYZ[mesh.numVertices]; vertIter.reset(); if(hasAttr) { MColor col; for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ ) { MIntArray conn_face; vertIter.getConnectedFaces(conn_face); vertIter.getColor(col, conn_face[0], &sColorSet); colbuf[i].x = col.r; colbuf[i].y = col.g; colbuf[i].z = col.b; } } else { for( unsigned int i=0; i<vertIter.count(); i++ ) colbuf[i] = XYZ(1.0f); } vertIter.reset(); XYZ *vsbuf = new XYZ[mesh.numVertices]; for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ ) { MIntArray conn_face, conn_edge; vertIter.getConnectedFaces(conn_face); vertIter.getConnectedEdges(conn_edge); MPoint Q; for(unsigned j=0; j<conn_face.length(); j++) { int pre_id; faceIter.setIndex(conn_face[j],pre_id); Q += faceIter.center(MSpace::kWorld); } Q = Q/(double)conn_face.length(); MPoint R; for(unsigned j=0; j<conn_edge.length(); j++) { int pre_id; edgeIter.setIndex(conn_edge[j], pre_id); R += edgeIter.center(MSpace::kWorld); } R = R/(double)conn_edge.length(); MPoint S = vertIter.position(MSpace::kWorld); int nv = conn_edge.length(); MPoint nS = (Q + R*2 + S*(nv-3))/nv; vsbuf[i].x = nS.x; vsbuf[i].y = nS.y; vsbuf[i].z = nS.z; } XYZ *tangbuf = new XYZ[mesh.numVertices]; vertIter.reset(); for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ ) { MIntArray conn_face; MVector tang(0,0,0); vertIter.getConnectedFaces(conn_face); //for(int j = 0; j<conn_face.length(); j++) { MVector ttang; meshFn.getFaceVertexTangent (conn_face[0], i, ttang, MSpace::kWorld, &uvset); tang += ttang; } tang.normalize(); tangbuf[i].x = tang.x; tangbuf[i].y = tang.y; tangbuf[i].z = tang.z; tangbuf[i] = norbuf[i].cross(tangbuf[i]); tangbuf[i].normalize(); } */ FMCFMesh fmesh; fmesh.save(mesh.numVertices, mesh.numFaceVertices, mesh.numPolygons, mesh.numUVs, mesh.skip_interreflection, mesh.skip_scattering, fcbuf, vertex_id, uv_id, pbuf, //vsbuf, //norbuf, //tangbuf, //colbuf, ubuf, vbuf, filename); delete[] fcbuf; delete[] vertex_id; delete[] uv_id; delete[] pbuf; //delete[] vsbuf; //delete[] norbuf; //delete[] tangbuf; //delete[] colbuf; delete[] ubuf; delete[] vbuf; return MS::kSuccess; }
void MayaMeshWriter::getPolyNormals(std::vector<float> & oNormals) { MStatus status = MS::kSuccess; MFnMesh lMesh( mDagPath, &status ); if ( !status ) { MGlobal::displayError( "MFnMesh() failed for MayaMeshWriter" ); } // no normals bail early if (mNoNormals) { return; } MPlug plug = lMesh.findPlug("noNormals", true, &status); if (status == MS::kSuccess && plug.asBool() == true) { return; } // we need to check the locked state of the normals else if ( status != MS::kSuccess ) { bool userSetNormals = false; // go through all per face-vertex normals and verify if any of them // has been tweaked by users unsigned int numFaces = lMesh.numPolygons(); for (unsigned int faceIndex = 0; faceIndex < numFaces; faceIndex++) { MIntArray normals; lMesh.getFaceNormalIds(faceIndex, normals); unsigned int numNormals = normals.length(); for (unsigned int n = 0; n < numNormals; n++) { if (lMesh.isNormalLocked(normals[n])) { userSetNormals = true; break; } } } // we looped over all the normals and they were all calculated by Maya // so we just need to check to see if any of the edges are hard // before we decide not to write the normals. if (!userSetNormals) { bool hasHardEdges = false; // go through all edges and verify if any of them is hard edge unsigned int numEdges = lMesh.numEdges(); for (unsigned int edgeIndex = 0; edgeIndex < numEdges; edgeIndex++) { if (!lMesh.isEdgeSmooth(edgeIndex)) { hasHardEdges = true; break; } } // all the edges were smooth, we don't need to write the normals if (!hasHardEdges) { return; } } } bool flipNormals = false; plug = lMesh.findPlug("flipNormals", true, &status); if ( status == MS::kSuccess ) flipNormals = plug.asBool(); // get the per vertex per face normals (aka vertex) unsigned int numFaces = lMesh.numPolygons(); for (unsigned int faceIndex = 0; faceIndex < numFaces; faceIndex++ ) { MIntArray vertexList; lMesh.getPolygonVertices(faceIndex, vertexList); // re-pack the order of normals in this vector before writing into prop // so that Renderman can also use it unsigned int numVertices = vertexList.length(); for ( int v = numVertices-1; v >=0; v-- ) { unsigned int vertexIndex = vertexList[v]; MVector normal; lMesh.getFaceVertexNormal(faceIndex, vertexIndex, normal); if (flipNormals) normal = -normal; oNormals.push_back(static_cast<float>(normal[0])); oNormals.push_back(static_cast<float>(normal[1])); oNormals.push_back(static_cast<float>(normal[2])); } } }
MStatus DDConvexHullUtils::componentToVertexIDs(MIntArray &outIndices, const MObject &mesh, const MObject &component) { // Create the funciton sets MFnSingleIndexedComponent compFn(component); MFnMesh meshFn(mesh); MIntArray elems; compFn.getElements(elems); uint elemLen = elems.length(); // Convert the components to vertices based on component type uint compType = compFn.componentType(); if (compType == MFn::kMeshVertComponent) { outIndices = elems; } else if (compType == MFn::kMeshEdgeComponent) { for (uint i=0; i < elemLen; i++) { int2 edgeVerts; meshFn.getEdgeVertices(elems[i], edgeVerts); outIndices.append(edgeVerts[0]); outIndices.append(edgeVerts[1]); } } else if (compType == MFn::kMeshPolygonComponent) { for (uint i=0; i < elemLen; i++) { // Grab verts for the current poly MIntArray polyVerts; meshFn.getPolygonVertices(elems[i], polyVerts); uint polyVertsLen = polyVerts.length(); for (uint j=0; j < polyVertsLen; j++) { outIndices.append(polyVerts[j]); } } } else if (compType == MFn::kMeshFaceVertComponent) { // I think this is how you convert face to object // relative vertices... MIntArray faceCounts; MIntArray faceVerts; meshFn.getVertices(faceCounts, faceVerts); for (uint j=0; j < elemLen; j++) { outIndices.append(faceVerts[j]); } } else { // Not supported return MStatus::kNotImplemented; } return MStatus::kSuccess; }
bool CXRayObjectExport::initializeSetsAndLookupTables( bool exportAll ) // // Description : // Creates a list of all sets in Maya, a list of mesh objects, // and polygon/vertex lookup tables that will be used to // determine which sets are referenced by the poly components. // { int i=0,j=0, length; MStatus stat; // Initialize class data. // Note: we cannot do this in the constructor as it // only gets called upon registry of the plug-in. // numSets = 0; sets = NULL; lastSets = NULL; lastMaterials = NULL; objectId = 0; objectCount = 0; polygonTable = NULL; vertexTable = NULL; polygonTablePtr = NULL; vertexTablePtr = NULL; objectGroupsTablePtr = NULL; objectNodeNamesArray.clear(); transformNodeNameArray.clear(); ////////////////////////////////////////////////////////////////// // // Find all sets in Maya and store the ones we care about in // the 'sets' array. Also make note of the number of sets. // ////////////////////////////////////////////////////////////////// // Get all of the sets in maya and put them into // a selection list // MStringArray result; MGlobal::executeCommand( "ls -sets", result ); MSelectionList * setList = new MSelectionList(); length = result.length(); for ( i=0; i<length; i++ ) { setList->add( result[i] ); } // Extract each set as an MObject and add them to the // sets array. // We may be excluding groups, matierials, or ptGroups // in which case we can ignore those sets. // MObject mset; sets = new MObjectArray(); length = setList->length(); for ( i=0; i<length; i++ ) { setList->getDependNode( i, mset ); MFnSet fnSet( mset, &stat ); if ( stat ) { if ( MFnSet::kRenderableOnly == fnSet.restriction(&stat) ) { sets->append( mset ); } } } xr_delete(setList); numSets = sets->length(); ////////////////////////////////////////////////////////////////// // // Do a dag-iteration and for every mesh found, create facet and // vertex look-up tables. These tables will keep track of which // sets each component belongs to. // // If exportAll is false then iterate over the activeSelection // list instead of the entire DAG. // // These arrays have a corrisponding entry in the name // stringArray. // ////////////////////////////////////////////////////////////////// MIntArray vertexCounts; MIntArray polygonCounts; if ( exportAll ) { MItDag dagIterator( MItDag::kBreadthFirst, MFn::kInvalid, &stat); if ( MS::kSuccess != stat) { fprintf(stderr,"Failure in DAG iterator setup.\n"); return false; } objectNames = new MStringArray(); for ( ; !dagIterator.isDone(); dagIterator.next() ) { MDagPath dagPath; stat = dagIterator.getPath( dagPath ); if ( stat ) { // skip over intermediate objects // MFnDagNode dagNode( dagPath, &stat ); if (dagNode.isIntermediateObject()) { continue; } if (( dagPath.hasFn(MFn::kMesh)) && ( dagPath.hasFn(MFn::kTransform))) { // We want only the shape, // not the transform-extended-to-shape. continue; } else if ( dagPath.hasFn(MFn::kMesh)) { // We have a mesh so create a vertex and polygon table // for this object. // MFnMesh fnMesh( dagPath ); int vtxCount = fnMesh.numVertices(); int polygonCount = fnMesh.numPolygons(); // we do not need this call anymore, we have the shape. // dagPath.extendToShape(); MString name = dagPath.fullPathName(); objectNames->append( name ); objectNodeNamesArray.append( fnMesh.name() ); vertexCounts.append( vtxCount ); polygonCounts.append( polygonCount ); objectCount++; } } } }else{ MSelectionList slist; MGlobal::getActiveSelectionList( slist ); MItSelectionList iter( slist ); MStatus status; objectNames = new MStringArray(); // We will need to interate over a selected node's heirarchy // in the case where shapes are grouped, and the group is selected. MItDag dagIterator( MItDag::kDepthFirst, MFn::kInvalid, &status); for ( ; !iter.isDone(); iter.next() ){ MDagPath objectPath; stat = iter.getDagPath( objectPath ); // reset iterator's root node to be the selected node. status = dagIterator.reset (objectPath.node(), MItDag::kDepthFirst, MFn::kInvalid ); // DAG iteration beginning at at selected node for ( ; !dagIterator.isDone(); dagIterator.next() ){ MDagPath dagPath; MObject component = MObject::kNullObj; status = dagIterator.getPath(dagPath); if (!status){ fprintf(stderr,"Failure getting DAG path.\n"); freeLookupTables(); return false; } // skip over intermediate objects // MFnDagNode dagNode( dagPath, &stat ); if (dagNode.isIntermediateObject()) continue; if (( dagPath.hasFn(MFn::kMesh)) && ( dagPath.hasFn(MFn::kTransform))){ // We want only the shape, // not the transform-extended-to-shape. continue; }else if ( dagPath.hasFn(MFn::kMesh)){ // We have a mesh so create a vertex and polygon table // for this object. // MFnMesh fnMesh( dagPath ); int vtxCount = fnMesh.numVertices(); int polygonCount = fnMesh.numPolygons(); // we do not need this call anymore, we have the shape. // dagPath.extendToShape(); MString name = dagPath.fullPathName(); objectNames->append( name ); objectNodeNamesArray.append( fnMesh.name() ); vertexCounts.append( vtxCount ); polygonCounts.append( polygonCount ); objectCount++; } } } } // Now we know how many objects we are dealing with // and we have counts of the vertices/polygons for each // object so create the maya group look-up table. // if( objectCount > 0 ) { // To export Maya groups we traverse the hierarchy starting at // each objectNodeNamesArray[i] going towards the root collecting transform // nodes as we go. length = objectNodeNamesArray.length(); for( i=0; i<length; i++ ) { MIntArray transformNodeNameIndicesArray; recFindTransformDAGNodes( objectNodeNamesArray[i], transformNodeNameIndicesArray ); } if( transformNodeNameArray.length() > 0 ) { objectGroupsTablePtr = xr_alloc<bool*>(objectCount);// (bool**) malloc( sizeof(bool*)*objectCount ); length = transformNodeNameArray.length(); for ( i=0; i<objectCount; i++ ) { // objectGroupsTablePtr[i] = (bool*)calloc( length, sizeof(bool) ); objectGroupsTablePtr[i] = xr_alloc<bool>(length); ZeroMemory(objectGroupsTablePtr[i],length*sizeof(bool)); // XXX nitrocaster: remove this 'cause malloc failure shouldn't be handled there if ( objectGroupsTablePtr[i] == NULL ) { Log("! calloc returned NULL (objectGroupsTablePtr)"); return false; } } } // else{ // Log("! Can't find transform for node."); // return false; // } } // Create the vertex/polygon look-up tables. // if ( objectCount > 0 ) { vertexTablePtr = xr_alloc<bool*>(objectCount); //(bool**) malloc( sizeof(bool*)*objectCount ); polygonTablePtr = xr_alloc<bool*>(objectCount); //(bool**) malloc( sizeof(bool*)*objectCount ); for ( i=0; i<objectCount; i++ ) { // vertexTablePtr[i] = (bool*)calloc( vertexCounts[i]*numSets, sizeof(bool) ); vertexTablePtr[i] = xr_alloc<bool>(vertexCounts[i]*numSets); ZeroMemory(vertexTablePtr[i],vertexCounts[i]*numSets*sizeof(bool)); // XXX nitrocaster: remove this 'cause malloc failure shouldn't be handled there if ( vertexTablePtr[i] == NULL ) { Log("! calloc returned NULL (vertexTable)"); return false; } // polygonTablePtr[i] = (bool*)calloc( polygonCounts[i]*numSets, sizeof(bool) ); polygonTablePtr[i] = xr_alloc<bool>(polygonCounts[i]*numSets); ZeroMemory(polygonTablePtr[i],polygonCounts[i]*numSets*sizeof(bool)); // XXX nitrocaster: remove this 'cause malloc failure shouldn't be handled there if ( polygonTablePtr[i] == NULL ) { Log("! calloc returned NULL (polygonTable)"); return false; } } } // If we found no meshes then return // if ( objectCount == 0 ) { return false; } ////////////////////////////////////////////////////////////////// // // Go through all of the set members (flattened lists) and mark // in the lookup-tables, the sets that each mesh component belongs // to. // // ////////////////////////////////////////////////////////////////// bool flattenedList = true; MDagPath object; MObject component; MSelectionList memberList; for ( i=0; i<numSets; i++ ) { MFnSet fnSet( (*sets)[i] ); memberList.clear(); stat = fnSet.getMembers( memberList, flattenedList ); if (MS::kSuccess != stat) { fprintf(stderr,"Error in fnSet.getMembers()!\n"); } int m, numMembers; numMembers = memberList.length(); for ( m=0; m<numMembers; m++ ) { if ( memberList.getDagPath(m,object,component) ) { if ( (!component.isNull()) && (object.apiType() == MFn::kMesh) ) { if (component.apiType() == MFn::kMeshVertComponent) { MItMeshVertex viter( object, component ); for ( ; !viter.isDone(); viter.next() ) { int compIdx = viter.index(); MString name = object.fullPathName(); // Figure out which object vertexTable // to get. // int o, numObjectNames; numObjectNames = objectNames->length(); for ( o=0; o<numObjectNames; o++ ) { if ( (*objectNames)[o] == name ) { // Mark set i as true in the table // vertexTable = vertexTablePtr[o]; *(vertexTable + numSets*compIdx + i) = true; break; } } } } else if (component.apiType() == MFn::kMeshPolygonComponent) { MItMeshPolygon piter( object, component ); for ( ; !piter.isDone(); piter.next() ) { int compIdx = piter.index(); MString name = object.fullPathName(); // Figure out which object polygonTable // to get. // int o, numObjectNames; numObjectNames = objectNames->length(); for ( o=0; o<numObjectNames; o++ ) { if ( (*objectNames)[o] == name ) { // Mark set i as true in the table // // Check for bad components in the set // if ( compIdx >= polygonCounts[o] ) { Msg("! Bad polygon index '%d' found. Polygon skipped",compIdx); break; } polygonTable = polygonTablePtr[o]; *(polygonTable + numSets*compIdx + i) = true; break; } } } } } else { // There are no components, therefore we can mark // all polygons as members of the given set. // if (object.hasFn(MFn::kMesh)) { MFnMesh fnMesh( object, &stat ); if ( MS::kSuccess != stat) { fprintf(stderr,"Failure in MFnMesh initialization.\n"); return false; } // We are going to iterate over all the polygons. // MItMeshPolygon piter( object, MObject::kNullObj, &stat ); if ( MS::kSuccess != stat) { fprintf(stderr, "Failure in MItMeshPolygon initialization.\n"); return false; } for ( ; !piter.isDone(); piter.next() ) { int compIdx = piter.index(); MString name = object.fullPathName(); // Figure out which object polygonTable to get. // int o, numObjectNames; numObjectNames = objectNames->length(); for ( o=0; o<numObjectNames; o++ ) { if ( (*objectNames)[o] == name ) { // Check for bad components in the set // if ( compIdx >= polygonCounts[o] ) { Msg("! Bad polygon index '%d' found. Polygon skipped",compIdx); break; } // Mark set i as true in the table // polygonTable = polygonTablePtr[o]; *(polygonTable + numSets*compIdx + i) = true; break; } } } // end of piter.next() loop } // end of condition if (object.hasFn(MFn::kMesh)) } // end of else condifion if (!component.isNull()) } // end of memberList.getDagPath(m,object,component) } // end of memberList loop } // end of for-loop for sets // Go through all of the group members and mark in the // lookup-table, the group that each shape belongs to. length = objectNodeNamesArray.length(); if (objectGroupsTablePtr){ for( i=0; i<length; i++ ) { MIntArray groupTableIndicesArray; bool *objectGroupTable = objectGroupsTablePtr[i]; int length2; recFindTransformDAGNodes( objectNodeNamesArray[i], groupTableIndicesArray ); length2 = groupTableIndicesArray.length(); for( j=0; j<length2; j++ ) { int groupIdx = groupTableIndicesArray[j]; objectGroupTable[groupIdx] = true; } } } return true; }
// // Main routine /////////////////////////////////////////////////////////////////////////////// MStatus particleSystemInfoCmd::doIt( const MArgList& args ) { MStatus stat = parseArgs( args ); if( stat != MS::kSuccess ) return stat; if( particleNode.isNull() ) { MObject parent; MFnParticleSystem dummy; particleNode = dummy.create(&stat); CHECKRESULT(stat,"MFnParticleSystem::create(status) failed!"); MFnParticleSystem ps( particleNode, &stat ); CHECKRESULT(stat,"MFnParticleSystem::MFnParticleSystem(MObject,status) failed!"); MPointArray posArray; posArray.append(MPoint(-5, 5, 0)); posArray.append(MPoint(-5, 10, 0)); MVectorArray velArray; velArray.append(MPoint(1, 1, 0)); velArray.append(MPoint(1, 1, 0)); stat = ps.emit(posArray, velArray); CHECKRESULT(stat,"MFnParticleSystem::emit(posArray,velArray) failed!"); stat = ps.emit(MPoint(5, 5, 0)); CHECKRESULT(stat,"MFnParticleSystem::emit(pos) failed!"); stat = ps.emit(MPoint(5, 10, 0)); CHECKRESULT(stat,"MFnParticleSystem::emit(pos) failed!"); stat = ps.saveInitialState(); CHECKRESULT(stat,"MFnParticleSystem::saveInitialState() failed!"); MVectorArray accArray; accArray.setLength(4); for( unsigned int i=0; i<accArray.length(); i++ ) { MVector& acc = accArray[i]; acc.x = acc.y = acc.z = 3.0; } MString accName("acceleration"); ps.setPerParticleAttribute( accName, accArray, &stat ); CHECKRESULT(stat,"MFnParticleSystem::setPerParticleAttribute(vectorArray) failed!"); } MFnParticleSystem ps( particleNode, &stat ); CHECKRESULT(stat,"MFnParticleSystem::MFnParticleSystem(MObject,status) failed!"); if( ! ps.isValid() ) { MGlobal::displayError( "The function set is invalid!" ); return MS::kFailure; } const MString name = ps.particleName(); const MFnParticleSystem::RenderType psType = ps.renderType(); const unsigned int count = ps.count(); const char* typeString = NULL; switch( psType ) { case MFnParticleSystem::kCloud: typeString = "Cloud"; break; case MFnParticleSystem::kTube: typeString = "Tube system"; break; case MFnParticleSystem::kBlobby: typeString = "Blobby"; break; case MFnParticleSystem::kMultiPoint: typeString = "MultiPoint"; break; case MFnParticleSystem::kMultiStreak: typeString = "MultiStreak"; break; case MFnParticleSystem::kNumeric: typeString = "Numeric"; break; case MFnParticleSystem::kPoints: typeString = "Points"; break; case MFnParticleSystem::kSpheres: typeString = "Spheres"; break; case MFnParticleSystem::kSprites: typeString = "Sprites"; break; case MFnParticleSystem::kStreak: typeString = "Streak"; break; default: typeString = "Particle system"; assert( false ); break; } char buffer[256]; sprintf( buffer, "%s \"%s\" has %u primitives.", typeString, name.asChar(), count ); MGlobal::displayInfo( buffer ); unsigned i; MIntArray ids; ps.particleIds( ids ); sprintf( buffer, "count : %u ", count ); MGlobal::displayInfo( buffer ); sprintf( buffer, "%u ids.", ids.length() ); MGlobal::displayInfo( buffer ); assert( ids.length() == count ); for( i=0; i<ids.length(); i++ ) { sprintf( buffer, "id %d ", ids[i] ); MGlobal::displayInfo( buffer ); } MVectorArray positions; ps.position( positions ); assert( positions.length() == count ); for( i=0; i<positions.length(); i++ ) { MVector& p = positions[i]; sprintf( buffer, "pos %f %f %f ", p[0], p[1], p[2] ); MGlobal::displayInfo( buffer ); } MVectorArray vels; ps.velocity( vels ); assert( vels.length() == count ); for( i=0; i<vels.length(); i++ ) { const MVector& v = vels[i]; sprintf( buffer, "vel %f %f %f ", v[0], v[1], v[2] ); MGlobal::displayInfo( buffer ); } MVectorArray accs; ps.acceleration( accs ); assert( accs.length() == count ); for( i=0; i<accs.length(); i++ ) { const MVector& a = accs[i]; sprintf( buffer, "acc %f %f %f ", a[0], a[1], a[2] ); MGlobal::displayInfo( buffer ); } bool flag = ps.isDeformedParticleShape(&stat); CHECKRESULT(stat,"MFnParticleSystem::isDeformedParticleShape() failed!"); if( flag ) { MObject obj = ps.originalParticleShape(&stat); CHECKRESULT(stat,"MFnParticleSystem::originalParticleShape() failed!"); if( obj != MObject::kNullObj ) { MFnParticleSystem ps( obj ); sprintf( buffer, "original particle shape : %s ", ps.particleName().asChar() ); MGlobal::displayInfo( buffer ); } } flag = ps.isDeformedParticleShape(&stat); CHECKRESULT(stat,"MFnParticleSystem::isDeformedParticleShape() failed!"); if( !flag ) { MObject obj = ps.deformedParticleShape(&stat); CHECKRESULT(stat,"MFnParticleSystem::deformedParticleShape() failed!"); if( obj != MObject::kNullObj ) { MFnParticleSystem ps( obj ); sprintf( buffer, "deformed particle shape : %s ", ps.particleName().asChar() ); MGlobal::displayInfo( buffer ); } } if( ids.length() == positions.length() && ids.length() == vels.length() && ids.length() == accs.length() ) { setResult( int(ids.length()) ); } else { setResult( int(-1) ); } return MS::kSuccess; }
bool tm_polyExtract::extractFaces_Func( MSelectionList &selectionList, MStringArray &node_names) { MStatus status; MObject meshObj; status = selectionList.getDependNode( 0, meshObj); if(!status){MGlobal::displayError("tm_polyExtract::extractFaces_Func: Can't find object !");return false;} MFnMesh meshFn( meshObj, &status); if(!status){MGlobal::displayError("tm_polyExtract::extractFaces_Func: Non mesh object founded !");return false;} MDagPath meshDagPath_first, meshDagPath; selectionList.getDagPath( 0, meshDagPath_first); MObject multiFaceComponent; MIntArray inputFacesArray; inputFacesArray.clear(); inputFacesArray.setSizeIncrement( 4096); MFnComponentListData compListFn; compListFn.create(); for (MItSelectionList faceComponentIter(selectionList, MFn::kMeshPolygonComponent); !faceComponentIter.isDone(); faceComponentIter.next()) { faceComponentIter.getDagPath(meshDagPath, multiFaceComponent); if(!(meshDagPath_first == meshDagPath)) { MGlobal::displayError("tm_polyExtract::extractFaces_Func: Different meshes faces founded !"); return false; } if (!multiFaceComponent.isNull()) { for (MItMeshPolygon faceIter(meshDagPath, multiFaceComponent); !faceIter.isDone(); faceIter.next()) { int faceIndex = faceIter.index(); #ifdef _DEBUG infoMStr += faceIndex; infoMStr += " "; #endif inputFacesArray.append( faceIndex); compListFn.add( multiFaceComponent ); } } } if( inputFacesArray.length() == 0) { MGlobal::displayError("tm_polyExtract::extractFaces_Func: No faces founded !"); return false; } #ifdef _DEBUG MGlobal::displayInfo( infoMStr); #endif meshFn.setObject( meshDagPath_first); meshObj = meshFn.object(); // MDagModifier dagModifier; MFnDagNode meshDagNodeFn; MFnDependencyNode depNodeFn; meshDagNodeFn.setObject( meshDagPath_first); MString meshName = meshDagNodeFn.name(); MObject outMesh_attrObject = meshDagNodeFn.attribute( "outMesh"); // ----------------------------------- duplicate shape MObject duplicated_meshObjectA; MObject duplicated_meshObjectB; MObject inMesh_attrObjectA; MObject inMesh_attrObjectB; /* MStringArray commandResult; MSelectionList selList; MGlobal::executeCommand( "duplicate " + meshDagNodeFn.name(), commandResult, 1, 1); selList.add( commandResult[0]); selList.getDependNode( 0, duplicated_meshObjectA); meshDagNodeFn.setObject( duplicated_meshObjectA); meshDagNodeFn.setName( meshName + "_tA"); duplicated_meshObjectA = meshDagNodeFn.child(0); meshDagNodeFn.setObject( duplicated_meshObjectA); meshDagNodeFn.setName( meshName + "_sA"); inMesh_attrObjectA = meshDagNodeFn.attribute( "inMesh"); meshDagNodeFn.setObject( meshDagPath_first); selList.clear(); MGlobal::executeCommand( "duplicate " + meshDagNodeFn.name(), commandResult, 1, 1); selList.add( commandResult[0]); selList.getDependNode( 0, duplicated_meshObjectB); meshDagNodeFn.setObject( duplicated_meshObjectB); meshDagNodeFn.setName( meshName + "_tB"); duplicated_meshObjectB = meshDagNodeFn.child(0); meshDagNodeFn.setObject( duplicated_meshObjectB); meshDagNodeFn.setName( meshName + "_sB"); inMesh_attrObjectB = meshDagNodeFn.attribute( "inMesh"); */ duplicated_meshObjectA = meshDagNodeFn.duplicate(); meshDagNodeFn.setObject( duplicated_meshObjectA); meshDagNodeFn.setName( meshName + "_tA"); duplicated_meshObjectA = meshDagNodeFn.child(0); meshDagNodeFn.setObject( duplicated_meshObjectA); meshDagNodeFn.setName( meshName + "_sA"); inMesh_attrObjectA = meshDagNodeFn.attribute( "inMesh"); meshDagNodeFn.setObject( meshDagPath_first); duplicated_meshObjectB = meshDagNodeFn.duplicate(); meshDagNodeFn.setObject( duplicated_meshObjectB); meshDagNodeFn.setName( meshName + "_tB"); duplicated_meshObjectB = meshDagNodeFn.child(0); meshDagNodeFn.setObject( duplicated_meshObjectB); meshDagNodeFn.setName( meshName + "_sB"); inMesh_attrObjectB = meshDagNodeFn.attribute( "inMesh"); // ----------------------------------- create node deleteComponent MDGModifier dgModifier; MObject deleteComponent_nodeObjectA = dgModifier.createNode( MString("deleteComponent")); depNodeFn.setObject( deleteComponent_nodeObjectA ); MObject deleteComponent_attrObjectA( depNodeFn.attribute( "deleteComponents" )); MObject inputGeometry_attrObjectA( depNodeFn.attribute( "inputGeometry" )); MObject outputGeometry_attrObjectA( depNodeFn.attribute( "outputGeometry" )); dgModifier.doIt(); depNodeFn.setName( "dfA_" + meshName); node_names.append( depNodeFn.name()); MObject deleteComponent_nodeObjectB = dgModifier.createNode( MString("deleteComponent")); depNodeFn.setObject( deleteComponent_nodeObjectB ); MObject deleteComponent_attrObjectB( depNodeFn.attribute( "deleteComponents" )); MObject inputGeometry_attrObjectB( depNodeFn.attribute( "inputGeometry" )); MObject outputGeometry_attrObjectB( depNodeFn.attribute( "outputGeometry" )); dgModifier.doIt(); depNodeFn.setName( "dfB_" + meshName); node_names.append( depNodeFn.name()); // ----------------------------------- set attribute deleteComponent.deleteComponents MObject componentList_object = compListFn.object(); MPlug deleteComponents_plugA( deleteComponent_nodeObjectA, deleteComponent_attrObjectA ); status = deleteComponents_plugA.setValue( componentList_object ); MIntArray invertedFaces; int numPolygons = meshFn.numPolygons(); invertedFaces.setLength( numPolygons - inputFacesArray.length()); int selFace = 0; int invFace = 0; for( int f = 0; f < numPolygons; f++) { if( f == inputFacesArray[selFace]) selFace++; else invertedFaces[invFace++] = f; } MFnSingleIndexedComponent singleIndexedComponentFn( meshObj); singleIndexedComponentFn.create( MFn::kMeshPolygonComponent); singleIndexedComponentFn.addElements( invertedFaces); compListFn.clear(); compListFn.create(); componentList_object = singleIndexedComponentFn.object(); compListFn.add( componentList_object); componentList_object = compListFn.object(); MPlug deleteComponents_plugB( deleteComponent_nodeObjectB, deleteComponent_attrObjectB ); status = deleteComponents_plugB.setValue( componentList_object ); // ------------------------------------- connecting plugs /**/ dgModifier.connect( meshObj, outMesh_attrObject, deleteComponent_nodeObjectA, inputGeometry_attrObjectA ); dgModifier.connect( deleteComponent_nodeObjectA, outputGeometry_attrObjectA, duplicated_meshObjectA, inMesh_attrObjectA ); dgModifier.connect( meshObj, outMesh_attrObject, deleteComponent_nodeObjectB, inputGeometry_attrObjectB ); dgModifier.connect( deleteComponent_nodeObjectB, outputGeometry_attrObjectB, duplicated_meshObjectB, inMesh_attrObjectB ); dgModifier.doIt(); // ---------------------------------- assigning shading group /**/ meshDagNodeFn.setObject( meshDagPath_first); MObject instObjGroups_attrObject = meshDagNodeFn.attribute( "instObjGroups"); MPlug instObjGroups_plug( meshObj, instObjGroups_attrObject); instObjGroups_plug = instObjGroups_plug.elementByPhysicalIndex(0); MPlugArray instObjGroups_plug_connectionsArray; instObjGroups_plug.connectedTo( instObjGroups_plug_connectionsArray, false, true); if( instObjGroups_plug_connectionsArray.length() > 0) { MPlug dagSetMembers_plug = instObjGroups_plug_connectionsArray[0]; MObject shadingSetNode_object = dagSetMembers_plug.node(); MFnSet setFn( shadingSetNode_object); setFn.addMember( duplicated_meshObjectA); setFn.addMember( duplicated_meshObjectB); //depNodeFn.setObject(shadingSetNode_object); //MGlobal::displayInfo( depNodeFn.name()); } // ------------------------------------------------------------ return true; }
MStatus testNpassiveNode::compute(const MPlug &plug, MDataBlock &data) { MStatus stat; if ( plug == currentState ) { // get old positions and numVerts // if num verts is different, reset topo and zero velocity // if num verts is the same, compute new velocity int ii,jj; // initialize MnCloth MObject inMeshObj = data.inputValue(inputGeom).asMesh(); MFnMesh inputMesh(inMeshObj); unsigned int numVerts = 0; numVerts = inputMesh.numVertices(); unsigned int prevNumVerts; fNObject.getNumVertices(prevNumVerts); if(numVerts != prevNumVerts) { int numPolygons = inputMesh.numPolygons(); int * faceVertCounts = new int[numPolygons]; int facesArrayLength = 0; for(ii=0;ii<numPolygons;ii++) { MIntArray verts; inputMesh.getPolygonVertices(ii,verts); faceVertCounts[ii] = verts.length(); facesArrayLength += verts.length(); } int * faces = new int[facesArrayLength]; int currIndex = 0; for(ii=0;ii<numPolygons;ii++) { MIntArray verts; inputMesh.getPolygonVertices(ii,verts); for(jj=0;jj<(int)verts.length();jj++) { faces[currIndex++] = verts[jj]; } } int numEdges = inputMesh.numEdges(); int * edges = new int[2*numEdges]; currIndex = 0; for(ii=0;ii<numEdges;ii++) { int2 edge; inputMesh.getEdgeVertices(ii,edge); edges[currIndex++] = edge[0]; edges[currIndex++] = edge[1]; } // When you are doing the initialization, the first call must to be setTopology(). All other // calls must come after this. fNObject.setTopology(numPolygons, faceVertCounts, faces,numEdges, edges ); delete[] faceVertCounts; delete[] faces; delete[] edges; MFloatPointArray vertexArray; inputMesh.getPoints(vertexArray, MSpace::kWorld); fNObject.setPositions(vertexArray,true); MFloatPointArray velocitiesArray; velocitiesArray.setLength(numVerts); for(ii=0;ii<(int)numVerts;ii++) { velocitiesArray[ii].x = 0.0f; velocitiesArray[ii].y = 0.0f; velocitiesArray[ii].z = 0.0f; velocitiesArray[ii].w = 0.0f; } fNObject.setVelocities(velocitiesArray); } else { MFloatPointArray vertexArray; MFloatPointArray prevVertexArray; inputMesh.getPoints(vertexArray, MSpace::kWorld); fNObject.getPositions(prevVertexArray); // you may want to get the playback rate for the dt // double dt = MAnimControl::playbackBy() \ 24.0; // or get the real dt by caching the last eval time double dt = 1.0/24.0; MFloatPointArray velocitiesArray; velocitiesArray.setLength(numVerts); for(ii=0;ii<(int)numVerts;ii++) { velocitiesArray[ii].x = (float)( (vertexArray[ii].x - prevVertexArray[ii].x)/dt); velocitiesArray[ii].y = (float)( (vertexArray[ii].y - prevVertexArray[ii].y)/dt); velocitiesArray[ii].z = (float)( (vertexArray[ii].x - prevVertexArray[ii].z)/dt); velocitiesArray[ii].w = 0.0f; } fNObject.setVelocities(velocitiesArray); fNObject.setPositions(vertexArray,true); } // in real life, you'd get these attribute values each frame and set them fNObject.setThickness(0.1f); fNObject.setBounce(0.0f); fNObject.setFriction(0.1f); fNObject.setCollisionFlags(true, true, true); MFnNObjectData outputData; MObject mayaNObjectData = outputData.create(); outputData.setObject(mayaNObjectData); outputData.setObjectPtr(&fNObject); outputData.setCached(false); MDataHandle currStateOutputHandle = data.outputValue(currentState); currStateOutputHandle.set(outputData.object()); } if ( plug == startState ) { int ii,jj; // initialize MnCloth MObject inMeshObj = data.inputValue(inputGeom).asMesh(); MFnMesh inputMesh(inMeshObj); int numPolygons = inputMesh.numPolygons(); int * faceVertCounts = new int[numPolygons]; int facesArrayLength = 0; for(ii=0;ii<numPolygons;ii++) { MIntArray verts; inputMesh.getPolygonVertices(ii,verts); faceVertCounts[ii] = verts.length(); facesArrayLength += verts.length(); } int * faces = new int[facesArrayLength]; int currIndex = 0; for(ii=0;ii<numPolygons;ii++) { MIntArray verts; inputMesh.getPolygonVertices(ii,verts); for(jj=0;jj<(int)verts.length();jj++) { faces[currIndex++] = verts[jj]; } } int numEdges = inputMesh.numEdges(); int * edges = new int[2*numEdges]; currIndex = 0; for(ii=0;ii<numEdges;ii++) { int2 edge; inputMesh.getEdgeVertices(ii,edge); edges[currIndex++] = edge[0]; edges[currIndex++] = edge[1]; } // When you are doing the initialization, the first call must to be setTopology(). All other // calls must come after this. fNObject.setTopology(numPolygons, faceVertCounts, faces,numEdges, edges ); delete[] faceVertCounts; delete[] faces; delete[] edges; unsigned int numVerts = 0; numVerts = inputMesh.numVertices(); MFloatPointArray vertexArray; inputMesh.getPoints(vertexArray, MSpace::kWorld); fNObject.setPositions(vertexArray,true); MFloatPointArray velocitiesArray; velocitiesArray.setLength(numVerts); for(ii=0;ii<(int)numVerts;ii++) { velocitiesArray[ii].x = 0.0f; velocitiesArray[ii].y = 0.0f; velocitiesArray[ii].z = 0.0f; velocitiesArray[ii].w = 0.0f; } fNObject.setVelocities(velocitiesArray); fNObject.setThickness(0.1f); fNObject.setBounce(0.0f); fNObject.setFriction(0.1f); fNObject.setCollisionFlags(true, true, true); MFnNObjectData outputData; MObject mayaNObjectData = outputData.create(); outputData.setObject(mayaNObjectData); outputData.setObjectPtr(&fNObject); outputData.setCached(false); MDataHandle startStateOutputHandle = data.outputValue(startState); startStateOutputHandle.set(outputData.object()); } else { stat = MS::kUnknownParameter; } return stat; }
MStatus ColorSplineParameterHandler<S>::doSetValue( IECore::ConstParameterPtr parameter, MPlug &plug ) const { assert( parameter ); typename IECore::TypedParameter< S >::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter< S > >( parameter ); if( !p ) { return MS::kFailure; } MRampAttribute fnRAttr( plug ); if ( !fnRAttr.isColorRamp() ) { return MS::kFailure; } const S &spline = p->getTypedValue(); MStatus s; MIntArray indicesToReuse; plug.getExistingArrayAttributeIndices( indicesToReuse, &s ); assert( s ); int nextNewLogicalIndex = 0; if( indicesToReuse.length() ) { nextNewLogicalIndex = 1 + *std::max_element( MArrayIter<MIntArray>::begin( indicesToReuse ), MArrayIter<MIntArray>::end( indicesToReuse ) ); } assert( indicesToReuse.length() == fnRAttr.getNumEntries() ); size_t pointsSizeMinus2 = spline.points.size() - 2; unsigned pointIndex = 0; unsigned numExpectedPoints = 0; for ( typename S::PointContainer::const_iterator it = spline.points.begin(); it != spline.points.end(); ++it, ++pointIndex ) { // we commonly double up the endpoints on cortex splines to force interpolation to the end. // maya does this implicitly, so we skip duplicated endpoints when passing the splines into maya. // this avoids users having to be responsible for managing the duplicates, and gives them some consistency // with the splines they edit elsewhere in maya. if( ( pointIndex==1 && *it == *spline.points.begin() ) || ( pointIndex==pointsSizeMinus2 && *it == *spline.points.rbegin() ) ) { continue; } MPlug pointPlug; if( indicesToReuse.length() ) { pointPlug = plug.elementByLogicalIndex( indicesToReuse[0] ); indicesToReuse.remove( 0 ); } else { pointPlug = plug.elementByLogicalIndex( nextNewLogicalIndex++ ); } s = pointPlug.child( 0 ).setValue( it->first ); assert( s ); MPlug colorPlug = pointPlug.child( 1 ); colorPlug.child( 0 ).setValue( it->second[0] ); colorPlug.child( 1 ).setValue( it->second[1] ); colorPlug.child( 2 ).setValue( it->second[2] ); // hardcoding interpolation of 3 (spline) because the MRampAttribute::MInterpolation enum values don't actually // correspond to the necessary plug values at all. s = pointPlug.child( 2 ).setValue( 3 ); assert( s ); numExpectedPoints++; } // delete any of the original indices which we didn't reuse. we can't use MRampAttribute::deleteEntries // here as it's utterly unreliable. if( indicesToReuse.length() ) { MString plugName = plug.name(); MObject node = plug.node(); MFnDagNode fnDAGN( node ); if( fnDAGN.hasObj( node ) ) { plugName = fnDAGN.fullPathName() + "." + plug.partialName(); } for( unsigned i=0; i<indicesToReuse.length(); i++ ) { // using mel because there's no equivalant api method as far as i know. MString command = "removeMultiInstance -b true \"" + plugName + "[" + indicesToReuse[i] + "]\""; s = MGlobal::executeCommand( command ); assert( s ); if( !s ) { return s; } } } #ifndef NDEBUG { assert( fnRAttr.getNumEntries() == numExpectedPoints ); MIntArray indices; MFloatArray positions; MColorArray colors; MIntArray interps; fnRAttr.getEntries( indices, positions, colors, interps, &s ); assert( s ); assert( numExpectedPoints == positions.length() ); assert( numExpectedPoints == colors.length() ); assert( numExpectedPoints == interps.length() ); assert( numExpectedPoints == indices.length() ); for ( unsigned i = 0; i < positions.length(); i++ ) { float position = positions[ i ]; const MVector color( colors[ i ][ 0 ], colors[ i ][ 1 ], colors[ i ][ 2 ] ); bool found = false; for ( typename S::PointContainer::const_iterator it = spline.points.begin(); it != spline.points.end() && !found; ++it ) { MVector color2( it->second[0], it->second[1], it->second[2] ); if ( fabs( it->first - position ) < 1.e-3f && ( color2 - color ).length() < 1.e-3f ) { found = true; } } assert( found ); } } #endif return MS::kSuccess; }
MStatus ColorSplineParameterHandler<S>::doSetValue( const MPlug &plug, IECore::ParameterPtr parameter ) const { assert( parameter ); typename IECore::TypedParameter< S >::Ptr p = IECore::runTimeCast<IECore::TypedParameter< S > >( parameter ); if( !p ) { return MS::kFailure; } S spline; MStatus s; MRampAttribute fnRAttr( plug, &s ); assert( s ); if ( !fnRAttr.isColorRamp() ) { return MS::kFailure; } MIntArray indices; (const_cast<MPlug &>( plug )).getExistingArrayAttributeIndices( indices, &s ); for( unsigned i = 0; i < indices.length(); i++ ) { MPlug pointPlug = plug.elementByLogicalIndex( indices[i] ); MPlug colorPlug = pointPlug.child( 1 ); typename S::YType y( 1 ); y[0] = colorPlug.child( 0 ).asDouble(); y[1] = colorPlug.child( 1 ).asDouble(); y[2] = colorPlug.child( 2 ).asDouble(); spline.points.insert( typename S::PointContainer::value_type( pointPlug.child( 0 ).asDouble(), y ) ); } // maya seems to do an implicit doubling up of the end points to cause interpolation to the ends. // our spline has no such implicit behaviour so we explicitly double up. if( spline.points.size() ) { #ifndef NDEBUG size_t oldSplineSize = spline.points.size(); #endif assert( spline.points.begin()->first <= spline.points.rbegin()->first ); spline.points.insert( *spline.points.begin() ); spline.points.insert( *spline.points.rbegin() ); assert( spline.points.size() == oldSplineSize + 2 ); } p->setTypedValue( spline ); if( spline.points.size() ) { assert( spline.points.size() >= 2 ); assert( spline.points.size() == fnRAttr.getNumEntries() + 2 ); } return MS::kSuccess; }
//setEdgeVertexIndexListShear //----------------------------------------------- void TesselationVisualization::setEdgeVertexPositionListShear(MDataBlock &data) { //clear edgeVertexPositionList drawData.edgeVertexPositionList.clear(); //inputGeo MObject oInputGeo = data.inputValue(aInputGeo).asMesh(); //fnMeshInputGeo MFnMesh fnMeshInputGeo(oInputGeo); //vertexPositionList MPointArray vertexPositionList; fnMeshInputGeo.getPoints(vertexPositionList); //itMeshPolyInputGeo MItMeshPolygon itMeshPolyInputGeo(oInputGeo); //for each poly while(!itMeshPolyInputGeo.isDone()) { //get edges MIntArray edgeIndexList; itMeshPolyInputGeo.getEdges(edgeIndexList); //edgeVertexIndices int2* edgeVertexIndices = new int2[4]; for(int index = 0; index < edgeIndexList.length(); index++) { fnMeshInputGeo.getEdgeVertices(edgeIndexList[index], edgeVertexIndices[index]); }; //edgeVertexIndicesNoDuplicates std::set<int> setEdgeVertexIndicesNoDuplicates; for(int index = 0; index < edgeIndexList.length(); index++) { setEdgeVertexIndicesNoDuplicates.insert(edgeVertexIndices[index][0]); setEdgeVertexIndicesNoDuplicates.insert(edgeVertexIndices[index][1]); }; //vecEdgeVertexIndicesNoDuplicates std::vector<int> vecEdgeVertexIndicesNoDuplicates(setEdgeVertexIndicesNoDuplicates.begin(), setEdgeVertexIndicesNoDuplicates.end()); //get faceVertexList MPointArray faceVertexPointList = MPointArray(4); for(int index = 0; index < edgeIndexList.length(); index++) { MPoint faceVertexPoint = vertexPositionList[vecEdgeVertexIndicesNoDuplicates[index]]; faceVertexPointList.set(faceVertexPoint, index); }; //edge01 std::vector<float> edge01; edge01.push_back(faceVertexPointList[0].x);edge01.push_back(faceVertexPointList[0].y);edge01.push_back(faceVertexPointList[0].z); edge01.push_back(faceVertexPointList[1].x);edge01.push_back(faceVertexPointList[1].y);edge01.push_back(faceVertexPointList[1].z); //edge13 std::vector<float> edge13; edge13.push_back(faceVertexPointList[1].x);edge13.push_back(faceVertexPointList[1].y);edge13.push_back(faceVertexPointList[1].z); edge13.push_back(faceVertexPointList[3].x);edge13.push_back(faceVertexPointList[3].y);edge13.push_back(faceVertexPointList[3].z); //edge32 std::vector<float> edge32; edge32.push_back(faceVertexPointList[3].x);edge32.push_back(faceVertexPointList[3].y);edge32.push_back(faceVertexPointList[3].z); edge32.push_back(faceVertexPointList[2].x);edge32.push_back(faceVertexPointList[2].y);edge32.push_back(faceVertexPointList[2].z); //edge20 std::vector<float> edge20; edge20.push_back(faceVertexPointList[2].x);edge20.push_back(faceVertexPointList[2].y);edge20.push_back(faceVertexPointList[2].z); edge20.push_back(faceVertexPointList[0].x);edge20.push_back(faceVertexPointList[0].y);edge20.push_back(faceVertexPointList[0].z); //edge03 std::vector<float> edge03; edge03.push_back(faceVertexPointList[0].x);edge03.push_back(faceVertexPointList[0].y);edge03.push_back(faceVertexPointList[0].z); edge03.push_back(faceVertexPointList[3].x);edge03.push_back(faceVertexPointList[3].y);edge03.push_back(faceVertexPointList[3].z); //edge12 std::vector<float> edge12; edge12.push_back(faceVertexPointList[1].x);edge12.push_back(faceVertexPointList[1].y);edge12.push_back(faceVertexPointList[1].z); edge12.push_back(faceVertexPointList[2].x);edge12.push_back(faceVertexPointList[2].y);edge12.push_back(faceVertexPointList[2].z); //add to drawData.edgeVertexPositionList drawData.edgeVertexPositionList.push_back(edge01); drawData.edgeVertexPositionList.push_back(edge13); drawData.edgeVertexPositionList.push_back(edge32); drawData.edgeVertexPositionList.push_back(edge20); drawData.edgeVertexPositionList.push_back(edge03); drawData.edgeVertexPositionList.push_back(edge12); //del edgeVertexIndices delete [] edgeVertexIndices; //Advance itMeshPolyInputGeo.next(); }; };
MStatus genRod( const MPoint &p0, const MPoint &p1, const double radius, const unsigned int nSegs, int &nPolys, MPointArray &verts, MIntArray &polyCounts, MIntArray &polyConnects ) { verts.clear(); polyCounts.clear(); polyConnects.clear(); unsigned int nCirclePts = nSegs; unsigned int nVerts = 2 * nCirclePts; // Calculate the local axiis of the rod MVector vec( p1 - p0 ); MVector up( 0.0, 1.0, 0.0 ); MVector xAxis, yAxis, zAxis; yAxis = vec.normal(); if( up.isParallel( yAxis, 0.1 ) ) up = MVector( 1.0, 0.0, 0.0 ); xAxis = yAxis ^ up; zAxis = (xAxis ^ yAxis).normal(); xAxis = (yAxis ^ zAxis ).normal(); // Calculate the vertex positions verts.setLength( nVerts ); double angleIncr = 2.0 * M_PI / nSegs; double angle; MPoint p; double x, z; unsigned int i; for( i=0, angle=0; i < nCirclePts; i++, angle += angleIncr ) { // Calculate position in circle x = radius * cos( angle ); z = radius * sin( angle ); p = p0 + x * xAxis + z * zAxis; verts[ i ] = p; p += vec; verts[ i + nCirclePts ] = p; } nPolys = nSegs; // Generate polycounts polyCounts.setLength( nPolys ); for( i=0; i < polyCounts.length(); i++ ) polyCounts[i] = 4; // Generate polyconnects polyConnects.setLength( nPolys * 4 ); polyConnects.clear(); for( i=0; i < nSegs; i++ ) { polyConnects.append( linearIndex( 0, i, 2, nCirclePts ) ); polyConnects.append( linearIndex( 0, i+1, 2, nCirclePts ) ); polyConnects.append( linearIndex( 1, i+1, 2, nCirclePts ) ); polyConnects.append( linearIndex( 1, i, 2, nCirclePts ) ); } return MS::kSuccess; }
MStatus skinClusterWeights::redoIt() { MStatus status; unsigned int ptr = 0; MSelectionList selList; int geomLen = geometryArray.length(); fDagPathArray.setLength(geomLen); fComponentArray.setLength(geomLen); fInfluenceIndexArrayPtrArray = new MIntArray[geomLen]; fWeightsPtrArray = new MDoubleArray[geomLen]; for (int i = 0; i < geomLen; i++) { MDagPath dagPath; MObject component; selList.clear(); selList.add(geometryArray[i]); MStatus status = selList.getDagPath(0, dagPath, component); if (status != MS::kSuccess) { continue; } if (component.isNull()) dagPath.extendToShape(); MObject skinCluster = findSkinCluster(dagPath); if (!isSkinClusterIncluded(skinCluster)) { continue; } MFnSkinCluster skinClusterFn(skinCluster, &status); if (status != MS::kSuccess) { continue; } MIntArray influenceIndexArray; populateInfluenceIndexArray(skinClusterFn, influenceIndexArray); unsigned numInf = influenceIndexArray.length(); if (numInf == 0) continue; unsigned numCV = 0; if (dagPath.node().hasFn(MFn::kMesh)) { MItMeshVertex polyIter(dagPath, component, &status); if (status == MS::kSuccess) { numCV = polyIter.count(); } } else if (dagPath.node().hasFn(MFn::kNurbsSurface)) { MItSurfaceCV nurbsIter(dagPath, component, true, &status); if (status == MS::kSuccess) { while (!nurbsIter.isDone()) { numCV++; nurbsIter.next(); } } } else if (dagPath.node().hasFn(MFn::kNurbsCurve)) { MItCurveCV curveIter(dagPath, component, &status); if (status == MS::kSuccess) { while (!curveIter.isDone()) { numCV++; curveIter.next(); } } } unsigned numEntry = numCV * numInf; if (numEntry > 0) { MDoubleArray weights(numEntry); unsigned int numWeights = weightArray.length(); if (assignAllToSingle) { if (numInf <= numWeights) { for (unsigned j = 0; j < numEntry; j++) { weights[j] = weightArray[j % numInf]; } } else { MGlobal::displayError("Not enough weights specified\n"); return MS::kFailure; } } else { for (unsigned j = 0; j < numEntry; j++, ptr++) { if (ptr < numWeights) { weights[j] = weightArray[ptr]; } else { MGlobal::displayError("Not enough weights specified\n"); return MS::kFailure; } } } // support for undo fDagPathArray[i] = dagPath; fComponentArray[i] = component; fInfluenceIndexArrayPtrArray[i] = influenceIndexArray; MDoubleArray oldWeights; skinClusterFn.getWeights(dagPath, component, influenceIndexArray, oldWeights); fWeightsPtrArray[i] = oldWeights; skinClusterFn.setWeights(dagPath, component, influenceIndexArray, weights); } } return MS::kSuccess; }
void ExportACache::save(const char* filename, int frameNumber, char bfirst) { MStatus status; FXMLScene xml_f; xml_f.begin(filename, frameNumber, bfirst); for(unsigned it=0; it<m_mesh_list.length(); it++) { m_mesh_list[it].extendToShape(); MString surface = m_mesh_list[it].partialPathName(); AHelper::validateFilePath(surface); MFnDependencyNode fnode(m_mesh_list[it].node()); MString smsg("prtMsg"); MStatus hasMsg; MPlug pmsg = fnode.findPlug( smsg, 1, &hasMsg ); char bNoChange = 0; if(hasMsg) { MObject oattrib; AHelper::getConnectedNode(oattrib, pmsg); fnode.setObject(oattrib); bool iattr = 0; AHelper::getBoolAttributeByName(fnode, "noChange", iattr); if(iattr) bNoChange = 1; } xml_f.meshBegin(surface.asChar(), bNoChange); MFnMesh meshFn(m_mesh_list[it], &status ); MItMeshPolygon faceIter(m_mesh_list[it], MObject::kNullObj, &status ); MItMeshVertex vertIter(m_mesh_list[it], MObject::kNullObj, &status); MItMeshEdge edgeIter(m_mesh_list[it], MObject::kNullObj, &status); int n_tri = 0; float f_area = 0; double area; faceIter.reset(); for( ; !faceIter.isDone(); faceIter.next() ) { MIntArray vexlist; faceIter.getVertices ( vexlist ); n_tri += vexlist.length() - 2; faceIter.getArea( area, MSpace::kWorld ); f_area += (float)area; } xml_f.triangleInfo(n_tri, f_area); float avg_grid = sqrt(f_area/n_tri)/2; double light_intensity = 1.0; if(hasMsg) { MObject oattrib; AHelper::getConnectedNode(oattrib, pmsg); fnode.setObject(oattrib); bool iattr = 0; AHelper::getBoolAttributeByName(fnode, "noChange", iattr); if(iattr) xml_f.addAttribute("noChange", 1); AHelper::getBoolAttributeByName(fnode, "skipIndirect", iattr); if(iattr) xml_f.addAttribute("skipIndirect", 1); iattr = 0; AHelper::getBoolAttributeByName(fnode, "skipScatter", iattr); if(iattr) xml_f.addAttribute("skipScatter", 1); iattr = 0; AHelper::getBoolAttributeByName(fnode, "skipBackscatter", iattr); if(iattr) xml_f.addAttribute("skipBackscatter", 1); iattr = 0; AHelper::getBoolAttributeByName(fnode, "asLightsource", iattr); if(iattr) xml_f.addAttribute("asLightsource", 1); iattr = 0; AHelper::getBoolAttributeByName(fnode, "asGhost", iattr); if(iattr) xml_f.addAttribute("invisible", 1); iattr = 0; AHelper::getBoolAttributeByName(fnode, "castNoShadow", iattr); if(iattr) xml_f.addAttribute("noShadow", 1); double td; if(AHelper::getDoubleAttributeByName(fnode, "lightIntensity", td)) light_intensity = td; fnode.setObject(m_mesh_list[it].node()); } xml_f.staticBegin(); int n_poly = meshFn.numPolygons(); int n_vert = meshFn.numVertices(); int* polycount = new int[n_poly]; faceIter.reset(); for( ; !faceIter.isDone(); faceIter.next() ) polycount[ faceIter.index() ] = faceIter.polygonVertexCount(); xml_f.addFaceCount(n_poly, polycount); delete[] polycount; int n_facevertex = meshFn.numFaceVertices(); int* polyconnect = new int[n_facevertex]; int acc = 0; faceIter.reset(); for( ; !faceIter.isDone(); faceIter.next() ) { MIntArray vexlist; faceIter.getVertices ( vexlist ); for( int i=vexlist.length()-1; i >=0; i-- ) { polyconnect[acc] = vexlist[i]; acc++; } } xml_f.addFaceConnection(n_facevertex, polyconnect); delete[] polyconnect; int* triconnect = new int[3*n_tri]; acc = 0; faceIter.reset(); for( ; !faceIter.isDone(); faceIter.next() ) { MIntArray vexlist; faceIter.getVertices ( vexlist ); for( int i=vexlist.length()-2; i >0; i-- ) { triconnect[acc] = vexlist[vexlist.length()-1]; acc++; triconnect[acc] = vexlist[i]; acc++; triconnect[acc] = vexlist[i-1]; acc++; } } xml_f.addTriangleConnection(3*n_tri, triconnect); delete[] triconnect; if(meshFn.numUVSets() > 0) { MStringArray setNames; meshFn.getUVSetNames(setNames); for(unsigned i=0; i< setNames.length(); i++) { float* scoord = new float[n_facevertex]; float* tcoord = new float[n_facevertex]; acc = 0; faceIter.reset(); MFloatArray uarray, varray; if(faceIter.hasUVs (setNames[i], &status)) { for( ; !faceIter.isDone(); faceIter.next() ) { faceIter.getUVs ( uarray, varray, &setNames[i] ); for( int j=uarray.length()-1; j >=0 ; j-- ) { scoord[acc] = uarray[j]; tcoord[acc] = 1.0 - varray[j]; acc++; } } if(setNames[i] == "map1") { xml_f.uvSetBegin(setNames[i].asChar()); xml_f.addS("facevarying float s", meshFn.numFaceVertices(), scoord); xml_f.addT("facevarying float t", meshFn.numFaceVertices(), tcoord); xml_f.uvSetEnd(); } else { xml_f.uvSetBegin(setNames[i].asChar()); std::string paramname("facevarying float u_"); paramname.append(setNames[i].asChar()); xml_f.addS(paramname.c_str(), meshFn.numFaceVertices(), scoord); paramname = "facevarying float v_"; paramname.append(setNames[i].asChar()); xml_f.addT(paramname.c_str(), meshFn.numFaceVertices(), tcoord); xml_f.uvSetEnd(); } } else MGlobal::displayWarning(MString("Skip empty uv set: ") + setNames[i]); delete[] scoord; delete[] tcoord; } } MStringArray colorSetNames; meshFn.getColorSetNames (colorSetNames); for(unsigned int i=0; i<colorSetNames.length(); i++) { MStatus hasColor; XYZ *colors = new XYZ[n_vert]; vertIter.reset(); MString aset = colorSetNames[i]; MColor col; for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ ) { MIntArray conn_face; vertIter.getConnectedFaces(conn_face); vertIter.getColor(col, conn_face[0], &aset); colors[i].x = col.r*light_intensity; colors[i].y = col.g*light_intensity; colors[i].z = col.b*light_intensity; } xml_f.addVertexColor(aset.asChar(), n_vert, colors); delete[] colors; } //if(!bNoChange) { //} MPointArray p_vert; meshFn.getPoints ( p_vert, MSpace::kWorld ); MPoint corner_l(10e6, 10e6, 10e6); MPoint corner_h(-10e6, -10e6, -10e6); for( unsigned int i=0; i<p_vert.length(); i++) { if( p_vert[i].x < corner_l.x ) corner_l.x = p_vert[i].x; if( p_vert[i].y < corner_l.y ) corner_l.y = p_vert[i].y; if( p_vert[i].z < corner_l.z ) corner_l.z = p_vert[i].z; if( p_vert[i].x > corner_h.x ) corner_h.x = p_vert[i].x; if( p_vert[i].y > corner_h.y ) corner_h.y = p_vert[i].y; if( p_vert[i].z > corner_h.z ) corner_h.z = p_vert[i].z; } XYZ *cv = new XYZ[n_vert]; for( unsigned int i=0; i<p_vert.length(); i++) { cv[i].x = p_vert[i].x; cv[i].y = p_vert[i].y; cv[i].z= p_vert[i].z; } //if(!bNoChange) //else xml_f.addStaticP(n_vert, cv); XYZ *nor = new XYZ[n_vert]; XYZ *tang = new XYZ[n_vert]; vertIter.reset(); MVector vnor; for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ ) { vertIter.getNormal(vnor, MSpace::kWorld); vnor.normalize(); nor[i].x = vnor.x; nor[i].y = vnor.y; nor[i].z = vnor.z; } MString uvset("map1"); vertIter.reset(); for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ ) { MIntArray conn_face; vertIter.getConnectedFaces(conn_face); MVector ctang(0,0,0); MVector ttang; for(unsigned j = 0; j<conn_face.length(); j++) { meshFn.getFaceVertexTangent (conn_face[j], i, ttang, MSpace::kWorld, &uvset); ttang.normalize(); ctang += ttang; } ctang.normalize(); tang[i].x = ctang.x; tang[i].y = ctang.y; tang[i].z = ctang.z; tang[i] = nor[i].cross(tang[i]); tang[i].normalize(); } //if(!bNoChange) //else xml_f.addStaticN(n_vert, nor); //xml_f.addTangent(n_vert, tang); // export per-vertex thickness float* vgrd = new float[n_vert]; int pidx; vertIter.reset(); for( unsigned int i=0; !vertIter.isDone(); vertIter.next(), i++ ) { MIntArray connfaces; vertIter.getConnectedFaces( connfaces ); float connarea = 0; for(unsigned j=0; j<connfaces.length(); j++) { faceIter.setIndex(connfaces[j], pidx); faceIter.getArea(area, MSpace::kWorld ); connarea += (float)area/faceIter.polygonVertexCount(); } vgrd[i] = sqrt(connarea)/2; if(vgrd[i] > avg_grid) vgrd[i] = avg_grid; } //if(!bNoChange) //else xml_f.addStaticGridSize(n_vert, vgrd); // //else xml_f.staticEnd(); if(!bNoChange) { xml_f.dynamicBegin(); xml_f.addP(n_vert, cv); xml_f.addN(n_vert, nor); xml_f.addGridSize(n_vert, vgrd); xml_f.dynamicEnd(); } delete[] cv; delete[] tang; delete[] nor; delete[] vgrd; xml_f.addBBox(corner_l.x, corner_l.y, corner_l.z, corner_h.x, corner_h.y, corner_h.z); xml_f.meshEnd(bNoChange); } /* disable nurbs for now float aspace[4][4]; for(unsigned it=0; it<m_nurbs_list.length(); it++) { MVector scale = AHelper::getTransformWorldNoScale(m_nurbs_list[it].fullPathName(), aspace); MString surfacename = m_nurbs_list[it].fullPathName(); AHelper::validateFilePath(surfacename); xml_f.transformBegin(surfacename.asChar(), aspace); xml_f.addScale(scale.x, scale.y, scale.z); m_nurbs_list[it].extendToShape(); surfacename = m_nurbs_list[it].fullPathName(); AHelper::validateFilePath(surfacename); MFnNurbsSurface fsurface(m_nurbs_list[it]); int degreeU = fsurface.degreeU(); int degreeV = fsurface.degreeV(); int formU, formV; if(fsurface.formInU() == MFnNurbsSurface::kOpen ) formU = 0; else if(fsurface.formInU() == MFnNurbsSurface::kClosed ) formU = 1; else formU = 2; if(fsurface.formInV() == MFnNurbsSurface::kOpen ) formV = 0; else if(fsurface.formInV() == MFnNurbsSurface::kClosed ) formV = 1; else formV = 2; xml_f.nurbssurfaceBegin(surfacename.asChar(), degreeU, degreeV, formU, formV); xml_f.staticBegin(); MPointArray p_cvs; fsurface.getCVs( p_cvs, MSpace::kObject ); unsigned n_cvs = p_cvs.length(); XYZ *cv = new XYZ[n_cvs]; for(unsigned i=0; i<n_cvs; i++) { cv[i].x = p_cvs[i].x; cv[i].y = p_cvs[i].y; cv[i].z= p_cvs[i].z; } xml_f.addStaticVec("cvs", n_cvs, cv); delete[] cv; MDoubleArray knotu, knotv; fsurface.getKnotsInU(knotu); fsurface.getKnotsInV(knotv); unsigned n_ku = knotu.length(); unsigned n_kv = knotv.length(); float *ku = new float[n_ku]; for(unsigned i=0; i<n_ku; i++) ku[i] = knotu[i]; float *kv = new float[n_kv]; for(unsigned i=0; i<n_kv; i++) kv[i] = knotv[i]; xml_f.addStaticFloat("knotu", n_ku, ku); xml_f.addStaticFloat("knotv", n_kv, kv); delete[] ku; delete[] kv; xml_f.staticEnd(); xml_f.nurbssurfaceEnd(); xml_f.transformEnd(); } */ xml_f.cameraBegin("backscat_camera", m_space); xml_f.cameraEnd(); xml_f.cameraBegin("eye_camera", m_eye); p_eye.extendToShape(); MFnCamera feye(p_eye); xml_f.addAttribute("focal_length", (float)feye.focalLength()); xml_f.addAttribute("horizontal_film_aperture", (float)feye.horizontalFilmAperture()); xml_f.addAttribute("vertical_film_aperture", (float)feye.verticalFilmAperture()); xml_f.addAttribute("near_clipping_plane", (float)feye.nearClippingPlane()); xml_f.addAttribute("far_clipping_plane", (float)feye.farClippingPlane()); xml_f.cameraEnd(); xml_f.end(filename); }
// #### rebuildHbrMeshIfNeeded // // If the topology of the mesh changes, or any attributes that affect // how the mesh is computed the original HBR needs to be rebuilt // which will trigger a rebuild of the FAR mesh and subsequent buffers. // void OsdMeshData::rebuildHbrMeshIfNeeded(OpenSubdivShader *shader) { MStatus status = MS::kSuccess; if (!_meshTopoDirty && !shader->getHbrMeshDirty()) return; MFnMesh meshFn(_meshDagPath); // Cache attribute values _level = shader->getLevel(); _kernel = shader->getKernel(); _adaptive = shader->isAdaptive(); _uvSet = shader->getUVSet(); // Get Maya vertex topology and crease data MIntArray vertexCount; MIntArray vertexList; meshFn.getVertices(vertexCount, vertexList); MUintArray edgeIds; MDoubleArray edgeCreaseData; meshFn.getCreaseEdges(edgeIds, edgeCreaseData); MUintArray vtxIds; MDoubleArray vtxCreaseData; meshFn.getCreaseVertices(vtxIds, vtxCreaseData); if (vertexCount.length() == 0) return; // Copy Maya vectors into std::vectors std::vector<int> numIndices(&vertexCount[0], &vertexCount[vertexCount.length()]); std::vector<int> faceIndices(&vertexList[0], &vertexList[vertexList.length()]); std::vector<int> vtxCreaseIndices(&vtxIds[0], &vtxIds[vtxIds.length()]); std::vector<double> vtxCreases(&vtxCreaseData[0], &vtxCreaseData[vtxCreaseData.length()]); std::vector<double> edgeCreases(&edgeCreaseData[0], &edgeCreaseData[edgeCreaseData.length()]); // Edge crease index is stored as pairs of vertex ids int nEdgeIds = edgeIds.length(); std::vector<int> edgeCreaseIndices; edgeCreaseIndices.resize(nEdgeIds*2); for (int i = 0; i < nEdgeIds; ++i) { int2 vertices; status = meshFn.getEdgeVertices(edgeIds[i], vertices); if (status.error()) { MERROR(status, "OpenSubdivShader: Can't get edge vertices"); continue; } edgeCreaseIndices[i*2] = vertices[0]; edgeCreaseIndices[i*2+1] = vertices[1]; } // Convert attribute enums to HBR enums (this is why the enums need to match) HbrMeshUtil::SchemeType hbrScheme = (HbrMeshUtil::SchemeType) shader->getScheme(); OsdHbrMesh::InterpolateBoundaryMethod hbrInterpBoundary = (OsdHbrMesh::InterpolateBoundaryMethod) shader->getInterpolateBoundary(); OsdHbrMesh::InterpolateBoundaryMethod hbrInterpUVBoundary = (OsdHbrMesh::InterpolateBoundaryMethod) shader->getInterpolateUVBoundary(); // clear any existing face-varying descriptor if (_fvarDesc) { delete _fvarDesc; _fvarDesc = NULL; } // read UV data from maya and build per-face per-vert list of UVs for HBR face-varying data std::vector< float > uvList; status = buildUVList( meshFn, uvList ); if (! status.error()) { // Create face-varying data descriptor. The memory required for indices // and widths needs to stay alive as the HBR library only takes in the // pointers and assumes the client will maintain the memory so keep _fvarDesc // around as long as _hbrmesh is around. int fvarIndices[] = { 0, 1 }; int fvarWidths[] = { 1, 1 }; _fvarDesc = new FVarDataDesc( 2, fvarIndices, fvarWidths, 2, hbrInterpUVBoundary ); } if (_fvarDesc && hbrScheme != HbrMeshUtil::kCatmark) { MGlobal::displayWarning("Face-varying not yet supported for Loop/Bilinear, using Catmull-Clark"); hbrScheme = HbrMeshUtil::kCatmark; } // Convert Maya mesh to internal HBR representation _hbrmesh = ConvertToHBR(meshFn.numVertices(), numIndices, faceIndices, vtxCreaseIndices, vtxCreases, std::vector<int>(), std::vector<float>(), edgeCreaseIndices, edgeCreases, hbrInterpBoundary, hbrScheme, false, // no ptex _fvarDesc, _fvarDesc?&uvList:NULL); // yes fvar (if have UVs) // note: GL function can't be used in prepareForDraw API. _needsInitializeMesh = true; // Mesh topology data is up to date _meshTopoDirty = false; shader->setHbrMeshDirty(false); }
void collisionShapeNode::computeCollisionShape(const MPlug& plug, MDataBlock& data) { // std::cout << "collisionShapeNode::computeCollisionShape" << std::endl; MObject thisObject(thisMObject()); MPlug plgInShape(thisObject, ia_shape); MPlug plgType(thisObject, ia_type); int type; plgType.getValue(type); switch(type) { case 0: { //convex hull MPlugArray plgaConnectedTo; plgInShape.connectedTo(plgaConnectedTo, true, true); if(plgaConnectedTo.length() > 0) { MObject node = plgaConnectedTo[0].node(); if(node.hasFn(MFn::kMesh)) { MDagPath dagPath; MDagPath::getAPathTo(node, dagPath); MFnMesh fnMesh(dagPath); MFloatPointArray mpoints; MFloatVectorArray mnormals; MIntArray mtrianglecounts; MIntArray mtrianglevertices; fnMesh.getPoints(mpoints, MSpace::kObject); fnMesh.getNormals(mnormals, MSpace::kObject); fnMesh.getTriangles(mtrianglecounts, mtrianglevertices); std::vector<vec3f> vertices(mpoints.length()); std::vector<vec3f> normals(mpoints.length()); std::vector<unsigned int> indices(mtrianglevertices.length()); for(size_t i = 0; i < vertices.size(); ++i) { vertices[i] = vec3f(mpoints[i].x, mpoints[i].y, mpoints[i].z); normals[i] = vec3f(mnormals[i].x, mnormals[i].y, mnormals[i].z); } for(size_t i = 0; i < indices.size(); ++i) { indices[i] = mtrianglevertices[i]; } m_collision_shape = solver_t::create_convex_hull_shape(&(vertices[0]), vertices.size(), &(normals[0]), &(indices[0]), indices.size()); } } } break; case 1: //mesh { //convex hull MPlugArray plgaConnectedTo; plgInShape.connectedTo(plgaConnectedTo, true, true); if(plgaConnectedTo.length() > 0) { MObject node = plgaConnectedTo[0].node(); if(node.hasFn(MFn::kMesh)) { MDagPath dagPath; MDagPath::getAPathTo(node, dagPath); MFnMesh fnMesh(dagPath); MFloatPointArray mpoints; MFloatVectorArray mnormals; MIntArray mtrianglecounts; MIntArray mtrianglevertices; fnMesh.getPoints(mpoints, MSpace::kObject); fnMesh.getNormals(mnormals, MSpace::kObject); fnMesh.getTriangles(mtrianglecounts, mtrianglevertices); std::vector<vec3f> vertices(mpoints.length()); std::vector<vec3f> normals(mpoints.length()); std::vector<unsigned int> indices(mtrianglevertices.length()); for(size_t i = 0; i < vertices.size(); ++i) { vertices[i] = vec3f(mpoints[i].x, mpoints[i].y, mpoints[i].z); normals[i] = vec3f(mnormals[i].x, mnormals[i].y, mnormals[i].z); } for(size_t i = 0; i < indices.size(); ++i) { indices[i] = mtrianglevertices[i]; } m_collision_shape = solver_t::create_mesh_shape(&(vertices[0]), vertices.size(), &(normals[0]), &(indices[0]), indices.size()); } } } break; case 2: //cylinder break; case 3: //capsule break; case 4: //box m_collision_shape = solver_t::create_box_shape(); break; case 5: //sphere m_collision_shape = solver_t::create_sphere_shape(); break; case 6: //plane m_collision_shape = solver_t::create_plane_shape(); break; } assert(m_collision_shape); data.setClean(plug); }
void CageDeformerNode::tetMatrix(const MPointArray& p, const MIntArray& triangles, short cageMode, std::vector<Matrix4d>& m) /// prepare cage tetrahedra from points and triangulation { if(cageMode == 10 || cageMode == 11){ MVector u, v, q ; for(unsigned int i=0;i<triangles.length()/3;i++){ u=MVector(p[triangles[3*i+1]]-p[triangles[3*i]]); v=MVector(p[triangles[3*i+2]]-p[triangles[3*i]]); q=u^v; q.normalize(); m[i] << p[triangles[3*i]].x, p[triangles[3*i]].y, p[triangles[3*i]].z, 1, p[triangles[3*i+1]].x, p[triangles[3*i+1]].y, p[triangles[3*i+1]].z, 1, p[triangles[3*i+2]].x, p[triangles[3*i+2]].y, p[triangles[3*i+2]].z, 1, (p[triangles[3*i]]+q).x, (p[triangles[3*i]]+q).y, (p[triangles[3*i]]+q).z,1; } }else if (cageMode == 0){ for(unsigned int i=0;i<triangles.length()/4;i++){ m[i] << p[triangles[4*i]].x, p[triangles[4*i]].y, p[triangles[4*i]].z, 1, p[triangles[4*i+1]].x, p[triangles[4*i+1]].y, p[triangles[4*i+1]].z, 1, p[triangles[4*i+2]].x, p[triangles[4*i+2]].y, p[triangles[4*i+2]].z, 1, p[triangles[4*i+3]].x, p[triangles[4*i+3]].y, p[triangles[4*i+3]].z, 1; } }else if (cageMode == 1){ MVector u, v, q; for(unsigned int i=0;i<triangles.length()/4;i++){ u=MVector(p[triangles[4*i+1]]-p[triangles[4*i]]); v=MVector(p[triangles[4*i+2]]-p[triangles[4*i]]); q=MVector(p[triangles[4*i+3]]-p[triangles[4*i]]); u.normalize(); v.normalize(); q.normalize(); m[i] << p[triangles[4*i]].x, p[triangles[4*i]].y, p[triangles[4*i]].z, 1, u[0]+p[triangles[4*i]].x,u[1]+p[triangles[4*i]].y,u[2]+p[triangles[4*i]].z,1, v[0]+p[triangles[4*i]].x,v[1]+p[triangles[4*i]].y,v[2]+p[triangles[4*i]].z,1, q[0]+p[triangles[4*i]].x,q[1]+p[triangles[4*i]].y,q[2]+p[triangles[4*i]].z,1; } }else if (cageMode == 5 || cageMode == 6){ std::vector<Vector3d> normal(p.length(),Vector3d::Zero()); //averaged normal vector for vertex mode for(unsigned int i=0;i<triangles.length()/3;i++){ MVector q = MVector(p[triangles[3*i+1]]-p[triangles[3*i]]) ^ MVector(p[triangles[3*i+2]]-p[triangles[3*i]]); normal[triangles[3*i]] += Vector3d(q[0], q[1], q[2]); } if (cageMode == 5){ for(unsigned int i=0;i<triangles.length()/3;i++){ m[i] << p[triangles[3*i]].x, p[triangles[3*i]].y, p[triangles[3*i]].z, 1, p[triangles[3*i+1]].x, p[triangles[3*i+1]].y, p[triangles[3*i+1]].z, 1, p[triangles[3*i+2]].x, p[triangles[3*i+2]].y, p[triangles[3*i+2]].z, 1, p[triangles[3*i]].x + normal[triangles[3*i]][0], p[triangles[3*i]].y + normal[triangles[3*i]][1], p[triangles[3*i]].z + normal[triangles[3*i]][2],1; } }else if (cageMode == 6){ MVector u,v,q; for(unsigned int i=0;i<triangles.length()/3;i++){ u=MVector(p[triangles[3*i+1]]-p[triangles[3*i]]); v=MVector(p[triangles[3*i+2]]-p[triangles[3*i]]); u.normalize(); v.normalize(); normal[triangles[3*i]].normalize(); m[i] << p[triangles[3*i]].x, p[triangles[3*i]].y, p[triangles[3*i]].z, 1, u[0]+p[triangles[3*i]].x,u[1]+p[triangles[3*i]].y,u[2]+p[triangles[3*i]].z,1, v[0]+p[triangles[3*i]].x,v[1]+p[triangles[3*i]].y,v[2]+p[triangles[3*i]].z,1, normal[triangles[3*i]][0]+p[triangles[3*i]].x,normal[triangles[3*i]][1]+p[triangles[3*i]].y,normal[triangles[3*i]][2]+p[triangles[3*i]].z,1; } } } }
bool CXRayObjectExport::smoothingAlgorithm( int polyId, MFnMesh& fnMesh ) { MIntArray vertexList; fnMesh.getPolygonVertices( polyId, vertexList ); int vcount = vertexList.length(); bool smoothEdgeFound = false; for ( int vid=0; vid<vcount;vid++ ) { int a = vertexList[vid]; int b = vertexList[ vid==(vcount-1) ? 0 : vid+1 ]; SXREdgeInfoPtr elem = findEdgeInfo( a, b ); if ( NULL != elem ) { // NOTE: We assume there are at most 2 polygons per edge // halfEdge polygons get a smoothing group of // NO_SMOOTHING_GROUP which is equivalent to "s off" // if ( NO_SMOOTHING_GROUP != elem->polyIds[1] ) { // Edge not a border // We are starting a new smoothing group // if ( newSmoothingGroup ) { currSmoothingGroup = nextSmoothingGroup++; newSmoothingGroup = false; // This is a SEED (starting) polygon and so we always // give it the new smoothing group id. // Even if all edges are hard this must be done so // that we know we have visited the polygon. // polySmoothingGroups[polyId] = currSmoothingGroup; } // If we have a smooth edge then this poly must be a member // of the current smoothing group. // if ( elem->smooth ) { polySmoothingGroups[polyId] = currSmoothingGroup; smoothEdgeFound = true; } else { // Hard edge so ignore this polygon continue; } // Find the adjacent poly id // int adjPoly = elem->polyIds[0]; if ( adjPoly == polyId ) { adjPoly = elem->polyIds[1]; } // If we are this far then adjacent poly belongs in this // smoothing group. // If the adjacent polygon's smoothing group is not // NO_SMOOTHING_GROUP then it has already been visited // so we ignore it. // if ( NO_SMOOTHING_GROUP == polySmoothingGroups[adjPoly] ) { smoothingAlgorithm( adjPoly, fnMesh ); } else if ( polySmoothingGroups[adjPoly] != currSmoothingGroup ) { Msg("! smoothing group problem at polygon %d",adjPoly); } } } } return smoothEdgeFound; }
MStatus CageDeformerNode::deform( MDataBlock& data, MItGeometry& itGeo, const MMatrix &localToWorldMatrix, unsigned int mIndex ) { /// main MStatus status; MThreadUtils::syncNumOpenMPThreads(); // for OpenMP // load cage mesh and other attributes MObject oCageMesh = data.inputValue( aCageMesh ).asMesh(); short blendMode = data.inputValue(aBlendMode).asShort(); bool rotationCosistency = data.inputValue( aRotationConsistency ).asBool(); bool frechetSum = data.inputValue( aFrechetSum ).asBool(); short newConstraintMode = data.inputValue(aConstraintMode).asShort(); double newConstraintWeight = data.inputValue( aConstraintWeight ).asDouble(); if ( oCageMesh.isNull() || blendMode == 99) return MS::kSuccess; short newCageMode = data.inputValue(aCageMode).asShort(); MFnMesh fnCageMesh( oCageMesh, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MPointArray cagePoints; fnCageMesh.getPoints( cagePoints, MSpace::kWorld ); // save initial cage state if (initCagePoints.length() != cagePoints.length()){ initCageMesh = oCageMesh; initCagePoints=cagePoints; } // when cage mode is changed if(newCageMode != cageMode || newConstraintMode != constraintMode || newConstraintWeight != constraintWeight) { cageMode = newCageMode; constraintMode = newConstraintMode; constraintWeight = newConstraintWeight; std::vector<double> tetWeight; // read target mesh data MArrayDataHandle hInput = data.outputArrayValue( input, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); status = hInput.jumpToElement( mIndex ); CHECK_MSTATUS_AND_RETURN_IT( status ); MObject oInputGeom = hInput.outputValue().child( inputGeom ).asMesh(); MFnMesh inputMesh(oInputGeom); inputMesh.getPoints( pts ); numPts=pts.length(); for(int j=0; j<numPts; j++ ) pts[j] *= localToWorldMatrix; MIntArray count; inputMesh.getTriangles( count, meshTriangles ); numTet=meshTriangles.length()/3; std::vector<Matrix4d> P(numTet); tetCenter.resize(numTet); tetMatrixC(pts, meshTriangles, P, tetCenter); PI.resize(numTet); for(int i=0;i<numTet;i++) PI[i] = P[i].inverse(); // prepare cage tetrahedra MFnMesh fnInitCageMesh( initCageMesh, &status ); if(cageMode == 10 || cageMode == 11) // face mode { if(cageMode == 10){ // triangulate faces by MAYA standard MIntArray count; fnInitCageMesh.getTriangles( count, triangles ); tetWeight.resize(triangles.length()/3, 1.0f); }else if(cageMode ==11){ // trianglate faces with more than 3 edges in a symmetric way triangles.clear(); MItMeshPolygon iter(initCageMesh); MIntArray tmp; MVector normal; tetWeight.reserve(4*iter.count()); unsigned int l; for(unsigned int i=0; ! iter.isDone(); i++){ iter.getVertices(tmp); l=tmp.length(); if(l==3){ tetWeight.push_back(1.0); triangles.append(tmp[0]); triangles.append(tmp[1]); triangles.append(tmp[2]); }else{ for(unsigned int j=0;j<l;j++){ tetWeight.push_back((l-2.0)/l); triangles.append(tmp[j]); triangles.append(tmp[(j+1) % l]); triangles.append(tmp[(j+2) % l]); } } iter.next(); } } // face mode compute init matrix numPrb=triangles.length()/3; initMatrix.resize(numPrb); tetMatrix(initCagePoints, triangles, cageMode, initMatrix); // compute weight w.resize(numTet); std::vector< std::vector<double> > idist(numTet); for(int j=0;j<numTet;j++){ idist[j].resize(numPrb); w[j].resize(numPrb); double sidist = 0.0; for(int i=0;i<numPrb;i++){ idist[j][i] = tetWeight[i]/distPtTri(tetCenter[j],initMatrix[i]); sidist += idist[j][i]; } assert(sidist>0.0f); for(int i=0;i<numPrb;i++) w[j][i] = idist[j][i] /sidist; }// face mode end }else if(cageMode == 0 || cageMode == 1){ // vertex mode triangles.clear(); std::vector<int> tetCount(initCagePoints.length()); MItMeshVertex iter(initCageMesh); for(int j=0; ! iter.isDone(); j++){ MIntArray v; iter.getConnectedVertices(v); // at each vertex, construct tetrahedra from connected edges int l=v.length(); if(l==3){ if(isDegenerate(initCagePoints[j],initCagePoints[v[0]],initCagePoints[v[1]],initCagePoints[v[2]]) != 0){ tetCount[j]++; triangles.append(j); triangles.append(v[0]); triangles.append(v[1]); triangles.append(v[2]); } }else{ for(int k=0;k<l;k++){ if(isDegenerate(initCagePoints[j],initCagePoints[v[k]],initCagePoints[v[(k+1) % l]],initCagePoints[v[(k+2) % l]]) != 0){ tetCount[j]++; triangles.append(j); triangles.append(v[k]); triangles.append(v[(k+1) % l]); triangles.append(v[(k+2) % l]); } } } iter.next(); } numPrb=triangles.length()/4; initMatrix.resize(numPrb); tetMatrix(initCagePoints, triangles, cageMode, initMatrix); // vertex mode compute weight w.resize(numTet); std::vector< std::vector<double> > idist(numTet); tetWeight.resize(numPrb); for(int i=0;i<numPrb;i++) tetWeight[i]=1.0/(double)tetCount[triangles[4*i]]; for(int j=0;j<numTet;j++){ idist[j].resize(numPrb); w[j].resize(numPrb); double sidist = 0.0; for(int i=0;i<numPrb;i++){ Vector3d c(initCagePoints[triangles[4*i]].x,initCagePoints[triangles[4*i]].y,initCagePoints[triangles[4*i]].z); idist[j][i] = tetWeight[i] / ((tetCenter[j]-c).squaredNorm()); sidist += idist[j][i]; } assert(sidist>0.0f); for(int i=0;i<numPrb;i++) w[j][i] = idist[j][i] /sidist; } }else if(cageMode == 5 || cageMode == 6 ){ // vertex averaged normal mode triangles.clear(); std::vector<int> tetCount(initCagePoints.length()); MItMeshVertex iter(initCageMesh); for(int j=0; ! iter.isDone(); j++){ MIntArray v; iter.getConnectedVertices(v); int l=v.length(); for(int k=0;k<l;k++){ tetCount[j]++; triangles.append(j); triangles.append(v[k]); triangles.append(v[(k+1) % l]); } iter.next(); } numPrb=triangles.length()/3; initMatrix.resize(numPrb); tetMatrix(initCagePoints, triangles, cageMode, initMatrix); // vertex mode compute weight w.resize(numTet); std::vector< std::vector<double> > idist(numTet); tetWeight.resize(numPrb); for(int i=0;i<numPrb;i++) tetWeight[i]=1.0/(double)tetCount[triangles[3*i]]; for(int j=0;j<numTet;j++){ idist[j].resize(numPrb); w[j].resize(numPrb); double sidist = 0.0; for(int i=0;i<numPrb;i++){ Vector3d c(initCagePoints[triangles[3*i]].x,initCagePoints[triangles[3*i]].y,initCagePoints[triangles[3*i]].z); idist[j][i] = tetWeight[i] / ((tetCenter[j]-c).squaredNorm()); sidist += idist[j][i]; } assert(sidist>0.0f); for(int i=0;i<numPrb;i++) w[j][i] = idist[j][i] /sidist; } }// end of cage setup // find constraint points if(constraintMode == 1){ numConstraint = numPrb; }else{ numConstraint = 1; // at least one constraint is necessary to determine global translation } constraintTet.resize(numConstraint); constraintVector.resize(numConstraint); // for each cage tetrahedra, constraint the point on the mesh with largest weight for(int i=0;i<numConstraint;i++){ constraintTet[i] = 0; for(int j=1;j<numTet;j++){ if(w[j][i] > w[constraintTet[i]][i]){ constraintTet[i] = j; } } constraintVector[i] << tetCenter[constraintTet[i]](0), tetCenter[constraintTet[i]](1), tetCenter[constraintTet[i]](2), 1.0; } // precompute arap solver arapHI(PI, meshTriangles); } // compute deformation if( ! rotationCosistency || numPrb != prevNs.size()){ // clear previous rotation prevThetas.clear(); prevThetas.resize(numPrb, 0.0); prevNs.clear(); prevNs.resize(numPrb, Vector3d::Zero()); } // find affine transformations for tetrahedra std::vector<Matrix4d> cageMatrix(numPrb), SE(numPrb), logSE(numPrb),logAff(numPrb),aff(numPrb); std::vector<Matrix3d> logR(numPrb),R(numPrb),logS(numPrb),logGL(numPrb); std::vector<Vector3d> L(numPrb); std::vector<Vector4d> quat(numPrb); tetMatrix(cagePoints, triangles, cageMode, cageMatrix); for(int i=0; i<numPrb; i++) aff[i]=initMatrix[i].inverse()*cageMatrix[i]; // compute parametrisation if(blendMode == 0 || blendMode == 1 || blendMode == 5) // polarexp or quaternion { for(unsigned int i=0;i<numPrb;i++){ parametriseGL(aff[i].block(0,0,3,3), logS[i] ,R[i]); L[i] = transPart(aff[i]); if(blendMode == 0){ // Rotational log logR[i]=logSOc(R[i], prevThetas[i], prevNs[i]); }else if(blendMode == 1){ // Eucledian log SE[i]=affine(R[i], L[i]); logSE[i]=logSEc(SE[i], prevThetas[i], prevNs[i]); }else if(blendMode == 5){ // quaternion Quaternion<double> Q(R[i].transpose()); quat[i] << Q.x(), Q.y(), Q.z(), Q.w(); } } }else if(blendMode == 2){ //logmatrix3 for(unsigned int i=0;i<numPrb;i++){ logGL[i] = aff[i].block(0,0,3,3).log(); L[i] = transPart(aff[i]); } }else if(blendMode == 3){ // logmatrix4 for(unsigned int i=0;i<numPrb;i++){ logAff[i] = aff[i].log(); } } // compute blended matrices #pragma omp parallel for std::vector<Matrix4d> At(numTet); for(int j=0; j<numTet; j++ ){ if(blendMode==0){ Matrix3d RR=Matrix3d::Zero(); Matrix3d SS=Matrix3d::Zero(); Vector3d l=Vector3d::Zero(); for(unsigned int i=0; i<numPrb; i++){ RR += w[j][i] * logR[i]; SS += w[j][i] * logS[i]; l += w[j][i] * L[i]; } SS = expSym(SS); if(frechetSum){ RR = frechetSO(R, w[j]); }else{ RR = expSO(RR); } At[j] = affine(SS*RR, l); }else if(blendMode==1){ // rigid transformation Matrix4d EE=Matrix4d::Zero(); Matrix3d SS=Matrix3d::Zero(); for(unsigned int i=0; i<numPrb; i++){ EE += w[j][i] * logSE[i]; SS += w[j][i] * logS[i]; } if(frechetSum){ EE = frechetSE(SE, w[j]); }else{ EE = expSE(EE); } At[j] = affine(expSym(SS),Vector3d::Zero())*EE; }else if(blendMode == 2){ //logmatrix3 Matrix3d G=Matrix3d::Zero(); Vector3d l=Vector3d::Zero(); for(unsigned int i=0; i<numPrb; i++){ G += w[j][i] * logGL[i]; l += w[j][i] * L[i]; } At[j] = affine(G.exp(), l); }else if(blendMode == 3){ // logmatrix4 Matrix4d A=Matrix4d::Zero(); for(unsigned int i=0; i<numPrb; i++) A += w[j][i] * logAff[i]; At[j] = A.exp(); }else if(blendMode == 5){ // quaternion Vector4d q=Vector4d::Zero(); Matrix3d SS=Matrix3d::Zero(); Vector3d l=Vector3d::Zero(); for(unsigned int i=0; i<numPrb; i++){ q += w[j][i] * quat[i]; SS += w[j][i] * logS[i]; l += w[j][i] * L[i]; } SS = expSym(SS); Quaternion<double> Q(q); Matrix3d RR = Q.matrix().transpose(); At[j] = affine(SS*RR, l); }else if(blendMode==10){ At[j] = Matrix4d::Zero(); for(unsigned int i=0; i<numPrb; i++){ At[j] += w[j][i] * aff[i]; } } } // compute target vertices position MatrixXd G=MatrixXd::Zero(numTet+numPts,3); arapG(At, PI, meshTriangles, aff, G); MatrixXd Sol = solver.solve(G); for(unsigned int i=0;i<numPts;i++){ pts[i].x=Sol(i,0); pts[i].y=Sol(i,1); pts[i].z=Sol(i,2); pts[i] *= localToWorldMatrix.inverse(); } itGeo.setAllPositions(pts); return MS::kSuccess; }
MayaMeshWriter::MayaMeshWriter(MDagPath & iDag, Alembic::Abc::OObject & iParent, Alembic::Util::uint32_t iTimeIndex, const JobArgs & iArgs, GetMembersMap& gmMap, util::InstanceRecorder& instanceRecorder) : mNoNormals(iArgs.noNormals), mWriteUVs(iArgs.writeUVs), mWriteColorSets(iArgs.writeColorSets), mIsGeometryAnimated(false), mDagPath(iDag) { MStatus status = MS::kSuccess; MFnMesh lMesh( mDagPath, &status ); if ( !status ) { MGlobal::displayError( "MFnMesh() failed for MayaMeshWriter" ); } // intermediate objects aren't translated MObject surface = iDag.node(); if (iTimeIndex != 0 && util::isAnimated(surface)) mIsGeometryAnimated = true; std::vector<float> uvs; std::vector<Alembic::Util::uint32_t> indices; MString name = lMesh.name(); name = util::stripNamespaces(name, iArgs.stripNamespace); // check to see if this poly has been tagged as a SubD MPlug plug = lMesh.findPlug("SubDivisionMesh"); if ( !plug.isNull() && plug.asBool() ) { Alembic::AbcGeom::OSubD obj(iParent, name.asChar(), iTimeIndex); instanceRecorder.recordMaster(iDag,obj); mSubDSchema = obj.getSchema(); Alembic::AbcGeom::OV2fGeomParam::Sample uvSamp; if ( mWriteUVs ) { getUVs(uvs, indices); if (!uvs.empty()) { uvSamp.setScope( Alembic::AbcGeom::kFacevaryingScope ); uvSamp.setVals(Alembic::AbcGeom::V2fArraySample( (const Imath::V2f *) &uvs.front(), uvs.size() / 2)); if (!indices.empty()) { uvSamp.setIndices(Alembic::Abc::UInt32ArraySample( &indices.front(), indices.size())); } } } Alembic::Abc::OCompoundProperty cp; Alembic::Abc::OCompoundProperty up; if (AttributesWriter::hasAnyAttr(lMesh, iArgs)) { cp = mSubDSchema.getArbGeomParams(); up = mSubDSchema.getUserProperties(); } mAttrs = AttributesWriterPtr(new AttributesWriter(cp, up, obj, lMesh, iTimeIndex, iArgs)); writeSubD(uvSamp); } else { Alembic::AbcGeom::OPolyMesh obj(iParent, name.asChar(), iTimeIndex); instanceRecorder.recordMaster(iDag,obj); mPolySchema = obj.getSchema(); Alembic::AbcGeom::OV2fGeomParam::Sample uvSamp; if ( mWriteUVs ) { getUVs(uvs, indices); if (!uvs.empty()) { uvSamp.setScope( Alembic::AbcGeom::kFacevaryingScope ); uvSamp.setVals(Alembic::AbcGeom::V2fArraySample( (const Imath::V2f *) &uvs.front(), uvs.size() / 2)); if (!indices.empty()) { uvSamp.setIndices(Alembic::Abc::UInt32ArraySample( &indices.front(), indices.size())); } } } Alembic::Abc::OCompoundProperty cp; Alembic::Abc::OCompoundProperty up; if (AttributesWriter::hasAnyAttr(lMesh, iArgs)) { cp = mPolySchema.getArbGeomParams(); up = mPolySchema.getUserProperties(); } // set the rest of the props and write to the writer node mAttrs = AttributesWriterPtr(new AttributesWriter(cp, up, obj, lMesh, iTimeIndex, iArgs)); writePoly(uvSamp); } if (mWriteColorSets) { MStringArray colorSetNames; lMesh.getColorSetNames(colorSetNames); if (colorSetNames.length() > 0) { // Create the color sets compound prop Alembic::Abc::OCompoundProperty arbParams; if (mPolySchema) { arbParams = mPolySchema.getArbGeomParams(); } else { arbParams = mSubDSchema.getArbGeomParams(); } std::string currentColorSet = lMesh.currentColorSetName().asChar(); for (unsigned int i=0; i < colorSetNames.length(); ++i) { // Create an array property for each color set std::string colorSetPropName = colorSetNames[i].asChar(); Alembic::AbcCoreAbstract::MetaData md; if (currentColorSet == colorSetPropName) { md.set("mayaColorSet", "1"); } else { md.set("mayaColorSet", "0"); } if (lMesh.getColorRepresentation(colorSetNames[i]) == MFnMesh::kRGB) { Alembic::AbcGeom::OC3fGeomParam colorProp(arbParams, colorSetPropName, true, Alembic::AbcGeom::kFacevaryingScope, 1, iTimeIndex, md); mRGBParams.push_back(colorProp); } else { Alembic::AbcGeom::OC4fGeomParam colorProp(arbParams, colorSetPropName, true, Alembic::AbcGeom::kFacevaryingScope, 1, iTimeIndex, md); mRGBAParams.push_back(colorProp); } } writeColor(); } } // write out facesets if(!iArgs.writeFaceSets) return; // get the connected shading engines MObjectArray connSGObjs (getOutConnectedSG(mDagPath)); const unsigned int sgCount = connSGObjs.length(); for (unsigned int i = 0; i < sgCount; ++i) { MObject connSGObj, compObj; connSGObj = connSGObjs[i]; MFnDependencyNode fnDepNode(connSGObj); MString connSgObjName = fnDepNode.name(); // retrive the component MObject status = getSetComponents(mDagPath, connSGObj, gmMap, compObj); if (status != MS::kSuccess) { MFnDependencyNode fnDepNode(connSGObj); MString message; message.format("Could not retrive face indices from set ^1s.", connSgObjName); MGlobal::displayError(message); continue; } // retrieve the face indices MIntArray indices; MFnSingleIndexedComponent compFn; compFn.setObject(compObj); compFn.getElements(indices); const unsigned int numData = indices.length(); // encountered the whole object mapping. skip it. if (numData == 0) continue; std::vector<Alembic::Util::int32_t> faceIndices(numData); for (unsigned int j = 0; j < numData; ++j) { faceIndices[j] = indices[j]; } connSgObjName = util::stripNamespaces(connSgObjName, iArgs.stripNamespace); Alembic::AbcGeom::OFaceSet faceSet; std::string faceSetName(connSgObjName.asChar()); if (mPolySchema) { if (mPolySchema.hasFaceSet(faceSetName)) { faceSet = mPolySchema.getFaceSet(faceSetName); } else { faceSet = mPolySchema.createFaceSet(faceSetName); } } else { if (mSubDSchema.hasFaceSet(faceSetName)) { faceSet = mSubDSchema.getFaceSet(faceSetName); } else { faceSet = mSubDSchema.createFaceSet(faceSetName); } } Alembic::AbcGeom::OFaceSetSchema::Sample samp; samp.setFaces(Alembic::Abc::Int32ArraySample(faceIndices)); Alembic::AbcGeom::OFaceSetSchema faceSetSchema = faceSet.getSchema(); faceSetSchema.set(samp); faceSetSchema.setFaceExclusivity(Alembic::AbcGeom::kFaceSetExclusive); MFnDependencyNode iNode(connSGObj); Alembic::Abc::OCompoundProperty cp; Alembic::Abc::OCompoundProperty up; if (AttributesWriter::hasAnyAttr(iNode, iArgs)) { cp = faceSetSchema.getArbGeomParams(); up = faceSetSchema.getUserProperties(); } AttributesWriter attrWriter(cp, up, faceSet, iNode, iTimeIndex, iArgs); attrWriter.write(); } }
collision_shape_t::pointer boingRbCmd::createCollisionShape(const MObject& node) { collision_shape_t::pointer collision_shape = 0; //MObject thisObject(thisMObject()); //MPlug plgType(thisObject, ia_type); int type=0; //plgType.getValue(type); switch(type) { case 0: { //convex hull { cout<<"going on creating a convex hull collision shape"<<endl; if(node.hasFn(MFn::kMesh)) { MDagPath dagPath; MDagPath::getAPathTo(node, dagPath); MFnMesh fnMesh(dagPath); cout<<"going on creating a convex hull from : "<<fnMesh.name()<<endl; MFloatPointArray mpoints; MFloatVectorArray mnormals; MIntArray mtrianglecounts; MIntArray mtrianglevertices; fnMesh.getPoints(mpoints, MSpace::kObject); fnMesh.getNormals(mnormals, MSpace::kObject); fnMesh.getTriangles(mtrianglecounts, mtrianglevertices); std::vector<vec3f> vertices(mpoints.length()); std::vector<vec3f> normals(mpoints.length()); std::vector<unsigned int> indices(mtrianglevertices.length()); btAlignedObjectArray<btVector3> btVerts; //mb for(size_t i = 0; i < vertices.size(); ++i) { vertices[i] = vec3f(mpoints[i].x, mpoints[i].y, mpoints[i].z); normals[i] = vec3f(mnormals[i].x, mnormals[i].y, mnormals[i].z); #if UPDATE_SHAPE //future collision margin adjust btVerts.push_back(btVector3(mpoints[i].x, mpoints[i].y, mpoints[i].z)); //mb #endif } for(size_t i = 0; i < indices.size(); ++i) { indices[i] = mtrianglevertices[i]; } #if UPDATE_SHAPE //future collision margin adjust btAlignedObjectArray<btVector3> planeEquations; btGeometryUtil::getPlaneEquationsFromVertices(btVerts, planeEquations); btAlignedObjectArray<btVector3> shiftedPlaneEquations; for (int p=0;p<planeEquations.size();p++) { btVector3 plane = planeEquations[p]; plane[3] += collisionShapeNode::collisionMarginOffset; shiftedPlaneEquations.push_back(plane); } btAlignedObjectArray<btVector3> shiftedVertices; btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations, shiftedVertices); std::vector<vec3f> shiftedVerticesVec3f(shiftedVertices.size()); for(size_t i = 0; i < shiftedVertices.size(); ++i) { shiftedVerticesVec3f[i] = vec3f(shiftedVertices[i].getX(), shiftedVertices[i].getY(), shiftedVertices[i].getZ()); //std::cout << "orig verts: " << vertices[i][0] << " " << vertices[i][1] << " " << vertices[i][2] << std::endl; //std::cout << "shft verts: " << shiftedVertices[i].getX() << " " << shiftedVertices[i].getY() << " " << shiftedVertices[i].getZ() << std::endl; //std::cout << std::endl; } collision_shape = solver_t::create_convex_hull_shape(&(shiftedVerticesVec3f[0]), shiftedVerticesVec3f.size(), &(normals[0]), &(indices[0]), indices.size()); #endif #if UPDATE_SHAPE == 0 collision_shape = solver_t::create_convex_hull_shape(&(vertices[0]), vertices.size(), &(normals[0]), &(indices[0]), indices.size()); //original #endif } } } break; case 1: { //mesh { if(node.hasFn(MFn::kMesh)) { MDagPath dagPath; MDagPath::getAPathTo(node, dagPath); MFnMesh fnMesh(dagPath); MFloatPointArray mpoints; MFloatVectorArray mnormals; MIntArray mtrianglecounts; MIntArray mtrianglevertices; fnMesh.getPoints(mpoints, MSpace::kObject); fnMesh.getNormals(mnormals, MSpace::kObject); fnMesh.getTriangles(mtrianglecounts, mtrianglevertices); std::vector<vec3f> vertices(mpoints.length()); std::vector<vec3f> normals(mpoints.length()); std::vector<unsigned int> indices(mtrianglevertices.length()); for(size_t i = 0; i < vertices.size(); ++i) { vertices[i] = vec3f(mpoints[i].x, mpoints[i].y, mpoints[i].z); normals[i] = vec3f(mnormals[i].x, mnormals[i].y, mnormals[i].z); } for(size_t i = 0; i < indices.size(); ++i) { indices[i] = mtrianglevertices[i]; } bool dynamicMesh = true; collision_shape = solver_t::create_mesh_shape(&(vertices[0]), vertices.size(), &(normals[0]), &(indices[0]), indices.size(),dynamicMesh); } } } break; case 2: //cylinder break; case 3: //capsule break; case 7: //btBvhTriangleMeshShape { if(node.hasFn(MFn::kMesh)) { MDagPath dagPath; MDagPath::getAPathTo(node, dagPath); MFnMesh fnMesh(dagPath); MFloatPointArray mpoints; MFloatVectorArray mnormals; MIntArray mtrianglecounts; MIntArray mtrianglevertices; fnMesh.getPoints(mpoints, MSpace::kObject); fnMesh.getNormals(mnormals, MSpace::kObject); fnMesh.getTriangles(mtrianglecounts, mtrianglevertices); std::vector<vec3f> vertices(mpoints.length()); std::vector<vec3f> normals(mpoints.length()); std::vector<unsigned int> indices(mtrianglevertices.length()); for(size_t i = 0; i < vertices.size(); ++i) { vertices[i] = vec3f(mpoints[i].x, mpoints[i].y, mpoints[i].z); normals[i] = vec3f(mnormals[i].x, mnormals[i].y, mnormals[i].z); } for(size_t i = 0; i < indices.size(); ++i) { indices[i] = mtrianglevertices[i]; } bool dynamicMesh = false; collision_shape = solver_t::create_mesh_shape(&(vertices[0]), vertices.size(), &(normals[0]), &(indices[0]), indices.size(),dynamicMesh); } } break; case 8: //hacd convex decomposition { { if(node.hasFn(MFn::kMesh)) { MDagPath dagPath; MDagPath::getAPathTo(node, dagPath); MFnMesh fnMesh(dagPath); MFloatPointArray mpoints; MFloatVectorArray mnormals; MIntArray mtrianglecounts; MIntArray mtrianglevertices; fnMesh.getPoints(mpoints, MSpace::kObject); fnMesh.getNormals(mnormals, MSpace::kObject); fnMesh.getTriangles(mtrianglecounts, mtrianglevertices); std::vector<vec3f> vertices(mpoints.length()); std::vector<vec3f> normals(mpoints.length()); std::vector<unsigned int> indices(mtrianglevertices.length()); for(size_t i = 0; i < vertices.size(); ++i) { vertices[i] = vec3f(mpoints[i].x, mpoints[i].y, mpoints[i].z); normals[i] = vec3f(mnormals[i].x, mnormals[i].y, mnormals[i].z); } for(size_t i = 0; i < indices.size(); ++i) { indices[i] = mtrianglevertices[i]; } bool dynamicMesh = false; collision_shape = solver_t::create_hacd_shape(&(vertices[0]), vertices.size(), &(normals[0]), &(indices[0]), indices.size(),dynamicMesh); } } } break; default: { } } return collision_shape; }
// the arrays being passed in are assumed to be empty void MayaMeshWriter::fillTopology( std::vector<float> & oPoints, std::vector<Alembic::Util::int32_t> & oFacePoints, std::vector<Alembic::Util::int32_t> & oPointCounts) { MStatus status = MS::kSuccess; MFnMesh lMesh( mDagPath, &status ); if ( !status ) { MGlobal::displayError( "MFnMesh() failed for MayaMeshWriter" ); } MFloatPointArray pts; lMesh.getPoints(pts); if (pts.length() < 3 && pts.length() > 0) { MString err = lMesh.fullPathName() + " is not a valid mesh, because it only has "; err += pts.length(); err += " points."; MGlobal::displayError(err); return; } unsigned int numPolys = lMesh.numPolygons(); if (numPolys == 0) { MGlobal::displayWarning(lMesh.fullPathName() + " has no polygons."); return; } unsigned int i; int j; oPoints.resize(pts.length() * 3); // repack the float for (i = 0; i < pts.length(); i++) { size_t local = i * 3; oPoints[local] = pts[i].x; oPoints[local+1] = pts[i].y; oPoints[local+2] = pts[i].z; } /* oPoints - oFacePoints - vertex list oPointCounts - number of points per polygon */ MIntArray faceArray; for (i = 0; i < numPolys; i++) { lMesh.getPolygonVertices(i, faceArray); if (faceArray.length() < 3) { MGlobal::displayWarning("Skipping degenerate polygon"); continue; } // write backwards cause polygons in Maya are in a different order // from Renderman (clockwise vs counter-clockwise?) int faceArrayLength = faceArray.length() - 1; for (j = faceArrayLength; j > -1; j--) { oFacePoints.push_back(faceArray[j]); } oPointCounts.push_back(faceArray.length()); } }
void vixo_hairStyleMaya::exportFollicle(int hairNumValue,MString uvFileName,MString hairRootInfo,MDataBlock& data) { MObject meshObj=data.inputValue(inMesh).asMesh(); MItMeshPolygon iterFace(meshObj); double area=0.0; int triTotNum=0; for(iterFace.reset();!iterFace.isDone();iterFace.next()) { double areaTmp; iterFace.getArea(areaTmp); area+=areaTmp; int triTotNumTmp; iterFace.numTriangles(triTotNumTmp); triTotNum+=triTotNumTmp; if(iterFace.isDone()) break; } MFnMesh fnMesh(meshObj); vector<vector<float>> uv(triTotNum); vector<int> triInfoIndex(triTotNum,0); //numFollicle vector<streampos> triInfoPosIndex(triTotNum); vector<int> vertexCtrl(triTotNum*3); vector<vector<float>> vertexWeight(triTotNum); double diff=sqrt(area/hairNumValue); int hairIter=0; int triIter=0; for(iterFace.reset();!iterFace.isDone();iterFace.next()) { MIntArray faceVertexIndex; iterFace.getVertices(faceVertexIndex); MVectorArray faceNormals; iterFace.getNormals(faceNormals,MSpace::kWorld); MFloatVectorArray faceTangents; fnMesh.getFaceVertexTangents(iterFace.index(),faceTangents,MSpace::kWorld); map<int,int> vertexIndex2faceIndex; for(int i=0;i<faceVertexIndex.length();i++) { vertexIndex2faceIndex.insert(pair<int,int>(faceVertexIndex[i],i)); } int triNum; iterFace.numTriangles(triNum); MString uvset("map1"); for(int tri=0;tri<triNum;tri++) { MPointArray vertex; MIntArray vertexIndex; iterFace.getTriangle(tri,vertex,vertexIndex); int numLine1=MVector(vertex[1]-vertex[0]).length()/diff; int numLine2=MVector(vertex[2]-vertex[0]).length()/diff; MFloatArray uvs(6); float2 tempUV; iterFace.getUV(vertexIndex2faceIndex.find(vertexIndex[0])->second,tempUV,&uvset); uvs[0]=tempUV[0]; uvs[1]=tempUV[1]; iterFace.getUV(vertexIndex2faceIndex.find(vertexIndex[1])->second,tempUV,&uvset); uvs[2]=tempUV[0]; uvs[3]=tempUV[1]; iterFace.getUV(vertexIndex2faceIndex.find(vertexIndex[2])->second,tempUV,&uvset); uvs[4]=tempUV[0]; uvs[5]=tempUV[1]; vertexCtrl[3*triIter]=vertexIndex[1]; vertexCtrl[3*triIter+1]=vertexIndex[2]; vertexCtrl[3*triIter+2]=vertexIndex[0]; for(int i=0;i<numLine1;i++) { for(int j=0;j<(1-(float)i/numLine1)*numLine2;j++) { vertexWeight[triIter].push_back((float)i/numLine1); vertexWeight[triIter].push_back((float)j/numLine2); vertexWeight[triIter].push_back(1-(float)i/numLine1-(float)j/numLine2); int localHairIter=triInfoIndex[triIter]; uv[triIter].push_back(uvs[0]*vertexWeight[triIter][3*localHairIter+2]+uvs[2]*vertexWeight[triIter][3*localHairIter]+uvs[4]*vertexWeight[triIter][3*localHairIter+1]); uv[triIter].push_back(uvs[1]*vertexWeight[triIter][3*localHairIter+2]+uvs[3]*vertexWeight[triIter][3*localHairIter]+uvs[5]*vertexWeight[triIter][3*localHairIter+1]); hairIter++; triInfoIndex[triIter]++; } } triIter++; } if(iterFace.isDone()) break; } //print uv fstream fout(uvFileName.asChar(),ios_base::out|ios_base::binary); fout.write((char*)&triTotNum,sizeof(int)); fout.write((char*)&triInfoIndex[0],sizeof(int)*triTotNum); fout.write((char*)&vertexCtrl[0],sizeof(int)*3*triTotNum); //for cache export for(int i=0;i<triTotNum;i++) //for color info { fout.write((char*)&uv[i][0],sizeof(float)*2*triInfoIndex[i]); } fout.flush(); fout.close(); //~print uv /* //debug uv MString uvDebug=uvFileName+"debug"; fout.open(uvDebug.asChar(),ios_base::out); fout<<triTotNum<<endl; for(int i=0;i<triTotNum;i++) fout<<"tri"<<i<<":"<<'\t'<<triInfoIndex[i]<<'\t'<<vertexCtrl[3*i]<<'\t'<<vertexCtrl[3*i+1]<<'\t'<<vertexCtrl[3*i+2]<<endl; for(int i=0;i<triTotNum;i++) for(int j=0;j<triInfoIndex[i];j++) fout<<"tri"<<i<<":"<<'\t'<<j<<'\t'<<uv[i][2*j]<<'\t'<<uv[i][2*j+1]<<endl; fout.flush(); fout.close(); //~debug uv */ //prepare streampos triInfoPosIndex[0]=sizeof(int)+sizeof(streampos)*triTotNum; for(int i=1;i<triTotNum;i++) { triInfoPosIndex[i]=triInfoPosIndex[i-1].operator+(sizeof(int)+sizeof(float)*3*triInfoIndex[i-1]); } //~prepare streampos //print infos fout.open(hairRootInfo.asChar(),ios_base::out|ios_base::binary); fout.write((char*)&triTotNum,sizeof(int)); fout.write((char*)&triInfoPosIndex[0],sizeof(streampos)*triTotNum); for(int i=0;i<triTotNum;i++) //for color info { fout.write((char*)&triInfoIndex[i],sizeof(int)); fout.write((char*)&vertexWeight[i][0],sizeof(float)*3*triInfoIndex[i]); } fout.flush(); fout.close(); //~print infos /* //debug info MString hairRootInfoDebug=hairRootInfo+"debug"; fout.open(hairRootInfoDebug.asChar(),ios_base::out); fout<<triTotNum<<endl; for(int i=0;i<triTotNum;i++) fout<<"tri"<<i<<":"<<'\t'<<triInfoIndex[i]<<'\t'<<triInfoPosIndex[i]<<endl; for(int i=0;i<triTotNum;i++) for(int j=0;j<triInfoIndex[i];j++) fout<<"tri"<<i<<":"<<'\t'<<j<<'\t'<<vertexWeight[i][3*j]<<'\t'<<vertexWeight[i][3*j+1]<<'\t'<<vertexWeight[i][3*j+2]<<endl; fout.flush(); fout.close(); //~debug info */ }
//! Create OSD HBR mesh. //! Caller is expected to delete the resulting hbrMesh returned HMesh * createOsdHbrFromPoly( MFnMesh const & inMeshFn, MItMeshPolygon & inMeshItPolygon, std::vector<int> & fvarIndices, std::vector<int> & fvarWidths) { MStatus returnStatus; // == Mesh Properties // Gather FVarData MStringArray uvSetNames; MStringArray colorSetNames; std::vector<int> colorSetChannels; std::vector<MFnMesh::MColorRepresentation> colorSetReps; int totalColorSetChannels = 0; returnStatus = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, colorSetChannels, colorSetReps, totalColorSetChannels); MWARNERR(returnStatus, "Failed to retrieve Maya face-varying parameters"); // Create face-varying data with independent float channels of dimension 1 // Note: This FVarData needs to be kept around for the duration of the HBR mesh int totalFvarWidth = 2*uvSetNames.length() + totalColorSetChannels; fvarIndices.resize(totalFvarWidth); fvarWidths.resize(totalFvarWidth); for (int i=0; i < totalFvarWidth; ++i) { fvarIndices[i] = i; fvarWidths[i] = 1; } // temp storage for UVs and ColorSets for a face MIntArray fvArray; // face vertex array std::vector<MFloatArray> uvSet_uCoords(uvSetNames.length()); std::vector<MFloatArray> uvSet_vCoords(uvSetNames.length()); std::vector<MColorArray> colorSet_colors(colorSetNames.length()); // ===================================== // Init HBR // ===================================== // Determine HBR Subdiv Method static HCatmark _catmark; // Create HBR mesh assert(fvarIndices.size() == fvarWidths.size()); HMesh * hbrMesh = new HMesh( &_catmark, (int)fvarIndices.size(), (fvarIndices.size() > 0) ? &fvarIndices[0] : NULL, (fvarWidths.size() > 0) ? &fvarWidths[0] : NULL, totalFvarWidth ); // Create Stub HBR Vertices int numVerts = inMeshFn.numVertices(); OpenSubdiv::OsdVertex v; for(int i=0; i<numVerts; i++ ) { hbrMesh->NewVertex( i, v ); } // =================================================== // Create HBR Topology // =================================================== assert(totalFvarWidth == hbrMesh->GetTotalFVarWidth()); unsigned int ptxidx = 0; for( inMeshItPolygon.reset(); !inMeshItPolygon.isDone(); inMeshItPolygon.next() ) { // Verts for this face inMeshItPolygon.getVertices(fvArray); unsigned int nv = fvArray.length(); bool valid = true; for(unsigned int j=0;j<fvArray.length(); j++) { HVertex const * origin = hbrMesh->GetVertex( fvArray[j] ), * destination = hbrMesh->GetVertex( fvArray[(j+1)%nv] ); HHalfedge const * opposite = destination->GetEdge(origin); if(origin==NULL || destination==NULL) { fprintf(stderr, "Skipping face: An edge was specified that connected a nonexistent vertex\n"); valid = false; break; } if(origin == destination) { fprintf(stderr, "Skipping face: An edge was specified that connected a vertex to itself\n"); valid = false; break; } if(opposite && opposite->GetOpposite() ) { fprintf(stderr, "Skipping face: A non-manifold edge incident to more than 2 faces was found\n"); valid = false; break; } if(origin->GetEdge(destination)) { fprintf(stderr, "Skipping face: An edge connecting two vertices was specified more than once." " It's likely that an incident face was flipped\n"); valid = false; break; } } // Update faces const int * fvArrayPtr = &(fvArray[0]); // get the raw int* array from std::vector<int> OpenSubdiv::HbrFace<OpenSubdiv::OsdVertex> * face = hbrMesh->NewFace(nv, fvArrayPtr, 0); // Increment ptex index face->SetPtexIndex(ptxidx); // Add FaceVaryingData (UVSets, ...) if (totalFvarWidth > 0) { // Retrieve all UV and ColorSet data MIntArray faceCounts; for (unsigned int i=0; i < uvSetNames.length(); ++i) { returnStatus = inMeshItPolygon.getUVs(uvSet_uCoords[i], uvSet_vCoords[i], &uvSetNames[i] ); MWARNERR(returnStatus, "Cannot get UVs"); } for (unsigned int i=0; i < colorSetNames.length(); ++i) { returnStatus = inMeshItPolygon.getColors (colorSet_colors[i], &colorSetNames[i]); MWARNERR(returnStatus, "Cannot get face vertex colors"); } std::vector<float> fvarItem(totalFvarWidth); // storage for all the face-varying channels for this face-vertex // loop over each uvSet and the uvs within for (unsigned int fvid=0; fvid < fvArray.length(); ++fvid) { int fvarItemIndex = 0; // Handle uvSets for( unsigned int uvSetIt=0; uvSetIt < uvSetNames.length(); ++uvSetIt ) { fvarItem[fvarItemIndex] = uvSet_uCoords[uvSetIt][fvid]; fvarItem[fvarItemIndex+1] = uvSet_vCoords[uvSetIt][fvid]; fvarItemIndex +=2; } // Handle colorSets for( unsigned int colorSetIt=0; colorSetIt < colorSetNames.length(); ++colorSetIt ) { if (colorSetChannels[colorSetIt] == 1) { fvarItem[fvarItemIndex] = colorSet_colors[colorSetIt][fvid].a; } else if (colorSetChannels[colorSetIt] == 3) { fvarItem[fvarItemIndex] = colorSet_colors[colorSetIt][fvid].r; fvarItem[fvarItemIndex+1] = colorSet_colors[colorSetIt][fvid].g; fvarItem[fvarItemIndex+2] = colorSet_colors[colorSetIt][fvid].b; } else { // colorSetChannels[colorSetIt] == 4 fvarItem[fvarItemIndex] = colorSet_colors[colorSetIt][fvid].r; fvarItem[fvarItemIndex+1] = colorSet_colors[colorSetIt][fvid].g; fvarItem[fvarItemIndex+2] = colorSet_colors[colorSetIt][fvid].b; fvarItem[fvarItemIndex+3] = colorSet_colors[colorSetIt][fvid].a; } fvarItemIndex += colorSetChannels[colorSetIt]; } assert((fvarItemIndex) == totalFvarWidth); // For UVs, sanity check the resulting value // Insert into the HBR structure for that face HVertex * hbrVertex = hbrMesh->GetVertex( fvArray[fvid] ); HFvarData & fvarData = hbrVertex->GetFVarData(face); if (not fvarData.IsInitialized()) { fvarData.SetAllData(totalFvarWidth, &fvarItem[0]); } else if (not fvarData.CompareAll(totalFvarWidth, &fvarItem[0])) { // If data exists for this face vertex, but is different // (e.g. we're on a UV seam) create another fvar datum OpenSubdiv::HbrFVarData<OpenSubdiv::OsdVertex> &fvarData_new = hbrVertex->NewFVarData(face); fvarData_new.SetAllData( totalFvarWidth, &fvarItem[0] ); } } } // Increment ptxidx and store off ptex index values // The number of ptexIds needed is 1 if a quad. Otherwise it is the number of // vertices for the face. int numPtexIdsForFace; if (valid) { numPtexIdsForFace = ( nv != 4 ) ? nv : 1 ; } else { numPtexIdsForFace = 0; } ptxidx += numPtexIdsForFace; } // Apply Creases applyCreaseEdges( inMeshFn, hbrMesh ); applyCreaseVertices( inMeshFn, hbrMesh ); // Return the resulting HBR Mesh // Note that boundaryMethods and hbrMesh->Finish() still need to be called return hbrMesh; }
MStatus getObject::readMesh(yafaray::yafrayInterface_t &yI,std::map<string , yafaray::material_t *> &materialMap) { MStatus stat=MStatus::kSuccess; //select all the mesh in the scene MString readMeshCmd("ls -type mesh"); MStringArray readMeshResult; MGlobal::executeCommand(readMeshCmd, readMeshResult); for(unsigned int i=0; i<readMeshResult.length(); i++) { MSelectionList meshList; MGlobal::getSelectionListByName(readMeshResult[i],meshList); for(unsigned int index=0; index<meshList.length(); index++) { MDagPath meshPath; meshList.getDagPath(index, meshPath); //this is for getting the number of faces of the mesh MFnMesh meshFn(meshPath); cout<<"==============mesh test=============="<<endl; cout<<"mesh name:"<<meshFn.name()<<endl; //find the material of the mesh MObjectArray sgArray; MIntArray indexSG; meshFn.getConnectedShaders(0, sgArray, indexSG); MFnDependencyNode sgFn(sgArray[0]); MPlug surfacePlug=sgFn.findPlug("surfaceShader"); MPlugArray sourceArray; MString shaderName; if (surfacePlug.connectedTo(sourceArray, true, false)) { MPlug sourcePlug=sourceArray[0]; MObject sourceNode=sourcePlug.node(); MFnDependencyNode sourceFn(sourceNode); shaderName=sourceFn.name(); } string sName(shaderName.asChar()); cout<<"material name:"<<sName<<endl; std::map<string , yafaray::material_t *>::iterator iter=materialMap.find(sName); if(iter==materialMap.end()) { //if searched in the map and didn't find the shader name of this object(means this object didn't use yafaray's material) //we should give it an default shader //to implement this, should export a default shader first, in the read shader step //iter=materialMap.find("yafDefaultMaterial"); //using method above got some problem...when two shape use one trasform node //found this problem when using ncloth //so still jump the ones who didn't use yafaray's material cout<<"this mesh doesn't use yafaray's material"<<endl; MGlobal::displayInfo("(yafaray mesh) this mesh doesn't use yafaray's material!"); break; } unsigned int yafID=yI.getNextFreeID(); //itorate all the vertices and print them out MItMeshVertex meshVertex(meshPath); yI.paramsClearAll(); yI.startGeometry(); //since MFnMesh does not provide the number of triangles directly, so have to get it in another way MItMeshPolygon forCountTriangle(meshPath); int numTriangle=0; int count; for(;!forCountTriangle.isDone();forCountTriangle.next()) { forCountTriangle.numTriangles(count); numTriangle=numTriangle+count; } yI.startTriMesh(yafID, meshFn.numVertices(), numTriangle, false, false, 0); for(; !meshVertex.isDone();meshVertex.next()) { MPoint locationV=meshVertex.position(MSpace::kWorld); yI.addVertex(locationV.x,locationV.y,locationV.z); } //find every triangle face by face MItMeshPolygon meshFace(meshPath); for(;!meshFace.isDone();meshFace.next()) { MPointArray points; MIntArray pointIndices; float UV0[2]; float UV1[2]; float UV2[2]; meshFace.getTriangles(points,pointIndices,MSpace::kWorld); //get the indices for each vertex of the triangle. the index will be correspond to the point array before for(unsigned int i=0;i<pointIndices.length();i++) { meshFace.getUVAtPoint(points[i],UV0,MSpace::kObject); meshFace.getUVAtPoint(points[i+1],UV1,MSpace::kObject); meshFace.getUVAtPoint(points[i+2],UV2,MSpace::kObject); ////test output //cout<<"================="<<i<<"================"<<endl; //cout<<UV0[0]<<UV0[1]<<endl; //cout<<UV1[0]<<UV1[1]<<endl; //cout<<UV2[0]<<UV2[1]<<endl; int uvIndex0=yI.addUV(UV0[0],UV0[1]); int uvIndex1=yI.addUV(UV1[0],UV1[1]); int uvIndex2=yI.addUV(UV2[0],UV2[1]); yI.addTriangle(pointIndices[i],pointIndices[i+1],pointIndices[i+2],uvIndex0,uvIndex1,uvIndex2,iter->second); //yI.addTriangle(pointIndices[i],pointIndices[i+1],pointIndices[i+2],iter->second); i=i+2; } } yI.endTriMesh(); yI.smoothMesh(0, 181); yI.endGeometry(); } } return stat; }
MObject LSystemNode::createMesh(const double & angle, const double & step, const MString & grammar, const MTime& time, MObject& outData, MStatus& stat) { //int numVertices, frame; //float cubeSize; //MFloatPointArray points; MPointArray points; MIntArray faceCounts; MIntArray faceConnects; MFnMesh meshFS; LSystem lsys; lsys.setDefaultAngle(angle); //angle lsys.setDefaultStep(step); //step size string gram = grammar.asChar(); //grammar lsys.loadProgramFromString(gram); std::vector<LSystem::Branch> branches; lsys.process((int)time.value(),branches); CylinderMesh*cm; for(int j = 0;j<branches.size();j++) { vec3 Bstart = branches[j].first; vec3 Bend = branches[j].second; MPoint b_start(Bstart[0],Bstart[1],Bstart[2]); MPoint b_end(Bend[0],Bend[1],Bend[2]); cm = new CylinderMesh(b_start,b_end); cm->appendToMesh(points,faceCounts,faceConnects); } /* // Scale the cube on the frame number, wrap every 10 frames. frame = (int)time.as( MTime::kFilm ); if (frame == 0) frame = 1; cubeSize = 0.5f * (float)( frame % 10); const int numFaces = 6; numVertices = 8; const int numFaceConnects = 24;*/ /* MFloatPoint vtx_1( -cubeSize, -cubeSize, -cubeSize ); MFloatPoint vtx_2( cubeSize, -cubeSize, -cubeSize ); MFloatPoint vtx_3( cubeSize, -cubeSize, cubeSize ); MFloatPoint vtx_4( -cubeSize, -cubeSize, cubeSize ); MFloatPoint vtx_5( -cubeSize, cubeSize, -cubeSize ); MFloatPoint vtx_6( -cubeSize, cubeSize, cubeSize ); MFloatPoint vtx_7( cubeSize, cubeSize, cubeSize ); MFloatPoint vtx_8( cubeSize, cubeSize, -cubeSize ); points.append( vtx_1 ); points.append( vtx_2 ); points.append( vtx_3 ); points.append( vtx_4 ); points.append( vtx_5 ); points.append( vtx_6 ); points.append( vtx_7 ); points.append( vtx_8 ); // Set up an array containing the number of vertices // for each of the 6 cube faces (4 verticies per face) // int face_counts[numFaces] = { 4, 4, 4, 4, 4, 4 }; MIntArray faceCounts( face_counts, numFaces ); // Set up and array to assign vertices from points to each face // int face_connects[ numFaceConnects ] = { 0, 1, 2, 3, 4, 5, 6, 7, 3, 2, 6, 5, 0, 3, 5, 4, 0, 4, 7, 1, 1, 7, 6, 2 }; MIntArray faceConnects( face_connects, numFaceConnects ); MObject newMesh = meshFS.create(numVertices, numFaces, points, faceCounts, faceConnects, outData, &stat); return newMesh;*/ MObject newMesh = meshFS.create(points.length() ,faceCounts.length(),points,faceCounts ,faceConnects,outData,&stat); return newMesh; }
void OsdPtexMeshData::rebuildHbrMeshIfNeeded(OpenSubdivPtexShader *shader) { MStatus status; if (!_meshTopoDirty && !shader->getHbrMeshDirty()) return; MFnMesh meshFn(_meshDagPath, &status); if (status != MS::kSuccess) return; int level = shader->getLevel(); if (level < 1) level =1; SchemeType scheme = shader->getScheme(); if (scheme == kLoop) scheme = kCatmark; // XXX: avoid loop for now // Get Maya vertex topology and crease data MIntArray vertexCount; MIntArray vertexList; meshFn.getVertices(vertexCount, vertexList); MUintArray edgeIds; MDoubleArray edgeCreaseData; meshFn.getCreaseEdges(edgeIds, edgeCreaseData); MUintArray vtxIds; MDoubleArray vtxCreaseData; meshFn.getCreaseVertices(vtxIds, vtxCreaseData); if (vertexCount.length() == 0) return; // Cache attribute values _level = shader->getLevel(); _scheme = shader->getScheme(); _kernel = shader->getKernel(); _adaptive = shader->isAdaptive(); _interpBoundary = shader->getInterpolateBoundary(); // Copy Maya vectors into std::vectors std::vector<int> numIndices(&vertexCount[0], &vertexCount[vertexCount.length()]); std::vector<int> faceIndices(&vertexList[0], &vertexList[vertexList.length()]); std::vector<int> vtxCreaseIndices(&vtxIds[0], &vtxIds[vtxIds.length()]); std::vector<double> vtxCreases(&vtxCreaseData[0], &vtxCreaseData[vtxCreaseData.length()]); std::vector<double> edgeCreases(&edgeCreaseData[0], &edgeCreaseData[edgeCreaseData.length()]); // Edge crease index is stored as pairs of vertex ids int nEdgeIds = edgeIds.length(); std::vector<int> edgeCreaseIndices; edgeCreaseIndices.resize(nEdgeIds*2); for (int i = 0; i < nEdgeIds; ++i) { int2 vertices; status = meshFn.getEdgeVertices(edgeIds[i], vertices); if (status.error()) { status.perror("ERROR can't get creased edge vertices"); continue; } edgeCreaseIndices[i*2] = vertices[0]; edgeCreaseIndices[i*2+1] = vertices[1]; } // Convert attribute enums to HBR enums (this is why the enums need to match) // XXX use some sort of built-in transmorgification avoid assumption? HbrMeshUtil::SchemeType hbrScheme = (HbrMeshUtil::SchemeType) _scheme; OsdHbrMesh::InterpolateBoundaryMethod hbrInterpBoundary = (OsdHbrMesh::InterpolateBoundaryMethod) _interpBoundary; // Convert Maya mesh to internal HBR representation _hbrmesh = ConvertToHBR(meshFn.numVertices(), numIndices, faceIndices, vtxCreaseIndices, vtxCreases, std::vector<int>(), std::vector<float>(), edgeCreaseIndices, edgeCreases, hbrInterpBoundary, hbrScheme, true ); // add ptex indices to HBR // note: GL function can't be used in prepareForDraw API. _needsInitializeMesh = true; // Mesh topology data is up to date _meshTopoDirty = false; shader->setHbrMeshDirty(false); }
bool ProceduralHolderUI::select( MSelectInfo &selectInfo, MSelectionList &selectionList, MPointArray &worldSpaceSelectPts ) const { MStatus s; // early out if we're not selectable. we always allow components to be selected if we're highlighted, // but we don't allow ourselves to be selected as a whole unless meshes are in the selection mask. // it's not ideal that we act like a mesh, but it's at least consistent with the drawing mask we use. if( selectInfo.displayStatus() != M3dView::kHilite ) { MSelectionMask meshMask( MSelectionMask::kSelectMeshes ); if( !selectInfo.selectable( meshMask ) ) { return false; } } // early out if we have no scene to draw ProceduralHolder *proceduralHolder = static_cast<ProceduralHolder *>( surfaceShape() ); IECoreGL::ConstScenePtr scene = proceduralHolder->scene(); if( !scene ) { return false; } // we want to perform the selection using an IECoreGL::Selector, so we // can avoid the performance penalty associated with using GL_SELECT mode. // that means we don't really want to call view.beginSelect(), but we have to // call it just to get the projection matrix for our own selection, because as far // as i can tell, there is no other way of getting it reliably. M3dView view = selectInfo.view(); view.beginSelect(); Imath::M44d projectionMatrix; glGetDoublev( GL_PROJECTION_MATRIX, projectionMatrix.getValue() ); view.endSelect(); view.beginGL(); glMatrixMode( GL_PROJECTION ); glLoadMatrixd( projectionMatrix.getValue() ); IECoreGL::Selector::Mode selectionMode = IECoreGL::Selector::IDRender; if( selectInfo.displayStatus() == M3dView::kHilite && !selectInfo.singleSelection() ) { selectionMode = IECoreGL::Selector::OcclusionQuery; } IECoreGL::Selector selector; selector.begin( Imath::Box2f( Imath::V2f( 0 ), Imath::V2f( 1 ) ), selectionMode ); IECoreGL::State::bindBaseState(); selector.baseState()->bind(); scene->render( selector.baseState() ); if( selectInfo.displayStatus() != M3dView::kHilite ) { // we're not in component selection mode. we'd like to be able to select the procedural // object using the bounding box so we draw it too. MPlug pDrawBound( proceduralHolder->thisMObject(), ProceduralHolder::aDrawBound ); bool drawBound = true; pDrawBound.getValue( drawBound ); if( drawBound ) { IECoreGL::BoxPrimitive::renderWireframe( IECore::convert<Imath::Box3f>( proceduralHolder->boundingBox() ) ); } } std::vector<IECoreGL::HitRecord> hits; selector.end( hits ); view.endGL(); if( !hits.size() ) { return false; } // iterate over the hits, converting them into components and also finding // the closest one. MIntArray componentIndices; float depthMin = std::numeric_limits<float>::max(); int depthMinIndex = -1; for( int i=0, e = hits.size(); i < e; i++ ) { if( hits[i].depthMin < depthMin ) { depthMin = hits[i].depthMin; depthMinIndex = componentIndices.length(); } ProceduralHolder::ComponentsMap::const_iterator compIt = proceduralHolder->m_componentsMap.find( hits[i].name.value() ); assert( compIt != proceduralHolder->m_componentsMap.end() ); componentIndices.append( compIt->second.first ); } assert( depthMinIndex >= 0 ); // figure out the world space location of the closest hit MDagPath camera; view.getCamera( camera ); MFnCamera fnCamera( camera.node() ); float near = fnCamera.nearClippingPlane(); float far = fnCamera.farClippingPlane(); float z = -1; if( fnCamera.isOrtho() ) { z = Imath::lerp( near, far, depthMin ); } else { // perspective camera - depth isn't linear so linearise to get z float a = far / ( far - near ); float b = far * near / ( near - far ); z = b / ( depthMin - a ); } MPoint localRayOrigin; MVector localRayDirection; selectInfo.getLocalRay( localRayOrigin, localRayDirection ); MMatrix localToCamera = selectInfo.selectPath().inclusiveMatrix() * camera.inclusiveMatrix().inverse(); MPoint cameraRayOrigin = localRayOrigin * localToCamera; MVector cameraRayDirection = localRayDirection * localToCamera; MPoint cameraIntersectionPoint = cameraRayOrigin + cameraRayDirection * ( -( z - near ) / cameraRayDirection.z ); MPoint worldIntersectionPoint = cameraIntersectionPoint * camera.inclusiveMatrix(); // turn the processed hits into appropriate changes to the current selection if( selectInfo.displayStatus() == M3dView::kHilite ) { // selecting components MFnSingleIndexedComponent fnComponent; MObject component = fnComponent.create( MFn::kMeshPolygonComponent, &s ); assert( s ); if( selectInfo.singleSelection() ) { fnComponent.addElement( componentIndices[depthMinIndex] ); } else { fnComponent.addElements( componentIndices ); } MSelectionList items; items.add( selectInfo.multiPath(), component ); selectInfo.addSelection( items, worldIntersectionPoint, selectionList, worldSpaceSelectPts, MSelectionMask::kSelectMeshFaces, true ); } else { // selecting objects MSelectionList item; item.add( selectInfo.selectPath() ); selectInfo.addSelection( item, worldIntersectionPoint, selectionList, worldSpaceSelectPts, MSelectionMask::kSelectMeshes, false ); } return true; }
void RemapToOGLFmt( MFnMesh &mfnMesh, k3d::MeshData & outputMesh, MIntArray & triangleList, MIntArray & triangleNList, MIntArray & triangleUVList, MString & uvSetName) { assert(triangleList.length() == triangleNList.length()); assert(triangleNList.length() == triangleUVList.length()); typedef std::tuple<int, int, int> P_N_T; typedef std::map<P_N_T, int> PNTMap; typedef PNTMap::const_iterator PNTIter; PNTMap h; MFloatPointArray vertex; mfnMesh.getPoints(vertex); MFloatVectorArray normal; mfnMesh.getNormals(normal); MFloatArray uArray, vArray; mfnMesh.getUVs(uArray, vArray, &uvSetName); bool hasUV = (uArray.length() > 0); bool hasNormal = (normal.length() > 0); VtxFormat defaultVtxFmt = VtxFormat::POS3_F32; if (hasNormal && hasUV) { defaultVtxFmt = VtxFormat::POS3_F32_NOR3_F32_UV2_F32; } else if (hasNormal && !hasUV) { defaultVtxFmt = VtxFormat::POS3_F32_NOR3_F32; } else if (hasUV && !hasNormal) { defaultVtxFmt = VtxFormat::POS3_F32_UV2_F32; } outputMesh.SetVertexFormat(defaultVtxFmt); std::vector<uint32> indexBuffer; std::vector<k3d::Vertex3F3F2F> vertex332List; std::vector<k3d::Vertex3F3F> vertex33List; std::vector<k3d::Vertex3F> vertex3List; for (size_t i = 0, idx = 0; i < triangleList.length(); i++) { P_N_T p(triangleList[i], triangleNList[i], triangleUVList[i]); PNTIter match = h.find(p); // found if (match != h.end()) { indexBuffer.push_back(match->second); } else //Not Found { h[p] = idx; indexBuffer.push_back(idx++); int vid = std::get<0>(p); int nid = std::get<1>(p); int tid = std::get<2>(p); if (defaultVtxFmt == VtxFormat::POS3_F32_NOR3_F32_UV2_F32) { vertex332List.push_back({ vertex[vid].x, vertex[vid].y, vertex[vid].z, normal[nid].x, normal[nid].y, normal[nid].z, uArray[tid], vArray[tid] }); } else if (defaultVtxFmt == VtxFormat::POS3_F32_NOR3_F32) { vertex33List.push_back({ vertex[vid].x, vertex[vid].y, vertex[vid].z, normal[nid].x, normal[nid].y, normal[nid].z }); } else if (defaultVtxFmt == VtxFormat::POS3_F32) { vertex3List.push_back({ vertex[vid].x, vertex[vid].y, vertex[vid].z, }); } } } outputMesh.SetIndexBuffer(indexBuffer); if (defaultVtxFmt == VtxFormat::POS3_F32_NOR3_F32_UV2_F32) { outputMesh.SetVertexNum(vertex332List.size()); outputMesh.SetVertexBuffer(&vertex332List[0]); } else if (defaultVtxFmt == VtxFormat::POS3_F32_NOR3_F32) { outputMesh.SetVertexNum(vertex33List.size()); outputMesh.SetVertexBuffer(&vertex33List[0]); } else if (defaultVtxFmt == VtxFormat::POS3_F32) { outputMesh.SetVertexNum(vertex3List.size()); outputMesh.SetVertexBuffer(&vertex3List[0]); } }