Example #1
0
MStatus HRBFSkinCluster::skinLB(MMatrixArray&  transforms,
	int numTransforms,
	MArrayDataHandle& weightListHandle,
	MItGeometry& iter) {
	MStatus returnStatus;

	// Iterate through each point in the geometry.
	//
	for (; !iter.isDone(); iter.next()) {
		MPoint pt = iter.position();
		MPoint skinned;
		// get the weights for this point -> must be dependent on the iterator somehow
		MArrayDataHandle weightsHandle = weightListHandle.inputValue().child(weights);
		// compute the skinning -> TODO: what's the order that the weights are given in? Appears to just be maya list relatives order.
		for (int i = 0; i<numTransforms; ++i) {
			if (MS::kSuccess == weightsHandle.jumpToElement(i)) {
				skinned += (pt * transforms[i]) * weightsHandle.inputValue().asDouble();
			}
		}

		// Set the final position.
		iter.setPosition(skinned);
		// advance the weight list handle
		weightListHandle.next();
	}
	return returnStatus;
}
Example #2
0
MStatus
identityNode::deform( MDataBlock& block,
                      MItGeometry& iter,
                      const MMatrix& /*m*/,
                      unsigned int multiIndex)
//
// Method: deform
//
// Description:   "Deforms" the point with an identity transformation
//
// Arguments:
//   block      : the datablock of the node
//   iter       : an iterator for the geometry to be deformed
//   m          : matrix to transform the point into world space
//   multiIndex : the index of the geometry that we are deforming
//
//
{
    MStatus returnStatus;
    
    // Iterate through each point in the geometry.
    //
    for ( ; !iter.isDone(); iter.next()) {
        MPoint pt = iter.position();
        
        // Perform some calculation on pt.
        // ...
        
        // Set the final position.
        iter.setPosition(pt);
    }
    return returnStatus;
}
Example #3
0
MStatus
offset::deform( MDataBlock& block,
				MItGeometry& iter,
				const MMatrix& /*m*/,
				unsigned int multiIndex)
