示例#1
0
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 );
	    }
	}
}
示例#2
0
文件: writeUtil.cpp 项目: MWDD/USD
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;
}
示例#3
0
// 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;
}
示例#4
0
// 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;
}
示例#5
0
// 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]);
  }
}
示例#7
0
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]);
	    }
	}
    }
}
示例#8
0
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;
}
示例#9
0
// 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;
}
示例#10
0
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;
}
示例#11
0
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;
}
示例#12
0
文件: common.cpp 项目: chadmv/cvwrap
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;
  }
}
示例#13
0
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;
}
示例#14
0
文件: common.cpp 项目: chadmv/cvwrap
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;
  }
}
示例#15
0
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;

}
示例#16
0
文件: common.cpp 项目: chadmv/cvwrap
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);
}
示例#17
0
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);
}
示例#18
0
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;
}
示例#22
0
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;
}
示例#24
0
// 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;
}
示例#25
0
// 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);
}
示例#26
0
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();
}
示例#27
0
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);
}
示例#28
0
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 );
    }
  }
}
示例#29
0
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;
	}
}
示例#30
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);
}