MObject MG_poseReader::makePlane(const MVector& p1,const MVector& p2,const MVector& p3){ MFnMesh meshFn; MPoint p1p (p1); MPoint p2p (p2); MPoint p3p (p3); MPointArray pArray; pArray.append(p1p); pArray.append(p2p); pArray.append(p3p); MIntArray polyCount; polyCount.append(3); MIntArray polyConnect; polyConnect.append(0); polyConnect.append(1); polyConnect.append(2); MFnMeshData data; MObject polyData = data.create(); MStatus stat; meshFn.create(3,1,pArray,polyCount,polyConnect,polyData,&stat); return polyData; }
MObject animCube::createMesh(const MTime& time, MObject& outData, MStatus& stat) { int numVertices, frame; float cubeSize; MFloatPointArray points; MFnMesh meshFS; // 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; }
MStatus metro_model_translator::create_shape( const m2033::mesh_ptr m ) { MFloatPointArray v; MVectorArray norm; MIntArray p; MIntArray idx; MFnTransform transform_fn; MObject transform_obj = transform_fn.create( MObject::kNullObj ); transform_fn.setName( m->get_name().c_str() ); m2033::mesh::vertices mv = m->get_vertices(); m2033::mesh::indices mi = m->get_indices(); m2033::mesh::texcoords mt = m->get_tex_coords(); m2033::mesh::normals mn = m->get_normals(); for( unsigned i = 0; i < mv.size(); i++ ) { v.append( -mv[i].x, mv[i].y, mv[i].z ); norm.append( MVector( -mn[i].x, mn[i].y, mn[i].z ) ); } for( unsigned i = 0; i < mi.size() / 3; i++ ) { idx.append( mi[i*3+2] ); idx.append( mi[i*3+1] ); idx.append( mi[i*3] ); p.append( 3 ); } MFloatArray u_values, v_values; for( unsigned i = 0; i < mt.size(); i++ ) { u_values.append( mt[i].x ); v_values.append( -mt[i].y ); } MFnMesh meshFn; MObject mesh = meshFn.create( v.length(), p.length(), v, p, idx, u_values, v_values, transform_obj ); MString name = m->get_name().c_str(); meshFn.setName( name + MString("_shape") ); MStatus s = meshFn.assignUVs( p, idx, 0 ); if( !s ) { return s; } s = meshFn.unlockVertexNormals( idx ); if( !s ) { return s; } meshFn.setVertexNormals( norm, idx ); MObject mat = create_material( m->get_texture_name(), &s ); if( !s ) { return s; } MFnSet mat_fn(mat); mat_fn.addMember(mesh); return MS::kSuccess; }
static void makeCubes(std::vector<cube> &cubes, MString &name, MStatus *stat) { MFnMesh fnMesh; MObject result; MFloatPointArray points; MIntArray faceCounts; MIntArray faceConnects; int index_offset = 0; for (std::vector<cube>::iterator cit = cubes.begin(); cit != cubes.end(); ++cit) { point3 diag = cit->diagonal(); float scale = diag.x; point3 pos = cit->start + (diag * .5f); MFloatVector mpos(pos.x, pos.y, pos.z); addCube(scale, mpos, index_offset * (8), points, faceCounts, faceConnects); index_offset += 1; } unsigned int vtx_cnt = points.length(); unsigned int face_cnt = faceCounts.length(); MObject newMesh = fnMesh.create( /* numVertices */ vtx_cnt, /* numFaces */ face_cnt, points, faceCounts, faceConnects, MObject::kNullObj, stat); /* Harden all edges. */ int n_edges = fnMesh.numEdges(stat); for (int i = 0; i < n_edges; ++i) { fnMesh.setEdgeSmoothing(i, false); } fnMesh.cleanupEdgeSmoothing(); /* Must be called after editing edges. */ fnMesh.updateSurface(); /* Assign Shader. */ MSelectionList sel_list; if (!MFAIL(sel_list.add("initialShadingGroup"))) { MObject set_obj; sel_list.getDependNode(0, set_obj); MFnSet set(set_obj); set.addMember(newMesh); } /* Give it a swanky name. */ MFnDagNode parent(fnMesh.parent(0)); name = parent.setName("polyMengerSponge", false, stat); }
MStatus LSSolverNode::buildOutputMesh(MFnMesh& inputMesh, float* vertices, MObject &outputMesh) { MStatus stat; MPointArray points; unsigned vIndex = 0; int numVertices = inputMesh.numVertices(); for(int i=0; i<numVertices;i++) { double x = vertices[vIndex++]; double y = vertices[vIndex++]; double z = vertices[vIndex++]; //std::cout<<"("<<x<<","<<y<<","<<z<<")"<<endl; MPoint point(x,y,z); points.append(point); } const int numFaces = inputMesh.numPolygons(); int *face_counts = new int[numFaces]; for(int i = 0 ; i < numFaces ; i++) { face_counts[i] = 3; } MIntArray faceCounts( face_counts, numFaces ); // Set up and array to assign vertices from points to each face int numFaceConnects = numFaces * 3; int *face_connects = new int[numFaceConnects]; int faceConnectsIdx = 0; for ( int i=0; i<numFaces; i++ ) { MIntArray polyVerts; inputMesh.getPolygonVertices( i, polyVerts ); int pvc = polyVerts.length(); face_connects[faceConnectsIdx++] = polyVerts[0]; face_connects[faceConnectsIdx++]= polyVerts[1]; face_connects[faceConnectsIdx++] = polyVerts[2]; } MIntArray faceConnects( face_connects, numFaceConnects ); MFnMesh meshFS; MObject newMesh = meshFS.create(numVertices, numFaces, points, faceCounts, faceConnects, outputMesh, &stat); return stat; }
MObject AniMesh::readFrame(const MTime& time,MObject& outData,MStatus& stat) { MFloatPointArray points; MFnMesh meshFS; int frame = (int)time.as( MTime::kFilm ); if (frame == 0) frame = 1; vector<size_t> face_v; vector<double> points_v; char cfilename[256]; sprintf(cfilename, "%s%d.vrml",import_prefix.c_str(),frame); //sprintf(cfilename, "%s%d.vrml",import_prefix.c_str(),0); string filename = string(cfilename); fstream fp; fp.open(filename,ios::in); if (fp) { ImportVrml2 (filename, face_v, points_v); }else{ sprintf(cfilename, "%s%d.vrml",import_prefix.c_str(),0); string filename = string(cfilename); ImportVrml2(filename,face_v,points_v); } size_t numVertices = points_v.size()/3; size_t numFaces = face_v.size()/3; for(vector<double>::const_iterator it = points_v.begin();it != points_v.end();it+=3) { MFloatPoint vtx(*it,*(it+1),*(it+2)); points.append(vtx); } vector<int> face_count; for(int i=0;i<numFaces;i++) { face_count.push_back(3); } MIntArray faceCounts(&face_count[0],numFaces); vector<int> face_connects; face_connects.resize(face_v.size()); for(int i=0;i<face_v.size();++i) { face_connects[i] = face_v[i]; } MIntArray faceConnects( &face_connects[0], face_connects.size() ); MObject newMesh=meshFS.create(numVertices, numFaces,points, faceCounts, faceConnects,outData,&stat); return newMesh; }
void MayaGeoAttribute::transferValueToMaya(MPlug &plug, MDataBlock &data){ coral::Geo *coralGeo = value(); const std::vector<Imath::V3f> &coralPoints = coralGeo->points(); // transfer points MFloatPointArray mayaPoints; for(int i = 0; i < coralPoints.size(); ++i){ const Imath::V3f *coralPoint = &coralPoints[i]; mayaPoints.append(MFloatPoint(coralPoint->x, coralPoint->y, coralPoint->z)); } // transfer faces MIntArray mayaFaceCount; MIntArray mayaFaceVertices; const std::vector<std::vector<int> > coralFaces = coralGeo->rawFaces(); for(int polyId = 0; polyId < coralFaces.size(); ++polyId){ const std::vector<int> *coralFace = &coralFaces[polyId]; int faceVertexCount = coralFace->size(); mayaFaceCount.append(faceVertexCount); for(int i = 0; i < faceVertexCount; ++i){ mayaFaceVertices.append(coralFace->at(i)); } } // create maya mesh MDataHandle dataHandle = data.outputValue(plug); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(); MFnMesh newMesh; newMesh.create(mayaPoints.length(), coralFaces.size(), mayaPoints, mayaFaceCount, mayaFaceVertices, newOutputData); dataHandle.set(newOutputData); }
MStatus convertOsdFarToMayaMeshData( FMesh const * farMesh, OpenSubdiv::OsdCpuVertexBuffer * vertexBuffer, int subdivisionLevel, MFnMesh const & inMeshFn, MObject newMeshDataObj ) { MStatus returnStatus; // Get sizing data from OSD const OpenSubdiv::FarPatchTables *farPatchTables = farMesh->GetPatchTables(); int numPolygons = farPatchTables->GetNumFaces(); // use the highest level stored in the patch tables const unsigned int *polygonConnects_orig = farPatchTables->GetFaceVertices(); // use the highest level stored in the patch tables const OpenSubdiv::FarSubdivisionTables<OpenSubdiv::OsdVertex> *farSubdivTables = farMesh->GetSubdivisionTables(); unsigned int numVertices = farSubdivTables->GetNumVertices(subdivisionLevel); unsigned int vertexOffset = farSubdivTables->GetFirstVertexOffset(subdivisionLevel); // Init Maya Data MFloatPointArray points(numVertices); MIntArray faceCounts(numPolygons); // number of edges for each polygon. Assume quads (4-edges per face) MIntArray faceConnects(numPolygons*4); // array of vertex ids for all edges. assuming quads // -- Face Counts for (int i=0; i < numPolygons; ++i) { faceCounts[i] = 4; } // -- Face Connects for (unsigned int i=0; i < faceConnects.length(); i++) { faceConnects[i] = polygonConnects_orig[i] - vertexOffset; // adjust vertex indices so that v0 is at index 0 } // -- Points // Number of floats in each vertex. (positions, normals, etc) int numFloatsPerVertex = vertexBuffer->GetNumElements(); assert(numFloatsPerVertex == 3); // assuming only xyz stored for each vertex const float *vertexData = vertexBuffer->BindCpuBuffer(); float *ptrVertexData; for (unsigned int i=0; i < numVertices; i++) { // make sure to offset to the first osd vertex for that subd level unsigned int osdRawVertexIndex = i + vertexOffset; // Lookup the data in the vertexData ptrVertexData = (float *) vertexData + ((osdRawVertexIndex) * numFloatsPerVertex); points.set(i, ptrVertexData[0], ptrVertexData[1], ptrVertexData[2]); } // Create New Mesh from MFnMesh MFnMesh newMeshFn; MObject newMeshObj = newMeshFn.create(points.length(), faceCounts.length(), points, faceCounts, faceConnects, newMeshDataObj, &returnStatus); MCHECKERR(returnStatus, "Cannot create new mesh"); // Attach UVs (if present) // ASSUMPTION: Only tracking UVs as FVar data. Will need to change this // ASSUMPTION: OSD has a unique UV for each face-vertex int fvarTotalWidth = farMesh->GetTotalFVarWidth(); if (fvarTotalWidth > 0) { // Get face-varying set names and other info from the inMesh MStringArray uvSetNames; MStringArray colorSetNames; std::vector<int> colorSetChannels; std::vector<MFnMesh::MColorRepresentation> colorSetReps; int totalColorSetChannels = 0; returnStatus = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, colorSetChannels, colorSetReps, totalColorSetChannels); int numUVSets = uvSetNames.length(); int expectedFvarTotalWidth = numUVSets*2 + totalColorSetChannels; assert(fvarTotalWidth == expectedFvarTotalWidth); const OpenSubdiv::FarPatchTables::FVarDataTable &fvarDataTable = farPatchTables->GetFVarDataTable(); assert(fvarDataTable.size() == expectedFvarTotalWidth*faceConnects.length()); // Create an array of indices to map each face-vert to the UV and ColorSet Data MIntArray fvarConnects(faceConnects.length()); for (unsigned int i=0; i < faceConnects.length(); i++) { fvarConnects[i] = i; } MFloatArray uCoord(faceConnects.length()); MFloatArray vCoord(faceConnects.length()); for (int uvSetIndex=0; uvSetIndex < numUVSets; uvSetIndex++) { for(unsigned int vertid=0; vertid < faceConnects.length(); vertid++) { int fvarItem = vertid*fvarTotalWidth + uvSetIndex*2; // stride per vertex is the fvarTotalWidth uCoord[vertid] = fvarDataTable[fvarItem]; vCoord[vertid] = fvarDataTable[fvarItem+1]; } // Assign UV buffer and map the uvids for each face-vertex if (uvSetIndex != 0) { // assume uvset index 0 is the default UVset, so do not create returnStatus = newMeshFn.createUVSetDataMesh( uvSetNames[uvSetIndex] ); } MCHECKERR(returnStatus, "Cannot create UVSet"); newMeshFn.setUVs(uCoord,vCoord, &uvSetNames[uvSetIndex]); newMeshFn.assignUVs(faceCounts, fvarConnects, &uvSetNames[uvSetIndex]); } MColorArray colorArray(faceConnects.length()); int colorSetRelativeStartIndex = numUVSets*2; for (unsigned int colorSetIndex=0; colorSetIndex < colorSetNames.length(); colorSetIndex++) { for(unsigned int vertid=0; vertid < faceConnects.length(); vertid++) { int fvarItem = vertid*fvarTotalWidth + colorSetRelativeStartIndex; if (colorSetChannels[colorSetIndex] == 1) { colorArray[vertid].r = fvarDataTable[fvarItem]; colorArray[vertid].g = fvarDataTable[fvarItem]; colorArray[vertid].b = fvarDataTable[fvarItem]; colorArray[vertid].a = 1.0f; } else if (colorSetChannels[colorSetIndex] == 3) { colorArray[vertid].r = fvarDataTable[fvarItem]; colorArray[vertid].g = fvarDataTable[fvarItem+1]; colorArray[vertid].b = fvarDataTable[fvarItem+2]; colorArray[vertid].a = 1.0f; } else { colorArray[vertid].r = fvarDataTable[fvarItem]; colorArray[vertid].g = fvarDataTable[fvarItem+1]; colorArray[vertid].b = fvarDataTable[fvarItem+2]; colorArray[vertid].a = fvarDataTable[fvarItem+3]; } } // Assign UV buffer and map the uvids for each face-vertex // API Limitation: Cannot set MColorRepresentation here returnStatus = newMeshFn.createColorSetDataMesh(colorSetNames[colorSetIndex]); MCHECKERR(returnStatus, "Cannot create ColorSet"); bool isColorClamped = inMeshFn.isColorClamped(colorSetNames[colorSetIndex], &returnStatus); newMeshFn.setIsColorClamped(colorSetNames[colorSetIndex], isColorClamped); newMeshFn.setColors(colorArray, &colorSetNames[colorSetIndex], colorSetReps[colorSetIndex]); newMeshFn.assignColors(fvarConnects, &colorSetNames[colorSetIndex]); // Increment colorSet start location in fvar buffer colorSetRelativeStartIndex += colorSetChannels[colorSetIndex]; } } return MS::kSuccess; }
static MStatus convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner, std::vector<Vertex> const & refinedVerts, bool hasUVs, std::vector<FVarVertexUV> const & refinedUVs, bool hasColors, std::vector<FVarVertexColor> const & refinedColors, MFnMesh & inMeshFn, MObject newMeshDataObj) { MStatus status; typedef OpenSubdiv::Far::ConstIndexArray IndexArray; int maxlevel = refiner.GetMaxLevel(); OpenSubdiv::Far::TopologyLevel const & refLastLevel = refiner.GetLevel(maxlevel); int nfaces = refLastLevel.GetNumFaces(); // Init Maya Data // Face Counts MIntArray faceCounts(nfaces); for (int face=0; face < nfaces; ++face) { faceCounts[face] = 4; } // Face Connects MIntArray faceConnects(nfaces*4); for (int face=0, idx=0; face < nfaces; ++face) { IndexArray fverts = refLastLevel.GetFaceVertices(face); for (int vert=0; vert < fverts.size(); ++vert) { faceConnects[idx++] = fverts[vert]; } } // Points int nverts = refLastLevel.GetNumVertices(); int firstOfLastVert = refiner.GetNumVerticesTotal() - nverts - refiner.GetLevel(0).GetNumVertices(); MFloatPointArray points(nverts); for (int vIt = 0; vIt < nverts; ++vIt) { Vertex const & v = refinedVerts[firstOfLastVert + vIt]; points.set(vIt, v.position[0], v.position[1], v.position[2]); } // Create New Mesh from MFnMesh MFnMesh newMeshFn; MObject newMeshObj = newMeshFn.create(points.length(), faceCounts.length(), points, faceCounts, faceConnects, newMeshDataObj, &status); MCHECKERR(status, "Cannot create new mesh"); // Get face-varying set names and other info from the inMesh MStringArray uvSetNames; MStringArray colorSetNames; std::vector<int> colorSetChannels; std::vector<MFnMesh::MColorRepresentation> colorSetReps; int totalColorSetChannels = 0; status = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, colorSetChannels, colorSetReps, totalColorSetChannels); // Add new UVs back to the mesh if needed if (hasUVs) { MIntArray fvarConnects(faceConnects.length()); int count = 0; for (int f = 0; f < refLastLevel.GetNumFaces(); ++f) { IndexArray faceIndices = refLastLevel.GetFaceFVarValues(f, CHANNELUV); for (int index = 0 ; index < faceIndices.size() ; ++index) { fvarConnects[count++] = faceIndices[index]; } } int nuvs = refLastLevel.GetNumFVarValues(CHANNELUV); int firstOfLastUvs = refiner.GetNumFVarValuesTotal(CHANNELUV) - nuvs - refiner.GetLevel(0).GetNumFVarValues(CHANNELUV); MFloatArray uCoord(nuvs), vCoord(nuvs); for (int uvIt = 0; uvIt < nuvs; ++uvIt) { FVarVertexUV const & uv = refinedUVs[firstOfLastUvs + uvIt]; uCoord[uvIt] = uv.u; vCoord[uvIt] = uv.v; } // Currently, the plugin only supports one UV set int uvSetIndex = 0; if (uvSetIndex > 0) { status = newMeshFn.createUVSetDataMesh( uvSetNames[uvSetIndex] ); MCHECKERR(status, "Cannot create UVSet"); } static MString defaultUVName("map1"); MString const * uvname = uvSetIndex==0 ? &defaultUVName : &uvSetNames[uvSetIndex]; status = newMeshFn.setUVs(uCoord, vCoord, uvname); MCHECKERR(status, "Cannot set UVs for set : "+*uvname); status = newMeshFn.assignUVs(faceCounts, fvarConnects, uvname); MCHECKERR(status, "Cannot assign UVs"); } // Add new colors back to the mesh if needed if (hasColors) { int count = 0; MIntArray fvarConnects2(faceConnects.length()); for (int f = 0 ; f < refLastLevel.GetNumFaces(); ++f) { IndexArray faceIndices = refLastLevel.GetFaceFVarValues(f, CHANNELCOLOR); for (int index = 0 ; index < faceIndices.size() ; ++index) { fvarConnects2[count++] = faceIndices[index]; } } int ncols = refLastLevel.GetNumFVarValues(CHANNELCOLOR); int firstOfLastCols = refiner.GetNumFVarValuesTotal(CHANNELCOLOR) - ncols - refiner.GetLevel(0).GetNumFVarValues(CHANNELCOLOR); MColorArray colorArray(ncols); for (int colIt = 0; colIt < ncols; ++colIt) { FVarVertexColor const & c = refinedColors[firstOfLastCols + colIt]; colorArray.set(colIt, c.r, c.g, c.b, c.a); } // Currently, the plugin only supports one color sets int colorSetIndex = 0; // Assign color buffer and map the ids for each face-vertex // API Limitation: Cannot set MColorRepresentation here status = newMeshFn.createColorSetDataMesh( colorSetNames[colorSetIndex]); MCHECKERR(status, "Cannot create ColorSet"); bool isColorClamped = inMeshFn.isColorClamped( colorSetNames[colorSetIndex], &status); MCHECKERR(status, "Can not get Color Clamped "); status = newMeshFn.setIsColorClamped( colorSetNames[colorSetIndex], isColorClamped); MCHECKERR(status, "Can not set Color Clamped : " + isColorClamped); status = newMeshFn.setColors( colorArray, &colorSetNames[colorSetIndex], colorSetReps[colorSetIndex]); MCHECKERR(status, "Can not set Colors"); status = newMeshFn.assignColors( fvarConnects2, &colorSetNames[colorSetIndex]); MCHECKERR(status, "Can not assign Colors"); } return MS::kSuccess; }
MStatus fishVizNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; MObject arbitaryMesh = data.inputValue(aInMesh).asMesh(); MDoubleArray ptc_time_offset; MDoubleArray ptc_amplitude; MDoubleArray ptc_bend; MDoubleArray ptc_scale; MDoubleArray masses; MString cacheName = data.inputValue(acachename, &status).asString(); MTime currentTime = data.inputValue(atime, &status).asTime(); cacheName = cacheName+"."+250*int(currentTime.value())+".pdc"; pdcFile* fpdc = new pdcFile(); if(fpdc->load(cacheName.asChar())==1) { //MGlobal::displayInfo(MString("FishViz loaded cache file: ")+cacheName); fpdc->readPositions(ptc_positions, ptc_velocities, ptc_ups, ptc_views, ptc_time_offset, ptc_amplitude, ptc_bend, ptc_scale, masses); } else MGlobal::displayWarning(MString("FishViz cannot open cache file: ")+cacheName); if(currentTime.value()!=int(currentTime.value())) { float delta_t = currentTime.value()-int(currentTime.value()); for(int i=0; i<fpdc->getParticleCount(); i++) { ptc_positions[i] += ptc_velocities[i]*delta_t/24.0f; } } delete fpdc; double flapping = zGetDoubleAttr(data, aFlapping); double bending= zGetDoubleAttr(data, aBending); double oscillate= zGetDoubleAttr(data, aOscillate); double length = zGetDoubleAttr(data, aLength); m_fish_length = length; double frequency = zGetDoubleAttr(data, aFrequency); unsigned num_bones = zGetIntAttr(data, aNBone); unsigned int nptc = ptc_positions.length(); MPointArray vertices; MATRIX44F mat44, mat_bone; XYZ vert, front, up, side; MDataHandle outputHandle = data.outputValue(outMesh, &status); zCheckStatus(status, "ERROR getting polygon data handle\n"); if(m_num_fish != nptc || m_num_bone != num_bones) { m_num_bone = num_bones; m_num_fish = nptc; unsigned int vertex_count; unsigned int face_count; MIntArray pcounts; MIntArray pconnect; unsigned inmeshnv, inmeshnp; MPointArray pinmesh; MIntArray count_inmesh; MIntArray connect_inmesh; zWorks::extractMeshParams(arbitaryMesh, inmeshnv, inmeshnp, pinmesh, count_inmesh, connect_inmesh); vertex_count = inmeshnv * nptc; face_count = inmeshnp * nptc; for(unsigned int i=0; i<nptc; i++) { // calculate the bone transformations poseBones(length, num_bones, ptc_time_offset[i], frequency, ptc_amplitude[i], ptc_bend[i], flapping, bending, oscillate); front.x = ptc_views[i].x; front.y = ptc_views[i].y; front.z = ptc_views[i].z; up.x = ptc_ups[i].x; up.y = ptc_ups[i].y; up.z = ptc_ups[i].z; side = front.cross(up); side.normalize(); up = side.cross(front); up.normalize(); mat44.setIdentity(); mat44.setOrientations(side, up, front); mat44.scale(ptc_scale[i]); mat44.setTranslation(ptc_positions[i].x, ptc_positions[i].y, ptc_positions[i].z); for(unsigned int j=0; j<inmeshnv; j++) { vert.x = pinmesh[j].x; vert.y = pinmesh[j].y; vert.z = pinmesh[j].z; int bone_id; if(vert.z>0) bone_id = 0; else if(-vert.z>length) bone_id = num_bones-1; else bone_id = int(-vert.z/length*(num_bones-1)); mat_bone = m_pBone->getBoneById(bone_id); vert.z -= -length/(num_bones-1)*bone_id; mat_bone.transform(vert); mat44.transform(vert); vertices.append(MPoint(vert.x, vert.y, vert.z)); } for(unsigned int j=0; j<inmeshnp; j++) { pcounts.append(count_inmesh[j]); } } int acc=0; for(unsigned int i=0; i<nptc; i++) { for(unsigned int j=0; j<connect_inmesh.length(); j++) { pconnect.append(connect_inmesh[j]+acc); } acc += inmeshnv; } MObject m_mesh = outputHandle.asMesh(); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&status); zCheckStatusNR(status, "ERROR creating outputData"); MFnMesh meshFn; m_mesh= meshFn.create( vertex_count, // number of vertices face_count, // number of polygons vertices, // The points pcounts, // # of vertex for each poly pconnect, // Vertices index for each poly newOutputData, // Dependency graph data object &status ); zCheckStatusNR(status, "ERROE creating mesh"); // Update surface // outputHandle.set(newOutputData); } else { MObject m_mesh = outputHandle.asMesh(); MFnMesh meshFn(m_mesh); unsigned inmeshnv, inmeshnp; MPointArray pinmesh; MIntArray count_inmesh; MIntArray connect_inmesh; zWorks::extractMeshParams(arbitaryMesh, inmeshnv, inmeshnp, pinmesh, count_inmesh, connect_inmesh); vertices.setLength(nptc*inmeshnv); int acc=0; for(unsigned int i=0; i<nptc; i++) { // calculate the bone transformations poseBones(length, num_bones, ptc_time_offset[i], frequency, ptc_amplitude[i], ptc_bend[i], flapping, bending, oscillate); front.x = ptc_views[i].x; front.y = ptc_views[i].y; front.z = ptc_views[i].z; up.x = ptc_ups[i].x; up.y = ptc_ups[i].y; up.z = ptc_ups[i].z; side = front.cross(up); side.normalize(); up = side.cross(front); up.normalize(); mat44.setIdentity(); mat44.setOrientations(side, up, front); mat44.scale(ptc_scale[i]); mat44.setTranslation(ptc_positions[i].x, ptc_positions[i].y, ptc_positions[i].z); for(unsigned int j=0; j<inmeshnv; j++) { vert.x = pinmesh[j].x; vert.y = pinmesh[j].y; vert.z = pinmesh[j].z; int bone_id; if(vert.z>0) bone_id = 0; else if(-vert.z>length) bone_id = num_bones-1; else bone_id = int(-vert.z/length*(num_bones-1)); mat_bone = m_pBone->getBoneById(bone_id); vert.z -= -length/(num_bones-1)*bone_id; mat_bone.transform(vert); mat44.transform(vert); vertices[j+acc] = MPoint(vert.x, vert.y, vert.z); } acc += inmeshnv; } meshFn.setPoints(vertices); outputHandle.set(meshFn.object()); } //delete fmat; data.setClean( plug ); return MS::kSuccess; }
MObject ClothSimMayaPlugin::createMesh(const MTime& time, MObject& outData, MStatus& stat) { double t = time.as(MTime::kSeconds); if (t <= 1.0 / 24 && m_prevTime > 1.0/24) { m_simMesh.reset(0); } int nx = 60; int ny = 60; if (!m_simMesh.get()) { Eigen::VectorXf v((nx+1) * (ny+1) * 3); Eigen::VectorXf x((nx + 1) * (ny + 1) * 3); Eigen::VectorXf uv((nx + 1) * (ny + 1) * 2); for (int i = 0; i <= nx; ++i) { for (int j = 0; j <= ny; ++j) { int base = i + (nx+1) * j; uv[2 * base + 0] = (float)i / nx - 0.5f; uv[2 * base + 1] = (float)j / ny - 0.5f; x[3 * base + 0] = uv[2 * base + 0]; x[3 * base + 1] = 0; x[3 * base + 2] = uv[2 * base + 1]; v[3 * base + 0] = v[3 * base + 1] = v[3 * base + 2] = 0; } } std::vector<int> triangleInds; for (int i = 0; i < nx; ++i) { for (int j = 0; j < ny; ++j) { int base = i + (nx + 1) * j; triangleInds.push_back(base + 0); triangleInds.push_back(base + 1); triangleInds.push_back(base + (nx + 1)); triangleInds.push_back(base + 1); triangleInds.push_back(base + (nx + 2)); triangleInds.push_back(base + (nx + 1)); } } m_simMesh.reset( new ClothMesh<float>( x, v, uv, triangleInds, 0.01f, 1000000.0f, 1000000.0f, 0.01f, 1000.0f, 1000.0f, 1.0f ) ); } std::vector<int> constraintIndices; std::vector< Eigen::Matrix3f > constraintMatrices; Eigen::VectorXf constraintVelocityDeltas(m_simMesh->x().size()); constraintVelocityDeltas.setConstant(0); for (int i = 0; i <= nx; ++i) { for (int j = 0; j <= ny; ++j) { int idx = i + (nx + 1) * j; float x = (float)i / nx - 0.5f; float y = (float)j / ny - 0.5f; if (x * x + y * y < 0.3 * 0.3) { constraintIndices.push_back(idx); constraintMatrices.push_back(Eigen::Matrix3f::Zero()); } } } if (t > m_prevTime) { ConstrainedCGSolver<float> solver( constraintIndices, constraintMatrices, constraintVelocityDeltas, 0.01f, 400 ); GravityField<float> g( m_simMesh->m(), Eigen::Vector3f( 0,-9.8f, 0 ) ); std::vector< ForceField<float>* > forceFields; forceFields.push_back( &g ); try { std::cerr << "advance" << std::endl; m_simMesh->advance(forceFields, float(t - m_prevTime)*0.5f, solver); m_simMesh->advance(forceFields, float(t - m_prevTime)*0.5f, solver); std::cerr << "done" << std::endl; } catch (const std::exception &e) { std::cerr << e.what() << std::endl; stat = MStatus::kFailure; return MObject(); } catch (...) { std::cerr << "unknown exception" << std::endl; stat = MStatus::kFailure; return MObject(); } } m_prevTime = t; MFloatPointArray points; for (int i = 0; i < m_simMesh->x().size(); i += 3) { MFloatPoint p(m_simMesh->x()[i], m_simMesh->x()[i + 1], m_simMesh->x()[i + 2]); points.append(p); } MFnMesh meshFS; MIntArray faceCounts((int)m_simMesh->triangleIndices().size()/3, 3); MIntArray faceConnects; for (unsigned i = 0; i < m_simMesh->triangleIndices().size(); ++i) { faceConnects.append(m_simMesh->triangleIndices()[i]); } MObject newMesh = meshFS.create((int)m_simMesh->x().size() / 3, (int)m_simMesh->triangleIndices().size() / 3, points, faceCounts, faceConnects, outData, &stat); return newMesh; }
MStatus Molecule3Cmd::redoIt() { MStatus stat; MDagPath dagPath; MFnMesh meshFn; // Create a ball int nBallPolys; MPointArray ballVerts; MIntArray ballPolyCounts; MIntArray ballPolyConnects; MFloatArray ballUCoords; MFloatArray ballVCoords; MIntArray ballFvUVIDs; genBall( MPoint::origin, ballRodRatio * radius.value(), segs, nBallPolys, ballVerts, ballPolyCounts, ballPolyConnects, true, ballUCoords, ballVCoords, ballFvUVIDs ); unsigned int i, j, vertOffset; MPointArray meshVerts; MPoint p0, p1; MObject objTransform; // Setup for rods int nRodPolys; MPointArray rodVerts; MIntArray rodPolyCounts; MIntArray rodPolyConnects; MFloatArray rodUCoords; MFloatArray rodVCoords; MIntArray rodFvUVIDs; // Setup for newMesh int nNewPolys; MPointArray newVerts; MIntArray newPolyCounts; MIntArray newPolyConnects; MFloatArray newUCoords; MFloatArray newVCoords; MIntArray newFvUVIDs; int uvOffset; MDagModifier dagMod; MFnDagNode dagFn; objTransforms.clear(); // Iterate over the meshes unsigned int mi; for( mi=0; mi < selMeshes.length(); mi++ ) { dagPath = selMeshes[mi]; meshFn.setObject( dagPath ); uvOffset = 0; nNewPolys = 0; newVerts.clear(); newPolyCounts.clear(); newPolyConnects.clear(); newUCoords.clear(); newVCoords.clear(); newFvUVIDs.clear(); // Generate balls meshFn.getPoints( meshVerts, MSpace::kWorld ); for( i=0; i < meshVerts.length(); i++ ) { vertOffset = newVerts.length(); // Add the ball to the new mesh nNewPolys += nBallPolys; // Move the ball vertices to the mesh vertex. Add it to the newMesh for( j=0; j < ballVerts.length(); j++ ) newVerts.append( meshVerts[i] + ballVerts[j] ); for( j=0; j < ballPolyCounts.length(); j++ ) newPolyCounts.append( ballPolyCounts[j] ); for( j=0; j < ballPolyConnects.length(); j++ ) newPolyConnects.append( vertOffset + ballPolyConnects[j] ); // Only add the uv coordinates once, since they are shared // by all balls if( i == 0 ) { for( j=0; j < ballUCoords.length(); j++ ) { newUCoords.append( ballUCoords[j] ); newVCoords.append( ballVCoords[j] ); } } for( j=0; j < ballFvUVIDs.length(); j++ ) { newFvUVIDs.append( uvOffset + ballFvUVIDs[j] ); } } uvOffset = newUCoords.length(); // Generate rods int nRods = 0; MItMeshEdge edgeIter( dagPath ); for( ; !edgeIter.isDone(); edgeIter.next(), nRods++ ) { p0 = edgeIter.point( 0, MSpace::kWorld ); p1 = edgeIter.point( 1, MSpace::kWorld ); // N.B. Generate the uv coordinates only once since they // are referenced by all rods genRod( p0, p1, radius.value(), segs, nRodPolys, rodVerts, rodPolyCounts, rodPolyConnects, nRods == 0, rodUCoords, rodVCoords, rodFvUVIDs ); vertOffset = newVerts.length(); // Add the rod to the mesh nNewPolys += nRodPolys; for( i=0; i < rodVerts.length(); i++ ) newVerts.append( rodVerts[i] ); for( i=0; i < rodPolyCounts.length(); i++ ) newPolyCounts.append( rodPolyCounts[i] ); for( i=0; i < rodPolyConnects.length(); i++ ) newPolyConnects.append( vertOffset + rodPolyConnects[i] ); // First rod if( nRods == 0 ) { // Add rod's uv coordinates to the list for( i=0; i < rodUCoords.length(); i++ ) { newUCoords.append( rodUCoords[i] ); newVCoords.append( rodVCoords[i] ); } } // Set the face-vertex-uvIDs for( i=0; i < rodFvUVIDs.length(); i++ ) { newFvUVIDs.append( uvOffset + rodFvUVIDs[i] ); } } objTransform = meshFn.create( newVerts.length(), nNewPolys, newVerts, newPolyCounts, newPolyConnects, newUCoords, newVCoords, MObject::kNullObj, &stat ); if( !stat ) { MGlobal::displayError( MString( "Unable to create mesh: " ) + stat.errorString() ); return stat; } objTransforms.append( objTransform ); meshFn.assignUVs( newPolyCounts, newFvUVIDs ); meshFn.updateSurface(); // Rename transform node dagFn.setObject( objTransform ); dagFn.setName( "molecule" ); // Put mesh into the initial shading group dagMod.commandToExecute( MString( "sets -e -fe initialShadingGroup " ) + meshFn.name() ); } // Select all the newly created molecule meshes MString cmd( "select -r" ); for( i=0; i < objTransforms.length(); i++ ) { dagFn.setObject( objTransforms[i] ); cmd += " " + dagFn.name(); } dagMod.commandToExecute( cmd ); return dagMod.doIt(); }
MObject VMesh::createFeather() { MStatus stat; MFnMeshData dataCreator; MObject outMeshData = dataCreator.create(&stat); int numVertex = 0; int numPolygon = 0; MPointArray vertexArray; MFloatArray uArray, vArray; MIntArray polygonCounts, polygonConnects, polygonUVs; MFnMesh meshFn(pgrow, &stat); MItMeshVertex vertIter(pgrow, &stat); MItMeshPolygon faceIter(pgrow, &stat); MPoint S; MVector N, tang, ttang, binormal, dir, hair_up; MColor Cscale, Cerect, Crotate, Ccurl, Cwidth; float rot, lengreal; MATRIX44F hair_space; MString setScale("fb_scale"); MString setErect("fb_erect"); MString setRotate("fb_rotate"); MString setCurl("fb_curl"); MString setWidth("fb_width"); MIntArray conn_face; for( int i=0; !vertIter.isDone(); vertIter.next(), i++ ) { if(vertIter.onBoundary()) continue; vertIter.getNormal(N, MSpace::kWorld); N.normalize(); vertIter.getColor(Cscale, &setScale); vertIter.getColor(Cerect, &setErect); vertIter.getColor(Crotate, &setRotate); vertIter.getColor(Ccurl, &setCurl); vertIter.getColor(Cwidth, &setWidth); vertIter.getConnectedFaces(conn_face); tang = MVector(0,0,0); for(int j=0; j<conn_face.length(); j++) { meshFn.getFaceVertexTangent (conn_face[j], i, ttang, MSpace::kWorld); ttang.normalize(); tang += ttang; } tang /= conn_face.length(); conn_face.clear(); tang.normalize(); tang = N^tang; tang.normalize(); binormal = N^tang; if(Crotate.r<0.5) { rot = (0.5 - Crotate.r)*2; tang = tang + (binormal-tang)*rot; tang.normalize(); binormal = N^tang; } else { rot = (Crotate.r-0.5)*2; tang = tang + (binormal*-1-tang)*rot; tang.normalize(); binormal = N^tang; } dir = tang + (N - tang)*Cerect.r; dir.normalize(); //S = S+dir*Cscale.r*m_scale; //glVertex3f(S.x, S.y, S.z); hair_up = dir^binormal; hair_space.setIdentity(); hair_space.setOrientations(XYZ(binormal.x, binormal.y, binormal.z), XYZ(hair_up.x, hair_up.y, hair_up.z), XYZ(dir.x, dir.y, dir.z)); S = vertIter.position(MSpace::kWorld); hair_space.setTranslation(XYZ(S.x, S.y, S.z)); lengreal = Cscale.r*m_scale; fb->create(lengreal, 0, lengreal*(Ccurl.r-0.5)*2); XYZ pw; MPoint pvx; MPoint pright = S + binormal*Cwidth.r*m_width*lengreal; MPoint pleft = S - binormal*Cwidth.r*m_width*lengreal; MPoint phit; int polyhit; meshFn.getClosestPoint (pright, phit, MSpace::kObject, &polyhit); MVector topright = phit - S; topright.normalize(); topright *= Cwidth.r*m_width*lengreal; meshFn.getClosestPoint (pleft, phit, MSpace::kObject, &polyhit); MVector topleft = phit - S; topleft.normalize(); topleft *= Cwidth.r*m_width*lengreal; //tws_binormal = binormal*cos(0.2) + hair_up*sin(0.2); for(int j=0; j<NUMBENDSEG+1; j++) { fb->getPoint(j, pw); hair_space.transform(pw); pvx = MPoint(pw.x, pw.y, pw.z) + topleft;//- tws_binormal*Cwidth.r*m_width*lengreal; vertexArray.append(pvx); pvx = MPoint(pw.x, pw.y, pw.z); vertexArray.append(pvx); pvx = MPoint(pw.x, pw.y, pw.z) + topright;//tws_binormal*Cwidth.r*m_width*lengreal; vertexArray.append(pvx); uArray.append(0.0); vArray.append((float)j/NUMBENDSEG); uArray.append(0.5); vArray.append((float)j/NUMBENDSEG); uArray.append(1.0); vArray.append((float)j/NUMBENDSEG); } for(int j=0; j<NUMBENDSEG; j++) { polygonConnects.append(j*3 + numVertex); polygonConnects.append(j*3+3 + numVertex); polygonConnects.append(j*3+4 + numVertex); polygonConnects.append(j*3+1 + numVertex); polygonCounts.append(4); polygonConnects.append(j*3+1 + numVertex); polygonConnects.append(j*3+4 + numVertex); polygonConnects.append(j*3+5 + numVertex); polygonConnects.append(j*3+2 + numVertex); polygonCounts.append(4); polygonUVs.append(j*3 + numVertex); polygonUVs.append(j*3+3 + numVertex); polygonUVs.append(j*3+4 + numVertex); polygonUVs.append(j*3+1 + numVertex); polygonUVs.append(j*3+1 + numVertex); polygonUVs.append(j*3+4 + numVertex); polygonUVs.append(j*3+5 + numVertex); polygonUVs.append(j*3+2 + numVertex); } numVertex += (NUMBENDSEG+1)*3; numPolygon += NUMBENDSEG*2; } MIntArray connvert; int idxpre; float averg_scale, averg_erect, averg_rotate, averg_curl, averg_width; for( int i=0; !faceIter.isDone(); faceIter.next(), i++ ) { if(faceIter.onBoundary()) continue; faceIter.getNormal(N, MSpace::kWorld); N.normalize(); faceIter.getVertices(connvert); averg_scale=averg_erect=averg_rotate=averg_curl=0; for(int j=0; j<connvert.length(); j++) { vertIter.setIndex(connvert[j], idxpre); vertIter.getColor(Cscale, &setScale); vertIter.getColor(Cerect, &setErect); vertIter.getColor(Crotate, &setRotate); vertIter.getColor(Ccurl, &setCurl); vertIter.getColor(Cwidth, &setWidth); averg_scale += Cscale.r; averg_erect += Cerect.r; averg_rotate += Crotate.r; averg_curl += Ccurl.r; averg_width += Cwidth.r; } averg_scale /= connvert.length(); averg_erect /= connvert.length(); averg_rotate /= connvert.length(); averg_curl /= connvert.length(); averg_width /= connvert.length(); tang = MVector(0,0,0); for(int j=0; j<connvert.length(); j++) { meshFn.getFaceVertexTangent (i, connvert[j], ttang, MSpace::kWorld); ttang.normalize(); tang += ttang; } //tang /= conn_face.length(); connvert.clear(); tang.normalize(); tang = N^tang; tang.normalize(); binormal = N^tang; if(averg_rotate<0.5) { rot = (0.5 - averg_rotate)*2; tang = tang + (binormal-tang)*rot; tang.normalize(); binormal = N^tang; } else { rot = (averg_rotate-0.5)*2; tang = tang + (binormal*-1-tang)*rot; tang.normalize(); binormal = N^tang; } dir = tang + (N - tang)*averg_erect; dir.normalize(); //S = S+dir*Cscale.r*m_scale; //glVertex3f(S.x, S.y, S.z); hair_up = dir^binormal; hair_space.setIdentity(); hair_space.setOrientations(XYZ(binormal.x, binormal.y, binormal.z), XYZ(hair_up.x, hair_up.y, hair_up.z), XYZ(dir.x, dir.y, dir.z)); S = faceIter.center(MSpace::kWorld); hair_space.setTranslation(XYZ(S.x, S.y, S.z)); lengreal = Cscale.r*m_scale; fb->create(lengreal, 0, lengreal*(averg_curl-0.5)*2); MPoint pright = S + binormal*Cwidth.r*m_width*lengreal; MPoint pleft = S - binormal*Cwidth.r*m_width*lengreal; XYZ pw; MPoint pvx; MPoint phit; int polyhit; meshFn.getClosestPoint (pright, phit, MSpace::kObject, &polyhit); MVector topright = phit - S; topright.normalize(); topright *= Cwidth.r*m_width*lengreal; meshFn.getClosestPoint (pleft, phit, MSpace::kObject, &polyhit); MVector topleft = phit - S; topleft.normalize(); topleft *= Cwidth.r*m_width*lengreal; //tws_binormal = binormal*cos(0.2) + hair_up*sin(0.2); for(int j=0; j<NUMBENDSEG+1; j++) { fb->getPoint(j, pw); hair_space.transform(pw); pvx = MPoint(pw.x, pw.y, pw.z) + topleft;//- tws_binormal*averg_width*m_width*lengreal; vertexArray.append(pvx); pvx = MPoint(pw.x, pw.y, pw.z); vertexArray.append(pvx); pvx = MPoint(pw.x, pw.y, pw.z) + topright;//tws_binormal*averg_width*m_width*lengreal; vertexArray.append(pvx); uArray.append(0.0); vArray.append((float)j/NUMBENDSEG); uArray.append(0.5); vArray.append((float)j/NUMBENDSEG); uArray.append(1.0); vArray.append((float)j/NUMBENDSEG); } for(int j=0; j<NUMBENDSEG; j++) { polygonConnects.append(j*3 + numVertex); polygonConnects.append(j*3+3 + numVertex); polygonConnects.append(j*3+4 + numVertex); polygonConnects.append(j*3+1 + numVertex); polygonCounts.append(4); polygonConnects.append(j*3+1 + numVertex); polygonConnects.append(j*3+4 + numVertex); polygonConnects.append(j*3+5 + numVertex); polygonConnects.append(j*3+2 + numVertex); polygonCounts.append(4); polygonUVs.append(j*3 + numVertex); polygonUVs.append(j*3+3 + numVertex); polygonUVs.append(j*3+4 + numVertex); polygonUVs.append(j*3+1 + numVertex); polygonUVs.append(j*3+1 + numVertex); polygonUVs.append(j*3+4 + numVertex); polygonUVs.append(j*3+5 + numVertex); polygonUVs.append(j*3+2 + numVertex); } numVertex += (NUMBENDSEG+1)*3; numPolygon += NUMBENDSEG*2; } MFnMesh meshCreateFn; meshCreateFn.create( numVertex, numPolygon, vertexArray, polygonCounts, polygonConnects, outMeshData, &stat ); meshCreateFn.setUVs ( uArray, vArray ); meshCreateFn.assignUVs ( polygonCounts, polygonUVs ); return outMeshData; }
MObject blindDataMesh::createMesh(long seed, MObject& outData, MStatus& stat) { MFloatPointArray vertices; MIntArray faceDegrees; MIntArray faceVertices; int i, j; srand(seed); float planeSize = 20.0f; float planeOffset = planeSize / 2.0f; float planeDim = 0.5f; int numDivisions = (int) (planeSize / planeDim); // int numVertices = (numDivisions + 1) * (numDivisions + 1); // int numEdge = (2 * numDivisions) * (numDivisions + 1); int numFaces = numDivisions * numDivisions; // Set up an array containing the vertex positions for the plane. The // vertices are placed equi-distant on the X-Z plane to form a square // grid that has a side length of "planeSize". // // The Y-coordinate of each vertex is the average of the neighbors already // calculated, if there are any, with a small random offset added. Because // of the way the vertices are calculated, the whole plane will look like // it is streaked in a diagonal direction with mountains and depressions. // for (i = 0; i < (numDivisions + 1); ++i) { for (j = 0; j < (numDivisions + 1); ++j) { float height; if (i == 0 && j == 0) { height = ((rand() % 101) / 100.0f - 0.5f); } else if (i == 0) { float previousHeight = vertices[j - 1][1]; height = previousHeight + ((rand() % 101) / 100.0f - 0.5f); } else if (j == 0) { float previousHeight = vertices[(i-1)*(numDivisions + 1)][1]; height = previousHeight + ((rand() % 101) / 100.0f - 0.5f); } else { float previousHeight = vertices[(i-1)*(numDivisions + 1) + j][1]; float previousHeight2 = vertices[i*(numDivisions + 1) + j - 1][1]; height = (previousHeight + previousHeight2) / 2.0f + ((rand() % 101) / 100.0f - 0.5f); } MFloatPoint vtx( i * planeDim - planeOffset, height, j * planeDim - planeOffset ); vertices.append(vtx); } } // Set up an array containing the number of vertices // for each of the plane's faces // for (i = 0; i < numFaces; ++i) { faceDegrees.append(4); } // Set up an array to assign the vertices for each face // for (i = 0; i < numDivisions; ++i) { for (j = 0; j < numDivisions; ++j) { faceVertices.append(i*(numDivisions+1) + j); faceVertices.append(i*(numDivisions+1) + j + 1); faceVertices.append((i+1)*(numDivisions+1) + j + 1); faceVertices.append((i+1)*(numDivisions+1) + j); } } MFnMesh meshFn; MObject newMesh = meshFn.create(vertices.length(), numFaces, vertices, faceDegrees, faceVertices, outData, &stat); return newMesh; }
MStatus meshCacheNode::compute( const MPlug& plug, MDataBlock& data ) { MStatus stat; MString path = data.inputValue( input ).asString(); double time = data.inputValue( frame ).asTime().value(); int minfrm = data.inputValue( aminframe ).asInt(); //int maxfrm = data.inputValue( amaxframe ).asInt(); int frmstep = data.inputValue( aframestep ).asInt(); if( time < minfrm ) time = minfrm; int frame_lo = minfrm + int(time-minfrm)/frmstep*frmstep; int frame_hi = frame_lo+frmstep; char filename[256]; sprintf( filename, "%s.%d.mcf", path.asChar(), frame_lo ); FMCFMesh mesh; if(mesh.load(filename) != 1) { sprintf( filename, "%s.mcf", path.asChar()); if(mesh.load(filename) != 1) { MGlobal::displayError( MString("Failed to open file: ") + filename ); return MS::kFailure; } } int lo_n_vertex = mesh.getNumVertex(); vertexArray.clear(); vertexFArray.clear(); uArray.clear(); vArray.clear(); polygonCounts.clear(); polygonConnects.clear(); polygonUVs.clear(); for(unsigned int i = 0; i < mesh.getNumFace(); i++ ) { polygonCounts.append( mesh.getFaceCount(i) ); } for(unsigned int i = 0; i < mesh.getNumFaceVertex(); i++) { polygonConnects.append( mesh.getVertexId(i) ); polygonUVs.append( mesh.getUVId(i) ); } XYZ tp; for(unsigned int i = 0; i < mesh.getNumVertex(); i++) { mesh.getVertex(tp, i); vertexArray.append( MPoint( tp.x, tp.y, tp.z ) ); } for(unsigned int i = 0; i < mesh.getNumUV(); i++) { uArray.append( mesh.getS(i) ); vArray.append( mesh.getT(i) ); } if( time > frame_lo ) { sprintf( filename, "%s.%d.mcf", path.asChar(), frame_hi ); if(mesh.load(filename) != 1) { MGlobal::displayError( MString("Failed to open file: ") + filename ); } else if(mesh.getNumVertex() == lo_n_vertex) { XYZ tp; for(unsigned int i = 0; i < mesh.getNumVertex(); i++) { mesh.getVertex(tp, i); vertexFArray.append( MPoint( tp.x, tp.y, tp.z ) ); } double alpha = double(time-frame_lo) / (double)frmstep; for(unsigned int i = 0; i < mesh.getNumVertex(); i++) { vertexArray[i] = vertexArray[i] + alpha * ( vertexFArray[i] - vertexArray[i] ); } } } if( plug == outMesh ) { MDataHandle meshh = data.outputValue(outMesh, &stat); MFnMeshData dataCreator; MObject outMeshData = dataCreator.create(&stat); int numVertex = vertexArray.length(); int numPolygon = polygonCounts.length(); MFnMesh meshFn; meshFn.create( numVertex, numPolygon, vertexArray, polygonCounts, polygonConnects, outMeshData, &stat ); if( !stat ) { char log[256]; sprintf( log, "Failed to create mesh %s", filename ); MGlobal::displayError( log ); return MS::kFailure; } if( polygonUVs.length() != 0 ) { meshFn.setUVs ( uArray, vArray ); meshFn.assignUVs ( polygonCounts, polygonUVs ); } meshh.set(outMeshData); data.setClean(plug); } else { return MS::kUnknownParameter; } return MS::kSuccess; }
bool ToMayaMeshConverter::doConversion( IECore::ConstObjectPtr from, MObject &to, IECore::ConstCompoundObjectPtr operands ) const { MStatus s; IECore::ConstMeshPrimitivePtr mesh = IECore::runTimeCast<const IECore::MeshPrimitive>( from ); assert( mesh ); if ( !mesh->arePrimitiveVariablesValid() ) { return false; } MFloatPointArray vertexArray; MIntArray polygonCounts; MIntArray polygonConnects; MFnMesh fnMesh; int numVertices = 0; IECore::PrimitiveVariableMap::const_iterator it = mesh->variables.find("P"); if ( it != mesh->variables.end() ) { /// \todo Employ some M*Array converters to simplify this IECore::ConstV3fVectorDataPtr p = IECore::runTimeCast<const IECore::V3fVectorData>(it->second.data); if (p) { numVertices = p->readable().size(); vertexArray.setLength( numVertices ); for (int i = 0; i < numVertices; i++) { vertexArray[i] = IECore::convert<MFloatPoint, Imath::V3f>( p->readable()[i] ); } } else { IECore::ConstV3dVectorDataPtr p = IECore::runTimeCast<const IECore::V3dVectorData>(it->second.data); if (p) { numVertices = p->readable().size(); vertexArray.setLength( numVertices ); for (int i = 0; i < numVertices; i++) { vertexArray[i] = IECore::convert<MFloatPoint, Imath::V3d>( p->readable()[i] ); } } else { // "P" is not convertible to an array of "points" return false; } } } IECore::ConstIntVectorDataPtr verticesPerFace = mesh->verticesPerFace(); assert( verticesPerFace ); int numPolygons = verticesPerFace->readable().size(); polygonCounts.setLength( numPolygons ); for (int i = 0; i < numPolygons; i++) { polygonCounts[i] = verticesPerFace->readable()[i]; } IECore::ConstIntVectorDataPtr vertexIds = mesh->vertexIds(); assert( vertexIds ); int numPolygonConnects = vertexIds->readable().size(); polygonConnects.setLength( numPolygonConnects ); for (int i = 0; i < numPolygonConnects; i++) { polygonConnects[i] = vertexIds->readable()[i]; } MObject mObj = fnMesh.create( numVertices, numPolygons, vertexArray, polygonCounts, polygonConnects, to, &s ); if (!s) { return false; } it = mesh->variables.find("N"); if ( it != mesh->variables.end() ) { if (it->second.interpolation == IECore::PrimitiveVariable::FaceVarying ) { /// \todo Employ some M*Array converters to simplify this MVectorArray vertexNormalsArray; IECore::ConstV3fVectorDataPtr n = IECore::runTimeCast<const IECore::V3fVectorData>(it->second.data); if (n) { int numVertexNormals = n->readable().size(); vertexNormalsArray.setLength( numVertexNormals ); for (int i = 0; i < numVertexNormals; i++) { vertexNormalsArray[i] = IECore::convert<MVector, Imath::V3f>( n->readable()[i] ); } } else { IECore::ConstV3dVectorDataPtr n = IECore::runTimeCast<const IECore::V3dVectorData>(it->second.data); if (n) { int numVertexNormals = n->readable().size(); vertexNormalsArray.setLength( numVertexNormals ); for (int i = 0; i < numVertexNormals; i++) { vertexNormalsArray[i] = IECore::convert<MVector, Imath::V3d>( n->readable()[i] ); } } else { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"N\" has unsupported type \"%s\"." ) % it->second.data->typeName() ); } } if ( vertexNormalsArray.length() ) { MStatus status; MItMeshPolygon itPolygon( mObj, &status ); if( status != MS::kSuccess ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "Failed to create mesh iterator" ); } unsigned v = 0; MIntArray vertexIds; MIntArray faceIds; for ( ; !itPolygon.isDone(); itPolygon.next() ) { for ( v=0; v < itPolygon.polygonVertexCount(); ++v ) { faceIds.append( itPolygon.index() ); vertexIds.append( itPolygon.vertexIndex( v ) ); } } if( !fnMesh.setFaceVertexNormals( vertexNormalsArray, faceIds, vertexIds ) ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "Setting normals failed" ); } } } else { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "PrimitiveVariable \"N\" has unsupported interpolation (expected FaceVarying)." ); } } bool haveDefaultUVs = false; IECore::PrimitiveVariableMap::const_iterator sIt = mesh->variables.find( "s" ); IECore::RefCountedPtr sDataRef = ( sIt == mesh->variables.end() ) ? 0 : static_cast<IECore::RefCountedPtr>( sIt->second.data ); /// Add named UV sets std::set< std::string > uvSets; for ( it = mesh->variables.begin(); it != mesh->variables.end(); ++it ) { const std::string &sName = it->first; size_t suffixOffset = sName.rfind( "_s" ); if ( ( suffixOffset != std::string::npos) && ( suffixOffset == sName.length() - 2 ) ) { std::string uvSetNameStr = sName.substr( 0, suffixOffset ); if ( uvSetNameStr.size() ) { MString uvSetName = uvSetNameStr.c_str(); std::string tName = uvSetNameStr + "_t"; std::string stIdName = uvSetNameStr + "Indices"; addUVSet( fnMesh, polygonCounts, mesh, sName, tName, stIdName, &uvSetName ); uvSets.insert( uvSetNameStr ); if ( sDataRef == static_cast<IECore::RefCountedPtr>( it->second.data ) ) { haveDefaultUVs = true; } } } } /// Add default UV set if it isn't just a reference to a named set if ( !haveDefaultUVs ) { addUVSet( fnMesh, polygonCounts, mesh, "s", "t", "stIndices" ); } // We do the search again, but looking for primvars ending "_t", so we can catch cases where either "UVSETNAME_s" or "UVSETNAME_t" is present, but not both, taking care // not to attempt adding any duplicate sets for ( it = mesh->variables.begin(); it != mesh->variables.end(); ++it ) { const std::string &tName = it->first; size_t suffixOffset = tName.rfind( "_t" ); if ( ( suffixOffset != std::string::npos) && ( suffixOffset == tName.length() - 2 ) ) { std::string uvSetNameStr = tName.substr( 0, suffixOffset ); if ( uvSetNameStr.size() && uvSets.find( uvSetNameStr ) == uvSets.end() ) { MString uvSetName = uvSetNameStr.c_str(); std::string sName = uvSetNameStr + "_s"; std::string stIdName = uvSetNameStr + "Indices"; addUVSet( fnMesh, polygonCounts, mesh, sName, tName, stIdName, &uvSetName ); uvSets.insert( uvSetNameStr ); } } } /// If we're making a mesh node (rather than a mesh data) then make sure it belongs /// to the default shading group and add the ieMeshInterpolation attribute. MObject oMesh = fnMesh.object(); if( oMesh.apiType()==MFn::kMesh ) { assignDefaultShadingGroup( oMesh ); setMeshInterpolationAttribute( oMesh, mesh->interpolation() ); } /// \todo Other primvars, e.g. vertex color ("Cs") return true; }
MObject createPoly(double iFrame, PolyMeshAndColors & iNode, MObject & iParent) { Alembic::AbcGeom::IPolyMeshSchema schema = iNode.mMesh.getSchema(); MString name(iNode.mMesh.getName().c_str()); MObject obj; // add other properties if (!schema.isConstant()) { MFloatPointArray emptyPt; MIntArray emptyInt; MFnMesh fnMesh; obj = fnMesh.create(0, 0, emptyPt, emptyInt, emptyInt, iParent); fnMesh.setName(name); } else { Alembic::AbcCoreAbstract::index_t index, ceilIndex; double alpha = getWeightAndIndex(iFrame, schema.getTimeSampling(), schema.getNumSamples(), index, ceilIndex); Alembic::AbcGeom::IPolyMeshSchema::Sample samp; schema.get(samp, Alembic::Abc::ISampleSelector(index)); MFloatPointArray ptArray; Alembic::Abc::P3fArraySamplePtr ceilPoints; if (index != ceilIndex) { Alembic::AbcGeom::IPolyMeshSchema::Sample ceilSamp; schema.get(ceilSamp, Alembic::Abc::ISampleSelector(ceilIndex)); ceilPoints = ceilSamp.getPositions(); } fillPoints(ptArray, samp.getPositions(), ceilPoints, alpha); MFnMesh fnMesh; fillTopology(fnMesh, iParent, ptArray, samp.getFaceIndices(), samp.getFaceCounts()); fnMesh.setName(iNode.mMesh.getName().c_str()); setPolyNormals(iFrame, fnMesh, schema.getNormalsParam()); setUVs(iFrame, fnMesh, schema.getUVsParam()); obj = fnMesh.object(); } MFnMesh fnMesh(obj); MString pathName = fnMesh.partialPathName(); setInitialShadingGroup(pathName); setColors(iFrame, fnMesh, iNode.mC3s, iNode.mC4s, true); if ( !schema.getNormalsParam().valid() ) { MFnNumericAttribute attr; MString attrName("noNormals"); MObject attrObj = attr.create(attrName, attrName, MFnNumericData::kBoolean, true); attr.setKeyable(true); attr.setHidden(false); fnMesh.addAttribute(attrObj, MFnDependencyNode::kLocalDynamicAttr); } return obj; }
static MStatus convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner, std::vector<Vertex> const & vertexBuffer, MFnMesh const & inMeshFn, MObject newMeshDataObj) { MStatus status; typedef OpenSubdiv::Far::ConstIndexArray IndexArray; int maxlevel = refiner.GetMaxLevel(); OpenSubdiv::Far::TopologyLevel const & refLastLevel = refiner.GetLevel(maxlevel); int nfaces = refLastLevel.GetNumFaces(); // Init Maya Data // -- Face Counts MIntArray faceCounts(nfaces); for (int face=0; face < nfaces; ++face) { faceCounts[face] = 4; } // -- Face Connects MIntArray faceConnects(nfaces*4); for (int face=0, idx=0; face < nfaces; ++face) { IndexArray fverts = refLastLevel.GetFaceVertices(face); for (int vert=0; vert < fverts.size(); ++vert) { faceConnects[idx++] = fverts[vert]; } } // -- Points MFloatPointArray points(refLastLevel.GetNumVertices()); Vertex const * v = &vertexBuffer.at(0); for (int level=1; level<=maxlevel; ++level) { int nverts = refiner.GetLevel(level).GetNumVertices(); if (level==maxlevel) { for (int vert=0; vert < nverts; ++vert, ++v) { points.set(vert, v->position[0], v->position[1], v->position[2]); } } else { v += nverts; } } // Create New Mesh from MFnMesh MFnMesh newMeshFn; MObject newMeshObj = newMeshFn.create(points.length(), faceCounts.length(), points, faceCounts, faceConnects, newMeshDataObj, &status); MCHECKERR(status, "Cannot create new mesh"); int fvarTotalWidth = 0; if (fvarTotalWidth > 0) { // Get face-varying set names and other info from the inMesh MStringArray uvSetNames; MStringArray colorSetNames; std::vector<int> colorSetChannels; std::vector<MFnMesh::MColorRepresentation> colorSetReps; int totalColorSetChannels = 0; status = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, colorSetChannels, colorSetReps, totalColorSetChannels); #if defined(DEBUG) or defined(_DEBUG) int numUVSets = uvSetNames.length(); int expectedFvarTotalWidth = numUVSets*2 + totalColorSetChannels; assert(fvarTotalWidth == expectedFvarTotalWidth); #endif // XXXX fvar stuff here } return MS::kSuccess; }
MStatus TCC::createSubdividedMesh(int sdRes, int sdRefRes, MFnMesh &srcMesh, TCCData &tccData, MDataHandle outMeshHandle, float lineThickness, MStatus& stat) { HDS hds; bool shouldCreateUVs = true; size_t nV = srcMesh.numVertices(); size_t nF = srcMesh.numPolygons(); size_t nIHE = tccData.F.length(); bool consistentSizes= (tccData.pole.length()==nV) && (tccData.T.length()==nIHE) && (tccData.itv.length()==nIHE) & (tccData.corner.length()==nV); if ((nV==0)||(nF==0)||(!consistentSizes)) return MS::kFailure; MFloatArray uArray, vArray, sc_uArray, sc_vArray; MIntArray uvIdx; if (shouldCreateUVs) { createUVset(tccData, sdRes, uArray, vArray, sc_uArray, sc_vArray, uvIdx, lineThickness); } MFloatPointArray points; srcMesh.getPoints(points); store_in_hds(hds, points, tccData.nFV, tccData.F); // convert to HDS finalize_HDS(hds); size_t nHE = hds.nHE(); hds.T.setDims(1, nHE); hds.itv.setDims(1, nHE); hds.corner.setDims(1, nV); // interior halfedge tags for (size_t k=0; k<nV; k++) { hds.corner[k] = tccData.corner[k]; } // interior halfedge tags for (size_t k=0; k<nIHE; k++) { hds.T[k] = tccData.T[k]; hds.itv[k] = tccData.itv[k]; } // border halfedge tags for (size_t k=nIHE; k<nHE; k++) { hds.T[k] = false; hds.itv[k] = hds.itv[hds.twin[k]]; } TCC_MAX::subdivide(hds, sdRes); if (sdRefRes>0) { HDS hds2; copy_HDS(hds, hds2); TCC_MAX::subdivide(hds2, sdRefRes); memcpy(&hds.V[0], &hds2.V[0], hds.V.size() * sizeof(double)); } MObject outMeshObj = outMeshHandle.asMesh(); MFnMesh outMeshFn(outMeshObj); // if no topology change necessary, just update points! if ( (outMeshFn.numFaceVertices() == hds.nIHE()) && (outMeshFn.numPolygons() == hds.nF()) ) { size_t nV = hds.nV(); points.setLength(nV); for (size_t k=0; k<nV; k++) { points[k](0) = hds.V[3*k+0]; points[k](1) = hds.V[3*k+1]; points[k](2) = hds.V[3*k+2]; } stat = outMeshFn.setPoints(points); McheckErr(stat, "ERROR creating outputData"); if (shouldCreateUVs) { MString uvSet = "UnitPatchUVs"; MString sc_uvSet = "ScaledPatchUVs"; stat = outMeshFn.setUVs(uArray, vArray, &uvSet); McheckErr(stat, "ERROR setting UVs"); stat = outMeshFn.setUVs(sc_uArray, sc_vArray, &sc_uvSet); McheckErr(stat, "ERROR setting UVs"); } return MS::kSuccess; } // Have to update connectivity and geometry load_from_hds(hds, points, tccData.nFV, tccData.F); nV = points.length(); nF = tccData.nFV.length(); MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&stat); McheckErr(stat, "ERROR creating outputData"); MFnMesh newOutMeshFn; MObject newMesh; newMesh = newOutMeshFn.create(nV, nF, points, tccData.nFV, tccData.F, newOutputData, &stat); McheckErr(stat, "ERROR in MFnMesh.create\n"); if (shouldCreateUVs) { MString uvSet = "UnitPatchUVs"; MString sc_uvSet = "ScaledPatchUVs"; uvSet = newOutMeshFn.createUVSetDataMeshWithName(uvSet, &stat); McheckErr(stat, "ERROR creating UVset"); stat = newOutMeshFn.clearUVs(&uvSet); stat = newOutMeshFn.setUVs(uArray, vArray, &uvSet); McheckErr(stat, "ERROR setting UVs"); stat = newOutMeshFn.assignUVs(tccData.nFV, uvIdx, &uvSet); McheckErr(stat, "ERROR assigning UVs"); sc_uvSet = newOutMeshFn.createUVSetDataMeshWithName(sc_uvSet, &stat); McheckErr(stat, "ERROR creating UVset"); stat = newOutMeshFn.clearUVs(&sc_uvSet); stat = newOutMeshFn.setUVs(sc_uArray, sc_vArray, &sc_uvSet); McheckErr(stat, "ERROR setting UVs"); stat = newOutMeshFn.assignUVs(tccData.nFV, uvIdx, &sc_uvSet); McheckErr(stat, "ERROR assigning UVs"); } if (stat == MS::kSuccess) { outMeshHandle.set(newOutputData); } return MS::kSuccess; }
// Maps vertex points in uv coordinates (uPoints and vPoints) onto plane and creates a new mesh // Only works with planes with the local normal along the y-axis for now (default Maya polyplane) MStatus SplitFromImage::addPlaneSubMesh(MObject &object, MFloatArray uPoints, MFloatArray vPoints, const MFnMesh &planeMesh) { if(uPoints.length() != vPoints.length()) return MS::kFailure; MPointArray planePoints; MIntArray planeVertexCount; MIntArray planeVertexList; planeMesh.getPoints(planePoints); planeMesh.getVertices(planeVertexCount, planeVertexList); cout << "planeVertexCount: " << planeVertexCount.length() << endl; cout << "planeVertexList: " << planeVertexList.length() << endl; double minX, minZ, maxX, maxZ; minX = minZ = 100000; maxX = maxZ = -100000; // Find min and max points of the plane for(unsigned int i = 0; i < planePoints.length(); i++) { double x = planePoints[i].x; double z = planePoints[i].z; if(planePoints[i].x < minX) minX = x; if(planePoints[i].x > maxX) maxX = x; if(planePoints[i].z < minZ) minZ = x; if(planePoints[i].z > maxZ) maxZ = z; } // Set plane's corner pos and width and height double planeX = minX; double planeY = minZ; double planeWidth = maxX - minX; double planeHeight = maxZ - minZ; // Prepare stuff for MFnMesh int numVertices = uPoints.length(); int numPolygons = 1; MPointArray pointArray; int polygon_counts[1] = {numVertices}; MIntArray polygonCounts(polygon_counts, 1); int *polygon_connects = new int[numVertices]; for(int i = 0; i < numVertices; i++) { polygon_connects[i] = i; MPoint point(planeX + planeWidth * uPoints[i], 0, planeY + planeHeight * vPoints[i]); pointArray.append(point); } MIntArray polygonConnects(polygon_connects, numVertices); delete[] polygon_connects; // cout << "numVertices: " << numVertices << endl // << "numPolygons: " << numPolygons << endl // << "pointArray: " << pointArray << endl // << "polygonCounts: " << polygonCounts << endl // << "polygonConnects: " << polygonConnects << endl // << "planeX: " << planeX << endl // << "planeY: " << planeY << endl // << "planeWidth: " << planeWidth << endl // << "planeHeight: " << planeHeight << endl; for (int i = 0; i < vPoints.length(); i++){ vPoints[i] = 1.0 - vPoints[i]; } MFnMesh mesh; object = mesh.create(numVertices, numPolygons, pointArray, polygonCounts, polygonConnects, uPoints, vPoints); mesh.assignUVs(polygonCounts, polygonConnects); return MS::kSuccess; }
MStatus ropeGenerator::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; if ( plug == outMesh ) { //Get Curve MDataHandle inCurve_Hdl = data.inputValue( inCurve, &status ); if (status != MS::kSuccess ){ MGlobal::displayError( "Node ropeGenerator needs an Input Curve" ); return MS::kSuccess; } MObject inCurveObj = inCurve_Hdl.asNurbsCurve(); MFnNurbsCurve curveFn( inCurveObj ); //Get Attributes int inDiv = data.inputValue( divisions ).asInt(); bool inCreateRope = data.inputValue( createRope ).asBool(); int inRopesCount = data.inputValue( ropesCount ).asInt(); int inPointsPerRope = data.inputValue( pointsPerRope ).asInt(); int inPointsCount = data.inputValue( pointsCount ).asInt(); float inRopesStrength = data.inputValue( ropesStrength ).asFloat(); float inRadius = data.inputValue( radius ).asFloat(); MRampAttribute inRadRamp( thisMObject(), taperRamp ); float inTwist = data.inputValue( twist ).asFloat(); MRampAttribute inTwistRamp( thisMObject(), twistRamp ); float inUvWidth = data.inputValue( uvWidth ).asFloat(); float inUvHeight = data.inputValue( uvHeight ).asFloat(); float inUvCapSize = data.inputValue( uvCapSize ).asFloat(); MFnMesh fnMesh; MFnMeshData dataCreator; MObject outMeshData; outMeshData = dataCreator.create(); MDataHandle outputHandle = data.outputValue(outMesh); //createBase MIntArray faceCounts, faceConnects, uvIds; MFloatArray uArray, vArray; MFloatPointArray points; faceCounts.clear(); faceConnects.clear(); points.clear(); if (inCreateRope) inPointsCount = ( inPointsPerRope + 2 ) * inRopesCount; int numVertices = ( inDiv + 1 ) * inPointsCount; int numFaces = ( inPointsCount * inDiv ) + 2; float param; float lengPerDiv = curveFn.length() / inDiv; PrevNormal = MVector( curveFn.normal( 0.0, MSpace::kWorld ).normal() ); float baseLeng = lengPerDiv; float baseParamForRamp = 0; float paramForRamp = 1.0 / float( inDiv ); float uDivNumber = inUvWidth / float( inPointsCount ); float vDivNumber = inUvHeight / float( inDiv ); for (int d = 0; d < inDiv + 1; d++) { if (d == 0) { param = 0; faceCounts.append( inPointsCount ); for ( int i = inPointsCount - 1; i >= 0; i-- ) { faceConnects.append( i ); } for ( int i = 0; i < inPointsCount; i++ ) { uvIds.append( i ); } MFloatArray uTmpArray, vTmpArray; if (inCreateRope) createRopesUvs( inRopesCount, inPointsPerRope, inRopesStrength, inUvCapSize, uTmpArray, vTmpArray, 1.0 ); else createCircleUvs( inPointsCount, inUvCapSize, uTmpArray, vTmpArray, 1.0 ); for ( int u = uTmpArray.length() - 1; u >= 0 ; u-- ) { uArray.append( uTmpArray[u] + 1.0 ); vArray.append( vTmpArray[u] ); } for ( int i = 0; i < inPointsCount + 1; i++ ) { uArray.append( uDivNumber * float( i ) ); vArray.append( vDivNumber * float( d ) ); } }else{ param = curveFn.findParamFromLength( baseLeng ); for ( int i = 0; i < inPointsCount + 1; i++ ) { uArray.append( uDivNumber * float( i ) ); vArray.append( vDivNumber * float( d ) ); } for ( int f = 0; f < inPointsCount; f++ ) { faceCounts.append( 4 ); if( f == ( inPointsCount - 1 )) { faceConnects.append( ( f + 1 + ( d * inPointsCount ) ) - inPointsCount - inPointsCount ); faceConnects.append( ( f + 1 + ( d * inPointsCount ) - inPointsCount ) ); faceConnects.append( f + 1 + ( d * inPointsCount ) - 1 ); faceConnects.append( f + 1 + ( d * inPointsCount ) - inPointsCount - 1 ); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + 1 + f ); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + 1 + f); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + f); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + f); }else{ faceConnects.append( ( f + ( d * inPointsCount ) ) - inPointsCount ); faceConnects.append( f + 1 + ( d * inPointsCount ) - inPointsCount ); faceConnects.append( f + 1 + ( d * inPointsCount ) ); faceConnects.append( ( f + ( d * inPointsCount )) ); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + f); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d - 1 )) + 1 + f ); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + 1 + f); uvIds.append( inPointsCount + (( inPointsCount + 1 ) * float( d )) + f); } } if ( d == inDiv ) { faceCounts.append( inPointsCount ); for ( int i = 0; i < inPointsCount; i++ ) { faceConnects.append( ( inPointsCount * inDiv ) + i ); uvIds.append( ( inPointsCount * ( inDiv + 2)) + i + inDiv + 1 ); } MFloatArray uTmpArray, vTmpArray; if (inCreateRope) createRopesUvs( inRopesCount, inPointsPerRope, inRopesStrength, inUvCapSize, uTmpArray, vTmpArray, -1.0 ); else createCircleUvs( inPointsCount, inUvCapSize, uTmpArray, vTmpArray, -1.0 ); for ( int u = 0; u < uTmpArray.length(); u++ ) { uArray.append( uTmpArray[u] + 2.0 ); vArray.append( vTmpArray[u] ); } } baseLeng += lengPerDiv; } float divTwist; inTwistRamp.getValueAtPosition( baseParamForRamp, divTwist ); float divTaper; inRadRamp.getValueAtPosition( baseParamForRamp, divTaper ); baseParamForRamp += paramForRamp; if (inCreateRope) createRopesRings( inRopesCount, getMatrixFromParamCurve( curveFn, param, inTwist, MAngle( divTwist, MAngle::kDegrees ) ), points, inPointsPerRope, inRopesStrength, inRadius * divTaper); else createCriclePoints( inPointsCount, getMatrixFromParamCurve( curveFn, param, inTwist, MAngle( divTwist, MAngle::kDegrees ) ), points, inRadius * divTaper ); } fnMesh.create( numVertices, numFaces, points, faceCounts, faceConnects, uArray, vArray, outMeshData ); fnMesh.assignUVs( faceCounts, uvIds ); outputHandle.set(outMeshData); outputHandle.setClean(); } return MS::kSuccess; }
//---------------------------------------------------------------------------------------------------------------------- void OceanNode::createGrid(int _resolution, double _time, double _choppiness, MObject& _outputData, MStatus &_status){ int numTris = (_resolution-1)*(_resolution-1)*2; MFloatPointArray vertices; MIntArray numFaceVertices; MIntArray faceVertices; int tris[numTris*3]; int width = 500; int depth = 500; // calculate the deltas for the x,z values of our point float wStep=(float)width/(float)_resolution; float dStep=(float)depth/(float)_resolution; // now we assume that the grid is centered at 0,0,0 so we make // it flow from -w/2 -d/2 float xPos=-((float)width/2.0); float zPos=-((float)depth/2.0); // now loop from top left to bottom right and generate points m_ocean->update(_time); float2* heights = m_ocean->getHeights(); float2* chopXArray = m_ocean->getChopX(); float2* chopZArray = m_ocean->getChopZ(); // Sourced form Jon Macey's NGL library for(int z=0; z<_resolution; z++){ for(int x=0; x<_resolution; x++){ // Divide the values we get out of the FFT by 50000 to get them in a suitable range float height = heights[z * _resolution + x].x/50000.0; float chopX = _choppiness * chopXArray[z * _resolution + x].x/50000.0; float chopZ= _choppiness * chopZArray[z * _resolution + x].x/50000.0; int sign = 1.0; if ((x+z) % 2 != 0){ sign = -1.0; } vertices.append((xPos + (chopX * sign)), height * sign, (zPos + (chopZ * sign))); // calculate the new position zPos+=dStep; } // now increment to next z row xPos+=wStep; // we need to re-set the xpos for new row zPos=-((float)depth/2.0); } // Array for num vertices in each face for (int i=0; i<numTris; i++){ numFaceVertices.append(3); } // Assign vertices to each face int fidx = 0; for (int i=0; i<(_resolution-1); i++){ for (int j=0; j<(_resolution-1); j++){ tris[fidx*3+0] = (i+1)*_resolution+j; tris[fidx*3+1] = i*_resolution+j+1; tris[fidx*3+2] = i*_resolution+j; fidx++; tris[fidx*3+0] = (i+1)*_resolution+j; tris[fidx*3+1] = (i+1)*_resolution+j+1; tris[fidx*3+2] = i*_resolution+j+1; fidx++; } } for (uint i=0; i<sizeof(tris)/sizeof(int); i++){ faceVertices.append(tris[i]); } MFnMesh grid; grid.create(vertices.length(), numTris, vertices, numFaceVertices, faceVertices, _outputData, &_status); }
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; }
MStatus AlembicNode::compute(const MPlug & plug, MDataBlock & dataBlock) { MStatus status; // update the frame number to be imported MDataHandle speedHandle = dataBlock.inputValue(mSpeedAttr, &status); double speed = speedHandle.asDouble(); MDataHandle offsetHandle = dataBlock.inputValue(mOffsetAttr, &status); double offset = offsetHandle.asDouble(); MDataHandle timeHandle = dataBlock.inputValue(mTimeAttr, &status); MTime t = timeHandle.asTime(); double inputTime = t.as(MTime::kSeconds); double fps = getFPS(); // scale and offset inputTime. inputTime = computeAdjustedTime(inputTime, speed, offset/fps); // this should be done only once per file if (mFileInitialized == false) { mFileInitialized = true; MDataHandle dataHandle = dataBlock.inputValue(mAbcFileNameAttr); MFileObject fileObject; fileObject.setRawFullName(dataHandle.asString()); MString fileName = fileObject.resolvedFullName(); // TODO, make sure the file name, or list of files create a valid // Alembic IArchive // initialize some flags for plug update mSubDInitialized = false; mPolyInitialized = false; // When an alembic cache will be imported at the first time using // AbcImport, we need to set mIncludeFilterAttr (filterHandle) to be // mIncludeFilterString for later use. When we save a maya scene(.ma) // mIncludeFilterAttr will be saved. Then when we load the saved // .ma file, mIncludeFilterString will be set to be mIncludeFilterAttr. MDataHandle includeFilterHandle = dataBlock.inputValue(mIncludeFilterAttr, &status); MString& includeFilterString = includeFilterHandle.asString(); if (mIncludeFilterString.length() > 0) { includeFilterHandle.set(mIncludeFilterString); dataBlock.setClean(mIncludeFilterAttr); } else if (includeFilterString.length() > 0) { mIncludeFilterString = includeFilterString; } MDataHandle excludeFilterHandle = dataBlock.inputValue(mExcludeFilterAttr, &status); MString& excludeFilterString = excludeFilterHandle.asString(); if (mExcludeFilterString.length() > 0) { excludeFilterHandle.set(mExcludeFilterString); dataBlock.setClean(mExcludeFilterAttr); } else if (excludeFilterString.length() > 0) { mExcludeFilterString = excludeFilterString; } MFnDependencyNode dep(thisMObject()); MPlug allSetsPlug = dep.findPlug("allColorSets"); CreateSceneVisitor visitor(inputTime, !allSetsPlug.isNull(), MObject::kNullObj, CreateSceneVisitor::NONE, "", mIncludeFilterString, mExcludeFilterString); { mData.getFrameRange(mSequenceStartTime, mSequenceEndTime); MDataHandle startFrameHandle = dataBlock.inputValue(mStartFrameAttr, &status); startFrameHandle.set(mSequenceStartTime*fps); MDataHandle endFrameHandle = dataBlock.inputValue(mEndFrameAttr, &status); endFrameHandle.set(mSequenceEndTime*fps); } } // Retime MDataHandle cycleHandle = dataBlock.inputValue(mCycleTypeAttr, &status); short playType = cycleHandle.asShort(); inputTime = computeRetime(inputTime, mSequenceStartTime, mSequenceEndTime, playType); clamp<double>(mSequenceStartTime, mSequenceEndTime, inputTime); // update only when the time lapse is big enough if (fabs(inputTime - mCurTime) > 0.00001) { mOutRead = std::vector<bool>(mOutRead.size(), false); mCurTime = inputTime; } if (plug == mOutPropArrayAttr) { if (mOutRead[0]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[0] = true; unsigned int propSize = static_cast<unsigned int>(mData.mPropList.size()); if (propSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutPropArrayAttr, &status); unsigned int outHandleIndex = 0; MDataHandle outHandle; // for all of the nodes with sampled attributes for (unsigned int i = 0; i < propSize; i++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(); } else { continue; } if (mData.mPropList[i].mArray.valid()) { readProp(mCurTime, mData.mPropList[i].mArray, outHandle); } else if (mData.mPropList[i].mScalar.valid()) { // for visibility only if (mData.mPropList[i].mScalar.getName() == Alembic::AbcGeom::kVisibilityPropertyName) { Alembic::Util::int8_t visVal = 1; mData.mPropList[i].mScalar.get(&visVal, Alembic::Abc::ISampleSelector(mCurTime, Alembic::Abc::ISampleSelector::kNearIndex )); outHandle.setGenericBool(visVal != 0, false); } else { // for all scalar props readProp(mCurTime, mData.mPropList[i].mScalar, outHandle); } } outArrayHandle.next(); } outArrayHandle.setAllClean(); } } else if (plug == mOutTransOpArrayAttr ) { if (mOutRead[1]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[1] = true; unsigned int xformSize = static_cast<unsigned int>(mData.mXformList.size()); if (xformSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutTransOpArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutTransOpArrayAttr); MDataHandle outHandle; unsigned int outHandleIndex = 0; for (unsigned int i = 0; i < xformSize; i++) { std::vector<double> sampleList; if (mData.mIsComplexXform[i]) { readComplex(mCurTime, mData.mXformList[i], sampleList); } else { Alembic::AbcGeom::XformSample samp; read(mCurTime, mData.mXformList[i], sampleList, samp); } unsigned int sampleSize = (unsigned int)sampleList.size(); for (unsigned int j = 0; j < sampleSize; j++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(&status); } else continue; outArrayHandle.next(); outHandle.set(sampleList[j]); } } outArrayHandle.setAllClean(); } } else if (plug == mOutLocatorPosScaleArrayAttr ) { if (mOutRead[8]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[8] = true; unsigned int locSize = static_cast<unsigned int>(mData.mLocList.size()); if (locSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutLocatorPosScaleArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutLocatorPosScaleArrayAttr); MDataHandle outHandle; unsigned int outHandleIndex = 0; for (unsigned int i = 0; i < locSize; i++) { std::vector< double > sampleList; read(mCurTime, mData.mLocList[i], sampleList); unsigned int sampleSize = (unsigned int)sampleList.size(); for (unsigned int j = 0; j < sampleSize; j++) { // only use the handle if it matches the index. // The index wont line up in the sparse case so we // can just skip that element. if (outArrayHandle.elementIndex() == outHandleIndex++) { outHandle = outArrayHandle.outputValue(&status); } else continue; outArrayHandle.next(); outHandle.set(sampleList[j]); } } outArrayHandle.setAllClean(); } } else if (plug == mOutSubDArrayAttr) { if (mOutRead[2]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutSubDArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[2] = true; unsigned int subDSize = static_cast<unsigned int>(mData.mSubDList.size()); if (subDSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutSubDArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < subDSize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFnMesh fnMesh(obj); readSubD(mCurTime, fnMesh, obj, mData.mSubDList[j], mSubDInitialized); outHandle.set(obj); } } mSubDInitialized = true; outArrayHandle.setAllClean(); } // for the case where we don't have any nodes, we want to make sure // to push out empty meshes on our connections, this can happen if // the input file was offlined, currently we only need to do this for // meshes as Nurbs, curves, and the other channels don't crash Maya else { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutSubDArrayAttr, &status); if (outArrayHandle.elementCount() > 0) { do { MDataHandle outHandle = outArrayHandle.outputValue(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFloatPointArray emptyVerts; MIntArray emptyCounts; MIntArray emptyConnects; MFnMesh emptyMesh; emptyMesh.create(0, 0, emptyVerts, emptyCounts, emptyConnects, obj); outHandle.set(obj); } } while (outArrayHandle.next() == MS::kSuccess); } mSubDInitialized = true; outArrayHandle.setAllClean(); } } else if (plug == mOutPolyArrayAttr) { if (mOutRead[3]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutPolyArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[3] = true; unsigned int polySize = static_cast<unsigned int>(mData.mPolyMeshList.size()); if (polySize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutPolyArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < polySize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFnMesh fnMesh(obj); readPoly(mCurTime, fnMesh, obj, mData.mPolyMeshList[j], mPolyInitialized); outHandle.set(obj); } } mPolyInitialized = true; outArrayHandle.setAllClean(); } // for the case where we don't have any nodes, we want to make sure // to push out empty meshes on our connections, this can happen if // the input file was offlined, currently we only need to do this for // meshes as Nurbs, curves, and the other channels don't crash Maya else { MArrayDataHandle outArrayHandle = dataBlock.outputValue( mOutPolyArrayAttr, &status); if (outArrayHandle.elementCount() > 0) { do { MDataHandle outHandle = outArrayHandle.outputValue(&status); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kMesh)) { MFloatPointArray emptyVerts; MIntArray emptyCounts; MIntArray emptyConnects; MFnMesh emptyMesh; emptyMesh.create(0, 0, emptyVerts, emptyCounts, emptyConnects, obj); outHandle.set(obj); } } while (outArrayHandle.next() == MS::kSuccess); } mPolyInitialized = true; outArrayHandle.setAllClean(); } } else if (plug == mOutCameraArrayAttr) { if (mOutRead[4]) { dataBlock.setClean(plug); return MS::kSuccess; } mOutRead[4] = true; unsigned int cameraSize = static_cast<unsigned int>(mData.mCameraList.size()); if (cameraSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutCameraArrayAttr, &status); MPlug arrayPlug(thisMObject(), mOutCameraArrayAttr); double angleConversion = 1.0; switch (MAngle::uiUnit()) { case MAngle::kRadians: angleConversion = 0.017453292519943295; break; case MAngle::kAngMinutes: angleConversion = 60.0; break; case MAngle::kAngSeconds: angleConversion = 3600.0; break; default: break; } MDataHandle outHandle; unsigned int index = 0; for (unsigned int cameraIndex = 0; cameraIndex < cameraSize; cameraIndex++) { Alembic::AbcGeom::ICamera & cam = mData.mCameraList[cameraIndex]; std::vector<double> array; read(mCurTime, cam, array); for (unsigned int dataIndex = 0; dataIndex < array.size(); dataIndex++, index++) { // skip over sparse elements if (index != outArrayHandle.elementIndex()) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); // not shutter angle index, so not an angle if (dataIndex != 11) { outHandle.set(array[dataIndex]); } else { outHandle.set(array[dataIndex] * angleConversion); } } // for the per camera data handles } // for each camera outArrayHandle.setAllClean(); } } else if (plug == mOutNurbsSurfaceArrayAttr) { if (mOutRead[5]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[5] = true; unsigned int nSurfaceSize = static_cast<unsigned int>(mData.mNurbsList.size()); if (nSurfaceSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status); MDataHandle outHandle; for (unsigned int j = 0; j < nSurfaceSize; j++) { // these elements can be sparse if they have been deleted if (outArrayHandle.elementIndex() != j) continue; outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); MObject obj = outHandle.data(); if (obj.hasFn(MFn::kNurbsSurface)) { readNurbs(mCurTime, mData.mNurbsList[j], obj); outHandle.set(obj); } } outArrayHandle.setAllClean(); } } else if (plug == mOutNurbsCurveGrpArrayAttr) { if (mOutRead[6]) { // Reference the output to let EM know we are the writer // of the data. EM sets the output to holder and causes // race condition when evaluating fan-out destinations. MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status); const unsigned int elementCount = outArrayHandle.elementCount(); for (unsigned int j = 0; j < elementCount; j++) { outArrayHandle.outputValue().data(); outArrayHandle.next(); } outArrayHandle.setAllClean(); return MS::kSuccess; } mOutRead[6] = true; unsigned int nCurveGrpSize = static_cast<unsigned int>(mData.mCurvesList.size()); if (nCurveGrpSize > 0) { MArrayDataHandle outArrayHandle = dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status); MDataHandle outHandle; std::vector<MObject> curvesObj; for (unsigned int i = 0; i < nCurveGrpSize; ++i) { readCurves(mCurTime, mData.mCurvesList[i], mData.mNumCurves[i], curvesObj); } std::size_t numChild = curvesObj.size(); // not the best way to do this // only reading bunches of curves based on the connections would be // more efficient when there is a bunch of broken connections for (unsigned int i = 0; i < numChild; i++) { if (outArrayHandle.elementIndex() != i) { continue; } outHandle = outArrayHandle.outputValue(&status); outArrayHandle.next(); status = outHandle.set(curvesObj[i]); } outArrayHandle.setAllClean(); } } else { return MS::kUnknownParameter; } dataBlock.setClean(plug); return status; }
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; }
PXR_NAMESPACE_OPEN_SCOPE /* static */ bool PxrUsdMayaTranslatorMesh::Create( const UsdGeomMesh& mesh, MObject parentNode, const PxrUsdMayaPrimReaderArgs& args, PxrUsdMayaPrimReaderContext* context) { if (!mesh) { return false; } const UsdPrim& prim = mesh.GetPrim(); MStatus status; // Create node (transform) MObject mayaNodeTransformObj; if (!PxrUsdMayaTranslatorUtil::CreateTransformNode(prim, parentNode, args, context, &status, &mayaNodeTransformObj)) { return false; } VtArray<GfVec3f> points; VtArray<GfVec3f> normals; VtArray<int> faceVertexCounts; VtArray<int> faceVertexIndices; UsdAttribute fvc = mesh.GetFaceVertexCountsAttr(); if (fvc.ValueMightBeTimeVarying()){ // at some point, it would be great, instead of failing, to create a usd/hydra proxy node // for the mesh, perhaps? For now, better to give a more specific error MGlobal::displayError( TfStringPrintf("<%s> is a topologically varying Mesh (animated faceVertexCounts). Skipping...", prim.GetPath().GetText()).c_str()); return false; } else { // for any non-topo-varying mesh, sampling at zero will get us the right answer fvc.Get(&faceVertexCounts, 0); } UsdAttribute fvi = mesh.GetFaceVertexIndicesAttr(); if (fvi.ValueMightBeTimeVarying()){ // at some point, it would be great, instead of failing, to create a usd/hydra proxy node // for the mesh, perhaps? For now, better to give a more specific error MGlobal::displayError( TfStringPrintf("<%s> is a topologically varying Mesh (animated faceVertexIndices). Skipping...", prim.GetPath().GetText()).c_str()); return false; } else { // for any non-topo-varying mesh, sampling at zero will get us the right answer fvi.Get(&faceVertexIndices, 0); } // Sanity Checks. If the vertex arrays are empty, skip this mesh if (faceVertexCounts.size() == 0 || faceVertexIndices.size() == 0) { MGlobal::displayError( TfStringPrintf("FaceVertex arrays are empty [Count:%zu Indices:%zu] on Mesh <%s>. Skipping...", faceVertexCounts.size(), faceVertexIndices.size(), prim.GetPath().GetText()).c_str()); return false; // invalid mesh, so exit } // Gather points and normals // If args.GetReadAnimData() is TRUE, // pick the first avaiable sample or default UsdTimeCode pointsTimeSample=UsdTimeCode::EarliestTime(); UsdTimeCode normalsTimeSample=UsdTimeCode::EarliestTime(); std::vector<double> pointsTimeSamples; size_t pointsNumTimeSamples = 0; if (args.GetReadAnimData()) { PxrUsdMayaTranslatorUtil::GetTimeSamples(mesh.GetPointsAttr(), args, &pointsTimeSamples); pointsNumTimeSamples = pointsTimeSamples.size(); if (pointsNumTimeSamples>0) { pointsTimeSample = pointsTimeSamples[0]; } std::vector<double> normalsTimeSamples; PxrUsdMayaTranslatorUtil::GetTimeSamples(mesh.GetNormalsAttr(), args, &normalsTimeSamples); if (normalsTimeSamples.size()) { normalsTimeSample = normalsTimeSamples[0]; } } mesh.GetPointsAttr().Get(&points, pointsTimeSample); mesh.GetNormalsAttr().Get(&normals, normalsTimeSample); if (points.size() == 0) { MGlobal::displayError( TfStringPrintf("Points arrays is empty on Mesh <%s>. Skipping...", prim.GetPath().GetText()).c_str()); return false; // invalid mesh, so exit } // == Convert data size_t mayaNumVertices = points.size(); MPointArray mayaPoints(mayaNumVertices); for (size_t i=0; i < mayaNumVertices; i++) { mayaPoints.set( i, points[i][0], points[i][1], points[i][2] ); } MIntArray polygonCounts( faceVertexCounts.cdata(), faceVertexCounts.size() ); MIntArray polygonConnects( faceVertexIndices.cdata(), faceVertexIndices.size() ); // == Create Mesh Shape Node MFnMesh meshFn; MObject meshObj = meshFn.create(mayaPoints.length(), polygonCounts.length(), mayaPoints, polygonCounts, polygonConnects, mayaNodeTransformObj, &status ); if (status != MS::kSuccess) { return false; } // Since we are "decollapsing", we will create a xform and a shape node for each USD prim std::string usdPrimName(prim.GetName().GetText()); std::string shapeName(usdPrimName); shapeName += "Shape"; // Set mesh name and register meshFn.setName(MString(shapeName.c_str()), false, &status); if (context) { std::string usdPrimPath(prim.GetPath().GetText()); std::string shapePath(usdPrimPath); shapePath += "/"; shapePath += shapeName; context->RegisterNewMayaNode( shapePath, meshObj ); // used for undo/redo } // If a material is bound, create (or reuse if already present) and assign it // If no binding is present, assign the mesh to the default shader const TfToken& shadingMode = args.GetShadingMode(); PxrUsdMayaTranslatorMaterial::AssignMaterial(shadingMode, mesh, meshObj, context); // Mesh is a shape, so read Gprim properties PxrUsdMayaTranslatorGprim::Read(mesh, meshObj, context); // Set normals if supplied MIntArray normalsFaceIds; if (normals.size() == static_cast<size_t>(meshFn.numFaceVertices())) { for (size_t i=0; i < polygonCounts.length(); i++) { for (int j=0; j < polygonCounts[i]; j++) { normalsFaceIds.append(i); } } if (normalsFaceIds.length() == static_cast<size_t>(meshFn.numFaceVertices())) { MVectorArray mayaNormals(normals.size()); for (size_t i=0; i < normals.size(); i++) { mayaNormals.set( MVector(normals[i][0], normals[i][1], normals[i][2]), i); } if (meshFn.setFaceVertexNormals(mayaNormals, normalsFaceIds, polygonConnects) != MS::kSuccess) { } } } // Determine if PolyMesh or SubdivMesh TfToken subdScheme = PxrUsdMayaMeshUtil::setSubdivScheme(mesh, meshFn, args.GetDefaultMeshScheme()); // If we are dealing with polys, check if there are normals // If we are dealing with SubdivMesh, read additional attributes and SubdivMesh properties if (subdScheme == UsdGeomTokens->none) { if (normals.size() == static_cast<size_t>(meshFn.numFaceVertices())) { PxrUsdMayaMeshUtil::setEmitNormals(mesh, meshFn, UsdGeomTokens->none); } } else { PxrUsdMayaMeshUtil::setSubdivInterpBoundary(mesh, meshFn, UsdGeomTokens->edgeAndCorner); PxrUsdMayaMeshUtil::setSubdivFVLinearInterpolation(mesh, meshFn); _AssignSubDivTagsToMesh(mesh, meshObj, meshFn); } // Set Holes VtArray<int> holeIndices; mesh.GetHoleIndicesAttr().Get(&holeIndices); // not animatable if ( holeIndices.size() != 0 ) { MUintArray mayaHoleIndices; mayaHoleIndices.setLength( holeIndices.size() ); for (size_t i=0; i < holeIndices.size(); i++) { mayaHoleIndices[i] = holeIndices[i]; } if (meshFn.setInvisibleFaces(mayaHoleIndices) == MS::kFailure) { MGlobal::displayError(TfStringPrintf("Unable to set Invisible Faces on <%s>", meshFn.fullPathName().asChar()).c_str()); } } // GETTING PRIMVARS std::vector<UsdGeomPrimvar> primvars = mesh.GetPrimvars(); TF_FOR_ALL(iter, primvars) { const UsdGeomPrimvar& primvar = *iter; const TfToken& name = primvar.GetBaseName(); const SdfValueTypeName& typeName = primvar.GetTypeName(); // If the primvar is called either displayColor or displayOpacity check // if it was really authored from the user. It may not have been // authored by the user, for example if it was generated by shader // values and not an authored colorset/entity. // If it was not really authored, we skip the primvar. if (name == PxrUsdMayaMeshColorSetTokens->DisplayColorColorSetName || name == PxrUsdMayaMeshColorSetTokens->DisplayOpacityColorSetName) { if (!PxrUsdMayaRoundTripUtil::IsAttributeUserAuthored(primvar)) { continue; } } // XXX: Maya stores UVs in MFloatArrays and color set data in MColors // which store floats, so we currently only import primvars holding // float-typed arrays. Should we still consider other precisions // (double, half, ...) and/or numeric types (int)? if (typeName == SdfValueTypeNames->Float2Array) { // We assume that Float2Array primvars are UV sets. if (!_AssignUVSetPrimvarToMesh(primvar, meshFn)) { MGlobal::displayWarning( TfStringPrintf("Unable to retrieve and assign data for UV set <%s> on mesh <%s>", name.GetText(), mesh.GetPrim().GetPath().GetText()).c_str()); } } else if (typeName == SdfValueTypeNames->FloatArray || typeName == SdfValueTypeNames->Float3Array || typeName == SdfValueTypeNames->Color3fArray || typeName == SdfValueTypeNames->Float4Array || typeName == SdfValueTypeNames->Color4fArray) { if (!_AssignColorSetPrimvarToMesh(mesh, primvar, meshFn)) { MGlobal::displayWarning( TfStringPrintf("Unable to retrieve and assign data for color set <%s> on mesh <%s>", name.GetText(), mesh.GetPrim().GetPath().GetText()).c_str()); } } } // We only vizualize the colorset by default if it is "displayColor". MStringArray colorSetNames; if (meshFn.getColorSetNames(colorSetNames)==MS::kSuccess) { for (unsigned int i=0; i < colorSetNames.length(); i++) { const MString colorSetName = colorSetNames[i]; if (std::string(colorSetName.asChar()) == PxrUsdMayaMeshColorSetTokens->DisplayColorColorSetName.GetString()) { MFnMesh::MColorRepresentation csRep= meshFn.getColorRepresentation(colorSetName); if (csRep==MFnMesh::kRGB || csRep==MFnMesh::kRGBA) { // both of these are needed to show the colorset. MPlug plg=meshFn.findPlug("displayColors"); if ( !plg.isNull() ) { plg.setBool(true); } meshFn.setCurrentColorSetName(colorSetName); } break; } } } // == Animate points == // Use blendShapeDeformer so that all the points for a frame are contained in a single node // if (pointsNumTimeSamples > 0) { MPointArray mayaPoints(mayaNumVertices); MObject meshAnimObj; MFnBlendShapeDeformer blendFn; MObject blendObj = blendFn.create(meshObj); if (context) { context->RegisterNewMayaNode( blendFn.name().asChar(), blendObj ); // used for undo/redo } for (unsigned int ti=0; ti < pointsNumTimeSamples; ++ti) { mesh.GetPointsAttr().Get(&points, pointsTimeSamples[ti]); for (unsigned int i=0; i < mayaNumVertices; i++) { mayaPoints.set( i, points[i][0], points[i][1], points[i][2] ); } // == Create Mesh Shape Node MFnMesh meshFn; if ( meshAnimObj.isNull() ) { meshAnimObj = meshFn.create(mayaPoints.length(), polygonCounts.length(), mayaPoints, polygonCounts, polygonConnects, mayaNodeTransformObj, &status ); if (status != MS::kSuccess) { continue; } } else { // Reuse the already created mesh by copying it and then setting the points meshAnimObj = meshFn.copy(meshAnimObj, mayaNodeTransformObj, &status); meshFn.setPoints(mayaPoints); } // Set normals if supplied // // NOTE: This normal information is not propagated through the blendShapes, only the controlPoints. // mesh.GetNormalsAttr().Get(&normals, pointsTimeSamples[ti]); if (normals.size() == static_cast<size_t>(meshFn.numFaceVertices()) && normalsFaceIds.length() == static_cast<size_t>(meshFn.numFaceVertices())) { MVectorArray mayaNormals(normals.size()); for (size_t i=0; i < normals.size(); i++) { mayaNormals.set( MVector(normals[i][0], normals[i][1], normals[i][2]), i); } if (meshFn.setFaceVertexNormals(mayaNormals, normalsFaceIds, polygonConnects) != MS::kSuccess) { } } // Add as target and set as an intermediate object blendFn.addTarget(meshObj, ti, meshAnimObj, 1.0); meshFn.setIntermediateObject(true); if (context) { context->RegisterNewMayaNode( meshFn.fullPathName().asChar(), meshAnimObj ); // used for undo/redo } } // Animate the weights so that mesh0 has a weight of 1 at frame 0, etc. MFnAnimCurve animFn; // Construct the time array to be used for all the keys MTimeArray timeArray; timeArray.setLength(pointsNumTimeSamples); for (unsigned int ti=0; ti < pointsNumTimeSamples; ++ti) { timeArray.set( MTime(pointsTimeSamples[ti]), ti); } // Key/Animate the weights MPlug plgAry = blendFn.findPlug( "weight" ); if ( !plgAry.isNull() && plgAry.isArray() ) { for (unsigned int ti=0; ti < pointsNumTimeSamples; ++ti) { MPlug plg = plgAry.elementByLogicalIndex(ti, &status); MDoubleArray valueArray(pointsNumTimeSamples, 0.0); valueArray[ti] = 1.0; // Set the time value where this mesh's weight should be 1.0 MObject animObj = animFn.create(plg, NULL, &status); animFn.addKeys(&timeArray, &valueArray); if (context) { context->RegisterNewMayaNode(animFn.name().asChar(), animObj ); // used for undo/redo } } } } return true; }
bool CSGSlicer::slice( const Cell& cell, const MeshSlicerInfo& info, MFnMesh& outMesh ) { // copy maya mesh to csg.js model csgjs_model jsModel; MItMeshVertex it(_sourceMesh); while( !it.isDone() ) { csgjs_vertex vtx; // get position MPoint pos = it.position(MSpace::kWorld); vtx.pos = csgjs_vector(static_cast<float>(pos.x), static_cast<float>(pos.y), static_cast<float>(pos.z)); // add position jsModel.vertices.push_back(vtx); it.next(); } MIntArray triangleCounts; MIntArray triangleVertices; MFnMesh(_sourceMesh).getTriangles(triangleCounts, triangleVertices); for( unsigned int i = 0; i < triangleVertices.length(); ++i ) { jsModel.indices.push_back(triangleVertices[i]); } // convert cell into csgjs_model csgjs_model cellModel; int indexOffset = 0; const auto& planePoints = cell.getPlanePoints(); for( const auto& points : planePoints ) { for( const auto& pnt : points ) { csgjs_vertex vtx; vtx.pos = csgjs_vector(pnt.x, pnt.y, pnt.z); cellModel.vertices.push_back(vtx); } const auto& indices = HadanConvexTriangulate(points); for( const auto& idx : indices ) { cellModel.indices.push_back(indexOffset + idx[0]); cellModel.indices.push_back(indexOffset + idx[1]); cellModel.indices.push_back(indexOffset + idx[2]); } indexOffset += static_cast<int>(points.size()); } // perform intersection const csgjs_model result = csgjs_intersection(jsModel, cellModel); // copy back to maya mesh MPointArray pointArray; for( const auto& vtx : result.vertices ) { pointArray.append(MPoint(vtx.pos.x, vtx.pos.y, vtx.pos.z)); } MIntArray faceConnects; for( const auto& idx : result.indices ) { faceConnects.append(idx); } MIntArray faceCounts; for( size_t i = 0; i < result.indices.size() / 3; ++i ) { faceCounts.append(3); } { std::unique_lock<std::mutex> lock(CSGJS_CREATEMESH_MUTEX); outMesh.create(pointArray.length(), faceCounts.length(), pointArray, faceCounts, faceConnects); } return true; }