//
// Method: deform
//
// Description:   Deform the point with a squash algorithm
//
// Arguments:
//   block		: the datablock of the node
//	 iter		: an iterator for the geometry to be deformed
//   m    		: matrix to transform the point into world space
//	 multiIndex : the index of the geometry that we are deforming
//
//
{
	MStatus returnStatus;
	
	// Envelope data from the base class.
	// The envelope is simply a scale factor.
	//
	MDataHandle envData = block.inputValue(envelope, &returnStatus);
	if (MS::kSuccess != returnStatus) return returnStatus;
	float env = envData.asFloat();	

	// Get the matrix which is used to define the direction and scale
	// of the offset.
	//
	MDataHandle matData = block.inputValue(offsetMatrix, &returnStatus );
	if (MS::kSuccess != returnStatus) return returnStatus;
	MMatrix omat = matData.asMatrix();
	MMatrix omatinv = omat.inverse();

	// iterate through each point in the geometry
	//
	for ( ; !iter.isDone(); iter.next()) {
		MPoint pt = iter.position();
		pt *= omatinv;
		
		float weight = weightValue(block,multiIndex,iter.index());
		
		// offset algorithm
		//
		pt.y = pt.y + env*weight;
		//
		// end of offset algorithm

		pt *= omat;
		iter.setPosition(pt);
	}
	return returnStatus;
}
Example #4
0
MStatus DucttapeMergeDeformer::deform( MDataBlock& block,
				MItGeometry& iter,
				const MMatrix& m,
				unsigned int multiIndex)
{
	MStatus status;
	MDataHandle envData = block.inputValue(envelope,&status);
	const float env = envData.asFloat();
	if(env < 1e-3f) return status;
	
	if(multiIndex == 0) {
		if(m_inputGeomIter) {
			delete m_inputGeomIter;
			m_inputGeomIter = NULL;
		}
		
		MDataHandle hmesh = block.inputValue(ainmesh);
		
		MItGeometry * aiter = new MItGeometry( hmesh, true, &status );
		if(!status) {
			AHelper::Info<int>("DucttapeMergeDeformer error no geom it", 0);
			return status;
		}
		
		m_inputGeomIter = aiter;
	}
	
	if(!m_inputGeomIter) return status;
	
	MPoint pd;
	MVector dv;
	for (; !iter.isDone(); iter.next()) {
		if(m_inputGeomIter->isDone() ) return status;
		
		float wei = env * weightValue(block, multiIndex, iter.index() );
		if(wei > 1e-3f) {
			pd = iter.position();
			dv = m_inputGeomIter->position() - pd;
			pd = pd + dv * wei;
			iter.setPosition(pd);
		}
		
		m_inputGeomIter->next();
	}
	return status;
}
Example #5
0
MStatus RippleDeformer::deform(MDataBlock& dataBlock,
								MItGeometry& itGeo,
								const MMatrix& localToWorldMatrix,
								unsigned int geomIndex)
{
	MStatus status;
	
	//get attriubtes as a datahandle
	float env = dataBlock.inputValue(envelope).asFloat();
	float amplitude = dataBlock.inputValue(aAmplitude).asFloat();
	float displace = dataBlock.inputValue(aDisplace).asFloat();
	//get the mesh 
	
	//retrieve the handle to the input 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);
	//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);
	if (oInputGeom.isNull())
	{
		return MS::kSuccess;
	}

	MFloatVectorArray normals;
	fnMesh.getVertexNormals(false, normals);

	MPoint pointPos;
	float weight;
	
	for (; !itGeo.isDone(); itGeo.next())
	{
		//get current point position
		pointPos = itGeo.position();
		weight = weightValue(dataBlock, geomIndex, itGeo.index());
		pointPos.x = pointPos.x + sin(itGeo.index() + displace) * amplitude * normals[itGeo.index()].x * weight * env;
		pointPos.y = pointPos.y + sin(itGeo.index() + displace) * amplitude * normals[itGeo.index()].y * weight * env;
		pointPos.z = pointPos.z + sin(itGeo.index() + displace) * amplitude * normals[itGeo.index()].z * weight * env;
		//setPosition
		itGeo.setPosition(pointPos);
	}	
	
	return MS::kSuccess;
}
Example #6
0
// COMPUTE ======================================
MStatus gear_curveCns::deform( MDataBlock& data, MItGeometry& iter, const MMatrix &mat, unsigned int mIndex )
{
    MStatus returnStatus;

	MArrayDataHandle adh = data.inputArrayValue( inputs );
	int deformer_count = adh.elementCount( &returnStatus );

	// Process
	while (! iter.isDone()){
		if (iter.index() < deformer_count){
			adh.jumpToElement(iter.index());
			MTransformationMatrix m(adh.inputValue().asMatrix() * mat.inverse());
			MVector v = m.getTranslation(MSpace::kWorld, &returnStatus );
			MPoint pt(v);
			iter.setPosition(pt);
		}
		iter.next();
	}
 
    return MS::kSuccess;
}
MStatus SwirlDeformer::deform( MDataBlock& block, MItGeometry &iter,
												const MMatrix &localToWorld, unsigned int geomIndex )
{
MStatus stat;
	
MDataHandle envData = block.inputValue( envelope );
float env = envData.asFloat();	
if( env == 0.0 ) // Deformer has no effect
	return MS::kSuccess;

MDataHandle matData = block.inputValue( deformSpace );
MMatrix mat = matData.asMatrix();
MMatrix invMat = mat.inverse();

MDataHandle startDistHnd = block.inputValue( startDist );
double startDist = startDistHnd.asDouble();	

MDataHandle endDistHnd = block.inputValue( endDist );
double endDist = endDistHnd.asDouble();	

MPoint pt;
float weight;
double dist;
double ang;
double cosAng;
double sinAng;
double x;
double distFactor;
for( iter.reset(); !iter.isDone(); iter.next() ) 
	{
	weight = weightValue( block, geomIndex, iter.index() );
	if( weight == 0.0f )
		continue;

	pt = iter.position();
	pt *= invMat;

	dist = sqrt( pt.x * pt.x + pt.z * pt.z );
	if( dist < startDist || dist > endDist )
		continue;

	distFactor = 1 - ((dist - startDist) / (endDist - startDist));

	ang = distFactor * M_PI * 2.0 * env * weight;
	if( ang == 0.0 )
		continue;

	cosAng = cos( ang );
	sinAng = sin( ang );
	x = pt.x * cosAng - pt.z * sinAng;
	pt.z = pt.x * sinAng + pt.z * cosAng;
	pt.x = x;

	pt *= mat;
	
	iter.setPosition( pt );
	}

return stat;
}
Example #8
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;

}
Example #9
0
MStatus nwayDeformerNode::deform( MDataBlock& data, MItGeometry& itGeo, const MMatrix &localToWorldMatrix, unsigned int mIndex )
{
//            clock_t clock_start=clock();

    MObject thisNode = thisMObject();
    MStatus status;
    MThreadUtils::syncNumOpenMPThreads();    // for OpenMP

    MArrayDataHandle hBlendMesh = data.inputArrayValue(aBlendMesh);
    short numIter = data.inputValue( aIteration ).asShort();
    short nblendMode = data.inputValue( aBlendMode ).asShort();
    short ntetMode = data.inputValue( aTetMode ).asShort();
    double visualisationMultiplier = data.inputValue(aVisualisationMultiplier).asDouble();
    bool visualiseEnergy = data.inputValue( aVisualiseEnergy ).asBool();
    bool nrotationCosistency = data.inputValue( aRotationConsistency ).asBool();
    if( nrotationCosistency != rotationCosistency) {
        numMesh = 0;
        rotationCosistency = nrotationCosistency;
    }
    MPointArray Mpts;
    itGeo.allPositions(Mpts);
    int nnumMesh = hBlendMesh.elementCount();
    int numPts = Mpts.length();
    int numTet = (int)tetList.size()/4;
    // initialisation
    if(tetMode != ntetMode) {
//        clock_t clock_start=clock();
        tetMode = ntetMode;
        numMesh = 0;
        // point list
        pts.resize(numPts);
        for(int i=0; i<numPts; i++) {
            pts[i] << Mpts[i].x, Mpts[i].y, Mpts[i].z;
        }
        std::vector<Matrix4d> P;
        getMeshData(data, input, inputGeom, mIndex, tetMode, pts, tetList, faceList, edgeList, vertexList, P);
        dim = removeDegenerate(tetMode, numPts, tetList, faceList, edgeList, vertexList, P);
        makeAdjacencyList(tetMode, tetList, edgeList, vertexList, adjacencyList);
        makeTetMatrix(tetMode, pts, tetList, faceList, edgeList, vertexList, P);
        // prepare ARAP solver
        numTet = (int)tetList.size()/4;
        PI.resize(numTet);
        for(int i=0; i<numTet; i++) {
            PI[i] = P[i].inverse().eval();
        }
        std::vector<double> tetWeight(numTet,1.0);
        std::vector< std::map<int,double> > constraint(0);
        //constraint[0][0]=1.0;
        isError = ARAPprecompute(PI, tetList, tetWeight, constraint, EPSILON, dim, constraintMat, solver);
//        MString es="Init timing: ";
//        double timing=(double)(clock()- clock_start)/CLOCKS_PER_SEC;
//        es += timing;
//        MGlobal::displayInfo(es);
    }
    if(isError>0) return MS::kFailure;
    // if blend mesh is added, compute log for each tet
    logR.resize(nnumMesh);
    logS.resize(nnumMesh);
    R.resize(nnumMesh);
    S.resize(nnumMesh);
    GL.resize(nnumMesh);
    logGL.resize(nnumMesh);
    quat.resize(nnumMesh);
    L.resize(nnumMesh);
    // for recomputation of parametrisation
    if(numMesh>nnumMesh || nblendMode != blendMode) {
        numMesh =0;
        blendMode = nblendMode;
    }
    for(int j=numMesh; j<nnumMesh; j++) {
        hBlendMesh.jumpToElement(j);
        MFnMesh blendMesh(hBlendMesh.inputValue().asMesh());
        MPointArray Mbpts;
        blendMesh.getPoints( Mbpts );
        if(numPts != Mbpts.length()) {
            MGlobal::displayInfo("incompatible mesh");
            return MS::kFailure;
        }
        std::vector<Vector3d> bpts(numPts);
        for(int i=0; i<numPts; i++) {
            bpts[i] << Mbpts[i].x, Mbpts[i].y, Mbpts[i].z;
        }
        std::vector<Matrix4d> Q(numTet);
        makeTetMatrix(tetMode, bpts, tetList, faceList, edgeList, vertexList, Q);
        logR[j].resize(numTet);
        logS[j].resize(numTet);
        R[j].resize(numTet);
        S[j].resize(numTet);
        GL[j].resize(numTet);
        logGL[j].resize(numTet);
        quat[j].resize(numTet);
        L[j].resize(numTet);
        for(int i=0; i<numTet; i++)  {
            Matrix4d aff=PI[i]*Q[i];
            GL[j][i]=aff.block(0,0,3,3);
            L[j][i]=transPart(aff);
            parametriseGL(GL[j][i], logS[j][i] ,R[j][i]);
        }
        if( blendMode == BM_LOG3) {
            for(int i=0; i<numTet; i++)
                logGL[j][i]=GL[j][i].log();
        } else if( blendMode == BM_SQL) {
            for(int i=0; i<numTet; i++) {
                S[j][i]=expSym(logS[j][i]);
                Quaternion<double> q(R[j][i].transpose());
                quat[j][i] << q.x(), q.y(), q.z(), q.w();
            }
        } else if( blendMode == BM_SlRL) {
            for(int i=0; i<numTet; i++) {
                S[j][i]=expSym(logS[j][i]);
            }
        }
        // traverse tetrahedra to compute continuous log of rotation
        if(rotationCosistency) {
            std::set<int> remain;
            std::queue<int> later;
            // load initial rotation from the attr
            Matrix3d initR;
            double angle = data.inputValue(aInitRotation).asDouble();
            initR << 0,M_PI * angle/180.0,0,  -M_PI * angle/180.0,0,0, 0,0,0;
            std::vector<Matrix3d> prevSO(numTet, initR);
            // create the adjacency graph to traverse
            for(int i=0; i<numTet; i++) {
                remain.insert(remain.end(),i);
            }
            while(!remain.empty()) {
                int next;
                if( !later.empty()) {
                    next = later.front();
                    later.pop();
                    remain.erase(next);
                } else {
                    next = *remain.begin();
                    remain.erase(remain.begin());
                }
                logR[j][next]=logSOc(R[j][next],prevSO[next]);
                for(int k=0; k<adjacencyList[next].size(); k++) {
                    int f=adjacencyList[next][k];
                    if(remain.erase(f)>0) {
                        prevSO[f]=logR[j][next];
                        later.push(f);
                    }
                }
            }
        } else {
            for(int i=0; i<numTet; i++)
                logR[j][i] = logSO(R[j][i]);
        }
    }
    numMesh=nnumMesh;
    if(numMesh == 0) return MS::kSuccess;

    // load weights
    std::vector<double> weight(numMesh);
    MArrayDataHandle hWeight = data.inputArrayValue(aWeight);
    if(hWeight.elementCount() != numMesh) {
        return MS::kSuccess;
    }
    for(int i=0; i<numMesh; i++) {
        hWeight.jumpToArrayElement(i);
        weight[i]=hWeight.inputValue().asDouble();
    }
    // compute ideal affine
    std::vector<Vector3d> new_pts(numPts);
    std::vector<Matrix4d> A(numTet);
    std::vector<Matrix3d> AR(numTet),AS(numTet);
    std::vector<Vector3d> AL(numTet);

    blendMatList(L, weight, AL);
    if(blendMode==BM_SRL) {
        blendMatList(logR, weight, AR);
        blendMatList(logS, weight, AS);
        #pragma omp parallel for
        for(int i=0; i<numTet; i++) {
            AR[i] = expSO(AR[i]);
            AS[i] = expSym(AS[i]);
        }
    } else if(blendMode == BM_LOG3) { // log
        blendMatList(logGL, weight, AR);
        #pragma omp parallel for
        for(int i=0; i<numTet; i++) {
            AR[i] = AR[i].exp();
            AS[i] = Matrix3d::Identity();
        }
    } else if(blendMode == BM_SQL) { // quaternion
        std::vector<Vector4d> Aq(numTet);
        blendMatLinList(S, weight, AS);
        blendQuatList(quat, weight, Aq);
        #pragma omp parallel for
        for(int i=0; i<numTet; i++) {
            Quaternion<double> Q(Aq[i]);
            AR[i] = Q.matrix().transpose();
        }
    } else if(blendMode == BM_SlRL) { // expSO+linear Sym
        blendMatList(logR, weight, AR);
        blendMatLinList(S, weight, AS);
        #pragma omp parallel for
        for(int i=0; i<numTet; i++) {
            AR[i] = expSO(AR[i]);
        }
    } else if(blendMode == BM_AFF) { // linear
        blendMatLinList(GL, weight, AR);
        for(int i=0; i<numTet; i++) {
            AS[i] = Matrix3d::Identity();
        }
    } else {
        return MS::kFailure;
    }

    MatrixXd G(dim+1,3),Sol;
    std::vector<double> tetEnergy(numTet);
    // iterate to determine vertices position
    for(int k=0; k<numIter; k++) {
        for(int i=0; i<numTet; i++) {
            A[i]=pad(AS[i]*AR[i],AL[i]);
        }
        // solve ARAP
        std::vector<Vector3d> constraintVector(0);
        std::vector<double> tetWeight(numTet,1.0);
        //constraintVector[0]=pts[0];
        ARAPSolve(A, PI, tetList, tetWeight, constraintVector, EPSILON, dim, constraintMat, solver, Sol);

        // set new vertices position
        for(int i=0; i<numPts; i++) {
            new_pts[i][0]=Sol(i,0);
            new_pts[i][1]=Sol(i,1);
            new_pts[i][2]=Sol(i,2);
        }
        // if iteration continues
        if(k+1<numIter || visualiseEnergy) {
            std::vector<Matrix4d> Q(numTet);
            makeTetMatrix(tetMode, new_pts, tetList, faceList, edgeList, vertexList, Q);
            Matrix3d S,R;
            #pragma omp parallel for
            for(int i=0; i<numTet; i++)  {
                polarHigham((PI[i]*Q[i]).block(0,0,3,3), S, AR[i]);
                tetEnergy[i] = (S-AS[i]).squaredNorm();
            }
        }
    }
    // set new vertex position
    for(int i=0; i<numPts; i++) {
        Mpts[i].x=Sol(i,0);
        Mpts[i].y=Sol(i,1);
        Mpts[i].z=Sol(i,2);
    }
    itGeo.setAllPositions(Mpts);

    // set vertex color according to ARAP energy
    if(visualiseEnergy) {
        std::vector<double> ptsEnergy;
        makePtsWeightList(tetMode, numPts, tetList, faceList, edgeList, vertexList, tetEnergy, ptsEnergy);
        //double max_energy = *std::max_element(ptsEnergy.begin(), ptsEnergy.end());
        outputAttr(data, aEnergy, ptsEnergy);
        for(int i=0; i<numPts; i++) {
            ptsEnergy[i] *= visualisationMultiplier;     //  or /= max_energy
        }
        visualise(data, outputGeom, ptsEnergy);
    }

//    MString es="Runtime timing: ";
//    double timing=(double)(clock()- clock_start)/CLOCKS_PER_SEC;
//    es += timing;
//    MGlobal::displayInfo(es);

    return MS::kSuccess;
}
Example #10
0
void TestDeformer::_deform_on_one_mesh(MDataBlock& data,
                                      MItGeometry& iter,
                                      const MMatrix& localToWorldMatrix,
                                      unsigned int mIndex,
                                      MObject &driver_mesh,
                                      const MDataHandle &envelopeHandle, MArrayDataHandle &vertMapArrayData, MPointArray &tempOutputPts)
{
    MStatus status;

    float env = envelopeHandle.asFloat();

    // use driver_meshVertIter to walk through the vertex of the current driver mesh
    MItMeshVertex driver_meshVertIter( driver_mesh, &status );
    CHECK_MSTATUS( status );

    int i = 0;
    iter.reset();
    while( !iter.isDone(&status) )
    {
        CHECK_MSTATUS( status );

        // get the weight
        float weight = weightValue( data, mIndex, iter.index() ); //painted weight
        float ww = weight * env;

        if ( fabs(ww) > FLT_EPSILON )//if ( ww != 0 )
        {
            __debug("%s(), vertMapArrayData.elementCount()=%d, iter.index()=%d",
                    __FUNCTION__, vertMapArrayData.elementCount(), iter.index());

            // get index_mapped to which the currrent vertex vI is mapped
            CHECK_MSTATUS(vertMapArrayData.jumpToElement(iter.index()));
            int index_mapped = vertMapArrayData.inputValue(&status).asInt();
            CHECK_MSTATUS( status );

            if( index_mapped >= 0 )
            {
                __debug("index_mapped=%d", index_mapped);

                int prevInt;
                CHECK_MSTATUS( driver_meshVertIter.setIndex(index_mapped, prevInt) );

                // vertex wrold position on driver mesh
                MPoint mappedPt = driver_meshVertIter.position( MSpace::kWorld, &status );
                CHECK_MSTATUS( status );
                // vertex wrold position on driven mesh
                MPoint iterPt = iter.position(MSpace::kObject, &status) * localToWorldMatrix;
                CHECK_MSTATUS( status );

                // use ww to interpolate between mappedPt and iterPt
                MPoint pt = iterPt + ((mappedPt - iterPt) * ww );
                pt = pt * localToWorldMatrix.inverse();

                /// put the deform points to tempOutputPts
                tempOutputPts[i] += pt;
            }
        }//if
        CHECK_MSTATUS(iter.next());
        ++i;
    }//while
}
Example #11
0
void TestDeformer::initVertMapping(MDataBlock& data,
                          MItGeometry& iter,
                          const MMatrix& localToWorldMatrix,
                          unsigned int mIndex)
{
    MStatus status;


    MArrayDataHandle vertMapOutArrayData = data.outputArrayValue( vert_map, &status );
    CHECK_MSTATUS( status );

    // use vertMapOutArrayBuilder to modify vertMapOutArrayData
    iter.reset();
    int count = iter.count();
    MArrayDataBuilder vertMapOutArrayBuilder( vert_map, count, &status );
    CHECK_MSTATUS( status );


    MPointArray allPts;// world vertex position of the driven mesh
    allPts.clear();

    // walk through the driven mesh
    /// copy MItGeometry's vertex to vertMapOutArrayData
    int i = 0;
    while( !iter.isDone(&status) )
    {
        CHECK_MSTATUS( status );

        MDataHandle initIndexDataHnd = vertMapOutArrayBuilder.addElement( i, &status );
        CHECK_MSTATUS( status );

        int negIndex = -1;

        initIndexDataHnd.setInt( negIndex );
        initIndexDataHnd.setClean();

        // append a vertex position(world coordination) to allPts
        CHECK_MSTATUS(allPts.append( iter.position() * localToWorldMatrix ));
        i = i+1;
        iter.next();
    }
    CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder ));




    /// Append more vertex from each driver mesh to vertMapOutArrayData
    MArrayDataHandle meshAttrHandle = data.inputArrayValue( driver_mesh, &status );
    CHECK_MSTATUS( status );

    int numMeshes = meshAttrHandle.elementCount();
    __debug("%s(), numMeshes=%d", __FUNCTION__, numMeshes);

    CHECK_MSTATUS(meshAttrHandle.jumpToElement(0));
    for( int meshIndex=0; meshIndex < numMeshes; ++meshIndex )
    {
        __debug("%s(), meshIndex=%d", __FUNCTION__, meshIndex);

        MDataHandle currentMesh = meshAttrHandle.inputValue(&status);
        CHECK_MSTATUS(status);

        MObject meshMobj = currentMesh.asMesh();
        __debug("%s(), meshMobj.apiTypeStr()=%s", __FUNCTION__, meshMobj.apiTypeStr());

        __debugMeshInfo(__FUNCTION__, meshMobj);
        {
            _initVertMapping_on_one_mesh(meshMobj, vertMapOutArrayBuilder, allPts);// Note: vertMapOutArrayBuilder is updated in this function!
            //CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder ));
        }

        if( !meshAttrHandle.next() )
        {
            break;
        }
    }// for (mesh
    CHECK_MSTATUS(vertMapOutArrayData.set( vertMapOutArrayBuilder ));



}
Example #12
0
MStatus TestDeformer::deform(MDataBlock& data,
                          MItGeometry& iter,
                          const MMatrix& localToWorldMatrix,
                          unsigned int mIndex)
{
    MStatus status;

    // get the current node state
    short initialized_mapping = data.inputValue( initialized_data, &status).asShort();
    CHECK_MSTATUS(status);
    __debug("%s(), initialized_mapping=%d, mIndex=%d", __FUNCTION__, initialized_mapping, mIndex);

    if( initialized_mapping == 1 )
    {
        initVertMapping(data, iter, localToWorldMatrix, mIndex);

        // set initialized_data to 2 automatically. User don't have to set it manully.
        MObject tObj  =  thisMObject();
        MPlug setInitMode = MPlug( tObj, initialized_data  );
        setInitMode.setShort( 2 );
        // and sync initialized_mapping from initialized_data
        // so, the code section:
        //     if (initialized_mapping == 2)
        //     {
        //         ...
        //     }
        // will be executed when this deform() function is called next time.
        initialized_mapping = data.inputValue( initialized_data, &status ).asShort();
        CHECK_MSTATUS(status);
    }

    if( initialized_mapping == 2 )
    {
        envelope = MPxDeformerNode::envelope;
        MDataHandle envelopeHandle = data.inputValue( envelope, &status );
        CHECK_MSTATUS( status );

        MArrayDataHandle vertMapArrayData  = data.inputArrayValue( vert_map, &status  );
        CHECK_MSTATUS( status );

        MArrayDataHandle meshAttrHandle = data.inputArrayValue( driver_mesh, &status );
        CHECK_MSTATUS( status );


        /// 1. init tempOutputPts to zero points
        MPointArray tempOutputPts;
        iter.reset();
        while( !iter.isDone(&status) )
        {
            CHECK_MSTATUS(tempOutputPts.append(MPoint(0, 0, 0)));
            CHECK_MSTATUS(iter.next());
        }
        assert(tempOutputPts.length() == iter.count());


        /// 2. set tempOutputPts to deform values which comes from each driver mesh
        iter.reset();

        int numMeshes = meshAttrHandle.elementCount();
        __debug("%s(), numMeshes=%d", __FUNCTION__, numMeshes);

        CHECK_MSTATUS(meshAttrHandle.jumpToElement(0));
        // for each driver mesh
        for( int count=0; count < numMeshes; ++count )
        {
            __debug("%s(), count=%d", __FUNCTION__, count);

            // for one driver mesh: currentMesh
            MDataHandle currentMesh = meshAttrHandle.inputValue(&status);
            CHECK_MSTATUS( status );
            MObject meshMobj = currentMesh.asMesh();
            __debugMeshInfo(__FUNCTION__, meshMobj);

            // accumulate deform values of currentMesh to tempOutputPts
            _deform_on_one_mesh(data, iter, localToWorldMatrix, mIndex,
                                meshMobj,
                                envelopeHandle, vertMapArrayData, tempOutputPts );


            if( !meshAttrHandle.next() )
            {
                break;
            }

        }// for each driver mesh


        /// 3. add deform value to this geometry(driven mesh)
        int i = 0;
        iter.reset();
        while( !iter.isDone(&status) )
        {
            MPoint p = iter.position(MSpace::kObject, &status);
            CHECK_MSTATUS(status);

            // add the deform value to this vertex
            CHECK_MSTATUS(iter.setPosition( p + tempOutputPts[i]/numMeshes ));

            CHECK_MSTATUS(iter.next());
            ++i;
        }
        assert(tempOutputPts.length() == iter.count());
    }// if

	return( MS::kSuccess );
}
Example #13
0
MStatus inverseSkinCluster::deform(MDataBlock& data,
	MItGeometry& itGeo,
	const MMatrix& localToWorldMatrix,
	unsigned int geomIndex)
{
	MStatus status;

	MMatrix geomMatrix;
	bool updateSkinInfo;

	MDataHandle hInMesh = data.inputValue( aInMesh, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
	MObject oInMesh = hInMesh.asMesh();
	if( oInMesh.isNull() )
		return MS::kFailure;
	MFnMesh inMesh = oInMesh;
	inMesh.getPoints( m_meshPoints );

	if( originalMeshUpdated )
	{
		itGeo.allPositions( pTaskData->basePoints );
		originalMeshUpdated = false;
	}

	MDataHandle hGeomMatrix = data.inputValue( aGeomMatrix );
	geomMatrix = hGeomMatrix.asMatrix();

	MDataHandle hUpdateWeightList = data.inputValue( aUpdateWeightList );
	updateSkinInfo = hUpdateWeightList.asBool();

	MDataHandle hEnvelop = data.inputValue( envelope );
	envelopValue = hEnvelop.asFloat();

	pTaskData->envelop = envelopValue;
	pTaskData->invEnv  = 1.0f - envelopValue;
	pTaskData->beforePoints = m_meshPoints;

	if( updateSkinInfo )
	{	
		MDataHandle hUpdateSkinInfoOutput = data.outputValue( aUpdateWeightList );
		hUpdateSkinInfoOutput.set( false );
		weightListUpdated = false;
	}

	if( logicalIndexArray.length() == 0 )
		updateLogicalIndexArray();

	MDataHandle hUpdateMatrix = data.inputValue( aUpdateMatrix );

	if( hUpdateMatrix.asBool() )
	{
		matrixAttrUpdated = false;
		matrixInfoUpdated = false;
	}

	MArrayDataHandle hArrMatrix = data.inputArrayValue( aMatrix );
	MArrayDataHandle hArrBindPreMatrix = data.inputArrayValue( aBindPreMatrix );
	updateMatrixAttribute( hArrMatrix, hArrBindPreMatrix );

	if( !matrixInfoUpdated )
	{
		updateMatrixInfo( hArrMatrix, hArrBindPreMatrix );
	}

	if( !weightListUpdated )
	{
		pTaskData->afterPoints.setLength( m_meshPoints.length() );
		pTaskData->envPoints.setLength( m_meshPoints.length() );

		updateWeightList();
	}

	if( !matrixInfoUpdated || !weightListUpdated )
	{
		if( pSkinInfo->weightsArray.size() > 0 )
			getWeightedMatrices( geomMatrix );
		else
			return MS::kFailure;

		matrixInfoUpdated = true;
		weightListUpdated = true;
	}

	if( envelopValue )
	{
		setThread();
		MThreadPool::newParallelRegion( parallelCompute, pThread );
		endThread();

		itGeo.setAllPositions( pTaskData->envPoints );
	}
	else
	{
		itGeo.setAllPositions( pTaskData->basePoints );
	}

	return MS::kSuccess;
}
Example #14
0
MStatus mapBlendShape::deform(MDataBlock& data, 
							  MItGeometry& itGeo, 
							  const MMatrix& localToWorldMatrix, 
							  unsigned int geomIndex)
{
    MStatus status;

	// get the blendMesh 
	MDataHandle hBlendMesh = data.inputValue( aBlendMesh, &status );
    CHECK_MSTATUS_AND_RETURN_IT( status );
    MObject oBlendMesh = hBlendMesh.asMesh();
    if (oBlendMesh.isNull())
    {
        return MS::kSuccess;
    }

	MFnMesh fnMesh( oBlendMesh, &status );
    CHECK_MSTATUS_AND_RETURN_IT( status );
    MPointArray blendPoints;
    fnMesh.getPoints( blendPoints );

	// get the dirty flags for the input and blendMap
	bool inputGeomClean = data.isClean(inputGeom, &status);
	bool blendMapClean  = data.isClean(aBlendMap, &status);

	if (!blendMapClean) {
		lumValues.reserve(itGeo.count());
	}
	
	MDoubleArray uCoords, vCoords;
	MVectorArray resultColors;
	MDoubleArray resultAlphas;

	uCoords.setLength(1);
	vCoords.setLength(1);

	bool hasTextureNode;
	bool useBlendMap = data.inputValue(aUseBlendMap).asBool();
	float blendMapMultiplier = data.inputValue(aBlendMapMultiplier).asFloat();

	if (blendMapMultiplier<=0.0) {
		useBlendMap = false;
	}

	if (useBlendMap) {
		hasTextureNode = MDynamicsUtil::hasValidDynamics2dTexture(thisMObject(), aBlendMap);
	}

	float env = data.inputValue(envelope).asFloat();
    MPoint point;
	float2 uvPoint;
    float w, lum;

    for ( ; !itGeo.isDone(); itGeo.next() )
    {
		lum = 1.0;

		if (useBlendMap) {
			if (!blendMapClean) {
				fnMesh.getUVAtPoint(blendPoints[itGeo.index()], uvPoint);

				if (hasTextureNode) {
					uCoords[0] = uvPoint[0];
					vCoords[0] = uvPoint[1];
					MDynamicsUtil::evalDynamics2dTexture(thisMObject(), aBlendMap, uCoords, vCoords, &resultColors, &resultAlphas);
					lum = float(resultColors[0][0]);
				}
				lumValues[itGeo.index()] = lum;
			} else {
				lum = lumValues[itGeo.index()];
			}
		}

        point = itGeo.position();
        w = weightValue( data, geomIndex, itGeo.index() );
        point += (blendPoints[itGeo.index()] - point) * env * w * lum * blendMapMultiplier;
        itGeo.setPosition( point );
    }

	return MS::kSuccess;
}
Example #15
0
MStatus
tm_noisePerlin::deform( MDataBlock& block,
                        MItGeometry& iter,
                        const MMatrix& /*m*/,
                        unsigned int /*multiIndex*/)
{
    MStatus status = MS::kSuccess;

    // It's a fake data access try to workaround strange behavior on x86_64 linux systems...
    MDataHandle dummyData = block.inputValue(dummy,&status);

    MDataHandle lev_MampData = block.inputValue(lev_Mamp,&status);
    McheckErr(status, "Error getting lev_Mamp data handle\n");
    double _lev_Mamp = lev_MampData.asDouble();

    MDataHandle lev_MfreqData = block.inputValue(lev_Mfreq,&status);
    McheckErr(status, "Error getting lev_Mfreq data handle\n");
    double lev_Mfreq = lev_MfreqData.asDouble();

    MDataHandle levelsData = block.inputValue(levels,&status);
    McheckErr(status, "Error getting frequency data handle\n");
    short levels = levelsData.asShort();

    MDataHandle scaleData = block.inputValue(scale,&status);
    McheckErr(status, "Error getting scale data handle\n");
    double scale = scaleData.asDouble();

    MDataHandle scaleAmpXData = block.inputValue(scaleAmpX,&status);
    McheckErr(status, "Error getting scaleAmpX data handle\n");
    double scaleAmpX = scaleAmpXData.asDouble();

    MDataHandle scaleAmpYData = block.inputValue(scaleAmpY,&status);
    McheckErr(status, "Error getting scaleAmpY data handle\n");
    double scaleAmpY = scaleAmpYData.asDouble();

    MDataHandle scaleAmpZData = block.inputValue(scaleAmpZ,&status);
    McheckErr(status, "Error getting scaleAmpZ data handle\n");
    double scaleAmpZ = scaleAmpZData.asDouble();

    MDataHandle scaleFreqXData = block.inputValue(scaleFreqX,&status);
    McheckErr(status, "Error getting scaleFreqX data handle\n");
    double scaleFreqX = scaleFreqXData.asDouble();

    MDataHandle scaleFreqYData = block.inputValue(scaleFreqY,&status);
    McheckErr(status, "Error getting scaleFreqY data handle\n");
    double scaleFreqY = scaleFreqYData.asDouble();

    MDataHandle scaleFreqZData = block.inputValue(scaleFreqZ,&status);
    McheckErr(status, "Error getting scaleFreqZ data handle\n");
    double scaleFreqZ = scaleFreqZData.asDouble();

    MDataHandle variationData = block.inputValue(variation,&status);
    McheckErr(status, "Error getting variation data handle\n");
    double variation = variationData.asDouble();

    MDataHandle envData = block.inputValue(envelope,&status);
    McheckErr(status, "Error getting envelope data handle\n");
    double env = envData.asDouble();

    MDataHandle amplitudeData = block.inputValue(amplitude,&status);
    McheckErr(status, "Error getting amplitude data handle\n");
    double amplitude = amplitudeData.asDouble();

    MDataHandle frequencyData = block.inputValue(frequency,&status);
    McheckErr(status, "Error getting frequency data handle\n");
    double frequency = frequencyData.asDouble();

    amplitude = amplitude * scale;
    frequency = frequency * 0.01 / scale;


    for ( ; !iter.isDone(); iter.next()) {

        MPoint pt = iter.position();
        vector noisePnt;
        noisePnt.x = 0;
        noisePnt.y = 0;
        noisePnt.z = 0;

        double l_amp = amplitude;

        double x = scaleFreqX * pt.x * frequency;
        double y = scaleFreqY * pt.y * frequency;
        double z = scaleFreqZ * pt.z * frequency;

        for( int lev = 0; lev < levels; lev++)
        {
            x *= lev_Mfreq;
            y *= lev_Mfreq;
            z *= lev_Mfreq;
            vector lev_Pnt = INoise::noise4d_v(x, y, z, variation);
            noisePnt.x += lev_Pnt.x * l_amp;
            noisePnt.y += lev_Pnt.y * l_amp;
            noisePnt.z += lev_Pnt.z * l_amp;
            l_amp *= _lev_Mamp;
        }

        pt.x += noisePnt.x * scaleAmpX;
        pt.y += noisePnt.y * scaleAmpY;
        pt.z += noisePnt.z * scaleAmpZ;

        iter.setPosition(pt);
    }
    return status;
}
Example #16
0
MStatus
HRBFSkinCluster::deform( MDataBlock& block,
                      MItGeometry& iter,
                      const MMatrix& m,
                      unsigned int multiIndex)
//
// Method: deform1
//
// Description:   Deforms the point with a simple smooth skinning algorithm
//
// Arguments:
//   block      : the datablock of the node
//   iter       : an iterator for the geometry to be deformed
//   m          : matrix to transform the point into world space
//   multiIndex : the index of the geometry that we are deforming
//
//
{
	MStatus returnStatus;

	// get HRBF status
	MDataHandle HRBFstatusData = block.inputValue(rebuildHRBF, &returnStatus);
	McheckErr(returnStatus, "Error getting rebuildHRBF handle\n");
	int rebuildHRBFStatusNow = HRBFstatusData.asInt();
	// handle signaling to the rest of deform that HRBFs must be rebuild
	bool signalRebuildHRBF = false;
	signalRebuildHRBF = (rebuildHRBFStatus != rebuildHRBFStatusNow);
	MMatrixArray bindTFs; // store just the bind transforms in here.
	MMatrixArray boneTFs; // ALWAYS store just the bone transforms in here.

	// get HRBF export status
	MDataHandle exportCompositionData = block.inputValue(exportComposition, &returnStatus);
	McheckErr(returnStatus, "Error getting exportComposition handle\n");
	int exportCompositionStatusNow = exportCompositionData.asInt();

	MDataHandle HRBFExportSamplesData = block.inputValue(exportHRBFSamples, &returnStatus);
	McheckErr(returnStatus, "Error getting exportHRBFSamples handle\n");
	std::string exportHRBFSamplesStatusNow = HRBFExportSamplesData.asString().asChar();

	MDataHandle HRBFExportValuesData = block.inputValue(exportHRBFValues, &returnStatus);
	McheckErr(returnStatus, "Error getting exportHRBFValues handle\n");
	std::string exportHRBFValuesStatusNow = HRBFExportValuesData.asString().asChar();

	// get skinning type
	MDataHandle useDQData = block.inputValue(useDQ, &returnStatus);
	McheckErr(returnStatus, "Error getting useDQ handle\n");
	int useDQNow = useDQData.asInt();

	// determine if we're using HRBF
	MDataHandle useHRBFData = block.inputValue(useHRBF, &returnStatus);
	McheckErr(returnStatus, "Error getting useHRBFData handle\n");
	int useHRBFnow = useHRBFData.asInt();

	// get envelope because why not
	MDataHandle envData = block.inputValue(envelope, &returnStatus);
	float env = envData.asFloat();

	// get point in space for evaluating HRBF
	MDataHandle checkHRBFAtData = block.inputValue(checkHRBFAt, &returnStatus);
	McheckErr(returnStatus, "Error getting useDQ handle\n");
	double* data = checkHRBFAtData.asDouble3();

	// get the influence transforms
	//
	MArrayDataHandle transformsHandle = block.inputArrayValue( matrix ); // tell block what we want
	int numTransforms = transformsHandle.elementCount();
	if ( numTransforms == 0 ) { // no transforms, no problems
		return MS::kSuccess;
	}
	MMatrixArray transforms; // fetch transform matrices -> actual joint matrices
	for ( int i=0; i<numTransforms; ++i ) {
		MMatrix worldTF = MFnMatrixData(transformsHandle.inputValue().data()).matrix();
		transforms.append(worldTF);
		boneTFs.append(worldTF);
		transformsHandle.next();
	}
	// inclusive matrices inverse of the driving transform at time of bind
	// matrices for transforming vertices to joint local space
	MArrayDataHandle bindHandle = block.inputArrayValue( bindPreMatrix ); // tell block what we want
	if ( bindHandle.elementCount() > 0 ) {
		for ( int i=0; i<numTransforms; ++i ) {
			MMatrix bind = MFnMatrixData(bindHandle.inputValue().data()).matrix();
			transforms[i] = bind * transforms[i];
			bindHandle.next();
			if (signalRebuildHRBF) bindTFs.append(bind);
		}
	}

	MArrayDataHandle weightListHandle = block.inputArrayValue(weightList);
	if (weightListHandle.elementCount() == 0) {
		// no weights - nothing to do
		std::cout << "no weights!" << std::endl;
		//rebuildHRBFStatus = rebuildHRBFStatusNow - 1; // HRBFs will need to rebuilt no matter what
		return MS::kSuccess;
	}

	// print HRBF samples if requested
	if (exportHRBFSamplesStatusNow != exportHRBFSamplesStatus) {
		std::cout << "instructed to export HRBF samples: " << exportHRBFSamplesStatusNow.c_str() << std::endl;
		exportHRBFSamplesStatus = exportHRBFSamplesStatusNow;
		// TODO: handle exporting HRBFs to the text file format
		hrbfMan->debugSamplesToConsole(exportHRBFSamplesStatus);
	}

	// print HRBF values if requested
	if (exportHRBFValuesStatusNow != exportHRBFValuesStatus) {
		std::cout << "instructed to export HRBF values: " << exportHRBFValuesStatusNow.c_str() << std::endl;
		exportHRBFValuesStatus = exportHRBFValuesStatusNow;
		// TODO: handle exporting HRBFs to the text file format
		hrbfMan->debugValuesToConsole(exportHRBFValuesStatus);
	}

	// print HRBF composition if requested
	if (exportCompositionStatusNow != exportCompositionStatus) {
		std::cout << "instructed to export HRBF composition." << std::endl;
		exportCompositionStatus = exportCompositionStatusNow;
		// TODO: handle exporting HRBFs to the text file format
		hrbfMan->debugCompositionToConsole(boneTFs, numTransforms);
	}

	// check the HRBF value if the new point is significantly different
	MPoint checkHRBFHereNow(data[0], data[1], data[2]);
	if ((checkHRBFHereNow - checkHRBFHere).length() > 0.0001) {
		if (hrbfMan->m_HRBFs.size() == numTransforms) {
			std::cout << "checking HRBF at x:" << data[0] << " y: " << data[1] << " z: " << data[2] << std::endl;
			hrbfMan->compose(boneTFs);
			float val = 0.0f;
			float dx = 0.0f;
			float dy = 0.0f;
			float dz = 0.0f;
			float grad = 0.0f;

			hrbfMan->mf_vals->trilinear(data[0], data[1], data[2], val);
			hrbfMan->mf_gradX->trilinear(data[0], data[1], data[2], dx);
			hrbfMan->mf_gradY->trilinear(data[0], data[1], data[2], dy);
			hrbfMan->mf_gradZ->trilinear(data[0], data[1], data[2], dz);
			hrbfMan->mf_gradMag->trilinear(data[0], data[1], data[2], grad);
			std::cout << "val: " << val << " dx: " << dx << " dy: " << dy << " dz: " << dz << " grad: " << grad << std::endl;
			checkHRBFHere = checkHRBFHereNow;
		}
	}

	// rebuild HRBFs if needed
	if (signalRebuildHRBF) {
		std::cout << "instructed to rebuild HRBFs" << std::endl;
		rebuildHRBFStatus = rebuildHRBFStatusNow;

		MArrayDataHandle parentIDCsHandle = block.inputArrayValue(jointParentIdcs); // tell block what we want
		std::vector<int> jointParentIndices(numTransforms);
		if (parentIDCsHandle.elementCount() > 0) {
			for (int i = 0; i<numTransforms; ++i) {
				jointParentIndices[i] = parentIDCsHandle.inputValue().asInt();
				parentIDCsHandle.next();
			}
		}

		MArrayDataHandle jointNamesHandle = block.inputArrayValue(jointNames); // tell block what we want
		std::vector<std::string> jointNames(numTransforms);
		if (jointNamesHandle.elementCount() > 0) {
			for (int i = 0; i<numTransforms; ++i) {
				jointNames[i] = jointNamesHandle.inputValue().asString().asChar();
				jointNamesHandle.next();
			}
		}

		// debug
		//std::cout << "got joint hierarchy info! it's:" << std::endl;
		//for (int i = 0; i < numTransforms; ++i) {
		//	std::cout << i << ": " << jointNames[i].c_str() << " : " << jointParentIndices[i] << std::endl;
		//}
		std::cout << "rebuilding HRBFs... " << std::endl;
		hrbfMan->buildHRBFs(jointParentIndices, jointNames, bindTFs, boneTFs, 
			weightListHandle, iter, weights);
		std::cout << "done rebuilding!" << std::endl;
		weightListHandle.jumpToElement(0); // reset this, it's an iterator. trust me.
		iter.reset(); // reset this iterator so we can go do normal skinning
	}


	// perform traditional skinning
	if (useDQNow != 0) {
		returnStatus = skinDQ(transforms, numTransforms, weightListHandle, iter);
	}
	else {
		returnStatus = skinLB(transforms, numTransforms, weightListHandle, iter);
	}

	// do HRBF corrections
	if (useHRBFnow != 0) {
		if (hrbfMan->m_HRBFs.size() == numTransforms) {
			hrbfMan->compose(boneTFs);
			iter.reset();
			hrbfMan->correct(iter);
		}
	}

	return returnStatus;
}
MStatus AlembicCurvesDeformNode::deform(MDataBlock &dataBlock,
                                        MItGeometry &iter,
                                        const MMatrix &localToWorld,
                                        unsigned int geomIndex)
{
  // get the envelope data
  float env = dataBlock.inputValue(envelope).asFloat();
  if (env == 0.0f) {  // deformer turned off
    return MStatus::kSuccess;
  }

  // update the frame number to be imported
  double inputTime =
      dataBlock.inputValue(mTimeAttr).asTime().as(MTime::kSeconds);
  MString &fileName = dataBlock.inputValue(mFileNameAttr).asString();
  MString &identifier = dataBlock.inputValue(mIdentifierAttr).asString();

  // check if we have the file
  if (fileName != mFileName || identifier != mIdentifier) {
    mSchema.reset();
    if (fileName != mFileName) {
      delRefArchive(mFileName);
      mFileName = fileName;
      addRefArchive(mFileName);
    }
    mIdentifier = identifier;

    // get the object from the archive
    Abc::IObject iObj = getObjectFromArchive(mFileName, identifier);
    if (!iObj.valid()) {
      MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier +
                              "' not found in archive '" + mFileName + "'.");
      return MStatus::kFailure;
    }
    AbcG::ICurves obj(iObj, Abc::kWrapExisting);
    if (!obj.valid()) {
      MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier +
                              "' in archive '" + mFileName +
                              "' is not a Curves.");
      return MStatus::kFailure;
    }
    mSchema = obj.getSchema();
  }

  if (!mSchema.valid()) {
    return MStatus::kFailure;
  }

  {
    ESS_PROFILE_SCOPE("AlembicCurvesDeformNode::deform readProps");
    Alembic::Abc::ICompoundProperty arbProp = mSchema.getArbGeomParams();
    Alembic::Abc::ICompoundProperty userProp = mSchema.getUserProperties();
    readProps(inputTime, arbProp, dataBlock, thisMObject());
    readProps(inputTime, userProp, dataBlock, thisMObject());

    // Set all plugs as clean
    // Even if one of them failed to get set,
    // trying again in this frame isn't going to help
    for (unsigned int i = 0; i < mGeomParamPlugs.length(); i++) {
      dataBlock.outputValue(mGeomParamPlugs[i]).setClean();
    }

    for (unsigned int i = 0; i < mUserAttrPlugs.length(); i++) {
      dataBlock.outputValue(mUserAttrPlugs[i]).setClean();
    }
  }

  // get the sample
  SampleInfo sampleInfo = getSampleInfo(inputTime, mSchema.getTimeSampling(),
                                        mSchema.getNumSamples());

  // check if we have to do this at all
  if (mLastSampleInfo.floorIndex == sampleInfo.floorIndex &&
      mLastSampleInfo.ceilIndex == sampleInfo.ceilIndex) {
    return MStatus::kSuccess;
  }

  mLastSampleInfo = sampleInfo;

  // access the camera values
  AbcG::ICurvesSchema::Sample sample;
  AbcG::ICurvesSchema::Sample sample2;
  mSchema.get(sample, sampleInfo.floorIndex);
  if (sampleInfo.alpha != 0.0) {
    mSchema.get(sample2, sampleInfo.ceilIndex);
  }

  Abc::P3fArraySamplePtr samplePos = sample.getPositions();
  Abc::P3fArraySamplePtr samplePos2;
  if (sampleInfo.alpha != 0.0) {
    samplePos2 = sample2.getPositions();
  }

  // iteration should not be necessary. the iteration is only
  // required if the same mesh is attached to the same deformer
  // several times
  float blend = (float)sampleInfo.alpha;
  float iblend = 1.0f - blend;
  unsigned int index = 0;
  for (iter.reset(); !iter.isDone(); iter.next()) {
    index = iter.index();
    // MFloatPoint pt = iter.position();
    MPoint pt = iter.position();
    MPoint abcPos = pt;
    float weight = weightValue(dataBlock, geomIndex, index) * env;
    if (weight == 0.0f) {
      continue;
    }
    float iweight = 1.0f - weight;
    if (index >= samplePos->size()) {
      continue;
    }
    bool done = false;
    if (sampleInfo.alpha != 0.0) {
      if (samplePos2->size() == samplePos->size()) {
        abcPos.x = iweight * pt.x +
                   weight * (samplePos->get()[index].x * iblend +
                             samplePos2->get()[index].x * blend);
        abcPos.y = iweight * pt.y +
                   weight * (samplePos->get()[index].y * iblend +
                             samplePos2->get()[index].y * blend);
        abcPos.z = iweight * pt.z +
                   weight * (samplePos->get()[index].z * iblend +
                             samplePos2->get()[index].z * blend);
        done = true;
      }
    }
    if (!done) {
      abcPos.x = iweight * pt.x + weight * samplePos->get()[index].x;
      abcPos.y = iweight * pt.y + weight * samplePos->get()[index].y;
      abcPos.z = iweight * pt.z + weight * samplePos->get()[index].z;
    }
    iter.setPosition(abcPos);
  }
  return MStatus::kSuccess;
}
Example #18
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;
}
Example #19
0
MStatus
HRBFSkinCluster::skinDQ(MMatrixArray&  transforms,
						int numTransforms,
						MArrayDataHandle& weightListHandle,
						MItGeometry& iter) {
	MStatus returnStatus;

	// compute dual quaternions. we're storing them as a parallel array.
	std::vector<MQuaternion> tQuaternions(numTransforms); // translation quaterions
	std::vector<MQuaternion> rQuaternions(numTransforms); // rotation quaternions

	for (int i = 0; i < numTransforms; i++) {
		rQuaternions.at(i) = getRotationQuaternion(transforms[i]);
		rQuaternions.at(i).normalizeIt();
		tQuaternions.at(i) = getTranslationQuaternion(transforms[i], rQuaternions.at(i));
#if DEBUG_PRINTS
		std::cout << "rota quaternion " << i << " is: " << rQuaternions.at(i) << std::endl;
		std::cout << "tran quaternion " << i << " is: " << tQuaternions.at(i) << std::endl;
#endif
	}

	MQuaternion rBlend; // blended rotation quaternions
	MQuaternion tBlend; // blended translation quaternions
	MQuaternion scaleMe; // Maya's quaternion scaling is in-place
	double weight;


	// Iterate through each point in the geometry.
	//
	for (; !iter.isDone(); iter.next()) {
		MPoint pt = iter.position();
		MPoint skinned;

		rBlend = MQuaternion(); // reset
		tBlend = MQuaternion(); // reset
		rBlend[3] = 0.0;
		tBlend[3] = 0.0;

		// get the weights for this point
		MArrayDataHandle weightsHandle = weightListHandle.inputValue().child(weights);

		// compute the skinning
		for (int i = 0; i<numTransforms; ++i) {
			if (MS::kSuccess == weightsHandle.jumpToElement(i)) {
				weight = weightsHandle.inputValue().asDouble();
				scaleMe = rQuaternions.at(i);
				rBlend = rBlend + scaleMe.scaleIt(weight);
				scaleMe = tQuaternions.at(i);
				tBlend = tBlend + scaleMe.scaleIt(weight);
			}
		}

		MMatrix dqMatrix = makeDQMatrix(rBlend.normalizeIt(), tBlend);
		skinned = pt * dqMatrix;

		// Set the final position.
		iter.setPosition(skinned);

		// advance the weight list handle
		weightListHandle.next();
	}
	return returnStatus;
}
MStatus probeDeformerARAPNode::deform( MDataBlock& data, MItGeometry& itGeo, const MMatrix &localToWorldMatrix, unsigned int mIndex )
{
	MObject thisNode = thisMObject();
    MStatus status;
    MThreadUtils::syncNumOpenMPThreads();    // for OpenMP
    
    bool worldMode = data.inputValue( aWorldMode ).asBool();
    bool areaWeighted = data.inputValue( aAreaWeighted ).asBool();
    short stiffnessMode = data.inputValue( aStiffness ).asShort();
    short blendMode = data.inputValue( aBlendMode ).asShort();
    short tetMode = data.inputValue( aTetMode ).asShort();
    short numIter = data.inputValue( aIteration ).asShort();
    short constraintMode = data.inputValue( aConstraintMode ).asShort();
    short visualisationMode = data.inputValue( aVisualisationMode ).asShort();
    mesh.transWeight = data.inputValue( aTransWeight ).asDouble();
    double constraintWeight = data.inputValue( aConstraintWeight ).asDouble();
    double normExponent = data.inputValue( aNormExponent ).asDouble();
    double visualisationMultiplier = data.inputValue(aVisualisationMultiplier).asDouble();
    MArrayDataHandle hMatrixArray = data.inputArrayValue(aMatrix);
    MArrayDataHandle hInitMatrixArray = data.inputArrayValue(aInitMatrix);
    // check connection
    if(hMatrixArray.elementCount() > hInitMatrixArray.elementCount() || hMatrixArray.elementCount() == 0 || blendMode == BM_OFF){
        return MS::kSuccess;
    }else if(hMatrixArray.elementCount() < hInitMatrixArray.elementCount()){
        std::set<int> indices;
        for(int i=0;i<hInitMatrixArray.elementCount();i++){
            hInitMatrixArray.jumpToArrayElement(i);
            indices.insert(hInitMatrixArray.elementIndex());
        }
        for(int i=0;i<hMatrixArray.elementCount();i++){
            hMatrixArray.jumpToArrayElement(i);
            indices.erase(hMatrixArray.elementIndex());
        }
        deleteAttr(data, aInitMatrix, indices);
        deleteAttr(data, aProbeConstraintRadius, indices);
        deleteAttr(data, aProbeWeight, indices);
    }
    bool isNumProbeChanged = (numPrb != hMatrixArray.elementCount());
    numPrb = hMatrixArray.elementCount();
    B.setNum(numPrb);
    // read matrices from probes
    std::vector<Matrix4d> initMatrix(numPrb), matrix(numPrb);
    readMatrixArray(hInitMatrixArray, initMatrix);
    readMatrixArray(hMatrixArray, matrix);
    // read vertex positions
    MPointArray Mpts;
    itGeo.allPositions(Mpts);
    int numPts = Mpts.length();
    
    // compute distance
    if(!data.isClean(aARAP) || !data.isClean(aComputeWeight) || isNumProbeChanged){
        // load points list
        if(worldMode){
            for(int j=0; j<numPts; j++ )
                Mpts[j] *= localToWorldMatrix;
        }
        pts.resize(numPts);
        for(int i=0;i<numPts;i++){
            pts[i] << Mpts[i].x, Mpts[i].y, Mpts[i].z;
        }
        // make tetrahedral structure
        getMeshData(data, input, inputGeom, mIndex, tetMode, pts, mesh.tetList, faceList, edgeList, vertexList, mesh.tetMatrix, mesh.tetWeight);
        mesh.dim = removeDegenerate(tetMode, numPts, mesh.tetList, faceList, edgeList, vertexList, mesh.tetMatrix);
        makeTetMatrix(tetMode, pts, mesh.tetList, faceList, edgeList, vertexList, mesh.tetMatrix, mesh.tetWeight);
        makeTetCenterList(tetMode, pts, mesh.tetList, tetCenter);
        mesh.numTet = (int)mesh.tetList.size()/4;
        mesh.computeTetMatrixInverse();
        // initial probe position
        for(int i=0;i<numPrb;i++){
            B.centre[i] = transPart(initMatrix[i]);
        }
        // compute distance between probe and tetrahedra
        D.setNum(numPrb, numPts, mesh.numTet);
        D.computeDistTet(tetCenter, B.centre);
        D.findClosestTet();
        D.computeDistPts(pts, B.centre);
        D.findClosestPts();
        if(!areaWeighted){
            mesh.tetWeight.clear();
            mesh.tetWeight.resize(mesh.numTet,1.0);
        }
    }
    
    // (re)compute ARAP
    if(!data.isClean(aARAP) || isNumProbeChanged){
        // load painted weights
        if(stiffnessMode == SM_PAINT) {
            VectorXd ptsWeight(numPts);
            for (int i=0; !itGeo.isDone(); itGeo.next()){
                double w=weightValue(data, mIndex, itGeo.index());
                ptsWeight[i++] = (w>EPSILON) ? w : EPSILON;
            }
            makeTetWeightList(tetMode, mesh.tetList, faceList, edgeList, vertexList, ptsWeight, mesh.tetWeight);
        }else if(stiffnessMode == SM_LEARN) {
            std::vector<double> tetEnergy(mesh.numTet,0);
            MArrayDataHandle hSupervisedMesh = data.inputArrayValue(aSupervisedMesh);
            int numSupervisedMesh = hSupervisedMesh.elementCount();
            for(int j=0;j<numSupervisedMesh;j++){
                hSupervisedMesh.jumpToElement(j);
                MFnMesh ex_mesh(hSupervisedMesh.inputValue().asMesh());
                MPointArray Mspts;
                ex_mesh.getPoints( Mspts );
                if(numPts != Mspts.length()){
                    MGlobal::displayInfo("incompatible mesh");
                    return MS::kFailure;
                }
                std::vector<Vector3d> spts(numPts);
                for(int i=0;i<numPts;i++){
                    spts[i] << Mspts[i].x, Mspts[i].y, Mspts[i].z;
                }
                std::vector<double> dummy_weight;
                makeTetMatrix(tetMode, spts, mesh.tetList, faceList, edgeList, vertexList, Q, dummy_weight);
                Matrix3d S,R;
                for(int i=0;i<mesh.numTet;i++)  {
                    polarHigham((mesh.tetMatrixInverse[i]*Q[i]).block(0,0,3,3), S, R);
                    tetEnergy[i] += (S-Matrix3d::Identity()).squaredNorm();
                }
            }
            // compute weight (stiffness)
            double max_energy = *std::max_element(tetEnergy.begin(), tetEnergy.end());
            for(int i=0;i<mesh.numTet;i++)  {
                double w = 1.0 - tetEnergy[i]/(max_energy+EPSILON);
                mesh.tetWeight[i] *= w*w;
            }
        }

        // find constraint points
        constraint.resize(3*numPrb);
        for(int i=0;i<numPrb;i++){
            constraint[3*i] = T(i,mesh.tetList[4*D.closestTet[i]],constraintWeight);
            constraint[3*i+1] = T(i,mesh.tetList[4*D.closestTet[i]+1],constraintWeight);
            constraint[3*i+2] = T(i,mesh.tetList[4*D.closestTet[i]+2],constraintWeight);
        }
        if( constraintMode == CONSTRAINT_NEIGHBOUR ){
            std::vector<double> probeConstraintRadius(numPrb);
            MArrayDataHandle handle = data.inputArrayValue(aProbeConstraintRadius);
            if(handle.elementCount() != numPrb){
                MGlobal::displayInfo("# of Probes and probeConstraintRadius are different");
                return MS::kFailure;
            }
            for(int i=0;i<numPrb;i++){
                handle.jumpToArrayElement(i);
                probeConstraintRadius[i]=handle.inputValue().asDouble();
            }
            double constraintRadius = data.inputValue( aConstraintRadius ).asDouble();
            for(int i=0;i<numPrb;i++){
                double r = constraintRadius * probeConstraintRadius[i];
                for(int j=0;j<numPts;j++){
                    if(D.distPts[i][j]<r){
                        constraint.push_back(T(i,j,constraintWeight * pow((r-D.distPts[i][j])/r,normExponent)));
                    }
                }
            }
        }
        int numConstraint=constraint.size();
        mesh.constraintWeight.resize(numConstraint);
        mesh.constraintVal.resize(numConstraint,numPrb);
        for(int cur=0;cur<numConstraint;cur++){
            mesh.constraintWeight[cur] = std::make_pair(constraint[cur].col(), constraint[cur].value());
        }
        //
        isError = mesh.ARAPprecompute();
        status = data.setClean(aARAP);
    }        // END of ARAP precomputation
    
    if(isError>0){
        return MS::kFailure;
    }
    
    // probe weight computation
    if(!data.isClean(aComputeWeight) || isNumProbeChanged){
        // load probe weights
        MArrayDataHandle handle = data.inputArrayValue(aProbeWeight);
        if(handle.elementCount() != numPrb){
            MGlobal::displayInfo("# of Probes and probeWeight are different");
            isError = ERROR_ATTR;
            return MS::kFailure;
        }
        double effectRadius = data.inputValue( aEffectRadius ).asDouble();
        std::vector<double> probeWeight(numPrb), probeRadius(numPrb);
        for(int i=0;i<numPrb;i++){
            handle.jumpToArrayElement(i);
            probeWeight[i] = handle.inputValue().asDouble();
            probeRadius[i] = probeWeight[i] * effectRadius;
        }
        wr.resize(mesh.numTet);ws.resize(mesh.numTet);wl.resize(mesh.numTet);
        for(int j=0;j<mesh.numTet;j++){
            wr[j].resize(numPrb); ws[j].resize(numPrb); wl[j].resize(numPrb);
        }
        short weightMode = data.inputValue( aWeightMode ).asShort();
        if (weightMode == WM_INV_DISTANCE){
            for(int j=0;j<mesh.numTet;j++){
                double sum=0.0;
                std::vector<double> idist(numPrb);
                for (int i = 0; i<numPrb; i++){
                    idist[i] = probeRadius[i] / pow(D.distTet[i][j], normExponent);
                    sum += idist[i];
                }
                for (int i = 0; i<numPrb; i++){
                    wr[j][i] = ws[j][i] = wl[j][i] = sum > 0 ? idist[i] / sum : 0.0;
                }
            }
        }
        else if (weightMode == WM_CUTOFF_DISTANCE){
            for(int j=0;j<mesh.numTet;j++){
                for (int i = 0; i<numPrb; i++){
                    wr[j][i] = ws[j][i] = wl[j][i] = (D.distTet[i][j] > probeRadius[i])
                    ? 0 : pow((probeRadius[i] - D.distTet[i][j]) / probeRadius[i], normExponent);
                }
            }
        }else if (weightMode == WM_DRAW){
            float val;
            MRampAttribute rWeightCurveR( thisNode, aWeightCurveR, &status );
            MRampAttribute rWeightCurveS( thisNode, aWeightCurveS, &status );
            MRampAttribute rWeightCurveL( thisNode, aWeightCurveL, &status );
            for(int j=0;j<mesh.numTet;j++){
                for (int i = 0; i < numPrb; i++){
                    rWeightCurveR.getValueAtPosition(D.distTet[i][j] / probeRadius[i], val);
                    wr[j][i] = val;
                    rWeightCurveS.getValueAtPosition(D.distTet[i][j] / probeRadius[i], val);
                    ws[j][i] = val;
                    rWeightCurveL.getValueAtPosition(D.distTet[i][j] / probeRadius[i], val);
                    wl[j][i] = val;
                }
            }
        }else if(weightMode & WM_HARMONIC){
            Laplacian harmonicWeighting;
            makeFaceTet(data, input, inputGeom, mIndex, pts, harmonicWeighting.tetList, harmonicWeighting.tetMatrix, harmonicWeighting.tetWeight);
            harmonicWeighting.numTet = (int)harmonicWeighting.tetList.size()/4;
            std::vector<T> weightConstraint(numPrb);
            // the vertex closest to the probe is given probeWeight
            for(int i=0;i<numPrb;i++){
                weightConstraint[i]=T(i,D.closestPts[i],probeWeight[i]);
            }
            // vertices within effectRadius are given probeWeight
            if( data.inputValue( aNeighbourWeighting ).asBool() ){
                for(int i=0;i<numPrb;i++){
                    for(int j=0;j<numPts;j++){
                        if(D.distPts[i][j]<probeRadius[i]){
                            weightConstraint.push_back(T(i,j,probeWeight[i]));
                        }
                    }
                }
            }
            // set boundary condition for weight computation
            int numConstraint=weightConstraint.size();
            harmonicWeighting.constraintWeight.resize(numConstraint);
            harmonicWeighting.constraintVal.resize(numConstraint,numPrb);
            harmonicWeighting.constraintVal.setZero();
            for(int i=0;i<numConstraint;i++){
                harmonicWeighting.constraintVal(i,weightConstraint[i].row())=weightConstraint[i].value();
                harmonicWeighting.constraintWeight[i] = std::make_pair(weightConstraint[i].col(), weightConstraint[i].value());
            }
            // clear tetWeight
            if(!areaWeighted){
                harmonicWeighting.tetWeight.clear();
                harmonicWeighting.tetWeight.resize(harmonicWeighting.numTet,1.0);
            }
            // solve the laplace equation
            if( weightMode == WM_HARMONIC_ARAP){
                harmonicWeighting.computeTetMatrixInverse();
                harmonicWeighting.dim = numPts + harmonicWeighting.numTet;
                isError = harmonicWeighting.ARAPprecompute();
            }else if(weightMode == WM_HARMONIC_COTAN){
                harmonicWeighting.dim = numPts;
                isError = harmonicWeighting.cotanPrecompute();
            }
            if(isError>0) return MS::kFailure;
            std::vector< std::vector<double> > w_tet(numPrb);
            harmonicWeighting.harmonicSolve();
            for(int i=0;i<numPrb;i++){
                makeTetWeightList(tetMode, mesh.tetList, faceList, edgeList, vertexList, harmonicWeighting.Sol.col(i), w_tet[i]);
                for(int j=0;j<mesh.numTet; j++){
                    wr[j][i] = ws[j][i] = wl[j][i] = w_tet[i][j];
                }
            }
        }
        // normalise weights
        short normaliseWeightMode = data.inputValue( aNormaliseWeight ).asShort();
        for(int j=0;j<mesh.numTet;j++){
            D.normaliseWeight(normaliseWeightMode, wr[j]);
            D.normaliseWeight(normaliseWeightMode, ws[j]);
            D.normaliseWeight(normaliseWeightMode, wl[j]);
        }
        status = data.setClean(aComputeWeight);
    } // END of weight computation


    // setting up transformation matrix
    B.rotationConsistency = data.inputValue( aRotationConsistency ).asBool();
    bool frechetSum = data.inputValue( aFrechetSum ).asBool();
    blendedSE.resize(mesh.numTet); blendedR.resize(mesh.numTet); blendedS.resize(mesh.numTet); blendedL.resize(mesh.numTet);A.resize(mesh.numTet);
    for(int i=0;i<numPrb;i++){
        B.Aff[i]=initMatrix[i].inverse()*matrix[i];
    }
    B.parametrise(blendMode);
    

// prepare transform matrix for each simplex
#pragma omp parallel for
	for (int j = 0; j < mesh.numTet; j++){
		// blend matrix
		if (blendMode == BM_SRL){
			blendedS[j] = expSym(blendMat(B.logS, ws[j]));
			Vector3d l = blendMat(B.L, wl[j]);
            blendedR[j] = frechetSum ? frechetSO(B.R, wr[j]) : expSO(blendMat(B.logR, wr[j]));
			A[j] = pad(blendedS[j]*blendedR[j], l);
		}
		else if (blendMode == BM_SSE){
			blendedS[j] = expSym(blendMat(B.logS, ws[j]));
            blendedSE[j] = expSE(blendMat(B.logSE, wr[j]));
			A[j] = pad(blendedS[j], Vector3d::Zero()) * blendedSE[j];
		}
		else if (blendMode == BM_LOG3){
			blendedR[j] = blendMat(B.logGL, wr[j]).exp();
			Vector3d l = blendMat(B.L, wl[j]);
			A[j] = pad(blendedR[j], l);
		}
		else if (blendMode == BM_LOG4){
			A[j] = blendMat(B.logAff, wr[j]).exp();
		}
		else if (blendMode == BM_SQL){
			Vector4d q = blendQuat(B.quat, wr[j]);
			Vector3d l = blendMat(B.L, wl[j]);
			blendedS[j] = blendMatLin(B.S, ws[j]);
			Quaternion<double> RQ(q);
			blendedR[j] = RQ.matrix().transpose();
			A[j] = pad(blendedS[j]*blendedR[j], l);
		}
		else if (blendMode == BM_AFF){
			A[j] = blendMatLin(B.Aff, wr[j]);
		}
	}

    // compute target vertices position
    tetEnergy.resize(mesh.numTet);
    
    // set constraint
    int numConstraints = constraint.size();
    mesh.constraintVal.resize(numConstraints,3);
    RowVector4d cv;
    for(int cur=0;cur<numConstraints;cur++){
        cv = pad(pts[constraint[cur].col()]) * B.Aff[constraint[cur].row()];
        mesh.constraintVal(cur,0) = cv[0];
        mesh.constraintVal(cur,1) = cv[1];
        mesh.constraintVal(cur,2) = cv[2];
    }

    // iterate to determine vertices position
    for(int k=0;k<numIter;k++){
        // solve ARAP
        mesh.ARAPSolve(A);
        // set new vertices position
        new_pts.resize(numPts);
        for(int i=0;i<numPts;i++){
            new_pts[i][0]=mesh.Sol(i,0);
            new_pts[i][1]=mesh.Sol(i,1);
            new_pts[i][2]=mesh.Sol(i,2);
        }
        // if iteration continues
        if(k+1<numIter || visualisationMode == VM_ENERGY){
            std::vector<double> dummy_weight;
            makeTetMatrix(tetMode, new_pts, mesh.tetList, faceList, edgeList, vertexList, Q, dummy_weight);
            Matrix3d S,R,newS,newR;
            if(blendMode == BM_AFF || blendMode == BM_LOG4 || blendMode == BM_LOG3){
                for(int i=0;i<mesh.numTet;i++){
                    polarHigham(A[i].block(0,0,3,3), blendedS[i], blendedR[i]);
                }
            }
            #pragma omp parallel for
            for(int i=0;i<mesh.numTet;i++){
                polarHigham((mesh.tetMatrixInverse[i]*Q[i]).block(0,0,3,3), newS, newR);
                tetEnergy[i] = (newS-blendedS[i]).squaredNorm();
                A[i].block(0,0,3,3) = blendedS[i]*newR;
//                polarHigham((A[i].transpose()*PI[i]*Q[i]).block(0,0,3,3), newS, newR);
//                A[i].block(0,0,3,3) *= newR;
            }
        }
    }
    for(int i=0;i<numPts;i++){
        Mpts[i].x=mesh.Sol(i,0);
        Mpts[i].y=mesh.Sol(i,1);
        Mpts[i].z=mesh.Sol(i,2);
    }
    if(worldMode){
        for(int i=0;i<numPts;i++)
            Mpts[i] *= localToWorldMatrix.inverse();
    }
    itGeo.setAllPositions(Mpts);
    
    // set vertex colour
    if(visualisationMode != VM_OFF){
        std::vector<double> ptsColour(numPts, 0.0);
        if(visualisationMode == VM_ENERGY){
            makePtsWeightList(tetMode, numPts, mesh.tetList, faceList, edgeList, vertexList, tetEnergy, ptsColour);
            for(int i=0;i<numPts;i++){
                ptsColour[i] *= visualisationMultiplier;
            }
        }else if(visualisationMode == VM_STIFFNESS){
            makePtsWeightList(tetMode, numPts, mesh.tetList, faceList, edgeList, vertexList, mesh.tetWeight, ptsColour);
            double maxval = *std::max_element(ptsColour.begin(), ptsColour.end());
            for(int i=0;i<numPts;i++){
                ptsColour[i] = 1.0 - ptsColour[i]/maxval;
            }
        }else if(visualisationMode == VM_CONSTRAINT){
            for(int i=0;i<constraint.size();i++){
                ptsColour[constraint[i].col()] += constraint[i].value();
            }
        }else if(visualisationMode == VM_EFFECT){
            std:vector<double> wsum(mesh.numTet);
            for(int j=0;j<mesh.numTet;j++){
                //wsum[j] = std::accumulate(wr[j].begin(), wr[j].end(), 0.0);
                wsum[j]= visualisationMultiplier * wr[j][numPrb-1];
            }
            makePtsWeightList(tetMode, numPts, mesh.tetList, faceList, edgeList, vertexList, wsum, ptsColour);
        }
        visualise(data, outputGeom, ptsColour);
    }
    
    return MS::kSuccess;
}
Example #21
0
/*!
 * Description:   Deform the point using the Sederberg-Parry FFD algorithm.
 *
 * Arguments:
 *  block       : the datablock of the node
 *  iter        : an iterator for the geometry to be deformed
 *  m           : matrix to transform the point into world space
 *  multiIndex  : the index of the geometry that we are deforming
 */
