void dynExprField::apply( MDataBlock &block, int receptorSize, const MDoubleArray &magnitudeArray, const MDoubleArray &magnitudeOwnerArray, const MVectorArray &directionArray, const MVectorArray &directionOwnerArray, MVectorArray &outputForce ) // // Compute output force for each particle. If there exists the // corresponding per particle attribute, use the data passed from // particle shape (stored in magnitudeArray and directionArray). // Otherwise, use the attribute value from the field. // { // get the default values MVector defaultDir = direction(block); double defaultMag = magnitude(block); int magArraySize = magnitudeArray.length(); int dirArraySize = directionArray.length(); int magOwnerArraySize = magnitudeOwnerArray.length(); int dirOwnerArraySize = directionOwnerArray.length(); int numOfOwner = magOwnerArraySize; if( dirOwnerArraySize > numOfOwner ) numOfOwner = dirOwnerArraySize; double magnitude = defaultMag; MVector direction = defaultDir; for (int ptIndex = 0; ptIndex < receptorSize; ptIndex ++ ) { if(receptorSize == magArraySize) magnitude = magnitudeArray[ptIndex]; if(receptorSize == dirArraySize) direction = directionArray[ptIndex]; if( numOfOwner > 0) { for( int nthOwner = 0; nthOwner < numOfOwner; nthOwner++ ) { if(magOwnerArraySize == numOfOwner) magnitude = magnitudeOwnerArray[nthOwner]; if(dirOwnerArraySize == numOfOwner) direction = directionOwnerArray[nthOwner]; outputForce.append( direction * magnitude ); } } else { outputForce.append( direction * magnitude ); } } }
bool PxrUsdMayaWriteUtil::ReadMayaAttribute( const MFnDependencyNode& depNode, const MString& name, VtFloatArray* val) { MStatus status; depNode.attribute(name, &status); if (status == MS::kSuccess) { MPlug plug = depNode.findPlug(name); MObject dataObj; if ( (plug.getValue(dataObj) == MS::kSuccess) && (dataObj.hasFn(MFn::kDoubleArrayData)) ) { MFnDoubleArrayData dData(dataObj, &status); if (status == MS::kSuccess) { MDoubleArray arrayValues = dData.array(); size_t numValues = arrayValues.length(); val->resize(numValues); for (size_t i = 0; i < numValues; ++i) { (*val)[i] = arrayValues[i]; } return true; } } } return false; }
// Reference: OSD shape_utils.h:: applyTags() "crease" static float getCreaseEdges(MFnMesh const & inMeshFn, Descriptor & outDesc) { MUintArray tEdgeIds; MDoubleArray tCreaseData; float maxCreaseValue = 0.0f; if (inMeshFn.getCreaseEdges(tEdgeIds, tCreaseData)) { assert( tEdgeIds.length() == tCreaseData.length() ); int ncreases = tEdgeIds.length(); int * vertPairs = new int[ncreases*2]; float * weights = new float[ncreases]; int2 edgeVerts; for (unsigned int j=0; j < tEdgeIds.length(); j++) { assert( tCreaseData[j] >= 0.0 ); inMeshFn.getEdgeVertices(tEdgeIds[j], edgeVerts); vertPairs[j*2 ] = edgeVerts[0]; vertPairs[j*2+1] = edgeVerts[1]; weights[j] = float(tCreaseData[j]); maxCreaseValue = std::max(float(tCreaseData[j]), maxCreaseValue); } outDesc.numCreases = ncreases; outDesc.creaseVertexIndexPairs = vertPairs; outDesc.creaseWeights = weights; } return maxCreaseValue; }
// Reference: OSD shape_utils.h:: applyTags() "corner" static float getCreaseVertices( MFnMesh const & inMeshFn, Descriptor & outDesc) { MUintArray tVertexIds; MDoubleArray tCreaseData; float maxCreaseValue = 0.0f; if ( inMeshFn.getCreaseVertices(tVertexIds, tCreaseData) ) { assert( tVertexIds.length() == tCreaseData.length() ); int ncorners = tVertexIds.length(); int * verts = new int[ncorners*2]; float * weights = new float[ncorners]; // Has crease vertices for (unsigned int j=0; j < tVertexIds.length(); j++) { assert( tCreaseData[j] >= 0.0 ); verts[j] = tVertexIds[j]; weights[j] = float(tCreaseData[j]); maxCreaseValue = std::max(float(tCreaseData[j]), maxCreaseValue); } outDesc.numCorners = ncorners; outDesc.cornerVertexIndices = verts; outDesc.cornerWeights = weights; } return maxCreaseValue; }
// Reference: OSD shape_utils.h:: applyTags() "corner" float applyCreaseVertices( MFnMesh const & inMeshFn, HMesh * hbrMesh ) { MUintArray tVertexIds; MDoubleArray tCreaseData; float maxCreaseValue = 0.0f; if ( inMeshFn.getCreaseVertices(tVertexIds, tCreaseData) ) { assert( tVertexIds.length() == tCreaseData.length() ); // Has crease vertices for (unsigned int j=0; j < tVertexIds.length(); j++) { // Assumption: The OSD vert ids are identical to those of the Maya mesh HVertex * v = hbrMesh->GetVertex( tVertexIds[j] ); if(v) { assert( tCreaseData[j] >= 0.0 ); v->SetSharpness( (float)tCreaseData[j] ); maxCreaseValue = std::max(float(tCreaseData[j]), maxCreaseValue); } else { fprintf(stderr, "warning: cannot find vertex for corner tag (%d)\n", tVertexIds[j] ); } } } return maxCreaseValue; }
AlembicWriteJob::AlembicWriteJob(const MString &in_FileName, const MObjectArray &in_Selection, const MDoubleArray &in_Frames, bool use_ogawa, const std::vector<std::string> &in_prefixFilters, const std::set<std::string> &in_attributes, const std::vector<std::string> &in_userPrefixFilters, const std::set<std::string> &in_userAttributes) : useOgawa(use_ogawa), mPrefixFilters(in_prefixFilters), mAttributes(in_attributes), mUserPrefixFilters(in_userPrefixFilters), mUserAttributes(in_userAttributes) { // ensure to clear the isRefAnimated cache clearIsRefAnimatedCache(); mFileName = in_FileName; for (unsigned int i = 0; i < in_Selection.length(); i++) { mSelection.append(in_Selection[i]); } for (unsigned int i = 0; i < in_Frames.length(); i++) { mFrames.push_back(in_Frames[i]); } }
void skinClusterWeights::doItQuery() { MStatus status; unsigned int i, j; MDoubleArray weights; // To allow "skinClusterWeights -q" to return empty double array setResult(weights); MSelectionList selList; for (i = 0; i < geometryArray.length(); i++) { MDagPath dagPath; MObject component; selList.clear(); selList.add(geometryArray[i]); MStatus status = selList.getDagPath(0, dagPath, component); if (status != MS::kSuccess) { continue; } if (component.isNull()) dagPath.extendToShape(); MObject skinCluster = findSkinCluster(dagPath); if (!isSkinClusterIncluded(skinCluster)) { continue; } MFnSkinCluster skinClusterFn(skinCluster, &status); if (status != MS::kSuccess) { continue; } MIntArray influenceIndexArray; populateInfluenceIndexArray(skinClusterFn, influenceIndexArray); weights.clear(); skinClusterFn.getWeights(dagPath, component, influenceIndexArray, weights); if (weights.length() > 0) { for (j = 0; j < weights.length(); j++) { appendToResult(weights[j]); } } } }
MStatus XmlCacheFormat::writeDoubleArray( const MDoubleArray& array ) { int size = array.length(); assert(size != 0); writeXmlTagValue(sizeTag,size); startXmlBlock( doubleArrayTag ); for(int i = 0; i < size; i++) { writeXmlValue(array[i]); } endXmlBlock(); return MS::kSuccess; }
// Reference: OSD shape_utils.h:: applyTags() "crease" float applyCreaseEdges(MFnMesh const & inMeshFn, HMesh * hbrMesh) { MStatus returnStatus; MUintArray tEdgeIds; MDoubleArray tCreaseData; float maxCreaseValue = 0.0f; if (inMeshFn.getCreaseEdges(tEdgeIds, tCreaseData)) { assert( tEdgeIds.length() == tCreaseData.length() ); // Has crease edges int2 edgeVerts; for (unsigned int j=0; j < tEdgeIds.length(); j++) { // Get vert ids from maya edge int edgeId = tEdgeIds[j]; returnStatus = inMeshFn.getEdgeVertices(edgeId, edgeVerts); // Assumption: The OSD vert ids are identical to those of the Maya mesh HVertex const * v = hbrMesh->GetVertex( edgeVerts[0] ), * w = hbrMesh->GetVertex( edgeVerts[1] ); HHalfedge * e = 0; if( v and w ) { if( (e = v->GetEdge(w)) == 0) { e = w->GetEdge(v); } if(e) { assert( tCreaseData[j] >= 0.0 ); e->SetSharpness( (float)tCreaseData[j] ); maxCreaseValue = std::max(float(tCreaseData[j]), maxCreaseValue); } else { fprintf(stderr, "warning: cannot find edge for crease tag (%d,%d)\n", edgeVerts[0], edgeVerts[1] ); } } } } return maxCreaseValue; }
MStatus mDblSignedToUnsigned::doIt( const MArgList& args ) { // get the arguments MDoubleArray dblA; unsigned int count; MStatus stat = getArgDbl(args, dblA, count); ERROR_FAIL(stat); // do the actual job for (unsigned int i=0;i<dblA.length();i++) { dblA[i] = (0.5 * dblA[i] + 0.5); } setResult(dblA); return MS::kSuccess; }
MStatus mDbl1dNoise::doIt( const MArgList& args ) { // get the arguments MDoubleArray dblA; unsigned int count; MStatus stat = getArgDbl(args, dblA, count); ERROR_FAIL(stat); // do the actual job Noise noiseGen; for (unsigned int i=0;i<dblA.length();i++) { dblA[i] = noiseGen.improvedPerlin1dS(float(dblA[i])); } setResult(dblA); return MS::kSuccess; }
void GetValidUp(const MDoubleArray& weights, const MPointArray& points, const MIntArray& sampleIds, const MPoint& origin, const MVector& normal, MVector& up) { MVector unitUp = up.normal(); // Adjust up if it's parallel to normal or if it's zero length if (std::abs((unitUp * normal) - 1.0) < 0.001 || up.length() < 0.0001) { for (unsigned int j = 0; j < weights.length()-1; ++j) { up -= (points[sampleIds[j]] - origin) * weights[j]; unitUp = up.normal(); if (std::abs((unitUp * normal) - 1.0) > 0.001 && up.length() > 0.0001) { // If the up and normal vectors are no longer parallel and the up vector has a length, // then we are good to go. break; } } up.normalize(); } else { up = unitUp; } }
MStatus ReduceArrayNode::compute(const MPlug& plug, MDataBlock& data) { if (plug != aOutput) return MS::kUnknownParameter; MStatus status; MDataHandle inputHandle = data.inputValue(aInput, &status); CHECK_MSTATUS_AND_RETURN_IT(status); MFnDoubleArrayData inputArrayData(inputHandle.data()); MDoubleArray inputArray = inputArrayData.array(); int numInputs = inputArray.length(); short operation = data.inputValue(aOperation).asShort(); double output = numInputs > 0 ? inputArray[0] : 0.0; if (operation == kLENGTH) { output = double(numInputs); } else { for (int i = 1; i < numInputs; i++) { output = computeOutput(output, inputArray[i], operation, status); if (!status) { reportComputeError(this, operation); break; } } } MDataHandle outputHandle = data.outputValue(this->aOutput); outputHandle.setDouble(output); outputHandle.setClean(); return MS::kSuccess; }
void CalculateSampleWeights(const std::map<int, double>& distances, double radius, MIntArray& vertexIds, MDoubleArray& weights) { std::map<int, double>::const_iterator itDistance; std::vector<std::pair<int, double> > samples; for (itDistance = distances.begin(); itDistance != distances.end(); itDistance++) { double x = itDistance->second; double w = 1.0 - (x/radius); samples.push_back(std::pair<int, double>(itDistance->first, w)); } // Make the samples a multiple of 4 so we can use fast intrinsics! int remainder = 4 - ((samples.size()-1) % 4); if (remainder != 4) { for (int i = 0; i < remainder; ++i) { samples.push_back(std::pair<int, double>(0, 0.0)); } } unsigned int length = (unsigned int)samples.size(); weights.setLength(length); vertexIds.setLength(length); std::sort(samples.begin(), samples.end(), SampleSort); std::vector<std::pair<int, double> >::iterator iter; int ii = 0; double sum = 0.0; for (iter = samples.begin(); iter != samples.end(); ++iter, ++ii) { vertexIds[ii] = (*iter).first; weights[ii] = (*iter).second; sum += (*iter).second; } assert(sum > 0.0); // Normalize the weights for (unsigned int i = 0; i < weights.length(); ++i) { weights[i] /= sum; } }
MStatus PushDeformer::deform(MDataBlock& dataBlock, MItGeometry& itGeo, const MMatrix& localToWorldMatrix, unsigned int geomIndex) { MStatus status; //get attribute handles double bulgeAmount = dataBlock.inputValue(aAmount, &status).asDouble(); CHECK_MSTATUS_AND_RETURN_IT(status); m_taskData.envelope = dataBlock.inputValue(envelope, &status).asFloat(); CHECK_MSTATUS_AND_RETURN_IT(status); bool useStressV = dataBlock.inputValue(aUseStress, &status).asBool(); CHECK_MSTATUS_AND_RETURN_IT(status); int multiThreadingType = dataBlock.inputValue(aMultiThreadingType, &status).asBool(); CHECK_MSTATUS_AND_RETURN_IT(status); if (m_taskData.envelope <= 0.001) { return MS::kSuccess; } // if the use stress plug is turned on pull MDoubleArray stressV; if (useStressV == true) { //pull out the raw data as an Mobject MObject stressMap = dataBlock.inputValue(aStressMap, &status).data(); CHECK_MSTATUS_AND_RETURN_IT(status); MFnDoubleArrayData stressDataFn(stressMap); m_taskData.stressV = stressDataFn.array(); } //retrieve the handle to the output array attribute MArrayDataHandle hInput = dataBlock.outputArrayValue(input, &status); CHECK_MSTATUS_AND_RETURN_IT(status); //get the input array index handle status = hInput.jumpToElement(geomIndex); //get the handle of geomIndex attribute MDataHandle hInputElement = hInput.outputValue(&status); CHECK_MSTATUS_AND_RETURN_IT(status); //Get the MObject of the input geometry of geomindex MObject oInputGeom = hInputElement.child(inputGeom).asMesh(); MFnMesh fnMesh(oInputGeom, &status); CHECK_MSTATUS_AND_RETURN_IT(status); fnMesh.getVertexNormals(false, m_taskData.normals, MSpace::kWorld); itGeo.allPositions(m_taskData.points, MSpace::kWorld); //MGlobal::displayInfo( "test" ); /*for (int i = 0; i < itGeo.count(); i++) { MGlobal::displayInfo( MFnAttribute(weightList).isArray ); }*/ m_taskData.bulgeAmount = bulgeAmount; if(multiThreadingType == 1) { ThreadData* pThreadData = createThreadData( NUM_TASKS, &m_taskData ); MThreadPool::newParallelRegion( createTasks, (void*)pThreadData ); itGeo.setAllPositions(m_taskData.points); delete [] pThreadData; return MS::kSuccess; } else if(multiThreadingType == 2) { tbb::parallel_for(size_t(0), size_t(itGeo.count()), [this](size_t i) { //const float w = weightValue(dataBlock, geomIndex, i); const float w = 1.0; if (m_taskData.useStressV == true && (m_taskData.stressV.length() > 0)) { //deform m_taskData.points[i] += (MVector(m_taskData.normals[i]) * m_taskData.bulgeAmount * m_taskData.envelope * w * m_taskData.stressV[i]); } else { //deform m_taskData.points[i] += m_taskData.normals[i] * m_taskData.bulgeAmount * m_taskData.envelope * w; } }); } // else if(multiThreadingType == 3) #pragma omp parallel for for (int i = 0; i < itGeo.count(); i++) { float w = weightValue(dataBlock, geomIndex, itGeo.index()); if (useStressV == true && (stressV.length() > 0)) { //deform m_taskData.points[i] += (MVector(m_taskData.normals[i]) * bulgeAmount * m_taskData.envelope * w * m_taskData.stressV[i]); } else { //deform m_taskData.points[i] += m_taskData.normals[i] * bulgeAmount * m_taskData.envelope * w; } } else { for (; !itGeo.isDone(); itGeo.next()) { float w = weightValue(dataBlock, geomIndex, itGeo.index()); if (useStressV == true && (stressV.length() > 0)) { //deform m_taskData.points[itGeo.index()] += (MVector(m_taskData.normals[itGeo.index()]) * bulgeAmount * m_taskData.envelope * w * m_taskData.stressV[itGeo.index()]); } else { //deform m_taskData.points[itGeo.index()] += m_taskData.normals[itGeo.index()] * bulgeAmount * m_taskData.envelope * w; } } } itGeo.setAllPositions(m_taskData.points); return MS::kSuccess; }
void CalculateBasisComponents(const MDoubleArray& weights, const BaryCoords& coords, const MIntArray& triangleVertices, const MPointArray& points, const MFloatVectorArray& normals, const MIntArray& sampleIds, double* alignedStorage, MPoint& origin, MVector& up, MVector& normal) { // Start with the recreated point and normal using the barycentric coordinates of the hit point. unsigned int hitIndex = weights.length()-1; #ifdef __AVX__ __m256d originV = Dot4<MPoint>(coords[0], coords[1], coords[2], 0.0, points[triangleVertices[0]], points[triangleVertices[1]], points[triangleVertices[2]], MPoint::origin); __m256d hitNormalV = Dot4<MVector>(coords[0], coords[1], coords[2], 0.0, normals[triangleVertices[0]], normals[triangleVertices[1]], normals[triangleVertices[2]], MVector::zero); __m256d hitWeightV = _mm256_set1_pd(weights[hitIndex]); // Create the barycentric point and normal. __m256d normalV = _mm256_mul_pd(hitNormalV, hitWeightV); // Then use the weighted adjacent data. for (unsigned int j = 0; j < hitIndex; j += 4) { __m256d tempNormal = Dot4<MVector>(weights[j], weights[j+1], weights[j+2], weights[j+3], normals[sampleIds[j]], normals[sampleIds[j+1]], normals[sampleIds[j+2]], normals[sampleIds[j+3]]); normalV = _mm256_add_pd(tempNormal, normalV); } _mm256_store_pd(alignedStorage, originV); origin.x = alignedStorage[0]; origin.y = alignedStorage[1]; origin.z = alignedStorage[2]; _mm256_store_pd(alignedStorage, normalV); normal.x = alignedStorage[0]; normal.y = alignedStorage[1]; normal.z = alignedStorage[2]; // Calculate the up vector const MPoint& pt1 = points[triangleVertices[0]]; const MPoint& pt2 = points[triangleVertices[1]]; __m256d p1 = _mm256_set_pd(pt1.w, pt1.z, pt1.y, pt1.x); __m256d p2 = _mm256_set_pd(pt2.w, pt2.z, pt2.y, pt2.x); p1 = _mm256_add_pd(p1, p2); __m256d half = _mm256_set_pd(0.5, 0.5, 0.5, 0.5); p1 = _mm256_mul_pd(p1, half); __m256d upV = _mm256_sub_pd(p1, originV); _mm256_store_pd(alignedStorage, upV); up.x = alignedStorage[0]; up.y = alignedStorage[1]; up.z = alignedStorage[2]; #else MVector hitNormal; // Create the barycentric point and normal. for (int i = 0; i < 3; ++i) { origin += points[triangleVertices[i]] * coords[i]; hitNormal += MVector(normals[triangleVertices[i]]) * coords[i]; } // Use crawl data to calculate normal normal = hitNormal * weights[hitIndex]; for (unsigned int j = 0; j < hitIndex; j++) { normal += MVector(normals[sampleIds[j]]) * weights[j]; } // Calculate the up vector // The triangle vertices are sorted by decreasing barycentric coordinates so the first two are // the two closest vertices in the triangle. up = ((points[triangleVertices[0]] + points[triangleVertices[1]]) * 0.5) - origin; #endif normal.normalize(); GetValidUp(weights, points, sampleIds, origin, normal, up); }
void OsdPtexMeshData::rebuildHbrMeshIfNeeded(OpenSubdivPtexShader *shader) { MStatus status; if (!_meshTopoDirty && !shader->getHbrMeshDirty()) return; MFnMesh meshFn(_meshDagPath, &status); if (status != MS::kSuccess) return; int level = shader->getLevel(); if (level < 1) level =1; SchemeType scheme = shader->getScheme(); if (scheme == kLoop) scheme = kCatmark; // XXX: avoid loop for now // Get Maya vertex topology and crease data MIntArray vertexCount; MIntArray vertexList; meshFn.getVertices(vertexCount, vertexList); MUintArray edgeIds; MDoubleArray edgeCreaseData; meshFn.getCreaseEdges(edgeIds, edgeCreaseData); MUintArray vtxIds; MDoubleArray vtxCreaseData; meshFn.getCreaseVertices(vtxIds, vtxCreaseData); if (vertexCount.length() == 0) return; // Cache attribute values _level = shader->getLevel(); _scheme = shader->getScheme(); _kernel = shader->getKernel(); _adaptive = shader->isAdaptive(); _interpBoundary = shader->getInterpolateBoundary(); // Copy Maya vectors into std::vectors std::vector<int> numIndices(&vertexCount[0], &vertexCount[vertexCount.length()]); std::vector<int> faceIndices(&vertexList[0], &vertexList[vertexList.length()]); std::vector<int> vtxCreaseIndices(&vtxIds[0], &vtxIds[vtxIds.length()]); std::vector<double> vtxCreases(&vtxCreaseData[0], &vtxCreaseData[vtxCreaseData.length()]); std::vector<double> edgeCreases(&edgeCreaseData[0], &edgeCreaseData[edgeCreaseData.length()]); // Edge crease index is stored as pairs of vertex ids int nEdgeIds = edgeIds.length(); std::vector<int> edgeCreaseIndices; edgeCreaseIndices.resize(nEdgeIds*2); for (int i = 0; i < nEdgeIds; ++i) { int2 vertices; status = meshFn.getEdgeVertices(edgeIds[i], vertices); if (status.error()) { status.perror("ERROR can't get creased edge vertices"); continue; } edgeCreaseIndices[i*2] = vertices[0]; edgeCreaseIndices[i*2+1] = vertices[1]; } // Convert attribute enums to HBR enums (this is why the enums need to match) // XXX use some sort of built-in transmorgification avoid assumption? HbrMeshUtil::SchemeType hbrScheme = (HbrMeshUtil::SchemeType) _scheme; OsdHbrMesh::InterpolateBoundaryMethod hbrInterpBoundary = (OsdHbrMesh::InterpolateBoundaryMethod) _interpBoundary; // Convert Maya mesh to internal HBR representation _hbrmesh = ConvertToHBR(meshFn.numVertices(), numIndices, faceIndices, vtxCreaseIndices, vtxCreases, std::vector<int>(), std::vector<float>(), edgeCreaseIndices, edgeCreases, hbrInterpBoundary, hbrScheme, true ); // add ptex indices to HBR // note: GL function can't be used in prepareForDraw API. _needsInitializeMesh = true; // Mesh topology data is up to date _meshTopoDirty = false; shader->setHbrMeshDirty(false); }
MStatus LSSolverNode::compute(const MPlug& plug, MDataBlock& data) { MStatus stat; if( plug == deformed) { MDataHandle tetWorldMatrixData = data.inputValue(tetWorldMatrix, &returnStatus); McheckErr(returnStatus, "Error getting tetWorldMatrix data handle\n"); MDataHandle restShapeData = data.inputValue(restShape, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle restVerticesData = data.inputValue(restVertices, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle restElementsData = data.inputValue(restElements, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle selectedConstraintVertsData = data.inputValue(selectedConstraintVerts, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle selectedForceVertsData = data.inputValue(selectedForceVerts, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle timeData = data.inputValue(time, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle outputMeshData = data.outputValue(deformed, &returnStatus); McheckErr(returnStatus, "Error getting outputMesh data handle\n"); MMatrix twmat = tetWorldMatrixData.asMatrix(); MObject rs = restShapeData.asMesh(); double t = timeData.asDouble(); MDataHandle poissonRatioData = data.inputValue(poissonRatio, &returnStatus); McheckErr(returnStatus, "Error getting poissonRatio data handle\n"); MDataHandle youngsModulusData = data.inputValue(youngsModulus, &returnStatus); McheckErr(returnStatus, "Error getting youngsmodulus data handle\n"); MDataHandle objectDensityData = data.inputValue(objectDensity, &returnStatus); McheckErr(returnStatus, "Error getting objectDensity data handle\n"); MDataHandle frictionData = data.inputValue(friction, &returnStatus); McheckErr(returnStatus, "Error getting friction data handle\n"); MDataHandle restitutionData = data.inputValue(restitution, &returnStatus); McheckErr(returnStatus, "Error getting restitution data handle\n"); MDataHandle dampingData = data.inputValue(damping, &returnStatus); McheckErr(returnStatus, "Error getting damping data handle\n"); MDataHandle userSuppliedDtData = data.inputValue(userSuppliedDt, &returnStatus); McheckErr(returnStatus, "Error getting user supplied dt data handle\n"); MDataHandle integrationTypeData = data.inputValue(integrationType, &returnStatus); McheckErr(returnStatus, "Error getting user integrationTypeData\n"); MDataHandle forceModelTypeData = data.inputValue(forceModelType, &returnStatus); McheckErr(returnStatus, "Error getting user forceModelTypeData\n"); MDataHandle forceApplicationTimeData = data.inputValue(forceApplicationTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceApplicationTime\n"); MDataHandle forceReleasedTimeData = data.inputValue(forceReleasedTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceReleasedTime\n"); MDataHandle forceIncrementTimeData = data.inputValue(forceIncrementTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceIncrementTime\n"); MDataHandle forceStartTimeData = data.inputValue(forceStartTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceStartTime\n"); MDataHandle forceStopTimeData = data.inputValue(forceStopTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceStopTime\n"); MDataHandle forceMagnitudeData = data.inputValue(forceMagnitude, &returnStatus); McheckErr(returnStatus, "Error getting user forceIdleTime\n"); MDataHandle useSuppliedForceData = data.inputValue(useSuppliedForce, &returnStatus); McheckErr(returnStatus, "Error getting user forceIdleTime\n"); MDataHandle useSuppliedConstraintsData = data.inputValue(useSuppliedConstraints, &returnStatus); McheckErr(returnStatus, "Error getting user forceIdleTime\n"); MDataHandle forceDirectionData = data.inputValue(forceDirection, &returnStatus); McheckErr(returnStatus, "Error getting user forceDirection\n"); MDataHandle contactKsData = data.inputValue(contactKs, &returnStatus); McheckErr(returnStatus, "Error getting user forceDirection\n"); MDataHandle contactKdData = data.inputValue(contactKd, &returnStatus); McheckErr(returnStatus, "Error getting user forceDirection\n"); MTime currentTime, maxTime; currentTime = MAnimControl::currentTime(); maxTime = MAnimControl::maxTime(); if (currentTime == MAnimControl::minTime()) { // retrive restVertices and restElements sTime=0; MFnDoubleArrayData restVertArrayData(restVerticesData.data()); MDoubleArray verts = restVertArrayData.array(); int vertArrayLen = verts.length(); double *vertArray = new double[vertArrayLen]; verts.get(vertArray); for(int v=0;v<vertArrayLen;v=v+3) { MPoint mpoint = MPoint(vertArray[v],vertArray[v+1],vertArray[v+2])*twmat; vertArray[v] = mpoint.x; vertArray[v+1] = mpoint.y; vertArray[v+2] = mpoint.z; } MFnIntArrayData restEleArrayData(restElementsData.data()); MIntArray ele = restEleArrayData.array(); int eleArrayLen = ele.length(); int *eleArray = new int[eleArrayLen]; ele.get(eleArray); MFnIntArrayData selectedConstraintVertsArrayData(selectedConstraintVertsData.data()); MIntArray sv = selectedConstraintVertsArrayData.array(); // building selectedConstraintVerts vector<int> selectedConstraintVertIndices; for (int i = 0 ; i < sv.length() ; i++) { selectedConstraintVertIndices.push_back(sv[i]); } MGlobal::displayInfo("!!!!!"); //std::string tmp=std::to_string((long double)selectedConstraintVertIndices.size()); //MGlobal::displayInfo(MString(tmp.c_str())); //std::cout<<currentConstriant<<" up"<<std::endl; for(int i=0;i<constraintIndex[currentConstriant].size();i++){ if(domainParentIndex[currentConstriant]==-1) selectedConstraintVertIndices.push_back(constraintIndex[currentConstriant][i]); //std::cout<<constraintIndex[currentConstriant][i]<<std::endl; } //std::cout<<currentConstriant<<" up"<<std::endl; /*for(int i=0;i<10;i++){ selectedConstraintVertIndices.push_back(i+1); }*/ MFnIntArrayData selectedForceVertsArrayData(selectedForceVertsData.data()); MIntArray sf = selectedForceVertsArrayData.array(); vector<int> selectedForceVertIndices; for (int i = 0 ; i < sf.length() ; i++) { selectedForceVertIndices.push_back(sf[i]); } // temporarily create force direction vector double *forceDir = forceDirectionData.asDouble3(); vector<double> dir; dir.push_back(forceDir[0]); dir.push_back(forceDir[1]);dir.push_back(forceDir[2]); prevDeformed = 0; double youngsModulusDouble = youngsModulusData.asDouble(); double poissonRatioDouble = poissonRatioData.asDouble(); double objectDensityDouble = objectDensityData.asDouble(); double frictionDouble = frictionData.asDouble(); double restitutionDouble = restitutionData.asDouble(); double dampingDouble = dampingData.asDouble(); double userSuppliedDtDouble = userSuppliedDtData.asDouble(); double forceMagnitudeDouble = forceMagnitudeData.asDouble(); int fAppT = forceApplicationTimeData.asInt(); int fReleasedT = forceReleasedTimeData.asInt(); int fIncT = forceIncrementTimeData.asInt(); int fStartT = forceStartTimeData.asInt(); int fStopT = forceStopTimeData.asInt(); int integrationTypeInt = integrationTypeData.asShort(); int forceModelTypeInt = forceModelTypeData.asShort(); bool useSuppliedForceBool = useSuppliedForceData.asBool(); bool useSuppliedConstraintsBool = useSuppliedConstraintsData.asBool(); double contactKs = contactKsData.asDouble(); double contactKd = contactKdData.asDouble(); if( sm) { delete sm; } sm = new SoftBodySim(youngsModulusDouble,poissonRatioDouble,objectDensityDouble, frictionDouble,restitutionDouble,dampingDouble, eleArrayLen, eleArray, vertArrayLen, vertArray,integrationTypeInt,forceModelTypeInt); sm->setContactAttributes(contactKs,contactKd); if (useSuppliedConstraintsBool) sm->initialize("",userSuppliedDtDouble, selectedConstraintVertIndices); else { vector<int> empty; sm->initialize("",userSuppliedDtDouble, empty); } if (useSuppliedForceBool) sm->setUserForceAttributes(forceMagnitudeDouble, dir,selectedForceVertIndices,fAppT,fReleasedT,fIncT,fStartT,fStopT); std::vector<int> childList=fdg.GetDomainChild(currentConstriant); if(childList.size()!=0){//not the root for(int i=0;i<childList.size();i++){ int childIndex=-1; for(int j=0;j<fdomain_list.size();j++){ if(fdomain_list[j]->index==childList[i]){ childIndex=j; } }//j glm::dvec3 oldPos=glm::dvec3(0,0,0); for(int j=0;j<parentConstraintIndex[childIndex].size();j++){ int index=3*parentConstraintIndex[childIndex][j]; oldPos.x+=sm->m_vertices[index]; oldPos.y+=sm->m_vertices[index+1]; oldPos.z+=sm->m_vertices[index+2]; } oldPos=oldPos*(1.0/parentConstraintIndex[childIndex].size()); parentLastPosOld[childIndex]=oldPos; parentLastPosNew[childIndex]=oldPos; }//i } domainID=currentConstriant; currentConstriant++; if(currentConstriant==fdomain_list.size()) currentConstriant=0; } else { std::vector<int> childList=fdg.GetDomainChild(domainID); if(childList.size()!=0){//not the root for(int i=0;i<childList.size();i++){ int childIndex=-1; for(int j=0;j<fdomain_list.size();j++){ if(fdomain_list[j]->index==childList[i]){ childIndex=j; } }//j glm::dvec3 newPos=glm::dvec3(0,0,0); for(int j=0;j<parentConstraintIndex[childIndex].size();j++){ int index=3*parentConstraintIndex[childIndex][j]; newPos.x+=sm->m_vertices[index]; newPos.y+=sm->m_vertices[index+1]; newPos.z+=sm->m_vertices[index+2]; } //std::cout<<newPos.x<<","<<newPos.y<<","<<newPos.z<<std::endl; newPos=newPos*(1.0/parentConstraintIndex[childIndex].size()); parentLastPosOld[childIndex]=parentLastPosNew[childIndex]; parentLastPosNew[childIndex]=newPos; }//i } //update the parents' fixed point moving distance std::vector<float> pos; int num=0; if(domainParentIndex[domainID]!=-1){//has parent for(int i=0;i<constraintIndex[domainID].size();i++){ int index=3*constraintIndex[domainID][i]; pos.push_back(sm->m_vertices[index]); pos.push_back(sm->m_vertices[index+1]); pos.push_back(sm->m_vertices[index+2]); } } sm->update(sTime); sTime++; if(domainParentIndex[domainID]!=-1){//has parent //std::cout<<sm->numOfVertices<<std::endl; for(int i=0;i<constraintIndex[domainID].size();i++){ int index=3*constraintIndex[domainID][i]; if(index>3*sm->numOfVertices) std::cout<<index-3*sm->numOfVertices<<"big "<<currentConstriant<<std::endl; glm::dvec3 movePos=parentLastPosNew[domainID]-parentLastPosOld[domainID]; //std::cout<<sm->m_vertices[index]<<","<<sm->m_vertices[index+1]<<","<<sm->m_vertices[index+2]<<std::endl; sm->m_vertices[index]=pos[num++]+movePos.x; sm->m_vertices[index+1]=pos[num++]+movePos.y; sm->m_vertices[index+2]=pos[num++]+movePos.z; //std::cout<<sm->m_vertices[index]<<","<<sm->m_vertices[index+1]<<","<<sm->m_vertices[index+2]<<"end"<<std::endl; //std::cout<<constraintIndex[domainID][i]<<std::endl; } } } MFnMesh surfFn(rs,&stat); McheckErr( stat, "compute - MFnMesh error" ); MFnMeshData ouputMeshDataCreator; MObject oMesh = ouputMeshDataCreator.create(&stat); buildOutputMesh(surfFn, sm->m_vertices,oMesh); outputMeshData.set(oMesh); data.setClean(plug); } else stat = MS::kUnknownParameter; return stat; }
void SubdivUserData::Populate(MObject mesh) { MStatus s; MFnMesh meshFn(mesh); MIntArray vertexCount, vertexList; meshFn.getVertices(vertexCount, vertexList); MUintArray edgeIds; MDoubleArray edgeCreaseData; meshFn.getCreaseEdges(edgeIds, edgeCreaseData); MUintArray vtxIds; MDoubleArray vtxCreaseData; meshFn.getCreaseVertices(vtxIds, vtxCreaseData ); short level = 1; FindAttribute(meshFn, "smoothLevel", &level); if(level < 1) level = 1; short interpBoundary = 0; FindAttribute(meshFn, "boundaryRule", &interpBoundary); if(CompareArray(_vertexList, vertexList) && CompareArray(_edgeIds, edgeIds) && CompareArray(_edgeCreaseData, edgeCreaseData) && CompareArray(_vtxIds, vtxIds) && CompareArray(_vtxCreaseData, vtxCreaseData) && _level == level && _interpBoundary == interpBoundary) { return; } // update topology _vertexList = vertexList; _edgeIds = edgeIds; _edgeCreaseData = edgeCreaseData; _vtxIds = vtxIds; _vtxCreaseData = vtxCreaseData; _level = level; _interpBoundary = interpBoundary; if(_loop){ MIntArray triangleCounts; meshFn.getTriangles(triangleCounts, vertexList); int numTriangles = vertexList.length()/3; vertexCount.clear(); for(int i = 0; i < numTriangles; ++i){ vertexCount.append(3); } } // XXX redundant copy... replace _vertexList with numIndices, etc // create Osd mesh std::vector<int> numIndices, faceIndices, edgeCreaseIndices, vtxCreaseIndices; std::vector<float> edgeCreases, vtxCreases; numIndices.resize(vertexCount.length()); faceIndices.resize(vertexList.length()); for(int i = 0; i < (int)vertexCount.length(); ++i) numIndices[i] = vertexCount[i]; for(int i = 0; i < (int)vertexList.length(); ++i) faceIndices[i] = vertexList[i]; vtxCreaseIndices.resize(vtxIds.length()); for(int i = 0; i < (int)vtxIds.length(); ++i) vtxCreaseIndices[i] = vtxIds[i]; vtxCreases.resize(vtxCreaseData.length()); for(int i = 0; i < (int)vtxCreaseData.length(); ++i) vtxCreases[i] = (float)vtxCreaseData[i]; edgeCreases.resize(edgeCreaseData.length()); for(int i = 0; i < (int)edgeCreaseData.length(); ++i) edgeCreases[i] = (float)edgeCreaseData[i]; // edge crease index is stored as pair of <face id> <edge localid> ... int nEdgeIds = edgeIds.length(); edgeCreaseIndices.resize(nEdgeIds*2); for(int i = 0; i < nEdgeIds; ++i){ int2 vertices; if (meshFn.getEdgeVertices(edgeIds[i], vertices) != MS::kSuccess) { s.perror("ERROR can't get creased edge vertices"); continue; } edgeCreaseIndices[i*2] = vertices[0]; edgeCreaseIndices[i*2+1] = vertices[1]; } OpenSubdiv::OsdHbrMesh *hbrMesh = ConvertToHBR(meshFn.numVertices(), numIndices, faceIndices, vtxCreaseIndices, vtxCreases, std::vector<int>(), std::vector<float>(), edgeCreaseIndices, edgeCreases, interpBoundary, _loop); int kernel = OpenSubdiv::OsdKernelDispatcher::kCPU; if (OpenSubdiv::OsdKernelDispatcher::HasKernelType(OpenSubdiv::OsdKernelDispatcher::kOPENMP)) { kernel = OpenSubdiv::OsdKernelDispatcher::kOPENMP; } _osdmesh->Create(hbrMesh, level, kernel); delete hbrMesh; // create vertex buffer if (_vertexBuffer) { delete _vertexBuffer; } _vertexBuffer = _osdmesh->InitializeVertexBuffer(6 /* position + normal */); // create element array buffer if (_elementArrayBuffer) delete _elementArrayBuffer; _elementArrayBuffer = _osdmesh->CreateElementArrayBuffer(level); _cachedTotal = -1; UpdatePoints(mesh); }
void OsdMeshData::populateIfNeeded(int lv, int scheme, int kernel) { MStatus s; MFnMesh meshFn(_mesh, &s); if (s != MS::kSuccess) return; if (lv < 1) lv =1; MIntArray vertexCount, vertexList; meshFn.getVertices(vertexCount, vertexList); MUintArray edgeIds; MDoubleArray edgeCreaseData; meshFn.getCreaseEdges(edgeIds, edgeCreaseData); MUintArray vtxIds; MDoubleArray vtxCreaseData; meshFn.getCreaseVertices(vtxIds, vtxCreaseData ); if (vertexCount.length() == 0) return; short interpBoundary = 0; FindAttribute(meshFn, "boundaryRule", &interpBoundary); if(CompareArray(_vertexList, vertexList) && CompareArray(_edgeIds, edgeIds) && CompareArray(_edgeCreaseData, edgeCreaseData) && CompareArray(_vtxIds, vtxIds) && CompareArray(_vtxCreaseData, vtxCreaseData) && _interpBoundary == interpBoundary && _scheme == scheme && _kernel == kernel && _maxlevel >= lv) { if(_level != lv) { _level = lv; _needsInitializeIndexBuffer = true; } return; } // printf("Populate %s, level = %d < %d\n", meshFn.name().asChar(), lv, _level); // update topology _vertexList = vertexList; _edgeIds = edgeIds; _edgeCreaseData = edgeCreaseData; _vtxIds = vtxIds; _vtxCreaseData = vtxCreaseData; _maxlevel = lv; _level = lv; _interpBoundary = interpBoundary; _scheme = scheme; _kernel = kernel; std::vector<int> numIndices, faceIndices, edgeCreaseIndices, vtxCreaseIndices; std::vector<float> edgeCreases, vtxCreases; numIndices.resize(vertexCount.length()); faceIndices.resize(vertexList.length()); for(int i = 0; i < (int)vertexCount.length(); ++i) numIndices[i] = vertexCount[i]; for(int i = 0; i < (int)vertexList.length(); ++i) faceIndices[i] = vertexList[i]; vtxCreaseIndices.resize(vtxIds.length()); for(int i = 0; i < (int)vtxIds.length(); ++i) vtxCreaseIndices[i] = vtxIds[i]; vtxCreases.resize(vtxCreaseData.length()); for(int i = 0; i < (int)vtxCreaseData.length(); ++i) vtxCreases[i] = (float)vtxCreaseData[i]; edgeCreases.resize(edgeCreaseData.length()); for(int i = 0; i < (int)edgeCreaseData.length(); ++i) edgeCreases[i] = (float)edgeCreaseData[i]; // edge crease index is stored as pair of <face id> <edge localid> ... int nEdgeIds = edgeIds.length(); edgeCreaseIndices.resize(nEdgeIds*2); for(int i = 0; i < nEdgeIds; ++i){ int2 vertices; if (meshFn.getEdgeVertices(edgeIds[i], vertices) != MS::kSuccess) { s.perror("ERROR can't get creased edge vertices"); continue; } edgeCreaseIndices[i*2] = vertices[0]; edgeCreaseIndices[i*2+1] = vertices[1]; } _hbrmesh = ConvertToHBR(meshFn.numVertices(), numIndices, faceIndices, vtxCreaseIndices, vtxCreases, std::vector<int>(), std::vector<float>(), edgeCreaseIndices, edgeCreases, interpBoundary, scheme); // GL function can't be used in prepareForDraw API. _needsInitializeOsd = true; }
MStatus LSSolverNode::compute(const MPlug& plug, MDataBlock& data) { MStatus stat; if( plug == deformed) { MDataHandle tetWorldMatrixData = data.inputValue(tetWorldMatrix, &returnStatus); McheckErr(returnStatus, "Error getting tetWorldMatrix data handle\n"); MDataHandle restShapeData = data.inputValue(restShape, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle restVerticesData = data.inputValue(restVertices, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle restElementsData = data.inputValue(restElements, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle selectedConstraintVertsData = data.inputValue(selectedConstraintVerts, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle selectedForceVertsData = data.inputValue(selectedForceVerts, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle timeData = data.inputValue(time, &returnStatus); McheckErr(returnStatus, "Error getting step data handle\n"); MDataHandle outputMeshData = data.outputValue(deformed, &returnStatus); McheckErr(returnStatus, "Error getting outputMesh data handle\n"); MMatrix twmat = tetWorldMatrixData.asMatrix(); MObject rs = restShapeData.asMesh(); double t = timeData.asDouble(); MDataHandle poissonRatioData = data.inputValue(poissonRatio, &returnStatus); McheckErr(returnStatus, "Error getting poissonRatio data handle\n"); MDataHandle youngsModulusData = data.inputValue(youngsModulus, &returnStatus); McheckErr(returnStatus, "Error getting youngsmodulus data handle\n"); MDataHandle objectDensityData = data.inputValue(objectDensity, &returnStatus); McheckErr(returnStatus, "Error getting objectDensity data handle\n"); MDataHandle frictionData = data.inputValue(friction, &returnStatus); McheckErr(returnStatus, "Error getting friction data handle\n"); MDataHandle restitutionData = data.inputValue(restitution, &returnStatus); McheckErr(returnStatus, "Error getting restitution data handle\n"); MDataHandle dampingData = data.inputValue(damping, &returnStatus); McheckErr(returnStatus, "Error getting damping data handle\n"); MDataHandle userSuppliedDtData = data.inputValue(userSuppliedDt, &returnStatus); McheckErr(returnStatus, "Error getting user supplied dt data handle\n"); MDataHandle integrationTypeData = data.inputValue(integrationType, &returnStatus); McheckErr(returnStatus, "Error getting user integrationTypeData\n"); MDataHandle forceModelTypeData = data.inputValue(forceModelType, &returnStatus); McheckErr(returnStatus, "Error getting user forceModelTypeData\n"); MDataHandle forceApplicationTimeData = data.inputValue(forceApplicationTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceApplicationTime\n"); MDataHandle forceReleasedTimeData = data.inputValue(forceReleasedTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceReleasedTime\n"); MDataHandle forceIncrementTimeData = data.inputValue(forceIncrementTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceIncrementTime\n"); MDataHandle forceStartTimeData = data.inputValue(forceStartTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceStartTime\n"); MDataHandle forceStopTimeData = data.inputValue(forceStopTime, &returnStatus); McheckErr(returnStatus, "Error getting user forceStopTime\n"); MDataHandle forceMagnitudeData = data.inputValue(forceMagnitude, &returnStatus); McheckErr(returnStatus, "Error getting user forceIdleTime\n"); MDataHandle useSuppliedForceData = data.inputValue(useSuppliedForce, &returnStatus); McheckErr(returnStatus, "Error getting user forceIdleTime\n"); MDataHandle useSuppliedConstraintsData = data.inputValue(useSuppliedConstraints, &returnStatus); McheckErr(returnStatus, "Error getting user forceIdleTime\n"); MDataHandle forceDirectionData = data.inputValue(forceDirection, &returnStatus); McheckErr(returnStatus, "Error getting user forceDirection\n"); MDataHandle contactKsData = data.inputValue(contactKs, &returnStatus); McheckErr(returnStatus, "Error getting user forceDirection\n"); MDataHandle contactKdData = data.inputValue(contactKd, &returnStatus); McheckErr(returnStatus, "Error getting user forceDirection\n"); MTime currentTime, maxTime; currentTime = MAnimControl::currentTime(); maxTime = MAnimControl::maxTime(); if (currentTime == MAnimControl::minTime()) { // retrive restVertices and restElements MFnDoubleArrayData restVertArrayData(restVerticesData.data()); MDoubleArray verts = restVertArrayData.array(); int vertArrayLen = verts.length(); double *vertArray = new double[vertArrayLen]; verts.get(vertArray); for(int v=0;v<vertArrayLen;v=v+3) { MPoint mpoint = MPoint(vertArray[v],vertArray[v+1],vertArray[v+2])*twmat; vertArray[v] = mpoint.x; vertArray[v+1] = mpoint.y; vertArray[v+2] = mpoint.z; } MFnIntArrayData restEleArrayData(restElementsData.data()); MIntArray ele = restEleArrayData.array(); int eleArrayLen = ele.length(); int *eleArray = new int[eleArrayLen]; ele.get(eleArray); MFnIntArrayData selectedConstraintVertsArrayData(selectedConstraintVertsData.data()); MIntArray sv = selectedConstraintVertsArrayData.array(); // building selectedConstraintVerts vector<int> selectedConstraintVertIndices; for (int i = 0 ; i < sv.length() ; i++) { selectedConstraintVertIndices.push_back(sv[i]); } MFnIntArrayData selectedForceVertsArrayData(selectedForceVertsData.data()); MIntArray sf = selectedForceVertsArrayData.array(); vector<int> selectedForceVertIndices; for (int i = 0 ; i < sf.length() ; i++) { selectedForceVertIndices.push_back(sf[i]); } // temporarily create force direction vector double *forceDir = forceDirectionData.asDouble3(); vector<double> dir; dir.push_back(forceDir[0]); dir.push_back(forceDir[1]);dir.push_back(forceDir[2]); prevDeformed = 0; double youngsModulusDouble = youngsModulusData.asDouble(); double poissonRatioDouble = poissonRatioData.asDouble(); double objectDensityDouble = objectDensityData.asDouble(); double frictionDouble = frictionData.asDouble(); double restitutionDouble = restitutionData.asDouble(); double dampingDouble = dampingData.asDouble(); double userSuppliedDtDouble = userSuppliedDtData.asDouble(); double forceMagnitudeDouble = forceMagnitudeData.asDouble(); int fAppT = forceApplicationTimeData.asInt(); int fReleasedT = forceReleasedTimeData.asInt(); int fIncT = forceIncrementTimeData.asInt(); int fStartT = forceStartTimeData.asInt(); int fStopT = forceStopTimeData.asInt(); int integrationTypeInt = integrationTypeData.asShort(); int forceModelTypeInt = forceModelTypeData.asShort(); bool useSuppliedForceBool = useSuppliedForceData.asBool(); bool useSuppliedConstraintsBool = useSuppliedConstraintsData.asBool(); double contactKs = contactKsData.asDouble(); double contactKd = contactKdData.asDouble(); if( sm) { delete sm; } sm = new SoftBodySim(youngsModulusDouble,poissonRatioDouble,objectDensityDouble, frictionDouble,restitutionDouble,dampingDouble, eleArrayLen, eleArray, vertArrayLen, vertArray,integrationTypeInt,forceModelTypeInt); sm->setContactAttributes(contactKs,contactKd); if (useSuppliedConstraintsBool) sm->initialize("",userSuppliedDtDouble, selectedConstraintVertIndices); else { vector<int> empty; sm->initialize("",userSuppliedDtDouble, empty); } if (useSuppliedForceBool) sm->setUserForceAttributes(forceMagnitudeDouble, dir,selectedForceVertIndices,fAppT,fReleasedT,fIncT,fStartT,fStopT); } else { sm->update(); } MFnMesh surfFn(rs,&stat); McheckErr( stat, "compute - MFnMesh error" ); MFnMeshData ouputMeshDataCreator; MObject oMesh = ouputMeshDataCreator.create(&stat); buildOutputMesh(surfFn, sm->m_vertices,oMesh); outputMeshData.set(oMesh); data.setClean(plug); } else stat = MS::kUnknownParameter; return stat; }
MStatus puttyNode::deform( MDataBlock& block, MItGeometry& iter, const MMatrix& worldMatrix, unsigned int multiIndex) { // MGlobal::displayInfo("deform"); MStatus status = MS::kSuccess; ///////////////////////////////////////////////////////////////////////////////////////////////// // // get inputs // // get the node ready flag MDataHandle dh = block.inputValue(aScriptSourced,&status); SYS_ERROR_CHECK(status, "Error getting aScriptSourced data handle\n"); bool scriptSourced = dh.asBool(); if (!scriptSourced) return MS::kSuccess; dh = block.inputValue(aNodeReady,&status); SYS_ERROR_CHECK(status, "Error getting node ready data handle\n"); bool nodeReady = dh.asBool(); // if it's not ready, don't do anything if (!nodeReady) return MS::kSuccess; dh = block.inputValue(aDefSpace,&status); SYS_ERROR_CHECK(status, "Error getting defSpace data handle\n"); short defSpace = dh.asShort(); dh = block.inputValue(aDefWeights,&status); SYS_ERROR_CHECK(status, "Error getting defWeights data handle\n"); short defWeights = dh.asShort(); dh = block.inputValue(aDefEnvelope,&status); SYS_ERROR_CHECK(status, "Error getting defEnvelope data handle\n"); short defEnvelope = dh.asShort(); // get the command dh = block.inputValue(aCmdBaseName,&status); SYS_ERROR_CHECK(status, "Error getting aCmdBaseName handle\n"); MString script = dh.asString(); /* if (script == "") { status = MS::kFailure; USER_ERROR_CHECK(status, "no script provided!\n"); } */ ///////////////////////////////////////////////////////////////////////////////////////////////// // // build mel cmd string // // check if it's a valid cmd // get the envelope // double env = 1; if (defEnvelope == MSD_ENVELOPE_AUTO) { dh = block.inputValue(envelope,&status); SYS_ERROR_CHECK(status, "Error getting envelope data handle\n"); env = double(dh.asFloat()); // early stop 'cause there is nothing more to do if (env == 0.0) return MS::kSuccess; } // get the points, transform them into the right space if needed // int count = iter.count(); MVectorArray points(count); for ( ; !iter.isDone(); iter.next()) points[iter.index()] = iter.position(); if ( defSpace == MSD_SPACE_WORLD ) { for (int i = 0;i<count;i++) points[i] = MPoint(points[i]) * worldMatrix; } // get the weights // MDoubleArray weights; if ( defWeights == MSD_WEIGHTS_AUTO) { weights.setLength(count); for (int i = 0;i<count;i++) weights[i] = weightValue(block,multiIndex,i); } // get the object name and type // get the input geometry, traverse through the data handles MArrayDataHandle adh = block.outputArrayValue( input, &status ); SYS_ERROR_CHECK(status,"error getting input array data handle.\n"); status = adh.jumpToElement( multiIndex ); SYS_ERROR_CHECK(status, "input jumpToElement failed.\n"); // compound data MDataHandle cdh = adh.inputValue( &status ); SYS_ERROR_CHECK(status, "error getting input inputValue\n"); // input geometry child dh = cdh.child( inputGeom ); MObject dInputGeometry = dh.data(); // get the type MString geometryType = dInputGeometry.apiTypeStr(); // get the name // MFnDagNode dagFn( dInputGeometry, &status); // SYS_ERROR_CHECK(status, "error converting geometry obj to dag node\n"); // MString geometryName = dagFn.fullPathName(&status); // SYS_ERROR_CHECK(status, "error getting full path name \n"); // MString geometryType = ""; // MString geometryName = ""; ///////////////////////////////////////////////////////////////////////////////////////////////// // // set the current values on the temp plugs for the script to be picked up // // the position MObject thisNode = thisMObject(); MPlug currPlug(thisNode,aCurrPosition); MFnVectorArrayData vecD; MObject currObj = vecD.create(points,&status); currPlug.setValue(currObj); SYS_ERROR_CHECK(status, "error setting currPosPlug value\n"); // the weights currPlug =MPlug(thisNode,aCurrWeight); MFnDoubleArrayData dblD; currObj = dblD.create(weights,&status); currPlug.setValue(currObj); SYS_ERROR_CHECK(status, "error setting currWeightsPlug value\n"); // world matrix currPlug =MPlug(thisNode,aCurrWorldMatrix); MFnMatrixData matD; currObj = matD.create(worldMatrix,&status); currPlug.setValue(currObj); SYS_ERROR_CHECK(status, "error setting currWorldMatrixPlug value\n"); // the multi index currPlug =MPlug(thisNode,aCurrMultiIndex); currPlug.setValue(int(multiIndex)); SYS_ERROR_CHECK(status, "error setting currMultiIndexPlug value\n"); // geometry name/type // currPlug =MPlug(thisNode,aCurrGeometryName); // currPlug.setValue(geometryName); // SYS_ERROR_CHECK(status, "error setting aCurrGeometryName value\n"); currPlug =MPlug(thisNode,aCurrGeometryType); currPlug.setValue(geometryType); SYS_ERROR_CHECK(status, "error setting aCurrGeometryType value\n"); ///////////////////////////////////////////////////////////////////////////////////////////////// // // execute the mel script // MString melCmd = script+"(\"" +name()+"\","+count+")"; MCommandResult melResult; status = MGlobal::executeCommand(melCmd,melResult); // if the command did not work, then try to resource the script // (might have been that we were in a fresh scene and nothing was ready yet if (status != MS::kSuccess) { dh = block.inputValue(aScript,&status); SYS_ERROR_CHECK(status, "Error getting aCmdBaseName handle\n"); MString scriptFile = dh.asString(); // try to source the script MString cmd = "source \"" + scriptFile+"\""; MCommandResult melResult; status = MGlobal::executeCommand(cmd,melResult); // if successfull, retry the command if (!status.error()) { status = MGlobal::executeCommand(melCmd,melResult); } } USER_ERROR_CHECK(status, "Error executing mel command, please check the function you provided is valid, error free and has the appropriate parameters!"); // check the result type if ((melResult.resultType()) != (MCommandResult::kDoubleArray)) { USER_ERROR_CHECK(MS::kFailure, "result of mel command has wrong type, should be doubleArray (which will be interpreted as vectorArray)!"); } // get the result as a double array MDoubleArray newP; status = melResult.getResult(newP); USER_ERROR_CHECK(status, "Error getting result of mel command!"); int newCount = newP.length()/3; // size check if (newCount != count) { USER_ERROR_CHECK(MS::kFailure, "the size of the result does not match the size of the input!"); } // convert the double array into a vector array MPointArray newPoints(newCount); for(int i=0;i<newCount;i++) newPoints[i]=MPoint(newP[i*3],newP[i*3+1],newP[i*3+2]); ///////////////////////////////////////////////////////////////////////////////////////////////// // // interprete and apply the result // // do the envelope and weights if ((defEnvelope == MSD_ENVELOPE_AUTO)||((defWeights == MSD_WEIGHTS_AUTO))) { MDoubleArray envPP(count, env); if (defWeights == MSD_WEIGHTS_AUTO) { for (int i = 0;i<count;i++) envPP[i] *= weights[i]; } // linear interpolation between old and new points for (int i = 0;i<count;i++) newPoints[i] = (points[i] * (1-envPP[i])) + (newPoints[i] * envPP[i]); } // retransform the result if it was in world space if ( defSpace == MSD_SPACE_WORLD ) { MMatrix worldMatrixInv = worldMatrix.inverse(); for (int i = 0;i<count;i++) newPoints[i] *= worldMatrixInv; } // set the points iter.reset(); for ( ; !iter.isDone(); iter.next()) iter.setPosition(newPoints[iter.index()]); return status; }
MStatus AlembicCurves::Save(double time, unsigned int timeIndex, bool isFirstFrame) { ESS_PROFILE_SCOPE("AlembicCurves::Save"); if (this->accumRef.get() != 0) { accumRef->save(GetRef(), time); ++mNumSamples; return MStatus::kSuccess; } // access the geometry MFnNurbsCurve node(GetRef()); // save the metadata SaveMetaData(this); // save the attributes if (isFirstFrame) { Abc::OCompoundProperty cp; Abc::OCompoundProperty up; if (AttributesWriter::hasAnyAttr(node, *GetJob())) { cp = mSchema.getArbGeomParams(); up = mSchema.getUserProperties(); } mAttrs = AttributesWriterPtr( new AttributesWriter(cp, up, GetMyParent(), node, timeIndex, *GetJob()) ); } else { mAttrs->write(); } // prepare the bounding box Abc::Box3d bbox; // check if we have the global cache option const bool globalCache = GetJob()->GetOption(L"exportInGlobalSpace").asInt() > 0; Abc::M44f globalXfo; if (globalCache) { globalXfo = GetGlobalMatrix(GetRef()); } MPointArray positions; node.getCVs(positions); mPosVec.resize(positions.length()); for (unsigned int i = 0; i < positions.length(); i++) { const MPoint &outPos = positions[i]; Imath::V3f &inPos = mPosVec[i]; inPos.x = (float)outPos.x; inPos.y = (float)outPos.y; inPos.z = (float)outPos.z; if (globalCache) { globalXfo.multVecMatrix(inPos, inPos); } bbox.extendBy(inPos); } // store the positions to the samples mSample.setPositions(Abc::P3fArraySample(&mPosVec.front(), mPosVec.size())); mSample.setSelfBounds(bbox); if (mNumSamples == 0) { // knot vector! MDoubleArray knots; node.getKnots(knots); mKnotVec.resize(knots.length()); for (unsigned int i = 0; i < knots.length(); ++i) { mKnotVec[i] = (float)knots[i]; } mKnotVectorProperty.set(Abc::FloatArraySample(mKnotVec)); mNbVertices.push_back(node.numCVs()); mSample.setCurvesNumVertices(Abc::Int32ArraySample(mNbVertices)); if (node.form() == MFnNurbsCurve::kOpen) { mSample.setWrap(AbcG::kNonPeriodic); } else { mSample.setWrap(AbcG::kPeriodic); } if (node.degree() == 3) { mSample.setType(AbcG::kCubic); } else { mSample.setType(AbcG::kLinear); } MPlug widthPlug = node.findPlug("width"); if (!widthPlug.isNull()) { mRadiusVec.push_back(widthPlug.asFloat()); } else { mRadiusVec.push_back(1.0); } mRadiusProperty.set( Abc::FloatArraySample(&mRadiusVec.front(), mRadiusVec.size())); } // save the sample mSchema.set(mSample); mNumSamples++; return MStatus::kSuccess; }
// virtual bool MayaNurbsCurveWriter::writeNurbsCurveAttrs(const UsdTimeCode &usdTime, UsdGeomNurbsCurves &primSchema) { MStatus status = MS::kSuccess; // Write parent class attrs writeTransformAttrs(usdTime, primSchema); // Return if usdTime does not match if shape is animated if (usdTime.IsDefault() == isShapeAnimated() ) { // skip shape as the usdTime does not match if shape isAnimated value return true; } MFnDependencyNode fnDepNode(getDagPath().node(), &status); MString name = fnDepNode.name(); MFnNurbsCurve curveFn( getDagPath(), &status ); if (!status) { MGlobal::displayError("MFnNurbsCurve() failed for MayaNurbsCurveWriter"); return false; } // Get curve attrs ====== unsigned int numCurves = 1; // Assuming only 1 curve for now VtArray<int> curveOrder(numCurves); VtArray<int> curveVertexCounts(numCurves); VtArray<float> curveWidths(numCurves); VtArray<GfVec2d> ranges(numCurves); curveOrder[0] = curveFn.degree()+1; curveVertexCounts[0] = curveFn.numCVs(); TF_AXIOM(curveOrder[0] <= curveVertexCounts[0] ); curveWidths[0] = 1.0; // TODO: Retrieve from custom attr double mayaKnotDomainMin; double mayaKnotDomainMax; status = curveFn.getKnotDomain(mayaKnotDomainMin, mayaKnotDomainMax); TF_AXIOM(status == MS::kSuccess); ranges[0][0] = mayaKnotDomainMin; ranges[0][1] = mayaKnotDomainMax; MPointArray mayaCurveCVs; status = curveFn.getCVs(mayaCurveCVs, MSpace::kObject); TF_AXIOM(status == MS::kSuccess); VtArray<GfVec3f> points(mayaCurveCVs.length()); // all CVs batched together for (unsigned int i=0; i < mayaCurveCVs.length(); i++) { points[i].Set(mayaCurveCVs[i].x, mayaCurveCVs[i].y, mayaCurveCVs[i].z); } MDoubleArray mayaCurveKnots; status = curveFn.getKnots(mayaCurveKnots); TF_AXIOM(status == MS::kSuccess); VtArray<double> curveKnots(mayaCurveKnots.length()); // all knots batched together for (unsigned int i=0; i < mayaCurveKnots.length(); i++) { curveKnots[i] = mayaCurveKnots[i]; } // Gprim VtArray<GfVec3f> extent(2); UsdGeomCurves::ComputeExtent(points, curveWidths, &extent); primSchema.CreateExtentAttr().Set(extent, usdTime); // Curve primSchema.GetOrderAttr().Set(curveOrder); // not animatable primSchema.GetCurveVertexCountsAttr().Set(curveVertexCounts); // not animatable primSchema.GetWidthsAttr().Set(curveWidths); // not animatable primSchema.GetKnotsAttr().Set(curveKnots); // not animatable primSchema.GetRangesAttr().Set(ranges); // not animatable primSchema.GetPointsAttr().Set(points, usdTime); // CVs // TODO: Handle periodic and non-periodic cases return true; }
// the arrays being passed in are assumed to be empty void MayaNurbsSurfaceWriter::write() { MFnNurbsSurface nurbs(mDagPath); double startU, endU, startV, endV; nurbs.getKnotDomain(startU, endU, startV, endV); Alembic::AbcGeom::ONuPatchSchema::Sample samp; samp.setUOrder(nurbs.degreeU() + 1); samp.setVOrder(nurbs.degreeV() + 1); unsigned int numKnotsInU = nurbs.numKnotsInU(); std::vector<float> sampKnotsInU; // guard against a degenerative case if (numKnotsInU > 1) { MDoubleArray knotsInU; nurbs.getKnotsInU(knotsInU); // pad the start and end with a knot on each side, since thats what // most apps, like Houdini and Renderman want these two extra knots sampKnotsInU.reserve(numKnotsInU+2); // push_back a dummy value, we will set it below sampKnotsInU.push_back(0.0); for (unsigned int i = 0; i < numKnotsInU; i++) sampKnotsInU.push_back( static_cast<float>(knotsInU[i])); double k1 = sampKnotsInU[1]; double k2 = sampKnotsInU[2]; double klast_1 = sampKnotsInU[numKnotsInU]; double klast_2 = sampKnotsInU[numKnotsInU-1]; sampKnotsInU[0] = static_cast<float>(2.0 * k1 - k2); sampKnotsInU.push_back(static_cast<float>(2.0 * klast_1 - klast_2)); samp.setUKnot(Alembic::Abc::FloatArraySample(sampKnotsInU)); } unsigned int numKnotsInV = nurbs.numKnotsInV(); std::vector<float> sampKnotsInV; // do it for V if (numKnotsInV > 1) { MDoubleArray knotsInV; nurbs.getKnotsInV(knotsInV); // pad the start and end with a knot on each side, since thats what // most apps, like Houdini and Renderman want these two extra knots sampKnotsInV.reserve(numKnotsInV+2); // push_back a dummy value, we will set it below sampKnotsInV.push_back(0.0); for (unsigned int i = 0; i < numKnotsInV; i++) sampKnotsInV.push_back(static_cast<float>(knotsInV[i])); double k1 = sampKnotsInV[1]; double k2 = sampKnotsInV[2]; double klast_1 = sampKnotsInV[numKnotsInV]; double klast_2 = sampKnotsInV[numKnotsInV-1]; sampKnotsInV[0] = static_cast<float>(2.0 * k1 - k2); sampKnotsInV.push_back(static_cast<float>(2.0 * klast_1 - klast_2)); samp.setVKnot(Alembic::Abc::FloatArraySample(sampKnotsInV)); } // for closed and periodic we are saving duplicate information MPointArray cvArray; nurbs.getCVs(cvArray); unsigned int numCVs = cvArray.length(); int numCVsInU = nurbs.numCVsInU(); int numCVsInV = nurbs.numCVsInV(); samp.setNu(numCVsInU); samp.setNv(numCVsInV); std::vector<Alembic::Abc::V3f> sampPos; sampPos.reserve(numCVs); std::vector<float> sampPosWeights; sampPosWeights.reserve(numCVs); bool weightsOne = true; // Maya stores the data where v varies the fastest (v,u order) // so we need to pack the data differently u,v order // (v reversed to make clockwise???) for (int v = numCVsInV - 1; v > -1; v--) { for (int u = 0; u < numCVsInU; u++) { int index = u * numCVsInV + v; sampPos.push_back(Alembic::Abc::V3f( static_cast<float>(cvArray[index].x), static_cast<float>(cvArray[index].y), static_cast<float>(cvArray[index].z) )); if (fabs(cvArray[index].w - 1.0) > 1e-12) { weightsOne = false; } sampPosWeights.push_back(static_cast<float>(cvArray[index].w)); } } samp.setPositions(Alembic::Abc::V3fArraySample(sampPos)); if (!weightsOne) { samp.setPositionWeights(Alembic::Abc::FloatArraySample(sampPosWeights)); } if (!nurbs.isTrimmedSurface()) { mSchema.set(samp); return; } unsigned int numRegions = nurbs.numRegions(); // each boundary is a curvegroup, it can have multiple trim curve segments // A Maya's trimmed NURBS surface has multiple regions. // Inside a region, there are multiple boundaries. // There are one CCW outer boundary and optional CW inner boundaries. // Each boundary is a closed boundary and consists of multiple curves. // Alembic has the same semantic as RenderMan. // RenderMan's doc says: "The curves of a loop connect // in head-to-tail fashion and must be explicitly closed. " // A Maya boundary is equivalent to an Alembic/RenderMan loop std::vector<Alembic::Util::int32_t> trimNumCurves; std::vector<Alembic::Util::int32_t> trimNumPos; std::vector<Alembic::Util::int32_t> trimOrder; std::vector<float> trimKnot; std::vector<float> trimMin; std::vector<float> trimMax; std::vector<float> trimU; std::vector<float> trimV; std::vector<float> trimW; Alembic::Util::int32_t numLoops = 0; for (unsigned int i = 0; i < numRegions; i++) { MTrimBoundaryArray result; // if the 3rd argument is set to be true, return the 2D curve nurbs.getTrimBoundaries(result, i, true); unsigned int numBoundaries = result.length(); for (unsigned int j = 0; j < numBoundaries; j++) { MObjectArray boundary = result[j]; unsigned int numTrimCurve = boundary.length(); trimNumCurves.push_back(static_cast<Alembic::Util::int32_t>(numTrimCurve)); numLoops++; for (unsigned int k = 0; k < numTrimCurve; k++) { MObject curveObj = boundary[k]; if (curveObj.hasFn(MFn::kNurbsCurve)) { MFnNurbsCurve mFnCurve(curveObj); Alembic::Util::int32_t numCVs = mFnCurve.numCVs(); trimNumPos.push_back(numCVs); trimOrder.push_back(mFnCurve.degree()+1); double start, end; mFnCurve.getKnotDomain(start, end); trimMin.push_back(static_cast<float>(start)); trimMax.push_back(static_cast<float>(end)); MPointArray cvArray; mFnCurve.getCVs(cvArray); //append to curveGrp.cv vector double offsetV = startV+endV; for (Alembic::Util::int32_t l = 0; l < numCVs; l++) { trimU.push_back(static_cast<float>(cvArray[l].x)); // v' = maxV + minV - v // this is because we flipped v on the surface trimV.push_back( static_cast<float>(offsetV-cvArray[l].y)); trimW.push_back(static_cast<float>(cvArray[l].w)); } MDoubleArray knot; mFnCurve.getKnots(knot); unsigned int numKnots = knot.length(); // push_back a dummy value, we will set it below std::size_t totalNumKnots = trimKnot.size(); trimKnot.push_back(0.0); for (unsigned int l = 0; l < numKnots; l++) { trimKnot.push_back(static_cast<float>(knot[l])); } // for a knot sequence with multiple end knots, duplicate // the existing first and last knots once more. // for a knot sequence with uniform end knots, create their // the new knots offset at an interval equal to the existing // first and last knot intervals double k1 = trimKnot[totalNumKnots+1]; double k2 = trimKnot[totalNumKnots+2]; double klast_1 = trimKnot[trimKnot.size()-1]; double klast_2 = trimKnot[trimKnot.size()-2]; trimKnot[totalNumKnots] = static_cast<float>(2.0 * k1 - k2); trimKnot.push_back( static_cast<float>(2.0 * klast_1 - klast_2)); } } // for k } // for j } // for i samp.setTrimCurve(numLoops, Alembic::Abc::Int32ArraySample(trimNumCurves), Alembic::Abc::Int32ArraySample(trimNumPos), Alembic::Abc::Int32ArraySample(trimOrder), Alembic::Abc::FloatArraySample(trimKnot), Alembic::Abc::FloatArraySample(trimMin), Alembic::Abc::FloatArraySample(trimMax), Alembic::Abc::FloatArraySample(trimU), Alembic::Abc::FloatArraySample(trimV), Alembic::Abc::FloatArraySample(trimW)); mSchema.set(samp); }
void MayaMeshWriter::writeSubD( const Alembic::AbcGeom::OV2fGeomParam::Sample & iUVs) { MStatus status = MS::kSuccess; MFnMesh lMesh( mDagPath, &status ); if ( !status ) { MGlobal::displayError( "MFnMesh() failed for MayaMeshWriter" ); } std::vector<float> points; std::vector<Alembic::Util::int32_t> facePoints; std::vector<Alembic::Util::int32_t> pointCounts; fillTopology(points, facePoints, pointCounts); Alembic::AbcGeom::OSubDSchema::Sample samp( Alembic::AbcGeom::V3fArraySample((const Imath::V3f *)&points.front(), points.size() / 3), Alembic::Abc::Int32ArraySample(facePoints), Alembic::Abc::Int32ArraySample(pointCounts)); samp.setUVs( iUVs ); MPlug plug = lMesh.findPlug("faceVaryingInterpolateBoundary"); if (!plug.isNull()) samp.setFaceVaryingInterpolateBoundary(plug.asInt()); plug = lMesh.findPlug("interpolateBoundary"); if (!plug.isNull()) samp.setInterpolateBoundary(plug.asInt()); plug = lMesh.findPlug("faceVaryingPropagateCorners"); if (!plug.isNull()) samp.setFaceVaryingPropagateCorners(plug.asInt()); std::vector <Alembic::Util::int32_t> creaseIndices; std::vector <Alembic::Util::int32_t> creaseLengths; std::vector <float> creaseSharpness; std::vector <Alembic::Util::int32_t> cornerIndices; std::vector <float> cornerSharpness; MUintArray edgeIds; MDoubleArray creaseData; if (lMesh.getCreaseEdges(edgeIds, creaseData) == MS::kSuccess) { unsigned int numCreases = creaseData.length(); creaseIndices.resize(numCreases * 2); creaseLengths.resize(numCreases, 2); creaseSharpness.resize(numCreases); for (unsigned int i = 0; i < numCreases; ++i) { int verts[2]; lMesh.getEdgeVertices(edgeIds[i], verts); creaseIndices[2 * i] = verts[0]; creaseIndices[2 * i + 1] = verts[1]; creaseSharpness[i] = static_cast<float>(creaseData[i]); } samp.setCreaseIndices(Alembic::Abc::Int32ArraySample(creaseIndices)); samp.setCreaseLengths(Alembic::Abc::Int32ArraySample(creaseLengths)); samp.setCreaseSharpnesses( Alembic::Abc::FloatArraySample(creaseSharpness)); } MUintArray cornerIds; MDoubleArray cornerData; if (lMesh.getCreaseVertices(cornerIds, cornerData) == MS::kSuccess) { unsigned int numCorners = cornerIds.length(); cornerIndices.resize(numCorners); cornerSharpness.resize(numCorners); for (unsigned int i = 0; i < numCorners; ++i) { cornerIndices[i] = cornerIds[i]; cornerSharpness[i] = static_cast<float>(cornerData[i]); } samp.setCornerSharpnesses( Alembic::Abc::FloatArraySample(cornerSharpness)); samp.setCornerIndices( Alembic::Abc::Int32ArraySample(cornerIndices)); } #if MAYA_API_VERSION >= 201100 MUintArray holes = lMesh.getInvisibleFaces(); unsigned int numHoles = holes.length(); std::vector <Alembic::Util::int32_t> holeIndices(numHoles); for (unsigned int i = 0; i < numHoles; ++i) { holeIndices[i] = holes[i]; } if (!holeIndices.empty()) { samp.setHoles(holeIndices); } #endif mSubDSchema.set(samp); writeColor(); writeUVSets(); }
void MayaNurbsCurveWriter::write() { Alembic::AbcGeom::OCurvesSchema::Sample samp; samp.setBasis(Alembic::AbcGeom::kBsplineBasis); MStatus stat; mCVCount = 0; // if inheritTransform is on and the curve group is animated, // bake the cv positions in the world space MMatrix exclusiveMatrixInv = mRootDagPath.exclusiveMatrixInverse(&stat); std::size_t numCurves = 1; if (mIsCurveGrp) numCurves = mNurbsCurves.length(); std::vector<Alembic::Util::int32_t> nVertices(numCurves); std::vector<float> points; std::vector<float> width; std::vector<float> knots; std::vector<Alembic::Util::uint8_t> orders(numCurves); MMatrix transformMatrix; bool useConstWidth = false; MFnDependencyNode dep(mRootDagPath.transform()); MPlug constWidthPlug = dep.findPlug("width"); if (!constWidthPlug.isNull()) { useConstWidth = true; width.push_back(constWidthPlug.asFloat()); } for (unsigned int i = 0; i < numCurves; i++) { MFnNurbsCurve curve; if (mIsCurveGrp) { curve.setObject(mNurbsCurves[i]); MMatrix inclusiveMatrix = mNurbsCurves[i].inclusiveMatrix(&stat); transformMatrix = inclusiveMatrix*exclusiveMatrixInv; } else { curve.setObject(mRootDagPath.node()); } if (i == 0) { if (curve.form() == MFnNurbsCurve::kOpen) { samp.setWrap(Alembic::AbcGeom::kNonPeriodic); } else { samp.setWrap(Alembic::AbcGeom::kPeriodic); } if (curve.degree() == 3) { samp.setType(Alembic::AbcGeom::kCubic); } else if (curve.degree() == 1) { samp.setType(Alembic::AbcGeom::kLinear); } else { samp.setType(Alembic::AbcGeom::kVariableOrder); } } else { if (curve.form() == MFnNurbsCurve::kOpen) { samp.setWrap(Alembic::AbcGeom::kNonPeriodic); } if ((samp.getType() == Alembic::AbcGeom::kCubic && curve.degree() != 3) || (samp.getType() == Alembic::AbcGeom::kLinear && curve.degree() != 1)) { samp.setType(Alembic::AbcGeom::kVariableOrder); } } orders[i] = static_cast<Alembic::Util::uint8_t>(curve.degree() + 1); Alembic::Util::int32_t numCVs = curve.numCVs(&stat); MPointArray cvArray; stat = curve.getCVs(cvArray, MSpace::kObject); mCVCount += numCVs; nVertices[i] = numCVs; for (Alembic::Util::int32_t j = 0; j < numCVs; j++) { MPoint transformdPt; if (mIsCurveGrp) { transformdPt = cvArray[j]*transformMatrix; } else { transformdPt = cvArray[j]; } points.push_back(static_cast<float>(transformdPt.x)); points.push_back(static_cast<float>(transformdPt.y)); points.push_back(static_cast<float>(transformdPt.z)); } MDoubleArray knotsArray; curve.getKnots(knotsArray); knots.reserve(knotsArray.length() + 2); // need to add a knot to the start and end (M + 2N + 1) if (knotsArray.length() > 1) { unsigned int knotsLength = knotsArray.length(); if (knotsArray[0] == knotsArray[knotsLength - 1] || knotsArray[0] == knotsArray[1]) { knots.push_back(knotsArray[0]); } else { knots.push_back(2 * knotsArray[0] - knotsArray[1]); } for (unsigned int j = 0; j < knotsLength; ++j) { knots.push_back(knotsArray[j]); } if (knotsArray[0] == knotsArray[knotsLength - 1] || knotsArray[knotsLength - 1] == knotsArray[knotsLength - 2]) { knots.push_back(knotsArray[knotsLength - 1]); } else { knots.push_back(2 * knotsArray[knotsLength - 1] - knotsArray[knotsLength - 2]); } } // width MPlug widthPlug = curve.findPlug("width"); if (!useConstWidth && !widthPlug.isNull()) { MObject widthObj; MStatus status = widthPlug.getValue(widthObj); MFnDoubleArrayData fnDoubleArrayData(widthObj, &status); MDoubleArray doubleArrayData = fnDoubleArrayData.array(); Alembic::Util::int32_t arraySum = doubleArrayData.length(); if (arraySum == numCVs) { for (Alembic::Util::int32_t i = 0; i < arraySum; i++) { width.push_back(static_cast<float>(doubleArrayData[i])); } } else if (status == MS::kSuccess) { MString msg = "Curve "; msg += curve.partialPathName(); msg += " has incorrect size for the width vector."; msg += "\nUsing default constant width of 0.1."; MGlobal::displayWarning(msg); width.clear(); width.push_back(0.1f); useConstWidth = true; } else { width.push_back(widthPlug.asFloat()); useConstWidth = true; } } else if (!useConstWidth) { // pick a default value width.clear(); width.push_back(0.1f); useConstWidth = true; } } Alembic::AbcGeom::GeometryScope scope = Alembic::AbcGeom::kVertexScope; if (useConstWidth) scope = Alembic::AbcGeom::kConstantScope; samp.setCurvesNumVertices(Alembic::Abc::Int32ArraySample(nVertices)); samp.setPositions(Alembic::Abc::V3fArraySample( (const Imath::V3f *)&points.front(), points.size() / 3 )); samp.setWidths(Alembic::AbcGeom::OFloatGeomParam::Sample( Alembic::Abc::FloatArraySample(width), scope) ); if (samp.getType() == Alembic::AbcGeom::kVariableOrder) { samp.setOrders(Alembic::Abc::UcharArraySample(orders)); } if (!knots.empty()) { samp.setKnots(Alembic::Abc::FloatArraySample(knots)); } mSchema.set(samp); }
void liqRibData::addAdditionalSurfaceParameters( MObject node ) { LIQDEBUGPRINTF("-> scanning for additional rman surface attributes \n"); MStatus status = MS::kSuccess; unsigned i; // work out how many elements there would be in a facevarying array if a mesh or subD // faceVaryingCount is a private data member if ( ( type() == MRT_Mesh ) || ( type() == MRT_Subdivision ) ) { faceVaryingCount = 0; MFnMesh fnMesh( node ); for ( uint pOn = 0; pOn < fnMesh.numPolygons(); pOn++ ) { faceVaryingCount += fnMesh.polygonVertexCount( pOn ); } } // find how many additional MFnDependencyNode nodeFn( node ); // find the attributes MStringArray floatAttributesFound = findAttributesByPrefix( "rmanF", nodeFn ); MStringArray pointAttributesFound = findAttributesByPrefix( "rmanP", nodeFn ); MStringArray vectorAttributesFound = findAttributesByPrefix( "rmanV", nodeFn ); MStringArray normalAttributesFound = findAttributesByPrefix( "rmanN", nodeFn ); MStringArray colorAttributesFound = findAttributesByPrefix( "rmanC", nodeFn ); MStringArray stringAttributesFound = findAttributesByPrefix( "rmanS", nodeFn ); if ( floatAttributesFound.length() > 0 ) { for ( i = 0; i < floatAttributesFound.length(); i++ ) { liqTokenPointer tokenPointerPair; MString cutString = floatAttributesFound[i].substring(5, floatAttributesFound[i].length()); MPlug fPlug = nodeFn.findPlug( floatAttributesFound[i] ); MObject plugObj; status = fPlug.getValue( plugObj ); if ( plugObj.apiType() == MFn::kDoubleArrayData ) { MFnDoubleArrayData fnDoubleArrayData( plugObj ); MDoubleArray doubleArrayData = fnDoubleArrayData.array( &status ); tokenPointerPair.set( cutString.asChar(), rFloat, ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false, true, false, doubleArrayData.length() ); for( unsigned int kk = 0; kk < doubleArrayData.length(); kk++ ) { tokenPointerPair.setTokenFloat( kk, doubleArrayData[kk] ); } if ( ( type() == MRT_NuCurve ) && ( cutString == MString( "width" ) ) ) { tokenPointerPair.setDetailType( rVarying); } else if ( ( ( type() == MRT_Mesh ) || ( type() == MRT_Subdivision ) ) && ( doubleArrayData.length() == faceVaryingCount ) ) { tokenPointerPair.setDetailType( rFaceVarying); } else { tokenPointerPair.setDetailType( rVertex ); } } else { if( fPlug.isArray() ) { int nbElts = fPlug.evaluateNumElements(); float floatValue; tokenPointerPair.set( cutString.asChar(), rFloat, ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false, false, true, // philippe :passed as uArray, otherwise it will think it is a single float nbElts ); MPlug elementPlug; for( unsigned int kk = 0; kk < nbElts; kk++ ) { elementPlug = fPlug.elementByPhysicalIndex(kk); elementPlug.getValue( floatValue ); tokenPointerPair.setTokenFloat( kk, floatValue ); } tokenPointerPair.setDetailType( rConstant ); } else { float floatValue; tokenPointerPair.set( cutString.asChar(), rFloat, ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false, false, false, 0 ); fPlug.getValue( floatValue ); tokenPointerPair.setTokenFloat( 0, floatValue ); tokenPointerPair.setDetailType( rConstant ); } } tokenPointerArray.push_back( tokenPointerPair ); } } if ( pointAttributesFound.length() > 0 ) { for ( i = 0; i < pointAttributesFound.length(); i++ ) { liqTokenPointer tokenPointerPair; MString cutString = pointAttributesFound[i].substring(5, pointAttributesFound[i].length()); MPlug pPlug = nodeFn.findPlug( pointAttributesFound[i] ); MObject plugObj; status = pPlug.getValue( plugObj ); if ( plugObj.apiType() == MFn::kPointArrayData ) { MFnPointArrayData fnPointArrayData( plugObj ); MPointArray pointArrayData = fnPointArrayData.array( &status ); tokenPointerPair.set( cutString.asChar(), rPoint, ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false, true, false, pointArrayData.length() ); if ( type() == MRT_Nurbs || type() == MRT_NuCurve ) { for ( int kk = 0; kk < pointArrayData.length(); kk++ ) { tokenPointerPair.setTokenFloat( kk, pointArrayData[kk].x, pointArrayData[kk].y, pointArrayData[kk].z, pointArrayData[kk].w ); } } else { for ( int kk = 0; kk < pointArrayData.length(); kk++ ) { tokenPointerPair.setTokenFloat( kk, pointArrayData[kk].x, pointArrayData[kk].y, pointArrayData[kk].z ); } } tokenPointerPair.setDetailType( rVertex ); } else { // Hmmmm float ? double ? float x, y, z; tokenPointerPair.set( cutString.asChar(), rPoint, ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false, false, false, 0 ); // Hmmm should check as for arrays if we are in nurbs mode : 4 values pPlug.child(0).getValue( x ); pPlug.child(1).getValue( y ); pPlug.child(2).getValue( z ); tokenPointerPair.setTokenFloat( 0, x, y, z ); tokenPointerPair.setDetailType( rConstant ); } tokenPointerArray.push_back( tokenPointerPair ); } } parseVectorAttributes( nodeFn, vectorAttributesFound, rVector ); parseVectorAttributes( nodeFn, normalAttributesFound, rNormal ); parseVectorAttributes( nodeFn, colorAttributesFound, rColor ); if ( stringAttributesFound.length() > 0 ) { for ( i = 0; i < stringAttributesFound.length(); i++ ) { liqTokenPointer tokenPointerPair; MString cutString = stringAttributesFound[i].substring(5, stringAttributesFound[i].length()); MPlug sPlug = nodeFn.findPlug( stringAttributesFound[i] ); MObject plugObj; status = sPlug.getValue( plugObj ); tokenPointerPair.set( cutString.asChar(), rString, ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false, false, false, 0 ); MString stringVal; sPlug.getValue( stringVal ); tokenPointerPair.setTokenString( 0, stringVal.asChar(), stringVal.length() ); tokenPointerPair.setDetailType( rConstant ); tokenPointerArray.push_back( tokenPointerPair ); } } }
IECore::DataPtr convert( const MCommandResult &result ) { MStatus s; switch (result.resultType()) { case MCommandResult::kInvalid: { // No result return 0; } case MCommandResult::kInt: { int i; s = result.getResult(i); assert(s); IECore::IntDataPtr data = new IECore::IntData(); data->writable() = i; return data; } case MCommandResult::kIntArray: { MIntArray v; s = result.getResult(v); assert(s); unsigned sz = v.length(); IECore::IntVectorDataPtr data = new IECore::IntVectorData(); data->writable().resize(sz); for (unsigned i = 0; i < sz; i++) { (data->writable())[i] = v[i]; } return data; } case MCommandResult::kDouble: { double d; s = result.getResult(d); assert(s); IECore::FloatDataPtr data = new IECore::FloatData(); data->writable() = static_cast<float>(d); return data; } case MCommandResult::kDoubleArray: { MDoubleArray v; s = result.getResult(v); assert(s); unsigned sz = v.length(); IECore::DoubleVectorDataPtr data = new IECore::DoubleVectorData(); data->writable().resize(sz); for (unsigned i = 0; i < sz; i++) { data->writable()[i] = v[i]; } return data; } case MCommandResult::kString: { MString str; s = result.getResult(str); assert(s); IECore::StringDataPtr data = new IECore::StringData(); data->writable() = std::string(str.asChar()); return data; } case MCommandResult::kStringArray: { MStringArray v; s = result.getResult(v); assert(s); unsigned sz = v.length(); IECore::StringVectorDataPtr data = new IECore::StringVectorData(); data->writable().resize(sz); for (unsigned i = 0; i < sz; i++) { data->writable()[i] = std::string(v[i].asChar()); } return data; } case MCommandResult::kVector: { MVector v; s = result.getResult(v); assert(s); IECore::V3fDataPtr data = new IECore::V3fData(); data->writable() = Imath::V3f(v.x, v.y, v.z); return data; } case MCommandResult::kVectorArray: { MVectorArray v; s = result.getResult(v); assert(s); unsigned sz = v.length(); IECore::V3fVectorDataPtr data = new IECore::V3fVectorData(); data->writable().resize(sz); for (unsigned i = 0; i < sz; i++) { data->writable()[i] = Imath::V3f(v[i].x, v[i].y, v[i].z); } return data; } case MCommandResult::kMatrix: { MDoubleArray v; int numRows, numColumns; s = result.getResult(v, numRows, numColumns); assert(s); if (numRows > 4 || numColumns > 4) { throw IECoreMaya::StatusException( MS::kFailure ); } IECore::M44fDataPtr data = new IECore::M44fData(); for (int i = 0; i < numColumns; i++) { for (int j = 0; j < numRows; j++) { (data->writable())[i][j] = v[i*numRows+j]; } } return data; } case MCommandResult::kMatrixArray: { return 0; } default: assert( false ); return 0; } }
// #### rebuildHbrMeshIfNeeded // // If the topology of the mesh changes, or any attributes that affect // how the mesh is computed the original HBR needs to be rebuilt // which will trigger a rebuild of the FAR mesh and subsequent buffers. // void OsdMeshData::rebuildHbrMeshIfNeeded(OpenSubdivShader *shader) { MStatus status = MS::kSuccess; if (!_meshTopoDirty && !shader->getHbrMeshDirty()) return; MFnMesh meshFn(_meshDagPath); // Cache attribute values _level = shader->getLevel(); _kernel = shader->getKernel(); _adaptive = shader->isAdaptive(); _uvSet = shader->getUVSet(); // Get Maya vertex topology and crease data MIntArray vertexCount; MIntArray vertexList; meshFn.getVertices(vertexCount, vertexList); MUintArray edgeIds; MDoubleArray edgeCreaseData; meshFn.getCreaseEdges(edgeIds, edgeCreaseData); MUintArray vtxIds; MDoubleArray vtxCreaseData; meshFn.getCreaseVertices(vtxIds, vtxCreaseData); if (vertexCount.length() == 0) return; // Copy Maya vectors into std::vectors std::vector<int> numIndices(&vertexCount[0], &vertexCount[vertexCount.length()]); std::vector<int> faceIndices(&vertexList[0], &vertexList[vertexList.length()]); std::vector<int> vtxCreaseIndices(&vtxIds[0], &vtxIds[vtxIds.length()]); std::vector<double> vtxCreases(&vtxCreaseData[0], &vtxCreaseData[vtxCreaseData.length()]); std::vector<double> edgeCreases(&edgeCreaseData[0], &edgeCreaseData[edgeCreaseData.length()]); // Edge crease index is stored as pairs of vertex ids int nEdgeIds = edgeIds.length(); std::vector<int> edgeCreaseIndices; edgeCreaseIndices.resize(nEdgeIds*2); for (int i = 0; i < nEdgeIds; ++i) { int2 vertices; status = meshFn.getEdgeVertices(edgeIds[i], vertices); if (status.error()) { MERROR(status, "OpenSubdivShader: Can't get edge vertices"); continue; } edgeCreaseIndices[i*2] = vertices[0]; edgeCreaseIndices[i*2+1] = vertices[1]; } // Convert attribute enums to HBR enums (this is why the enums need to match) HbrMeshUtil::SchemeType hbrScheme = (HbrMeshUtil::SchemeType) shader->getScheme(); OsdHbrMesh::InterpolateBoundaryMethod hbrInterpBoundary = (OsdHbrMesh::InterpolateBoundaryMethod) shader->getInterpolateBoundary(); OsdHbrMesh::InterpolateBoundaryMethod hbrInterpUVBoundary = (OsdHbrMesh::InterpolateBoundaryMethod) shader->getInterpolateUVBoundary(); // clear any existing face-varying descriptor if (_fvarDesc) { delete _fvarDesc; _fvarDesc = NULL; } // read UV data from maya and build per-face per-vert list of UVs for HBR face-varying data std::vector< float > uvList; status = buildUVList( meshFn, uvList ); if (! status.error()) { // Create face-varying data descriptor. The memory required for indices // and widths needs to stay alive as the HBR library only takes in the // pointers and assumes the client will maintain the memory so keep _fvarDesc // around as long as _hbrmesh is around. int fvarIndices[] = { 0, 1 }; int fvarWidths[] = { 1, 1 }; _fvarDesc = new FVarDataDesc( 2, fvarIndices, fvarWidths, 2, hbrInterpUVBoundary ); } if (_fvarDesc && hbrScheme != HbrMeshUtil::kCatmark) { MGlobal::displayWarning("Face-varying not yet supported for Loop/Bilinear, using Catmull-Clark"); hbrScheme = HbrMeshUtil::kCatmark; } // Convert Maya mesh to internal HBR representation _hbrmesh = ConvertToHBR(meshFn.numVertices(), numIndices, faceIndices, vtxCreaseIndices, vtxCreases, std::vector<int>(), std::vector<float>(), edgeCreaseIndices, edgeCreases, hbrInterpBoundary, hbrScheme, false, // no ptex _fvarDesc, _fvarDesc?&uvList:NULL); // yes fvar (if have UVs) // note: GL function can't be used in prepareForDraw API. _needsInitializeMesh = true; // Mesh topology data is up to date _meshTopoDirty = false; shader->setHbrMeshDirty(false); }