MStatus XmlCacheFormat::readDoubleVectorArray( MVectorArray& array, unsigned arraySize ) { MStringArray value; if( !readXmlTagValue(doubleVectorArrayTag, value) ) { return MS::kFailure; } assert( value.length() == arraySize * 3 ); array.setLength( arraySize ); for (unsigned i = 0; i < arraySize; i++ ) { double v[3]; v[0] = strtod( value[i*3].asChar(), NULL ); v[1] = strtod( value[i*3+1].asChar(), NULL ); v[2] = strtod( value[i*3+2].asChar(), NULL ); array.set( v, i ); } 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; }
MString CBPoseSpaceCmd::cacheResult(const MPointArray& bindPoints, const MPointArray& posePoints, const MVectorArray& dx, const MVectorArray& dy, const MVectorArray& dz) { MDGModifier modif; MObject opose = modif.createNode("sculptSpaceRecord"); modif.doIt(); unsigned count = dx.length(); MVectorArray row0Array; row0Array.setLength(count); MVectorArray row1Array; row1Array.setLength(count); MVectorArray row2Array; row2Array.setLength(count); MVectorArray row3Array; row3Array.setLength(count); MVectorArray bndArray; bndArray.setLength(count); MVectorArray posArray; posArray.setLength(count); float m[4][4]; for(unsigned i=0; i < count; i++) { m[0][0] = dx[i].x; m[0][1] = dx[i].y; m[0][2] = dx[i].z; m[0][3] = 0.f; m[1][0] = dy[i].x; m[1][1] = dy[i].y; m[1][2] = dy[i].z; m[1][3] = 0.f; m[2][0] = dz[i].x; m[2][1] = dz[i].y; m[2][2] = dz[i].z; m[2][3] = 0.f; m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f; MMatrix tm(m); tm = tm.inverse(); tm.get(m); row0Array[i].x = m[0][0]; row0Array[i].y = m[0][1]; row0Array[i].z = m[0][2]; row1Array[i].x = m[1][0]; row1Array[i].y = m[1][1]; row1Array[i].z = m[1][2]; row2Array[i].x = m[2][0]; row2Array[i].y = m[2][1]; row2Array[i].z = m[2][2]; row3Array[i].x = m[3][0]; row3Array[i].y = m[3][1]; row3Array[i].z = m[3][2]; bndArray[i] = bindPoints[i]; posArray[i] = posePoints[i]; } MFnDependencyNode fposec(opose); MStatus stat; MPlug pspacerow0 = fposec.findPlug("poseSpaceRow0", false, &stat); MPlug pspacerow1 = fposec.findPlug("poseSpaceRow1", false, &stat); MPlug pspacerow2 = fposec.findPlug("poseSpaceRow2", false, &stat); MPlug pspacerow3 = fposec.findPlug("poseSpaceRow3", false, &stat); MPlug pbind = fposec.findPlug("bpnt", false, &stat); MPlug ppose = fposec.findPlug("ppnt", false, &stat); MFnVectorArrayData frow0; MObject orow0 = frow0.create(row0Array); pspacerow0.setMObject(orow0); MFnVectorArrayData frow1; MObject orow1 = frow1.create(row1Array); pspacerow1.setMObject(orow1); MFnVectorArrayData frow2; MObject orow2 = frow2.create(row2Array); pspacerow2.setMObject(orow2); MFnVectorArrayData frow3; MObject orow3 = frow3.create(row3Array); pspacerow3.setMObject(orow3); MFnVectorArrayData fbind; MObject obind = fbind.create(bndArray); pbind.setMObject(obind); MFnVectorArrayData fpose; MObject oposed = fpose.create(posArray); ppose.setMObject(oposed); return fposec.name(); }
void CBPoseSpaceCmd::calculateVertexPoseSpace(const MObject& poseMesh, const MObject& bindMesh) { MStatus status; MFnMesh poseFn(poseMesh, &status); MPointArray originalPoseVertex; poseFn.getPoints ( originalPoseVertex, MSpace::kObject ); unsigned numVert = originalPoseVertex.length(); MFnMesh bindFn(bindMesh, &status); MPointArray originalbindVertex; bindFn.getPoints ( originalbindVertex, MSpace::kObject ); MPointArray movedVertex(originalbindVertex); for(unsigned i=0; i < numVert; i++) { movedVertex[i].x = originalbindVertex[i].x + 1.0; } bindFn.setPoints(movedVertex, MSpace::kObject ); bindFn.updateSurface(); poseFn.updateSurface(); MPointArray xPoseVertex; poseFn.getPoints ( xPoseVertex, MSpace::kObject ); MVectorArray dirx; dirx.setLength(numVert); for(unsigned i=0; i < numVert; i++) { dirx[i] = xPoseVertex[i] - originalPoseVertex[i]; } for(unsigned i=0; i < numVert; i++) { movedVertex[i].x = originalbindVertex[i].x; movedVertex[i].y = originalbindVertex[i].y + 1.0; } bindFn.setPoints(movedVertex, MSpace::kObject ); bindFn.updateSurface(); poseFn.updateSurface(); poseFn.getPoints ( xPoseVertex, MSpace::kObject ); MVectorArray diry; diry.setLength(numVert); for(unsigned i=0; i < numVert; i++) { diry[i] = xPoseVertex[i] - originalPoseVertex[i]; } for(unsigned i=0; i < numVert; i++) { movedVertex[i].y = originalbindVertex[i].y; movedVertex[i].z = originalbindVertex[i].z + 1.0; } bindFn.setPoints(movedVertex, MSpace::kObject ); bindFn.updateSurface(); poseFn.updateSurface(); poseFn.getPoints ( xPoseVertex, MSpace::kObject ); MVectorArray dirz; dirz.setLength(numVert); for(unsigned i=0; i < numVert; i++) { dirz[i] = xPoseVertex[i] - originalPoseVertex[i]; } bindFn.setPoints(originalbindVertex, MSpace::kObject ); bindFn.updateSurface(); const MString cacheNodeName = cacheResult(originalbindVertex, originalPoseVertex, dirx, diry, dirz); MGlobal::displayInfo(MString("correct shape recordes ") + numVert + " points in " + cacheNodeName); setResult(cacheNodeName); }
void simpleFluidEmitter::surfaceFluidEmitter( MFnFluid& fluid, const MMatrix& fluidWorldMatrix, int plugIndex, MDataBlock& block, double dt, double conversion, double dropoff ) //============================================================================== // // Method: // // simpleFluidEmitter::surfaceFluidEmitter // // Description: // // Emits fluid from one of a predefined set of volumes (cube, sphere, // cylinder, cone, torus). // // Parameters: // // fluid: fluid into which we are emitting // fluidWorldMatrix: object->world matrix for the fluid // plugIndex: identifies which fluid connected to the emitter // we are emitting into // block: datablock for the emitter, to retrieve attribute // values // dt: time delta for this frame // conversion: mapping from UI emission rates to internal units // dropoff: specifies how much emission rate drops off as // the surface points move away from the centers // of the voxels in which they lie. // // Notes: // // To associate an owner object with an emitter, use the // addDynamic MEL command, e.g. "addDynamic simpleFluidEmitter1 pPlane1". // //============================================================================== { // get relevant world matrices // MMatrix fluidInverseWorldMatrix = fluidWorldMatrix.inverse(); // get emission rates for density, fuel, heat, and emission color // double densityEmit = fluidDensityEmission( block ); double fuelEmit = fluidFuelEmission( block ); double heatEmit = fluidHeatEmission( block ); bool doEmitColor = fluidEmitColor( block ); MColor emitColor = fluidColor( block ); // rate modulation based on frame time, user value conversion factor, and // standard emitter "rate" value (not actually exposed in most fluid // emitters, but there anyway). // double theRate = getRate(block) * dt * conversion; // get voxel dimensions and sizes (object space) // double size[3]; unsigned int res[3]; fluid.getDimensions( size[0], size[1], size[2] ); fluid.getResolution( res[0], res[1], res[2] ); // voxel sizes double dx = size[0] / res[0]; double dy = size[1] / res[1]; double dz = size[2] / res[2]; // voxel centers double Ox = -size[0]/2; double Oy = -size[1]/2; double Oz = -size[2]/2; // get the "swept geometry" data for the emitter surface. This structure // tracks the motion of each emitter triangle over the time interval // for this simulation step. We just use positions on the emitter // surface at the end of the time step to do the emission. // MDataHandle sweptHandle = block.inputValue( mSweptGeometry ); MObject sweptData = sweptHandle.data(); MFnDynSweptGeometryData fnSweptData( sweptData ); // for "non-jittered" sampling, just reset the random state for each // triangle, which gives us a fixed set of samples all the time. // Sure, they're still jittered, but they're all jittered the same, // which makes them kinda uniform. // bool jitter = fluidJitter(block); if( !jitter ) { resetRandomState( plugIndex, block ); } if( fnSweptData.triangleCount() > 0 ) { // average voxel face area - use this as the canonical unit that // receives the emission rate specified by the users. Scale the // rate for other triangles accordingly. // double vfArea = pow(dx*dy*dz, 2.0/3.0); // very rudimentary support for textured emission rate and // textured emission color. We simply sample each texture once // at the center of each emitter surface triangle. This will // cause aliasing artifacts when these triangles are large. // MFnDependencyNode fnNode( thisMObject() ); MObject rateTextureAttr = fnNode.attribute( "textureRate" ); MObject colorTextureAttr = fnNode.attribute( "particleColor" ); bool texturedRate = hasValidEmission2dTexture( rateTextureAttr ); bool texturedColor = hasValidEmission2dTexture( colorTextureAttr ); // construct texture coordinates for each triangle center // MDoubleArray uCoords, vCoords; if( texturedRate || texturedColor ) { uCoords.setLength( fnSweptData.triangleCount() ); vCoords.setLength( fnSweptData.triangleCount() ); int t; for( t = 0; t < fnSweptData.triangleCount(); t++ ) { MDynSweptTriangle tri = fnSweptData.sweptTriangle( t ); MVector uv0 = tri.uvPoint(0); MVector uv1 = tri.uvPoint(1); MVector uv2 = tri.uvPoint(2); MVector uvMid = (uv0+uv1+uv2)/3.0; uCoords[t] = uvMid[0]; vCoords[t] = uvMid[1]; } } // evaluate textured rate and color values at the triangle centers // MDoubleArray texturedRateValues; if( texturedRate ) { texturedRateValues.setLength( uCoords.length() ); evalEmission2dTexture( rateTextureAttr, uCoords, vCoords, NULL, &texturedRateValues ); } MVectorArray texturedColorValues; if( texturedColor ) { texturedColorValues.setLength( uCoords.length() ); evalEmission2dTexture( colorTextureAttr, uCoords, vCoords, &texturedColorValues, NULL ); } for( int t = 0; t < fnSweptData.triangleCount(); t++ ) { // calculate emission rate and color values for this triangle // double curTexturedRate = texturedRate ? texturedRateValues[t] : 1.0; MColor curTexturedColor; if( texturedColor ) { MVector& curVec = texturedColorValues[t]; curTexturedColor.r = (float)curVec[0]; curTexturedColor.g = (float)curVec[1]; curTexturedColor.b = (float)curVec[2]; curTexturedColor.a = 1.0; } else { curTexturedColor = emitColor; } MDynSweptTriangle tri = fnSweptData.sweptTriangle( t ); MVector v0 = tri.vertex(0); MVector v1 = tri.vertex(1); MVector v2 = tri.vertex(2); // compute number of samples for this triangle based on area, // with large triangles receiving approximately 1 sample for // each voxel that they intersect // double triArea = tri.area(); int numSamples = (int)(triArea / vfArea); if( numSamples < 1 ) numSamples = 1; // compute emission rate for the points on the triangle. // Scale the canonical rate by the area ratio of this triangle // to the average voxel size, then split it amongst all the samples. // double triRate = (theRate*(triArea/vfArea))/numSamples; triRate *= curTexturedRate; for( int j = 0; j < numSamples; j++ ) { // generate a random point on the triangle, // map it into fluid local space // double r1 = randgen(); double r2 = randgen(); if( r1 + r2 > 1 ) { r1 = 1-r1; r2 = 1-r2; } double r3 = 1 - (r1+r2); MPoint randPoint = r1*v0 + r2*v1 + r3*v2; randPoint *= fluidInverseWorldMatrix; // figure out where the current point lies // ::int3 coord; fluid.toGridIndex( randPoint, coord ); if( (coord[0]<0) || (coord[1]<0) || (coord[2]<0) || (coord[0]>=(int)res[0]) || (coord[1]>=(int)res[1]) || (coord[2]>=(int)res[2]) ) { continue; } // do some falloff based on how far from the voxel center // the current point lies // MPoint gridPoint; gridPoint.x = Ox + (coord[0]+0.5)*dx; gridPoint.y = Oy + (coord[1]+0.5)*dy; gridPoint.z = Oz + (coord[2]+0.5)*dz; MVector diff = gridPoint - randPoint; double distSquared = diff * diff; double distDrop = dropoff * distSquared; double newVal = triRate * exp( -distDrop ); // emit into the voxel // if( newVal != 0 ) { fluid.emitIntoArrays( (float) newVal, coord[0], coord[1], coord[2], (float)densityEmit, (float)heatEmit, (float)fuelEmit, doEmitColor, curTexturedColor ); } } } } }
MStatus liqAttachPrefAttribute::redoIt() { MFnTypedAttribute tAttr; MStatus status; for ( unsigned i( 0 ); i < objectNames.length(); i++ ) { MSelectionList nodeList; nodeList.add( objectNames[i] ); MObject depNodeObj; nodeList.getDependNode( 0, depNodeObj ); MDagPath dagNode; nodeList.getDagPath( 0, dagNode ); MFnDependencyNode depNode( depNodeObj ); MObject prefAttr; MString attrName, varName; // make sure the renderer description is up to date liqglo.liquidRenderer.setRenderer(); // build the name of the attribute varName = ( ( exportN && depNodeObj.hasFn( MFn::kMesh ) )? "N":"P" ); attrName = "rman"; attrName += varName; attrName += ( ( liqglo.liquidRenderer.requires__PREF )? "__":"" ); attrName += varName + "ref"; // create the attribute prefAttr = tAttr.create( attrName, attrName, MFnData::kPointArray ); if ( depNodeObj.hasFn( MFn::kNurbsSurface ) ) { MFnNurbsSurface nodeFn( depNodeObj ); MPointArray nodePArray; MItSurfaceCV cvs( dagNode, MObject::kNullObj, liqglo.liquidRenderer.requires_SWAPPED_UVS == false, &status ); while( !cvs.isDone() ) { while( !cvs.isRowDone() ) { MPoint pt = (worldSpace)? cvs.position( MSpace::kWorld ) : cvs.position( MSpace::kObject ); nodePArray.append( pt ); cvs.next(); } cvs.nextRow(); } nodeFn.addAttribute( prefAttr ); MFnPointArrayData pArrayData; MObject prefDefault = pArrayData.create( nodePArray ); MPlug nodePlug( depNodeObj, prefAttr ); nodePlug.setValue( prefDefault ); } else if ( depNodeObj.hasFn( MFn::kNurbsCurve ) ) { // Carsten: added support for PREF on nurbs curves // MFnNurbsCurve nodeFn( depNodeObj ); MPointArray nodePArray; nodeFn.getCVs( nodePArray ); nodeFn.addAttribute( prefAttr ); MFnPointArrayData pArrayData; MObject prefDefault = pArrayData.create( nodePArray ); MPlug nodePlug( depNodeObj, prefAttr ); nodePlug.setValue( prefDefault ); } else if ( depNodeObj.hasFn( MFn::kMesh ) ) { MFnMesh nodeFn( depNodeObj ); // Moritz: modified this line to dim nodePArray -- otherwise // nodePArray.set() in the wile loop below throws an exception // which was why __Pref didn't work MPointArray nodePArray( MFnMesh( depNodeObj ).numVertices() ); unsigned count; nodeFn.addAttribute( prefAttr ); if ( exportN ) { // export Nref unsigned vertex; unsigned normal; unsigned face = 0; unsigned faceVertex = 0; unsigned int numNormals = nodeFn.numNormals(); unsigned int numPoints = nodeFn.numVertices(); MFloatVectorArray normals; MVectorArray normalAttArray; nodeFn.getNormals( normals ); if ( numNormals > numPoints ) { // if we get more than 1 normal per vertex, // force the arraysize to the full facevarying size unsigned faceVaryingCount( 0 ); for ( unsigned pOn( 0 ); pOn < nodeFn.numPolygons(); pOn++ ) faceVaryingCount += nodeFn.polygonVertexCount( pOn ); normalAttArray.setLength( faceVaryingCount ); } else normalAttArray.setLength(normals.length()); for ( MItMeshPolygon polyIt ( depNodeObj ); polyIt.isDone() == false; polyIt.next() ) { count = polyIt.polygonVertexCount(); while ( count > 0 ) { --count; normal = polyIt.normalIndex( count ); vertex = polyIt.vertexIndex( count ); if( numNormals == numPoints ) normalAttArray.set(normals[normal], vertex); else normalAttArray.set(normals[normal], faceVertex); ++faceVertex; } ++face; } MFnVectorArrayData pArrayData; MObject prefDefault = pArrayData.create( normalAttArray ); MPlug nodePlug( depNodeObj, prefAttr ); nodePlug.setValue( prefDefault ); } else { // TODO: do we need to account for the altMeshExport algo that's // used in liquidRibMeshData? // Moritz: no, it's basically the same as the algo below for ( MItMeshPolygon polyIt( dagNode, MObject::kNullObj ); !polyIt.isDone(); polyIt.next()) { count = polyIt.polygonVertexCount(); while ( count > 0 ) { --count; unsigned vertexIndex = polyIt.vertexIndex( count ); MPoint nodePoint = (worldSpace)? polyIt.point( count, MSpace::kWorld ) : polyIt.point( count, MSpace::kObject ); // Moritz: this returns MS::kFailure but seems to work?! nodePArray.set( nodePoint, vertexIndex ); } } MFnPointArrayData pArrayData; MObject prefDefault = pArrayData.create( nodePArray ); MPlug nodePlug( depNodeObj, prefAttr ); nodePlug.setValue( prefDefault ); } } else cerr << "Neither a Nurbs nor a Mesh !!" << endl; } return MS::kSuccess; }
// // Main routine /////////////////////////////////////////////////////////////////////////////// MStatus particleSystemInfoCmd::doIt( const MArgList& args ) { MStatus stat = parseArgs( args ); if( stat != MS::kSuccess ) return stat; if( particleNode.isNull() ) { MObject parent; MFnParticleSystem dummy; particleNode = dummy.create(&stat); CHECKRESULT(stat,"MFnParticleSystem::create(status) failed!"); MFnParticleSystem ps( particleNode, &stat ); CHECKRESULT(stat,"MFnParticleSystem::MFnParticleSystem(MObject,status) failed!"); MPointArray posArray; posArray.append(MPoint(-5, 5, 0)); posArray.append(MPoint(-5, 10, 0)); MVectorArray velArray; velArray.append(MPoint(1, 1, 0)); velArray.append(MPoint(1, 1, 0)); stat = ps.emit(posArray, velArray); CHECKRESULT(stat,"MFnParticleSystem::emit(posArray,velArray) failed!"); stat = ps.emit(MPoint(5, 5, 0)); CHECKRESULT(stat,"MFnParticleSystem::emit(pos) failed!"); stat = ps.emit(MPoint(5, 10, 0)); CHECKRESULT(stat,"MFnParticleSystem::emit(pos) failed!"); stat = ps.saveInitialState(); CHECKRESULT(stat,"MFnParticleSystem::saveInitialState() failed!"); MVectorArray accArray; accArray.setLength(4); for( unsigned int i=0; i<accArray.length(); i++ ) { MVector& acc = accArray[i]; acc.x = acc.y = acc.z = 3.0; } MString accName("acceleration"); ps.setPerParticleAttribute( accName, accArray, &stat ); CHECKRESULT(stat,"MFnParticleSystem::setPerParticleAttribute(vectorArray) failed!"); } MFnParticleSystem ps( particleNode, &stat ); CHECKRESULT(stat,"MFnParticleSystem::MFnParticleSystem(MObject,status) failed!"); if( ! ps.isValid() ) { MGlobal::displayError( "The function set is invalid!" ); return MS::kFailure; } const MString name = ps.particleName(); const MFnParticleSystem::RenderType psType = ps.renderType(); const unsigned int count = ps.count(); const char* typeString = NULL; switch( psType ) { case MFnParticleSystem::kCloud: typeString = "Cloud"; break; case MFnParticleSystem::kTube: typeString = "Tube system"; break; case MFnParticleSystem::kBlobby: typeString = "Blobby"; break; case MFnParticleSystem::kMultiPoint: typeString = "MultiPoint"; break; case MFnParticleSystem::kMultiStreak: typeString = "MultiStreak"; break; case MFnParticleSystem::kNumeric: typeString = "Numeric"; break; case MFnParticleSystem::kPoints: typeString = "Points"; break; case MFnParticleSystem::kSpheres: typeString = "Spheres"; break; case MFnParticleSystem::kSprites: typeString = "Sprites"; break; case MFnParticleSystem::kStreak: typeString = "Streak"; break; default: typeString = "Particle system"; assert( false ); break; } char buffer[256]; sprintf( buffer, "%s \"%s\" has %u primitives.", typeString, name.asChar(), count ); MGlobal::displayInfo( buffer ); unsigned i; MIntArray ids; ps.particleIds( ids ); sprintf( buffer, "count : %u ", count ); MGlobal::displayInfo( buffer ); sprintf( buffer, "%u ids.", ids.length() ); MGlobal::displayInfo( buffer ); assert( ids.length() == count ); for( i=0; i<ids.length(); i++ ) { sprintf( buffer, "id %d ", ids[i] ); MGlobal::displayInfo( buffer ); } MVectorArray positions; ps.position( positions ); assert( positions.length() == count ); for( i=0; i<positions.length(); i++ ) { MVector& p = positions[i]; sprintf( buffer, "pos %f %f %f ", p[0], p[1], p[2] ); MGlobal::displayInfo( buffer ); } MVectorArray vels; ps.velocity( vels ); assert( vels.length() == count ); for( i=0; i<vels.length(); i++ ) { const MVector& v = vels[i]; sprintf( buffer, "vel %f %f %f ", v[0], v[1], v[2] ); MGlobal::displayInfo( buffer ); } MVectorArray accs; ps.acceleration( accs ); assert( accs.length() == count ); for( i=0; i<accs.length(); i++ ) { const MVector& a = accs[i]; sprintf( buffer, "acc %f %f %f ", a[0], a[1], a[2] ); MGlobal::displayInfo( buffer ); } bool flag = ps.isDeformedParticleShape(&stat); CHECKRESULT(stat,"MFnParticleSystem::isDeformedParticleShape() failed!"); if( flag ) { MObject obj = ps.originalParticleShape(&stat); CHECKRESULT(stat,"MFnParticleSystem::originalParticleShape() failed!"); if( obj != MObject::kNullObj ) { MFnParticleSystem ps( obj ); sprintf( buffer, "original particle shape : %s ", ps.particleName().asChar() ); MGlobal::displayInfo( buffer ); } } flag = ps.isDeformedParticleShape(&stat); CHECKRESULT(stat,"MFnParticleSystem::isDeformedParticleShape() failed!"); if( !flag ) { MObject obj = ps.deformedParticleShape(&stat); CHECKRESULT(stat,"MFnParticleSystem::deformedParticleShape() failed!"); if( obj != MObject::kNullObj ) { MFnParticleSystem ps( obj ); sprintf( buffer, "deformed particle shape : %s ", ps.particleName().asChar() ); MGlobal::displayInfo( buffer ); } } if( ids.length() == positions.length() && ids.length() == vels.length() && ids.length() == accs.length() ) { setResult( int(ids.length()) ); } else { setResult( int(-1) ); } return MS::kSuccess; }