MStatus ffdPlanar::deform( MDataBlock& block,
                          MItGeometry& iter,
                          const MMatrix& /*m*/,
                          unsigned int multiIndex )
{
    MStatus status = MS::kSuccess;
    
    // Determine the displacement lattice points.
    MDataHandle row1Data = block.inputValue( latticeRow1, &status );
    MCheckErr( status, "Error getting r1 data handle\n" );
    MVector row1Vector = row1Data.asVector();
    
    MDataHandle row2Data = block.inputValue( latticeRow2, &status );
    MCheckErr( status, "Error getting r2 data handle\n" );
    MVector row2Vector = row2Data.asVector();
    
    MDataHandle row3Data = block.inputValue( latticeRow3, &status );
    MCheckErr( status, "Error getting r3 data\n" );
    MVector row3Vector = row3Data.asVector();

    // Determine the envelope (this is a global scale factor for the deformer).
    MDataHandle envData = block.inputValue(envelope,&status);
    MCheckErr(status, "Error getting envelope data handle\n");
    float env = envData.asFloat();
    
    // Generate the FFD lattice.
    MVector lattice[FFD_LATTICE_POINTS_S][FFD_LATTICE_POINTS_T][FFD_LATTICE_POINTS_U] = { // Since dimensions known ahead of time, generate array now.
        { // x = 0
            { MVector(0.f, row1Vector.x, 0.f), MVector(0.f, row1Vector.y, .5f), MVector(0.f, row1Vector.z, 1.f) }, // y = 0
        },
        { // x = 1
            { MVector(.5f, row2Vector.x, 0.f), MVector(.5f, row2Vector.y, .5f), MVector(.5f, row2Vector.z, 1.f) }, // y = 0
        },
        { // x = 2
            { MVector(1.f, row3Vector.x, 0.f), MVector(1.f, row3Vector.y, .5f), MVector(1.f, row3Vector.z, 1.f) }, // y = 0
        }
    };
    
    MBoundingBox boundingBox;
    status = getBoundingBox( block, multiIndex, boundingBox );
    MCheckErr( status, "Error getting bounding box\n" );
    
    MTransformationMatrix transform = getXyzToStuTransformation( boundingBox );
    MMatrix transformMatrix = transform.asMatrix();
    MMatrix inverseMatrix = transform.asMatrixInverse();
    
    // Iterate through each point in the geometry.
    for ( ; !iter.isDone(); iter.next() )
    {
        MPoint pt = iter.position();
        MPoint ptStu = pt * transformMatrix;
        MPoint deformed = getDeformedPoint( ptStu, lattice ) * inverseMatrix;

        if ( env != 1.f )
        {
            MVector diff = deformed - pt;
            deformed = pt + env * diff;
        }
        
        iter.setPosition( deformed );
    }
    return status;
}
MStatus CageDeformerNode::deform( MDataBlock& data, MItGeometry& itGeo, const MMatrix &localToWorldMatrix, unsigned int mIndex )
{
    /// main
    MStatus status;
    MThreadUtils::syncNumOpenMPThreads();    // for OpenMP
    // load cage mesh and other attributes
    MObject oCageMesh = data.inputValue( aCageMesh ).asMesh();
    short blendMode = data.inputValue(aBlendMode).asShort();
	bool rotationCosistency = data.inputValue( aRotationConsistency ).asBool();
	bool frechetSum = data.inputValue( aFrechetSum ).asBool();
    short newConstraintMode = data.inputValue(aConstraintMode).asShort();
    double newConstraintWeight = data.inputValue( aConstraintWeight ).asDouble();
    if ( oCageMesh.isNull() || blendMode == 99)
        return MS::kSuccess;
    short newCageMode = data.inputValue(aCageMode).asShort();
    MFnMesh fnCageMesh( oCageMesh, &status );
    CHECK_MSTATUS_AND_RETURN_IT( status );
    MPointArray cagePoints;
    fnCageMesh.getPoints( cagePoints,  MSpace::kWorld );
    // save initial cage state
    if (initCagePoints.length() != cagePoints.length()){
        initCageMesh = oCageMesh;
        initCagePoints=cagePoints;
    }
    // when cage mode is changed
    if(newCageMode != cageMode || newConstraintMode != constraintMode || newConstraintWeight != constraintWeight)
    {
        cageMode = newCageMode;
        constraintMode = newConstraintMode;
        constraintWeight = newConstraintWeight;
	    std::vector<double> tetWeight;
        // read target mesh data
        MArrayDataHandle hInput = data.outputArrayValue( input, &status );
        CHECK_MSTATUS_AND_RETURN_IT( status );
        status = hInput.jumpToElement( mIndex );
        CHECK_MSTATUS_AND_RETURN_IT( status );
        MObject oInputGeom = hInput.outputValue().child( inputGeom ).asMesh();
        MFnMesh inputMesh(oInputGeom);
        inputMesh.getPoints( pts );
		numPts=pts.length();
        for(int j=0; j<numPts; j++ )
            pts[j] *= localToWorldMatrix;
        MIntArray count;
        inputMesh.getTriangles( count, meshTriangles );
		numTet=meshTriangles.length()/3;
		std::vector<Matrix4d> P(numTet);
        tetCenter.resize(numTet);
        tetMatrixC(pts, meshTriangles, P, tetCenter);
        PI.resize(numTet);
		for(int i=0;i<numTet;i++)
			PI[i] = P[i].inverse();
        // prepare cage tetrahedra
        MFnMesh fnInitCageMesh( initCageMesh, &status );
        if(cageMode == 10 || cageMode == 11)  // face mode
        {
			if(cageMode == 10){       // triangulate faces by MAYA standard
                MIntArray count;
                fnInitCageMesh.getTriangles( count, triangles );
                tetWeight.resize(triangles.length()/3, 1.0f);
			}else if(cageMode ==11){  // trianglate faces with more than 3 edges in a symmetric way
				triangles.clear();
				MItMeshPolygon iter(initCageMesh);
				MIntArray tmp;
                MVector normal;
				tetWeight.reserve(4*iter.count());
                unsigned int l;
				for(unsigned int i=0; ! iter.isDone(); i++){
					iter.getVertices(tmp);
					l=tmp.length();
					if(l==3){
						tetWeight.push_back(1.0);
						triangles.append(tmp[0]);
						triangles.append(tmp[1]);
						triangles.append(tmp[2]);
					}else{
						for(unsigned int j=0;j<l;j++){
                            tetWeight.push_back((l-2.0)/l);
							triangles.append(tmp[j]);
							triangles.append(tmp[(j+1) % l]);
							triangles.append(tmp[(j+2) % l]);
						}
					}
					iter.next();
				}
            }
            // face mode compute init matrix
            numPrb=triangles.length()/3;
            initMatrix.resize(numPrb);
            tetMatrix(initCagePoints, triangles, cageMode, initMatrix);
            // compute weight
            w.resize(numTet);
            std::vector< std::vector<double> > idist(numTet);
            for(int j=0;j<numTet;j++){
                idist[j].resize(numPrb);
                w[j].resize(numPrb);
                double sidist = 0.0;
                for(int i=0;i<numPrb;i++){
                    idist[j][i] = tetWeight[i]/distPtTri(tetCenter[j],initMatrix[i]);
                    sidist += idist[j][i];
                }
                assert(sidist>0.0f);
                for(int i=0;i<numPrb;i++)
                    w[j][i] = idist[j][i] /sidist;
            }// face mode end
        }else if(cageMode == 0 || cageMode == 1){   // vertex mode
            triangles.clear();
            std::vector<int> tetCount(initCagePoints.length());
            MItMeshVertex iter(initCageMesh);
            for(int j=0; ! iter.isDone(); j++){
                MIntArray v;
                iter.getConnectedVertices(v);     // at each vertex, construct tetrahedra from connected edges
                int l=v.length();
                if(l==3){
                    if(isDegenerate(initCagePoints[j],initCagePoints[v[0]],initCagePoints[v[1]],initCagePoints[v[2]]) != 0){
                        tetCount[j]++;
                        triangles.append(j);
                        triangles.append(v[0]);
                        triangles.append(v[1]);
                        triangles.append(v[2]);
                    }
                }else{
                    for(int k=0;k<l;k++){
                        if(isDegenerate(initCagePoints[j],initCagePoints[v[k]],initCagePoints[v[(k+1) % l]],initCagePoints[v[(k+2) % l]]) != 0){
                            tetCount[j]++;
                            triangles.append(j);
                            triangles.append(v[k]);
                            triangles.append(v[(k+1) % l]);
                            triangles.append(v[(k+2) % l]);
                        }
                    }
                }
                iter.next();
            }
            numPrb=triangles.length()/4;
            initMatrix.resize(numPrb);
            tetMatrix(initCagePoints, triangles, cageMode, initMatrix);
            // vertex mode compute weight
            w.resize(numTet);
            std::vector< std::vector<double> > idist(numTet);
            tetWeight.resize(numPrb);
            for(int i=0;i<numPrb;i++)
                tetWeight[i]=1.0/(double)tetCount[triangles[4*i]];
            for(int j=0;j<numTet;j++){
                idist[j].resize(numPrb);
                w[j].resize(numPrb);
                double sidist = 0.0;
                for(int i=0;i<numPrb;i++){
                    Vector3d c(initCagePoints[triangles[4*i]].x,initCagePoints[triangles[4*i]].y,initCagePoints[triangles[4*i]].z);
                    idist[j][i] = tetWeight[i] / ((tetCenter[j]-c).squaredNorm());
                    sidist += idist[j][i];
                }
                assert(sidist>0.0f);
                for(int i=0;i<numPrb;i++)
                    w[j][i] = idist[j][i] /sidist;
            }
        }else if(cageMode == 5 || cageMode == 6 ){ // vertex averaged normal mode
            triangles.clear();
            std::vector<int> tetCount(initCagePoints.length());
            MItMeshVertex iter(initCageMesh);
            for(int j=0; ! iter.isDone(); j++){
                MIntArray v;
                iter.getConnectedVertices(v);
                int l=v.length();
                for(int k=0;k<l;k++){
                    tetCount[j]++;
                    triangles.append(j);
                    triangles.append(v[k]);
                    triangles.append(v[(k+1) % l]);
                }
                iter.next();
            }
            numPrb=triangles.length()/3;
            initMatrix.resize(numPrb);
            tetMatrix(initCagePoints, triangles, cageMode, initMatrix);
            // vertex mode compute weight
            w.resize(numTet);
            std::vector< std::vector<double> > idist(numTet);
            tetWeight.resize(numPrb);
            for(int i=0;i<numPrb;i++)
                tetWeight[i]=1.0/(double)tetCount[triangles[3*i]];
            for(int j=0;j<numTet;j++){
                idist[j].resize(numPrb);
                w[j].resize(numPrb);
                double sidist = 0.0;
                for(int i=0;i<numPrb;i++){
                    Vector3d c(initCagePoints[triangles[3*i]].x,initCagePoints[triangles[3*i]].y,initCagePoints[triangles[3*i]].z);
                    idist[j][i] = tetWeight[i] / ((tetCenter[j]-c).squaredNorm());
                    sidist += idist[j][i];
                }
                assert(sidist>0.0f);
                for(int i=0;i<numPrb;i++)
                    w[j][i] = idist[j][i] /sidist;
            }
        }// end of cage setup
        
        // find constraint points
        if(constraintMode == 1){
            numConstraint = numPrb;
        }else{
            numConstraint = 1;    // at least one constraint is necessary to determine global translation
        }
        constraintTet.resize(numConstraint);
        constraintVector.resize(numConstraint);
        // for each cage tetrahedra, constraint the point on the mesh with largest weight
        for(int i=0;i<numConstraint;i++){
            constraintTet[i] = 0;
            for(int j=1;j<numTet;j++){
                if(w[j][i] > w[constraintTet[i]][i]){
                    constraintTet[i] = j;
                }
            }
            constraintVector[i] << tetCenter[constraintTet[i]](0), tetCenter[constraintTet[i]](1), tetCenter[constraintTet[i]](2), 1.0;
        }
        // precompute arap solver
        arapHI(PI, meshTriangles);
    }
    // compute deformation
    if( ! rotationCosistency || numPrb != prevNs.size()){        // clear previous rotation
        prevThetas.clear();
        prevThetas.resize(numPrb, 0.0);
        prevNs.clear();
        prevNs.resize(numPrb, Vector3d::Zero());
    }
    //  find affine transformations for tetrahedra
    std::vector<Matrix4d> cageMatrix(numPrb), SE(numPrb), logSE(numPrb),logAff(numPrb),aff(numPrb);
    std::vector<Matrix3d> logR(numPrb),R(numPrb),logS(numPrb),logGL(numPrb);
    std::vector<Vector3d> L(numPrb);
    std::vector<Vector4d> quat(numPrb);
    tetMatrix(cagePoints, triangles, cageMode, cageMatrix);
    for(int i=0; i<numPrb; i++)
        aff[i]=initMatrix[i].inverse()*cageMatrix[i];
    // compute parametrisation
    if(blendMode == 0 || blendMode == 1 || blendMode == 5)  // polarexp or quaternion
    {
        for(unsigned int i=0;i<numPrb;i++){
            parametriseGL(aff[i].block(0,0,3,3), logS[i] ,R[i]);
            L[i] = transPart(aff[i]);
            if(blendMode == 0){  // Rotational log
                logR[i]=logSOc(R[i], prevThetas[i], prevNs[i]);
            }else if(blendMode == 1){ // Eucledian log
                SE[i]=affine(R[i], L[i]);
                logSE[i]=logSEc(SE[i], prevThetas[i], prevNs[i]);
            }else if(blendMode == 5){ // quaternion
                Quaternion<double> Q(R[i].transpose());
                quat[i] << Q.x(), Q.y(), Q.z(), Q.w();
            }
        }
    }else if(blendMode == 2){    //logmatrix3
        for(unsigned int i=0;i<numPrb;i++){
            logGL[i] = aff[i].block(0,0,3,3).log();
            L[i] = transPart(aff[i]);
        }
    }else if(blendMode == 3){   // logmatrix4
        for(unsigned int i=0;i<numPrb;i++){
            logAff[i] = aff[i].log();
        }
    }
    // compute blended matrices
#pragma omp parallel for
    std::vector<Matrix4d> At(numTet);
    for(int j=0; j<numTet; j++ ){
        if(blendMode==0){
            Matrix3d RR=Matrix3d::Zero();
            Matrix3d SS=Matrix3d::Zero();
            Vector3d l=Vector3d::Zero();
            for(unsigned int i=0; i<numPrb; i++){
                RR += w[j][i] * logR[i];
                SS += w[j][i] * logS[i];
                l += w[j][i] * L[i];
            }
            SS = expSym(SS);
            if(frechetSum){
                RR = frechetSO(R, w[j]);
            }else{
                RR = expSO(RR);
            }
            At[j] = affine(SS*RR, l);
        }else if(blendMode==1){    // rigid transformation
            Matrix4d EE=Matrix4d::Zero();
            Matrix3d SS=Matrix3d::Zero();
            for(unsigned int i=0; i<numPrb; i++){
                EE +=  w[j][i] * logSE[i];
                SS +=  w[j][i] * logS[i];
            }
            if(frechetSum){
                EE = frechetSE(SE, w[j]);
            }else{
                EE = expSE(EE);
            }
            At[j] = affine(expSym(SS),Vector3d::Zero())*EE;
        }else if(blendMode == 2){    //logmatrix3
            Matrix3d G=Matrix3d::Zero();
            Vector3d l=Vector3d::Zero();
            for(unsigned int i=0; i<numPrb; i++){
                G +=  w[j][i] * logGL[i];
                l += w[j][i] * L[i];
            }
            At[j] = affine(G.exp(), l);
        }else if(blendMode == 3){   // logmatrix4
            Matrix4d A=Matrix4d::Zero();
            for(unsigned int i=0; i<numPrb; i++)
                A +=  w[j][i] * logAff[i];
            At[j] = A.exp();
        }else if(blendMode == 5){ // quaternion
            Vector4d q=Vector4d::Zero();
            Matrix3d SS=Matrix3d::Zero();
            Vector3d l=Vector3d::Zero();
            for(unsigned int i=0; i<numPrb; i++){
                q += w[j][i] * quat[i];
                SS += w[j][i] * logS[i];
                l += w[j][i] * L[i];
            }
            SS = expSym(SS);
            Quaternion<double> Q(q);
            Matrix3d RR = Q.matrix().transpose();
            At[j] = affine(SS*RR, l);
        }else if(blendMode==10){
            At[j] = Matrix4d::Zero();
            for(unsigned int i=0; i<numPrb; i++){
                At[j] += w[j][i] * aff[i];
            }
        }
    }
    
    // compute target vertices position
    MatrixXd G=MatrixXd::Zero(numTet+numPts,3);
    arapG(At, PI, meshTriangles, aff, G);
    MatrixXd Sol = solver.solve(G);
    for(unsigned int i=0;i<numPts;i++){
        pts[i].x=Sol(i,0);
        pts[i].y=Sol(i,1);
        pts[i].z=Sol(i,2);
        pts[i] *= localToWorldMatrix.inverse();
    }
    itGeo.setAllPositions(pts);
    return MS::kSuccess;
}
MStatus sphericalBlendShape::deform(MDataBlock& data, MItGeometry& itGeo, const MMatrix& mat, unsigned int geomIndex) 
{
	MStatus status = MS::kSuccess;

	float env = data.inputValue(envelope).asFloat();
	if (env <= 0.0f) {
		return MS::kSuccess;
	}

	MMatrix spaceMatrix = data.inputValue(aSpaceMatrix).asMatrix();
	short poleAxis		= data.inputValue(aPoleAxis).asShort();
	short seamAxis		= data.inputValue(aSeamAxis).asShort();
	short method		= data.inputValue(aMethod).asShort();
	MMatrix warpMatrix	= data.inputValue(aWarpMatrix).asMatrix();

	MTransformationMatrix warpTransMatrix(warpMatrix);
	MPoint warpPoint = warpTransMatrix.getTranslation(MSpace::kWorld);
	
	status = checkPoleAndSeam(poleAxis, seamAxis);
	CHECK_MSTATUS_AND_RETURN_IT(status);


	MMatrix invGeoMatrix   = mat.inverse();
	MMatrix invSpaceMatrix = spaceMatrix.inverse();

	MPointArray defPoints;
	MPoint* defPoint;
	MPoint inPoint, returnPoint;

	itGeo.allPositions(defPoints);
	unsigned int count = defPoints.length();

	unsigned int i;
	switch(method) {
		// XYZ to Spherical
	case 0:
		for (i=0; i<count; i++) {
			defPoint = &defPoints[i];
			inPoint = *defPoint;

			// bring the point into world space
			inPoint *= invGeoMatrix;
			// bring into local space of the input matrix
			inPoint *= invSpaceMatrix;

			cartesianToSpherical(inPoint, poleAxis, seamAxis, warpPoint, returnPoint);

			// bring the point back into world space
			returnPoint *= spaceMatrix;
			// bring the point back into local space
			returnPoint *= mat;
				
			lerp(*defPoint, returnPoint, env, *defPoint);
		}
		break;

	case 1:
		for (i=0; i<count; i++) {
			defPoint = &defPoints[i];
			inPoint = *defPoint;

			// bring the point into world space
			inPoint *= invGeoMatrix;
			// bring into local space of the input matrix
			inPoint *= invSpaceMatrix;

			sphericalToCartesian(inPoint, poleAxis, seamAxis, warpPoint, returnPoint);

			// bring the point back into world space
			returnPoint *= spaceMatrix;
			// bring the point back into local space
			returnPoint *= mat;
				
			lerp(*defPoint, returnPoint, env, *defPoint);
		}
		break;
	}

	itGeo.setAllPositions(defPoints);

	return MS::kSuccess;
}
Example #24
0
MStatus snapDeformer::deform(MDataBlock &data, MItGeometry &iter, const MMatrix &mat, unsigned int multiIndex) {
	MStatus stat;


    //lets see if we need to do anything
	MDataHandle DataHandle = data.inputValue(envelope, &stat);
	float env = DataHandle.asFloat();
	if (env == 0)
		return stat;
    DataHandle = data.inputValue(weight, &stat);
	const float weight = DataHandle.asFloat();
    if (weight == 0)
		return stat;
    
    env = (env*weight);


	//space target
	DataHandle = data.inputValue(space, &stat);
    int SpaceInt = DataHandle.asInt();

    //space source
	DataHandle = data.inputValue(spaceSource, &stat);
    int SpaceSourceInt = DataHandle.asInt();

    //pointlist
    MArrayDataHandle pointArrayHandle = data.inputArrayValue(pointList);


	//snapMesh
	MFnMesh	SnapMesh;
	DataHandle = data.inputValue(snapMesh, &stat);
    if (!stat)
        return Err(stat,"Can't get mesh to snap to");
    MObject SnapMeshObj = DataHandle.asMesh();
    SnapMesh.setObject(SnapMeshObj);
    MPointArray snapPoints;
    if (SpaceSourceInt==0)
        SnapMesh.getPoints(snapPoints, MSpace::kWorld);
    else
        SnapMesh.getPoints(snapPoints, MSpace::kObject);
    


    iter.reset();
    for ( ; !iter.isDone(); iter.next()) 	{
        //check for painted weights
        float currEnv = env * weightValue(data, multiIndex, iter.index());

        //get point to snap to
        unsigned int index;
        stat = pointArrayHandle.jumpToElement(iter.index());
        if (!stat)
            index = 0;
        else {
            DataHandle = pointArrayHandle.outputValue();
            index = DataHandle.asInt();
        }

        if (index != -1) {
            //calc point location
            MPoint currPoint;
            if (snapPoints.length() > index)
                currPoint = snapPoints[index];

            if (SpaceInt == 0)
                currPoint *= mat.inverse();

            if (currEnv !=1)
            {
                MPoint p = (currPoint- iter.position());
                currPoint = iter.position() + (p*currEnv);
            }


            //set point location
            iter.setPosition(currPoint);
        }
            
            
    }

    return stat;
}
Example #25
0
//
//      Deform computation
//
MStatus jhMeshBlur::deform( MDataBlock& block,MItGeometry& iter,const MMatrix& m,unsigned int multiIndex)
{
    MStatus returnStatus;

    // Envelope
    float envData = block.inputValue(envelope, &returnStatus).asFloat();
	CHECK_MSTATUS(returnStatus);

    if(envData == 0)
		return MS::kFailure;

    /*
     VARIABLES
     */
    //float factor = block.inputValue(aShapeFactor, &returnStatus).asFloat();
    float fStrength = block.inputValue(aStrength, &returnStatus).asFloat();
	CHECK_MSTATUS(returnStatus);
	
	if (fStrength == 0)
		return MS::kFailure;
	
    float fThreshold = block.inputValue(aTreshhold, &returnStatus).asFloat();
	CHECK_MSTATUS(returnStatus);
    float fW = 0.0f; // weight
    float fDistance;
    fStrength *= envData;

    double dKracht = block.inputValue(aInterpPower, &returnStatus).asDouble();
	CHECK_MSTATUS(returnStatus);
    double dDotProduct;  // Dotproduct of the point

    bool bTweakblur = block.inputValue(aTweakBlur, &returnStatus).asBool();
	CHECK_MSTATUS(returnStatus);
	
    bool bQuad = block.inputValue(aQuadInterp, &returnStatus).asBool();
	CHECK_MSTATUS(returnStatus);
	
	MTime inTime = block.inputValue(aTime).asTime();
    int nTijd = (int)inTime.as(MTime::kFilm);


    MFloatVectorArray currentNormals;   // normals of mesh
    MFnPointArrayData fnPoints;         // help converting to MPointArrays
    MFloatVector dirVector;             // direction vector of the point
    MFloatVector normal;                // normal of the point
    MPointArray savedPoints;            // save all point before edited
    MMatrix matInv = m.inverse();       // inversed matrix
    MPoint ptA;                         // current point (iter mesh)
    MPoint ptB;                         // previous point (iter mesh)
    MPoint ptC;                         // mesh before previous point (iter mesh)

    // get node, use node to get inputGeom, use inputGeom to get mesh data, use mesh data to get normal data
    MFnDependencyNode nodeFn(this->thisMObject());

    MPlug inGeomPlug(nodeFn.findPlug(this->inputGeom,true));
    MObject inputObject(inGeomPlug.asMObject());
    MFnMesh inMesh(inputObject);

    inMesh.getVertexNormals(true, currentNormals);

    // get the previous mesh data
    MPlug oldMeshPlug = nodeFn.findPlug(MString("oldMesh"));
    MPlug oldMeshPositionsAPlug = oldMeshPlug.elementByLogicalIndex((multiIndex*4) + 0);
    MPlug oldMeshPositionsBPlug = oldMeshPlug.elementByLogicalIndex((multiIndex*4) + 1);
    MPlug oldMeshPositionsCPlug = oldMeshPlug.elementByLogicalIndex((multiIndex*4) + 2); // cache for tweak mode
    MPlug oldMeshPositionsDPlug = oldMeshPlug.elementByLogicalIndex((multiIndex*4) + 3); // cache for tweak mode

    // convert to MPointArrays
    MObject objOldMeshA;
    MObject objOldMeshB;
    MObject objOldMeshC; // cache
    MObject objOldMeshD; // cache

    oldMeshPositionsAPlug.getValue(objOldMeshA);
    oldMeshPositionsBPlug.getValue(objOldMeshB);
    oldMeshPositionsCPlug.getValue(objOldMeshC); // cache
    oldMeshPositionsDPlug.getValue(objOldMeshD); // cache

    fnPoints.setObject(objOldMeshA);
    MPointArray oldMeshPositionsA = fnPoints.array();
    
    fnPoints.setObject(objOldMeshB);
    MPointArray oldMeshPositionsB = fnPoints.array();
    
    fnPoints.setObject(objOldMeshC);
    MPointArray oldMeshPositionsC = fnPoints.array(); // cache
    
    fnPoints.setObject(objOldMeshD);
    MPointArray oldMeshPositionsD = fnPoints.array(); // cache

    
    
    // If mesh position variables are empty,fill them with default values
    if(oldMeshPositionsA.length() == 0 || nTijd <= 1){
        iter.allPositions(oldMeshPositionsA);

        for(int i=0; i < oldMeshPositionsA.length(); i++)
        {
            // convert to world
            oldMeshPositionsA[i] = oldMeshPositionsA[i] * m;
        }
		
        oldMeshPositionsB.copy(oldMeshPositionsA);
        oldMeshPositionsC.copy(oldMeshPositionsA); // cache
        oldMeshPositionsD.copy(oldMeshPositionsA); // cache
    }
	
	// get back old date again
	if (bTweakblur == true) { // restore cache
		oldMeshPositionsA.copy(oldMeshPositionsC);
		oldMeshPositionsB.copy(oldMeshPositionsD);
	}
    
    
    iter.allPositions(savedPoints);
    for(int i=0; i < savedPoints.length(); i++)
    {
        // convert points to world points
        savedPoints[i] = savedPoints[i] * m;
    }

    // Actual Iteration through points
    for (; !iter.isDone(); iter.next()){
        // get current position
        ptA = iter.position();
        // get old positions
        ptB = oldMeshPositionsA[iter.index()] * matInv;
        ptC = oldMeshPositionsB[iter.index()] * matInv;

        fDistance = ptA.distanceTo(ptB);
        fW = weightValue(block,multiIndex,iter.index());


        if (fDistance * (fStrength*fW) < fThreshold && fThreshold > 0){
            iter.setPosition(ptA);
        } else {
            // aim/direction vector to calculate strength
            dirVector = (ptA - ptB); // (per punt)
            dirVector.normalize();

            normal = currentNormals[iter.index()];

            dDotProduct = normal.x * dirVector.x + normal.y * dirVector.y + normal.z * dirVector.z;

            
            if(bQuad == true){
                MVector vecA(((ptB - ptC) + (ptA - ptB)) / 2);
                vecA.normalize();

                MPoint hiddenPt(ptB + (vecA * fDistance) * dKracht);
                ptA = quadInterpBetween(ptB, hiddenPt, ptA, (1 - fStrength * fW) + (linearInterp(dDotProduct, -1, 1) * (fStrength * fW) ) );
            } else {
                MPoint halfway = (ptA - ptB) * 0.5;
                MPoint offset = halfway * dDotProduct * (fStrength*fW);
                ptA = ptA - ((halfway * (fStrength*fW)) - offset); // + (offset * strength);
            }
            // set new value

            iter.setPosition(ptA);
        }
    }
    if(bTweakblur == false){
        oldMeshPositionsD.copy(oldMeshPositionsB);
        oldMeshPositionsC.copy(oldMeshPositionsA);
        oldMeshPositionsB.copy(oldMeshPositionsA);
        oldMeshPositionsA.copy(savedPoints);

        // Save back to plugs
        objOldMeshA = fnPoints.create(oldMeshPositionsA);
        objOldMeshB = fnPoints.create(oldMeshPositionsB);
        objOldMeshC = fnPoints.create(oldMeshPositionsC);
        objOldMeshD = fnPoints.create(oldMeshPositionsD);
		
        oldMeshPositionsAPlug.setValue(objOldMeshA);
        oldMeshPositionsBPlug.setValue(objOldMeshB);
        oldMeshPositionsCPlug.setValue(objOldMeshC);
        oldMeshPositionsDPlug.setValue(objOldMeshD);
    }
    
    return returnStatus;
}
Example #26
0
// COMPUTE ======================================
MStatus gear_slideCurve2::deform( MDataBlock& data, MItGeometry& iter, const MMatrix &mat, unsigned int mIndex )
{
    MStatus returnStatus;
	
    // Inputs ---------------------------------------------------------
    // Input NurbsCurve
	// Curve
	MFnNurbsCurve crv( data.inputValue( master_crv ).asNurbsCurve() );
    MMatrix m = data.inputValue(master_mat).asMatrix();
        
    // Input Sliders
    double in_sl = (double)data.inputValue(slave_length).asFloat();
    double in_ml = (double)data.inputValue(master_length).asFloat();
    double in_position = (double)data.inputValue(position).asFloat();
    double in_maxstretch = (double)data.inputValue(maxstretch).asFloat();
	double in_maxsquash = (double)data.inputValue(maxsquash).asFloat();
    double in_softness = (double)data.inputValue(softness).asFloat();
	
    // Init -----------------------------------------------------------
    double mstCrvLength = crv.length();

    int slvPointCount = iter.exactCount(); // Can we use .count() ? 
    int mstPointCount = crv.numCVs();
	
    // Stretch --------------------------------------------------------
	double expo = 1;
    if ((mstCrvLength > in_ml) && (in_maxstretch > 1)){
        if (in_softness != 0){
            double stretch = (mstCrvLength - in_ml) / (in_sl * in_maxstretch);
            expo = 1 - exp(-(stretch) / in_softness);
		}

        double ext = min(in_sl * (in_maxstretch - 1) * expo, mstCrvLength - in_ml);

        in_sl += ext;
	}
    else if ((mstCrvLength < in_ml) && (in_maxsquash < 1)){
        if (in_softness != 0){
            double squash = (in_ml - mstCrvLength) / (in_sl * in_maxsquash);
            expo = 1 - exp(-(squash) / in_softness);
		}

        double ext = min(in_sl * (1 - in_maxsquash) * expo, in_ml - mstCrvLength);

        in_sl -= ext;
	}
		
    // Position --------------------------------------------------------
    double size = in_sl / mstCrvLength;
    double sizeLeft = 1 - size;

    double start = in_position * sizeLeft;
    double end = start + size;

	double tStart, tEnd;
	crv.getKnotDomain(tStart, tEnd);
	
    // Process --------------------------------------------------------
    double step = (end - start) / (slvPointCount - 1.0);
    MPoint pt;
	MVector tan;
    while (! iter.isDone()){
        double perc = start + (iter.index() * step);

        double u = crv.findParamFromLength(perc * mstCrvLength);

        if ((0 <= perc) && (perc <= 1))
            crv.getPointAtParam(u, pt, MSpace::kWorld);
        else{
			double overPerc;
            if (perc < 0){
                overPerc = perc;
                crv.getPointAtParam(0, pt, MSpace::kWorld);
                tan = crv.tangent(0);
			}
            else{
                overPerc = perc - 1;
                crv.getPointAtParam(mstPointCount-3.0, pt, MSpace::kWorld);
                tan = crv.tangent(mstPointCount-3.0);

            tan.normalize();
            tan *= mstCrvLength * overPerc;

            pt += tan;
			}
		}

        pt *= mat.inverse();
        pt *= m;
        iter.setPosition(pt);
        iter.next();
	}
 
    return MS::kSuccess;
}
Example #27
0
MStatus sgBulgeDeformer::deform(MDataBlock& dataBlock, MItGeometry& iter, const MMatrix& mtx, unsigned int index)
{
	MStatus status;

	float bulgeWeight = dataBlock.inputValue(aBulgeWeight).asFloat();
	double bulgeRadius = dataBlock.inputValue(aBulgeRadius).asDouble();

	MArrayDataHandle hArrInputs = dataBlock.inputArrayValue(aBulgeInputs);

	MPointArray allPositions;
	iter.allPositions(allPositions);

	if (mem_resetElements)
	{
		unsigned int elementCount = hArrInputs.elementCount();
		mem_meshInfosInner.resize(mem_maxLogicalIndex);
		mem_meshInfosOuter.resize(mem_maxLogicalIndex);

		for (unsigned int i = 0; i < elementCount; i++, hArrInputs.next())
		{
			MDataHandle hInput = hArrInputs.inputValue();
			MDataHandle hMatrix = hInput.child(aMatrix);
			MDataHandle hMesh   = hInput.child(aMesh);

			MMatrix mtxMesh = hMatrix.asMatrix();
			MObject oMesh   = hMesh.asMesh();

			MFnMeshData meshDataInner, meshDataOuter;
			MObject oMeshInner = meshDataInner.create();
			MObject oMeshOuter = meshDataOuter.create();
			MFnMesh fnMesh;
			fnMesh.copy(oMesh, oMeshInner);
			fnMesh.copy(oMesh, oMeshOuter);

			sgMeshInfo* newMeshInfoInner = new sgMeshInfo(oMeshInner, hMatrix.asMatrix());
			sgMeshInfo* newMeshInfoOuter = new sgMeshInfo(oMeshOuter, hMatrix.asMatrix());

			mem_meshInfosInner[hArrInputs.elementIndex()] = newMeshInfoInner;
			mem_meshInfosOuter[hArrInputs.elementIndex()] = newMeshInfoOuter;
		}
	}
	
	for (unsigned int i = 0; i < elementCount; i++)
	{
		mem_meshInfosInner[i]->setBulge(bulgeWeight, MSpace::kWorld );
	}
	
	MFloatArray weightList;
	weightList.setLength(allPositions.length());
	for (unsigned int i = 0; i < weightList.length(); i++)
		weightList[i] = 0.0f;
	MMatrixArray inputMeshMatrixInverses;
	inputMeshMatrixInverses.setLength(elementCount);
	for (unsigned int i = 0; i < elementCount; i++)
	{
		inputMeshMatrixInverses[i] = mem_meshInfosInner[i]->matrix();
	}

	for (unsigned int i = 0; i < allPositions.length(); i++)
	{
		float resultWeight = 0;
		for (unsigned int infoIndex = 0; infoIndex < elementCount; infoIndex++)
		{
			MPoint localPoint = allPositions[i] * mtx* inputMeshMatrixInverses[infoIndex];
			MPoint innerPoint = mem_meshInfosInner[infoIndex]->getClosestPoint(localPoint);
			MPoint outerPoint = mem_meshInfosOuter[infoIndex]->getClosestPoint(localPoint);
			MVector innerVector = innerPoint - localPoint;
			MVector outerVector = outerPoint - localPoint;

			if (innerVector * outerVector < 0)
			{
				double innerLength = innerVector.length();
				double outerLength = outerVector.length();
				double allLength = innerLength + outerLength;

				float numerator = float( innerLength * outerLength );
				float denominator = float( pow(allLength / 2.0, 2) );

				resultWeight = numerator / denominator;
			}
		}
		weightList[i] = resultWeight;
	}

	for (unsigned int i = 0; i < allPositions.length(); i++)
	{
		allPositions[i] += weightList[i] * MVector(0, 1, 0);
	}
	
	iter.setAllPositions(allPositions);

	return MS::kSuccess;
}
Example #28
0
MStatus vxCacheDeformer::deform( MDataBlock& block,
				MItGeometry& iter,
				const MMatrix& m,
				unsigned int multiIndex)
{
	MStatus returnStatus;
	
	MDataHandle envData = block.inputValue(envelope,&returnStatus);
	float env = envData.asFloat();
	if(env == 0) return returnStatus;
	
	double time = block.inputValue( frame ).asTime().value();
	
	MDataHandle inPathData = block.inputValue( path );
	MString str_path =  inPathData.asString();
	
	MDataHandle inMinFrmData = block.inputValue( aminframe );
	int minfrm = inMinFrmData.asInt();
	
	MDataHandle inMaxFrmData = block.inputValue( amaxframe );
	MDataHandle inFrmStepData = block.inputValue( aframestep );
	int frmstep = inFrmStepData.asInt();
	
	if( time < minfrm )
		time = minfrm;
		
	int frame_lo = minfrm + int(time-minfrm)/frmstep*frmstep;
	int frame_hi = frame_lo+frmstep;
	
	if( strlen( str_path.asChar() ) > 0 ) 
	{
	
		char filename[256];
		sprintf( filename, "%s.%d.mcf", str_path.asChar(), frame_lo );
	
		FMCFMesh mesh;
		if(mesh.load(filename) != 1)
		{
			MGlobal::displayError( MString("Failed to open file: ") + filename );
			return MS::kFailure;
		}
		
		int lo_n_vertex = mesh.getNumVertex();
		
		vertexArray.clear();
		vertexFArray.clear();
		
		XYZ tp;
		for(unsigned int i = 0; i < mesh.getNumVertex(); i++) {
			mesh.getVertex(tp, i);
			vertexArray.append( MPoint( tp.x, tp.y, tp.z ) );
		}

		if( time > frame_lo ) 
		{
			sprintf( filename, "%s.%d.mcf", str_path.asChar(), frame_hi );

			if(mesh.load(filename) != 1) MGlobal::displayError( MString("Failed to open file: ") + filename );

			else if(mesh.getNumVertex() == lo_n_vertex)
			{
				XYZ tp;
				for(unsigned int i = 0; i < mesh.getNumVertex(); i++) 
				{
					mesh.getVertex(tp, i);
					vertexFArray.append( MPoint( tp.x, tp.y, tp.z ) );
				}
				
				double alpha = double(time-frame_lo) / (double)frmstep;

				for(unsigned int i = 0; i < mesh.getNumVertex(); i++) {
					
					vertexArray[i] = vertexArray[i] + ( vertexFArray[i] - vertexArray[i] )*alpha;
					
				}
			}
		}

		// iterate through each point in the geometry
		//
		for ( ; !iter.isDone(); iter.next()) 
		{
			MPoint pt = iter.position();
			pt = pt + (vertexArray[iter.index()] - pt)*env;
			iter.setPosition(pt);
		}
	}
	
	return returnStatus;
}