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; }
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; }
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; }
// // 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; }
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; }
MStatus PushDeformer::deform(MDataBlock& dataBlock, MItGeometry& itGeo, const MMatrix& localToWorldMatrix, unsigned int geomIndex) { MStatus status; //get attribute handles double bulgeAmount = dataBlock.inputValue(aAmount, &status).asDouble(); CHECK_MSTATUS_AND_RETURN_IT(status); m_taskData.envelope = dataBlock.inputValue(envelope, &status).asFloat(); CHECK_MSTATUS_AND_RETURN_IT(status); bool useStressV = dataBlock.inputValue(aUseStress, &status).asBool(); CHECK_MSTATUS_AND_RETURN_IT(status); int multiThreadingType = dataBlock.inputValue(aMultiThreadingType, &status).asBool(); CHECK_MSTATUS_AND_RETURN_IT(status); if (m_taskData.envelope <= 0.001) { return MS::kSuccess; } // if the use stress plug is turned on pull MDoubleArray stressV; if (useStressV == true) { //pull out the raw data as an Mobject MObject stressMap = dataBlock.inputValue(aStressMap, &status).data(); CHECK_MSTATUS_AND_RETURN_IT(status); MFnDoubleArrayData stressDataFn(stressMap); m_taskData.stressV = stressDataFn.array(); } //retrieve the handle to the output array attribute MArrayDataHandle hInput = dataBlock.outputArrayValue(input, &status); CHECK_MSTATUS_AND_RETURN_IT(status); //get the input array index handle status = hInput.jumpToElement(geomIndex); //get the handle of geomIndex attribute MDataHandle hInputElement = hInput.outputValue(&status); CHECK_MSTATUS_AND_RETURN_IT(status); //Get the MObject of the input geometry of geomindex MObject oInputGeom = hInputElement.child(inputGeom).asMesh(); MFnMesh fnMesh(oInputGeom, &status); CHECK_MSTATUS_AND_RETURN_IT(status); fnMesh.getVertexNormals(false, m_taskData.normals, MSpace::kWorld); itGeo.allPositions(m_taskData.points, MSpace::kWorld); //MGlobal::displayInfo( "test" ); /*for (int i = 0; i < itGeo.count(); i++) { MGlobal::displayInfo( MFnAttribute(weightList).isArray ); }*/ m_taskData.bulgeAmount = bulgeAmount; if(multiThreadingType == 1) { ThreadData* pThreadData = createThreadData( NUM_TASKS, &m_taskData ); MThreadPool::newParallelRegion( createTasks, (void*)pThreadData ); itGeo.setAllPositions(m_taskData.points); delete [] pThreadData; return MS::kSuccess; } else if(multiThreadingType == 2) { tbb::parallel_for(size_t(0), size_t(itGeo.count()), [this](size_t i) { //const float w = weightValue(dataBlock, geomIndex, i); const float w = 1.0; if (m_taskData.useStressV == true && (m_taskData.stressV.length() > 0)) { //deform m_taskData.points[i] += (MVector(m_taskData.normals[i]) * m_taskData.bulgeAmount * m_taskData.envelope * w * m_taskData.stressV[i]); } else { //deform m_taskData.points[i] += m_taskData.normals[i] * m_taskData.bulgeAmount * m_taskData.envelope * w; } }); } // else if(multiThreadingType == 3) #pragma omp parallel for for (int i = 0; i < itGeo.count(); i++) { float w = weightValue(dataBlock, geomIndex, itGeo.index()); if (useStressV == true && (stressV.length() > 0)) { //deform m_taskData.points[i] += (MVector(m_taskData.normals[i]) * bulgeAmount * m_taskData.envelope * w * m_taskData.stressV[i]); } else { //deform m_taskData.points[i] += m_taskData.normals[i] * bulgeAmount * m_taskData.envelope * w; } } else { for (; !itGeo.isDone(); itGeo.next()) { float w = weightValue(dataBlock, geomIndex, itGeo.index()); if (useStressV == true && (stressV.length() > 0)) { //deform m_taskData.points[itGeo.index()] += (MVector(m_taskData.normals[itGeo.index()]) * bulgeAmount * m_taskData.envelope * w * m_taskData.stressV[itGeo.index()]); } else { //deform m_taskData.points[itGeo.index()] += m_taskData.normals[itGeo.index()] * bulgeAmount * m_taskData.envelope * w; } } } itGeo.setAllPositions(m_taskData.points); return MS::kSuccess; }
void 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 }
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; }
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; }
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; }
bool AssimpModelImporter::Load(const std::string& Filename) { // Assimp Importer Assimp::Importer Importer; // Load Model assimp_model = Importer.ReadFile(Filename.c_str(),aiProcessPreset_TargetRealtime_Fast | aiProcess_OptimizeMeshes | aiProcess_JoinIdenticalVertices | aiProcess_LimitBoneWeights | aiProcess_FlipUVs | aiProcess_CalcTangentSpace); // Path Relative to Model File std::string RelativePath = Filename.substr(0,Filename.find_last_of("/")+1); if (!assimp_model) { echo("Failed To Import Model: " + Filename + " ERROR: " + Importer.GetErrorString()); return false; } else { // Build Skeleton // initial bone count boneCount = 0; // Get Skeleton GetBone(assimp_model->mRootNode); for (uint32 i=0;i<assimp_model->mNumMeshes;i++) { // loop through meshes const aiMesh* mesh = assimp_model->mMeshes[i]; // create submesh SubMesh subMesh; // set submesh id subMesh.ID = i; // set name subMesh.Name = mesh->mName.data; for (uint32 t = 0; t < mesh->mNumFaces;t++) { const aiFace* face = &mesh->mFaces[t]; subMesh.tIndex.push_back(face->mIndices[0]); subMesh.tIndex.push_back(face->mIndices[1]); subMesh.tIndex.push_back(face->mIndices[2]); } // get posisitons if (mesh->HasPositions()) { subMesh.hasVertex = true; subMesh.tVertex.resize(mesh->mNumVertices); memcpy(&subMesh.tVertex[0],&mesh->mVertices[0],mesh->mNumVertices*sizeof(Vec3)); } else subMesh.hasVertex = false; // get normals if (mesh->HasNormals()) { subMesh.hasNormal = true; subMesh.tNormal.resize(mesh->mNumVertices); memcpy(&subMesh.tNormal[0],&mesh->mNormals[0],mesh->mNumVertices*sizeof(Vec3)); } else subMesh.hasNormal = false; // get texcoords if (mesh->HasTextureCoords(0)) { subMesh.hasTexcoord = true; for (uint32 k = 0; k < mesh->mNumVertices;k++) { subMesh.tTexcoord.push_back(Vec2(mesh->mTextureCoords[0][k].x,mesh->mTextureCoords[0][k].y)); } } else subMesh.hasTexcoord = false; // get tangent if (mesh->HasTangentsAndBitangents()) { subMesh.hasTangentBitangent = true; subMesh.tTangent.resize(mesh->mNumVertices); subMesh.tBitangent.resize(mesh->mNumVertices); memcpy(&subMesh.tTangent[0],&mesh->mTangents[0],mesh->mNumVertices*sizeof(Vec3)); memcpy(&subMesh.tBitangent[0],&mesh->mBitangents[0],mesh->mNumVertices*sizeof(Vec3)); } else subMesh.hasTangentBitangent = false; // get vertex colors if (mesh->HasVertexColors(0)) { subMesh.hasVertexColor = true; subMesh.tVertexColor.resize(mesh->mNumVertices); memcpy(&subMesh.tVertexColor[0],&mesh->mColors[0],mesh->mNumVertices*sizeof(Vec4)); } else subMesh.hasVertexColor = false; // get vertex weights if (mesh->HasBones()) { // Set Flag subMesh.hasBones = true; // Create Bone's Sub Mesh Internal ID uint32 count = 0; for (uint32 k = 0; k < mesh->mNumBones; k++) { // Save Offset Matrix Matrix _offsetMatrix; _offsetMatrix.m[0] = mesh->mBones[k]->mOffsetMatrix.a1; _offsetMatrix.m[1] = mesh->mBones[k]->mOffsetMatrix.b1; _offsetMatrix.m[2] = mesh->mBones[k]->mOffsetMatrix.c1; _offsetMatrix.m[3] = mesh->mBones[k]->mOffsetMatrix.d1; _offsetMatrix.m[4] = mesh->mBones[k]->mOffsetMatrix.a2; _offsetMatrix.m[5] = mesh->mBones[k]->mOffsetMatrix.b2; _offsetMatrix.m[6] = mesh->mBones[k]->mOffsetMatrix.c2; _offsetMatrix.m[7] = mesh->mBones[k]->mOffsetMatrix.d2; _offsetMatrix.m[8] = mesh->mBones[k]->mOffsetMatrix.a3; _offsetMatrix.m[9] = mesh->mBones[k]->mOffsetMatrix.b3; _offsetMatrix.m[10] = mesh->mBones[k]->mOffsetMatrix.c3; _offsetMatrix.m[11] = mesh->mBones[k]->mOffsetMatrix.d3; _offsetMatrix.m[12] = mesh->mBones[k]->mOffsetMatrix.a4; _offsetMatrix.m[13] = mesh->mBones[k]->mOffsetMatrix.b4; _offsetMatrix.m[14] = mesh->mBones[k]->mOffsetMatrix.c4; _offsetMatrix.m[15] = mesh->mBones[k]->mOffsetMatrix.d4; uint32 boneID = GetBoneID(mesh->mBones[k]->mName.data); subMesh.BoneOffsetMatrix[boneID] = _offsetMatrix; subMesh.MapBoneIDs[boneID] = count; count++; } // Add Bones and Weights to SubMesh Structure, based on Internal IDs for (uint32 j = 0; j < mesh->mNumVertices; j++) { // get values std::vector<uint32> boneID(4,0); std::vector<f32> weightValue(4,0.f); uint32 count = 0; for (uint32 k = 0; k < mesh->mNumBones; k++) { for (uint32 l = 0; l < mesh->mBones[k]->mNumWeights; l++) { if (mesh->mBones[k]->mWeights[l].mVertexId == j) { // Convert Bone ID to Internal of the Sub Mesh boneID[count] = subMesh.MapBoneIDs[GetBoneID(mesh->mBones[k]->mName.data)]; // Add Bone Weight weightValue[count] = mesh->mBones[k]->mWeights[l].mWeight; count++; } } } subMesh.tBonesID.push_back(Vec4((f32)boneID[0],(f32)boneID[1],(f32)boneID[2],(f32)boneID[3])); subMesh.tBonesWeight.push_back(Vec4(weightValue[0],weightValue[1],weightValue[2],weightValue[3])); } } else subMesh.hasBones = false; // Get SubMesh Material ID subMesh.materialID = mesh->mMaterialIndex; // add to submeshes vector subMeshes.push_back(subMesh); } // Build Materials List for (uint32 i=0;i<assimp_model->mNumMaterials;++i) { MaterialProperties material; // Get Material const aiMaterial* pMaterial = assimp_model->mMaterials[i]; material.id = i; aiString name; pMaterial->Get(AI_MATKEY_NAME, name); material.Name.resize(name.length); memcpy(&material.Name[0], name.data, name.length); aiColor3D color; material.haveColor = false; if (pMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, color)==AI_SUCCESS) { material.haveColor = true; material.Color = Vec4(color.r, color.g, color.b, 1.0); } material.haveAmbient = false; if (pMaterial->Get(AI_MATKEY_COLOR_AMBIENT, color)==AI_SUCCESS) { material.haveAmbient = true; material.Ambient = Vec4(color.r, color.g, color.b, 1.0); } material.haveSpecular = false; if (pMaterial->Get(AI_MATKEY_COLOR_SPECULAR, color)==AI_SUCCESS) { material.haveSpecular = true; material.Specular = Vec4(color.r, color.g, color.b, 1.0); } material.haveEmissive = false; if (pMaterial->Get(AI_MATKEY_COLOR_EMISSIVE, color)==AI_SUCCESS) { material.haveEmissive = true; material.Emissive = Vec4(color.r, color.g, color.b, 1.0); } bool flag = false; pMaterial->Get(AI_MATKEY_ENABLE_WIREFRAME, flag); material.WireFrame = flag; flag = false; pMaterial->Get(AI_MATKEY_TWOSIDED, flag); material.Twosided = flag; f32 value = 1.0f; pMaterial->Get(AI_MATKEY_OPACITY, value); material.Opacity = value; value = 0.0f; pMaterial->Get(AI_MATKEY_SHININESS, value); material.Shininess = value; value = 0.0f; pMaterial->Get(AI_MATKEY_SHININESS_STRENGTH, value); material.ShininessStrength = value; // Save Properties aiString path; aiReturn texFound; // Diffuse texFound = assimp_model->mMaterials[i]->GetTexture(aiTextureType_DIFFUSE, 0, &path); if (texFound==AI_SUCCESS) { material.haveColorMap = true; material.colorMap.resize(path.length); memcpy(&material.colorMap[0],&path.data,path.length); std::replace(material.colorMap.begin(), material.colorMap.end(),'\\','/'); } // Bump Map texFound = assimp_model->mMaterials[i]->GetTexture(aiTextureType_NORMALS, 0, &path); if (texFound==AI_SUCCESS) { material.haveNormalMap = true; material.normalMap.resize(path.length); memcpy(&material.normalMap[0],&path.data,path.length); std::replace(material.normalMap.begin(), material.normalMap.end(),'\\','/'); } else { // Height Map texFound = assimp_model->mMaterials[i]->GetTexture(aiTextureType_HEIGHT, 0, &path); if (texFound==AI_SUCCESS) { material.haveNormalMap = true; material.normalMap.resize(path.length); memcpy(&material.normalMap[0],&path.data,path.length); std::replace(material.normalMap.begin(), material.normalMap.end(),'\\','/'); } } // Specular texFound = assimp_model->mMaterials[i]->GetTexture(aiTextureType_SPECULAR, 0, &path); if (texFound==AI_SUCCESS) { material.haveSpecularMap = true; material.specularMap.resize(path.length); memcpy(&material.specularMap[0],&path.data,path.length); std::replace(material.specularMap.begin(), material.specularMap.end(),'\\','/'); } // Add Material to List materials.push_back(material); } } Importer.FreeScene(); return true; }