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; }
void ProxyViz::updateViewFrustum(MObject & thisNode) { MPlug matplg(thisNode, acameraspace); MObject matobj; matplg.getValue(matobj); MFnMatrixData matdata(matobj); MMatrix cameramat = matdata.matrix(); AHelper::ConvertToMatrix44F(*cameraSpaceR(), cameramat); AHelper::ConvertToMatrix44F(*cameraInvSpaceR(), cameramat.inverse() ); float peye[3]; peye[0] = cameramat.matrix[3][0]; peye[1] = cameramat.matrix[3][1]; peye[2] = cameramat.matrix[3][2]; setEyePosition(peye); MPlug hfaplg(thisNode, ahapeture); float hfa = hfaplg.asFloat(); MPlug vfaplg(thisNode, avapeture); float vfa = vfaplg.asFloat(); MPlug flplg(thisNode, afocallength); float fl = flplg.asFloat(); float farClip = -20.f; if(numPlants() > 0) getFarClipDepth(farClip, gridBoundingBox() ); setFrustum(hfa, vfa, fl, -10.f, farClip ); MPlug overscanPlug(thisNode, ainoverscan); setOverscan(overscanPlug.asDouble() ); }
//--------------------------------------------------- // Retrieve the bind pose for a controller/joint std::pair // MMatrix DagHelper::getBindPoseInverse ( const MObject& controller, const MObject& influence ) { MStatus status; if ( controller.apiType() == MFn::kSkinClusterFilter ) { MFnSkinCluster controllerFn ( controller ); // Find the correct index for the pre-bind matrix uint index = controllerFn.indexForInfluenceObject ( MDagPath::getAPathTo ( influence ), &status ); if ( status != MStatus::kSuccess ) return MMatrix::identity; MPlug preBindMatrixPlug = controllerFn.findPlug ( "bindPreMatrix", &status ); preBindMatrixPlug = preBindMatrixPlug.elementByLogicalIndex ( index, &status ); if ( status != MStatus::kSuccess ) return MMatrix::identity; // Get the plug's matrix MMatrix ret; if ( !DagHelper::getPlugValue ( preBindMatrixPlug, ret ) ) return MMatrix::identity; return ret; } else if ( controller.apiType() == MFn::kJointCluster ) { MMatrix ret; DagHelper::getPlugValue ( influence, "bindPose", ret ); return ret.inverse(); } else return MMatrix::identity; }
MStatus transRotateCombineMatrix::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; MDataHandle hOutputMatrix = data.outputValue( aOutputMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hOutputInverseMatrix = data.outputValue( aOutputInverseMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hTransMatrix = data.inputValue( aInputTransMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hRotateMatrix = data.inputValue( aInputRotateMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MMatrix transMatrix = hTransMatrix.asMatrix(); MMatrix rotateMatrix = hRotateMatrix.asMatrix(); double buildMatrix[4][4] = { rotateMatrix( 0,0 ), rotateMatrix( 0,1 ), rotateMatrix( 0,2 ), 0, rotateMatrix( 1,0 ), rotateMatrix( 1,1 ), rotateMatrix( 1,2 ), 0, rotateMatrix( 2,0 ), rotateMatrix( 2,1 ), rotateMatrix( 2,2 ), 0, transMatrix( 3,0 ), transMatrix( 3,1 ), transMatrix( 3,2 ), 1 }; MMatrix buildMtx = buildMatrix; if( plug == aOutputMatrix ) hOutputMatrix.set( buildMtx ); if( plug == aOutputInverseMatrix ) hOutputInverseMatrix.set( buildMtx.inverse() ); data.setClean( plug ); return status; }
//------------------------------------------------------------------------------ // void GLPickingSelect::processTriangles( const SubNode::Ptr rootNode, const double seconds, const size_t numTriangles, VBOProxy::VBOMode vboMode ) { const unsigned int bufferSize = (unsigned int)std::min(numTriangles,size_t(100000)); boost::shared_array<GLuint>buffer (new GLuint[bufferSize*4]); M3dView view = fSelectInfo.view(); MMatrix projMatrix; view.projectionMatrix(projMatrix); MMatrix modelViewMatrix; view.modelViewMatrix(modelViewMatrix); unsigned int x, y, w, h; view.viewport(x, y, w, h); double viewportX = static_cast<int>(x); // can be less than 0 double viewportY = static_cast<int>(y); // can be less than 0 double viewportW = w; double viewportH = h; fSelectInfo.selectRect(x, y, w, h); double selectX = static_cast<int>(x); // can be less than 0 double selectY = static_cast<int>(y); // can be less than 0 double selectW = w; double selectH = h; MMatrix selectAdjustMatrix; selectAdjustMatrix[0][0] = viewportW / selectW; selectAdjustMatrix[1][1] = viewportH / selectH; selectAdjustMatrix[3][0] = ((viewportX + viewportW/2.0) - (selectX + selectW/2.0)) / viewportW * 2.0 * selectAdjustMatrix[0][0]; selectAdjustMatrix[3][1] = ((viewportY + viewportH/2.0) - (selectY + selectH/2.0)) / viewportH * 2.0 * selectAdjustMatrix[1][1]; MMatrix localToPort = modelViewMatrix * projMatrix * selectAdjustMatrix; view.beginSelect(buffer.get(), bufferSize*4); view.pushName(0); { Frustum frustum(localToPort.inverse()); MMatrix xform(modelViewMatrix); DrawShadedState state(frustum, seconds, vboMode); DrawShadedTraversal traveral(state, xform, false, Frustum::kUnknown); rootNode->accept(traveral); } view.popName(); int nbPick = view.endSelect(); if (nbPick > 0) { unsigned int Zdepth = closestElem(nbPick, buffer.get()); float depth = float(Zdepth)/MAX_HW_DEPTH_VALUE; fMinZ = std::min(depth,fMinZ); } }
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 MG_curve::compute(const MPlug& plug,MDataBlock& dataBlock) { if (plug==output) { //MStatus MStatus stat; //Point array for the curve MPointArray pointArray ; //Get data from inputs MDataHandle degreeH = dataBlock.inputValue(degree); int degreeValue = degreeH.asInt(); MDataHandle tmH = dataBlock.inputValue(transformMatrix); MMatrix tm = tmH.asMatrix(); MArrayDataHandle inputMatrixH = dataBlock.inputArrayValue(inputMatrix); inputMatrixH.jumpToArrayElement(0); //Loop to get matrix data and convert in points for (int unsigned i=0;i<inputMatrixH.elementCount();i++,inputMatrixH.next()) { MMatrix currentMatrix = inputMatrixH.inputValue(&stat).asMatrix() ; //Compensate the locator matrix MMatrix fixedMatrix = currentMatrix*tm.inverse(); MPoint matrixP (fixedMatrix[3][0],fixedMatrix[3][1],fixedMatrix[3][2]); pointArray.append(matrixP); } MFnNurbsCurve curveFn; MFnNurbsCurveData curveDataFn; MObject curveData= curveDataFn.create(); curveFn.createWithEditPoints(pointArray,degreeValue,MFnNurbsCurve::kOpen,0,0,0,curveData,&stat); MDataHandle outputH = dataBlock.outputValue(output); outputH.set(curveData); outputH.setClean(); } return MS::kSuccess; }
//--------------------------------------------------- // set the bind pose for a transform // MStatus DagHelper::setBindPoseInverse ( const MObject& node, const MMatrix& bindPoseInverse ) { MStatus status; MFnDependencyNode dgFn ( node ); MPlug bindPosePlug = dgFn.findPlug ( "bindPose", &status ); if ( status != MS::kSuccess ) { MGlobal::displayWarning ( MString ( "No bindPose found on node " ) + dgFn.name() ); return status; } MFnMatrixData matrixFn; MObject val = matrixFn.create ( bindPoseInverse.inverse(), &status ); MObject invval = matrixFn.create ( bindPoseInverse, &status ); if ( status != MS::kSuccess ) { MGlobal::displayWarning ( MString ( "Error setting bindPose on node " ) + dgFn.name() ); return status; } // set the bind pose on the joint itself bindPosePlug.setValue ( val ); // Now, perhaps more significantly, see if there's a // skinCluster using this bone and update its bind // pose (as the joint bind pose is not connected to // the skin - it's set at bind time from the joint's // current position, and our importer may not want to // disturb the current scene state just to put bones // in a bind position before creating skin clusters) MObject _node ( node ); MItDependencyGraph it ( _node, MFn::kSkinClusterFilter ); while ( !it.isDone() ) { MPlug plug = it.thisPlug(); unsigned int idx = plug.logicalIndex(); MFnDependencyNode skinFn ( plug.node() ); MPlug skinBindPosePlug = skinFn.findPlug ( "bindPreMatrix", &status ); if ( status == MS::kSuccess ) { // The skinCluster stores inverse inclusive matrix // so notice we use invval (the MObject created off // the inverse matrix here) skinBindPosePlug = skinBindPosePlug.elementByLogicalIndex ( idx ); skinBindPosePlug.setValue ( invval ); } it.next(); } return status; }
void writeTMatrixList( std::ofstream *outFile, std::vector<MMatrix>& transformMatrices, bool inverse, float scaleFactor) { for( int matrixId = 0; matrixId < transformMatrices.size(); matrixId++) { MMatrix tm = transformMatrices[matrixId]; if( inverse ) tm = tm.inverse(); if( matrixId == 0) { *outFile << "\t\tray_transform " << matrixToString(tm) << "\n"; // normal transform } else{ *outFile << "\t\tray_mtransform " << matrixToString(tm) << "\n"; // motion transform } } }
//------------------------------------------------------------------------------ // void RasterSelect::processTriangles( const SubNode::Ptr rootNode, double seconds, size_t /* numTriangles */, VBOProxy::VBOMode vboMode ) { M3dView view = fSelectInfo.view(); MMatrix projMatrix; view.projectionMatrix(projMatrix); MMatrix modelViewMatrix; view.modelViewMatrix(modelViewMatrix); unsigned int x, y, w, h; view.viewport(x, y, w, h); double viewportX = static_cast<int>(x); // can be less than 0 double viewportY = static_cast<int>(y); // can be less than 0 double viewportW = w; double viewportH = h; fSelectInfo.selectRect(x, y, w, h); double selectX = static_cast<int>(x); // can be less than 0 double selectY = static_cast<int>(y); // can be less than 0 double selectW = w; double selectH = h; MMatrix selectAdjustMatrix; selectAdjustMatrix[0][0] = viewportW / selectW; selectAdjustMatrix[1][1] = viewportH / selectH; selectAdjustMatrix[3][0] = ((viewportX + viewportW/2.0) - (selectX + selectW/2.0)) / viewportW * 2.0 * selectAdjustMatrix[0][0]; selectAdjustMatrix[3][1] = ((viewportY + viewportH/2.0) - (selectY + selectH/2.0)) / viewportH * 2.0 * selectAdjustMatrix[1][1]; MMatrix localToPort = modelViewMatrix * projMatrix * selectAdjustMatrix; { Frustum frustum(localToPort.inverse()); MMatrix xform(modelViewMatrix); DrawShadedState state(frustum, seconds, vboMode); DrawShadedTraversal traveral(state, xform, false, Frustum::kUnknown); rootNode->accept(traveral); } }
// 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; }
void simpleFluidEmitter::surfaceFluidEmitter( MFnFluid& fluid, const MMatrix& fluidWorldMatrix, int plugIndex, MDataBlock& block, double dt, double conversion, double dropoff ) //============================================================================== // // Method: // // simpleFluidEmitter::surfaceFluidEmitter // // Description: // // Emits fluid from one of a predefined set of volumes (cube, sphere, // cylinder, cone, torus). // // Parameters: // // fluid: fluid into which we are emitting // fluidWorldMatrix: object->world matrix for the fluid // plugIndex: identifies which fluid connected to the emitter // we are emitting into // block: datablock for the emitter, to retrieve attribute // values // dt: time delta for this frame // conversion: mapping from UI emission rates to internal units // dropoff: specifies how much emission rate drops off as // the surface points move away from the centers // of the voxels in which they lie. // // Notes: // // To associate an owner object with an emitter, use the // addDynamic MEL command, e.g. "addDynamic simpleFluidEmitter1 pPlane1". // //============================================================================== { // get relevant world matrices // MMatrix fluidInverseWorldMatrix = fluidWorldMatrix.inverse(); // get emission rates for density, fuel, heat, and emission color // double densityEmit = fluidDensityEmission( block ); double fuelEmit = fluidFuelEmission( block ); double heatEmit = fluidHeatEmission( block ); bool doEmitColor = fluidEmitColor( block ); MColor emitColor = fluidColor( block ); // rate modulation based on frame time, user value conversion factor, and // standard emitter "rate" value (not actually exposed in most fluid // emitters, but there anyway). // double theRate = getRate(block) * dt * conversion; // get voxel dimensions and sizes (object space) // double size[3]; unsigned int res[3]; fluid.getDimensions( size[0], size[1], size[2] ); fluid.getResolution( res[0], res[1], res[2] ); // voxel sizes double dx = size[0] / res[0]; double dy = size[1] / res[1]; double dz = size[2] / res[2]; // voxel centers double Ox = -size[0]/2; double Oy = -size[1]/2; double Oz = -size[2]/2; // get the "swept geometry" data for the emitter surface. This structure // tracks the motion of each emitter triangle over the time interval // for this simulation step. We just use positions on the emitter // surface at the end of the time step to do the emission. // MDataHandle sweptHandle = block.inputValue( mSweptGeometry ); MObject sweptData = sweptHandle.data(); MFnDynSweptGeometryData fnSweptData( sweptData ); // for "non-jittered" sampling, just reset the random state for each // triangle, which gives us a fixed set of samples all the time. // Sure, they're still jittered, but they're all jittered the same, // which makes them kinda uniform. // bool jitter = fluidJitter(block); if( !jitter ) { resetRandomState( plugIndex, block ); } if( fnSweptData.triangleCount() > 0 ) { // average voxel face area - use this as the canonical unit that // receives the emission rate specified by the users. Scale the // rate for other triangles accordingly. // double vfArea = pow(dx*dy*dz, 2.0/3.0); // very rudimentary support for textured emission rate and // textured emission color. We simply sample each texture once // at the center of each emitter surface triangle. This will // cause aliasing artifacts when these triangles are large. // MFnDependencyNode fnNode( thisMObject() ); MObject rateTextureAttr = fnNode.attribute( "textureRate" ); MObject colorTextureAttr = fnNode.attribute( "particleColor" ); bool texturedRate = hasValidEmission2dTexture( rateTextureAttr ); bool texturedColor = hasValidEmission2dTexture( colorTextureAttr ); // construct texture coordinates for each triangle center // MDoubleArray uCoords, vCoords; if( texturedRate || texturedColor ) { uCoords.setLength( fnSweptData.triangleCount() ); vCoords.setLength( fnSweptData.triangleCount() ); int t; for( t = 0; t < fnSweptData.triangleCount(); t++ ) { MDynSweptTriangle tri = fnSweptData.sweptTriangle( t ); MVector uv0 = tri.uvPoint(0); MVector uv1 = tri.uvPoint(1); MVector uv2 = tri.uvPoint(2); MVector uvMid = (uv0+uv1+uv2)/3.0; uCoords[t] = uvMid[0]; vCoords[t] = uvMid[1]; } } // evaluate textured rate and color values at the triangle centers // MDoubleArray texturedRateValues; if( texturedRate ) { texturedRateValues.setLength( uCoords.length() ); evalEmission2dTexture( rateTextureAttr, uCoords, vCoords, NULL, &texturedRateValues ); } MVectorArray texturedColorValues; if( texturedColor ) { texturedColorValues.setLength( uCoords.length() ); evalEmission2dTexture( colorTextureAttr, uCoords, vCoords, &texturedColorValues, NULL ); } for( int t = 0; t < fnSweptData.triangleCount(); t++ ) { // calculate emission rate and color values for this triangle // double curTexturedRate = texturedRate ? texturedRateValues[t] : 1.0; MColor curTexturedColor; if( texturedColor ) { MVector& curVec = texturedColorValues[t]; curTexturedColor.r = (float)curVec[0]; curTexturedColor.g = (float)curVec[1]; curTexturedColor.b = (float)curVec[2]; curTexturedColor.a = 1.0; } else { curTexturedColor = emitColor; } MDynSweptTriangle tri = fnSweptData.sweptTriangle( t ); MVector v0 = tri.vertex(0); MVector v1 = tri.vertex(1); MVector v2 = tri.vertex(2); // compute number of samples for this triangle based on area, // with large triangles receiving approximately 1 sample for // each voxel that they intersect // double triArea = tri.area(); int numSamples = (int)(triArea / vfArea); if( numSamples < 1 ) numSamples = 1; // compute emission rate for the points on the triangle. // Scale the canonical rate by the area ratio of this triangle // to the average voxel size, then split it amongst all the samples. // double triRate = (theRate*(triArea/vfArea))/numSamples; triRate *= curTexturedRate; for( int j = 0; j < numSamples; j++ ) { // generate a random point on the triangle, // map it into fluid local space // double r1 = randgen(); double r2 = randgen(); if( r1 + r2 > 1 ) { r1 = 1-r1; r2 = 1-r2; } double r3 = 1 - (r1+r2); MPoint randPoint = r1*v0 + r2*v1 + r3*v2; randPoint *= fluidInverseWorldMatrix; // figure out where the current point lies // ::int3 coord; fluid.toGridIndex( randPoint, coord ); if( (coord[0]<0) || (coord[1]<0) || (coord[2]<0) || (coord[0]>=(int)res[0]) || (coord[1]>=(int)res[1]) || (coord[2]>=(int)res[2]) ) { continue; } // do some falloff based on how far from the voxel center // the current point lies // MPoint gridPoint; gridPoint.x = Ox + (coord[0]+0.5)*dx; gridPoint.y = Oy + (coord[1]+0.5)*dy; gridPoint.z = Oz + (coord[2]+0.5)*dz; MVector diff = gridPoint - randPoint; double distSquared = diff * diff; double distDrop = dropoff * distSquared; double newVal = triRate * exp( -distDrop ); // emit into the voxel // if( newVal != 0 ) { fluid.emitIntoArrays( (float) newVal, coord[0], coord[1], coord[2], (float)densityEmit, (float)heatEmit, (float)fuelEmit, doEmitColor, curTexturedColor ); } } } } }
void simpleFluidEmitter::volumeFluidEmitter( MFnFluid& fluid, const MMatrix& fluidWorldMatrix, int plugIndex, MDataBlock& block, double dt, double conversion, double dropoff ) //============================================================================== // // Method: // // simpleFluidEmitter::volumeFluidEmitter // // Description: // // Emits fluid from points distributed over the surface of the // emitter's owner object. // // Parameters: // // fluid: fluid into which we are emitting // fluidWorldMatrix: object->world matrix for the fluid // plugIndex: identifies which fluid connected to the emitter // we are emitting into // block: datablock for the emitter, to retrieve attribute // values // dt: time delta for this frame // conversion: mapping from UI emission rates to internal units // dropoff: specifies how much emission rate drops off as // we move away from the local y-axis of the // volume emitter shape. // //============================================================================== { // get emitter position and relevant matrices // MPoint emitterPos = getWorldPosition(); MMatrix emitterWorldMatrix = getWorldMatrix(); MMatrix fluidInverseWorldMatrix = fluidWorldMatrix.inverse(); // get emission rates for density, fuel, heat, and emission color // double densityEmit = fluidDensityEmission( block ); double fuelEmit = fluidFuelEmission( block ); double heatEmit = fluidHeatEmission( block ); bool doEmitColor = fluidEmitColor( block ); MColor emitColor = fluidColor( block ); // rate modulation based on frame time, user value conversion factor, and // standard emitter "rate" value (not actually exposed in most fluid // emitters, but there anyway). // double theRate = getRate(block) * dt * conversion; // get voxel dimensions and sizes (object space) // double size[3]; unsigned int res[3]; fluid.getDimensions( size[0], size[1], size[2] ); fluid.getResolution( res[0], res[1], res[2] ); // voxel sizes double dx = size[0] / res[0]; double dy = size[1] / res[1]; double dz = size[2] / res[2]; // voxel centers double Ox = -size[0]/2; double Oy = -size[1]/2; double Oz = -size[2]/2; // find the voxels that intersect the bounding box of the volume // primitive associated with the emitter // MBoundingBox bbox; if( !volumePrimitiveBoundingBox( bbox ) ) { // shouldn't happen // return; } // transform volume primitive into fluid space // bbox.transformUsing( emitterWorldMatrix ); bbox.transformUsing( fluidInverseWorldMatrix ); MPoint lowCorner = bbox.min(); MPoint highCorner = bbox.max(); // get fluid voxel coord range of bounding box // ::int3 lowCoords; ::int3 highCoords; fluid.toGridIndex( lowCorner, lowCoords ); fluid.toGridIndex( highCorner, highCoords ); int i; for ( i = 0; i < 3; i++ ) { if ( lowCoords[i] < 0 ) { lowCoords[i] = 0; } else if ( lowCoords[i] > ((int)res[i])-1 ) { lowCoords[i] = ((int)res[i])-1; } if ( highCoords[i] < 0 ) { highCoords[i] = 0; } else if ( highCoords[i] > ((int)res[i])-1 ) { highCoords[i] = ((int)res[i])-1; } } // figure out the emitter size relative to the voxel size, and compute // a per-voxel sampling rate that uses 1 sample/voxel for emitters that // are >= 2 voxels big in all dimensions. For smaller emitters, use up // to 8 samples per voxel. // double emitterVoxelSize[3]; emitterVoxelSize[0] = (highCorner[0]-lowCorner[0])/dx; emitterVoxelSize[1] = (highCorner[1]-lowCorner[1])/dy; emitterVoxelSize[2] = (highCorner[2]-lowCorner[2])/dz; double minVoxelSize = MIN(emitterVoxelSize[0],MIN(emitterVoxelSize[1],emitterVoxelSize[2])); if( minVoxelSize < 1.0 ) { minVoxelSize = 1.0; } int maxSamples = 8; int numSamples = (int)(8.0/(minVoxelSize*minVoxelSize*minVoxelSize) + 0.5); if( numSamples < 1 ) numSamples = 1; if( numSamples > maxSamples ) numSamples = maxSamples; // non-jittered, just use one sample in the voxel center. Should replace // with uniform sampling pattern. // bool jitter = fluidJitter(block); if( !jitter ) { numSamples = 1; } // for each voxel that could potentially intersect the volume emitter // primitive, take some samples in the voxel. For those inside the // volume, compute their dropoff relative to the primitive's local y-axis, // and emit an appropriate amount into the voxel. // for( i = lowCoords[0]; i <= highCoords[0]; i++ ) { double x = Ox + (i+0.5)*dx; for( int j = lowCoords[1]; j < highCoords[1]; j++ ) { double y = Oy + (j+0.5)*dy; for( int k = lowCoords[2]; k < highCoords[2]; k++ ) { double z = Oz + (k+0.5)*dz; for ( int si = 0; si < numSamples; si++) { // compute voxel sample point (object space) // double rx, ry, rz; if(jitter) { rx = x + dx*(randgen() - 0.5); ry = y + dy*(randgen() - 0.5); rz = z + dz*(randgen() - 0.5); } else { rx = x; ry = y; rz = z; } // to world space MPoint pt( rx, ry, rz ); pt *= fluidWorldMatrix; // test to see if point is inside volume primitive // if( volumePrimitivePointInside( pt, emitterWorldMatrix ) ) { // compute dropoff // double dist = pt.distanceTo( emitterPos ); double distDrop = dropoff * (dist*dist); double newVal = (theRate * exp( -distDrop )) / (double)numSamples; // emit into arrays // if( newVal != 0.0 ) { fluid.emitIntoArrays( (float) newVal, i, j, k, (float)densityEmit, (float)heatEmit, (float)fuelEmit, doEmitColor, emitColor ); } } } } } } }
MStatus sgHair_controlJoint::setGravityJointPositionWorld() { MStatus status; m_mtxArrGravityAdd = m_mtxArrBase; if( m_weightGravity == 0 ) return MS::kSuccess; if( !m_bStaticRotation ) { double minParam = m_paramGravity - m_rangeGravity; double maxParam = m_paramGravity; double divRate = maxParam - minParam; if( divRate == 0 ) divRate = 0.0001; if( minParam > m_mtxArrBase.length()-1 ) return MS::kSuccess; MDoubleArray dArrGravityWeights; dArrGravityWeights.setLength( m_mtxArrBase.length() ); double beforeWeight = 1.0; for( int i= m_mtxArrBase.length()-1; i > minParam, i >= 0; i-- ) { double paramRate = ( i - minParam ) / divRate; if( paramRate > 1 ) paramRate = 1.0; else if( paramRate < 0 ) paramRate = 0.0; double cuRate = beforeWeight - paramRate; if( cuRate < 0 ) cuRate = 0; dArrGravityWeights[i] = cuRate * m_weightGravity; beforeWeight = paramRate; } MMatrix mtxDefault; MMatrix mtxMult; for( int i= m_mtxArrBase.length()-1; i > minParam, i >= 0; i-- ) { if( dArrGravityWeights[i] == 0 ) continue; double weight = dArrGravityWeights[i]; mtxDefault( 3,0 ) = m_mtxArrBase[i]( 3,0 ); mtxDefault( 3,1 ) = m_mtxArrBase[i]( 3,1 ); mtxDefault( 3,2 ) = m_mtxArrBase[i]( 3,2 ); mtxMult = getAngleWeightedMatrix( m_mtxGravityOffset, weight ); mtxMult( 3,0 ) = m_mtxArrBase[i]( 3,0 ); mtxMult( 3,1 ) = m_mtxArrBase[i]( 3,1 ); mtxMult( 3,2 ) = m_mtxArrBase[i]( 3,2 ); mtxMult = mtxDefault.inverse() * mtxMult; for( int j=i; j< m_mtxArrBase.length(); j++ ) { m_mtxArrGravityAdd[j] *= mtxMult; } } } else { double minParam = m_paramGravity - m_rangeGravity; double maxParam = m_paramGravity; double divRate = maxParam - minParam; if( divRate == 0 ) divRate = 0.0001; MDoubleArray dArrGravityWeights; dArrGravityWeights.setLength( m_mtxArrBase.length() ); double weight; for( int i= 0; i < m_mtxArrBase.length(); i++ ) { if( i < minParam )weight=0; else weight = (i-minParam)/divRate; if( weight > 1 ) weight = 1; m_mtxArrGravityAdd[i] = m_mtxArrBase[i]; double invWeight = 1-weight; MMatrix mtx = weight * m_mtxGravityOffset*m_mtxArrBase[i] + invWeight * m_mtxArrBase[i]; cleanMatrix( mtx ); m_mtxArrGravityAdd[i] = mtx; m_mtxArrGravityAdd[i]( 3,0 ) = m_mtxArrBase[i]( 3,0 ); m_mtxArrGravityAdd[i]( 3,1 ) = m_mtxArrBase[i]( 3,1 ); m_mtxArrGravityAdd[i]( 3,2 ) = m_mtxArrBase[i]( 3,2 ); } cout << endl; } 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 }
void MG_poseReader::draw( M3dView & view, const MDagPath & path, M3dView::DisplayStyle dispStyle, M3dView::DisplayStatus status ) { MPlug sizeP (thisMObject(),size); double sizeV; sizeP.getValue(sizeV); MPlug poseMatrixP (thisMObject(),poseMatrix); MObject poseMatrixData; poseMatrixP.getValue(poseMatrixData); MFnMatrixData matrixFn(poseMatrixData); MMatrix poseMatrixV =matrixFn.matrix(); MPlug readerMatrixP (thisMObject(),readerMatrix); MObject readerMatrixData; readerMatrixP.getValue(readerMatrixData); matrixFn.setObject(readerMatrixData); MMatrix readerMatrixV =matrixFn.matrix(); MMatrix poseMatrixFix =poseMatrixV*readerMatrixV.inverse(); MPlug aimAxisP (thisMObject(),aimAxis); int aimAxisV; aimAxisP.getValue(aimAxisV); MVector aimBall; MPlug readerOnOffP(thisMObject(),readerOnOff); MPlug axisOnOffP(thisMObject(),axisOnOff); MPlug poseOnOffP(thisMObject(),poseOnOff); double readerOnOffV; double axisOnOffV; double poseOnOffV; readerOnOffP.getValue(readerOnOffV); axisOnOffP.getValue(axisOnOffV); poseOnOffP.getValue(poseOnOffV); MPlug xPositiveP (thisMObject(),xPositive); MPlug xNegativeP (thisMObject(),xNegative); double xPositiveV; double xNegativeV; xPositiveP.getValue(xPositiveV); xNegativeP.getValue(xNegativeV); double xColor = xPositiveV; if (xPositiveV==0) { xColor=xNegativeV; } MPlug yPositiveP (thisMObject(),yPositive); MPlug yNegativeP (thisMObject(),yNegative); double yPositiveV; double yNegativeV; yPositiveP.getValue(yPositiveV); yNegativeP.getValue(yNegativeV); double yColor = yPositiveV; if (yPositiveV==0) { yColor=yNegativeV; } MPlug zPositiveP (thisMObject(),zPositive); MPlug zNegativeP (thisMObject(),zNegative); double zPositiveV; double zNegativeV; zPositiveP.getValue(zPositiveV); zNegativeP.getValue(zNegativeV); double zColor = zPositiveV; if (zPositiveV==0) { zColor=zNegativeV; } if (aimAxisV==0) { aimBall.x=poseMatrixFix[0][0]; aimBall.y=poseMatrixFix[0][1]; aimBall.z=poseMatrixFix[0][2]; } else if (aimAxisV==1) { aimBall.x=poseMatrixFix[1][0]; aimBall.y=poseMatrixFix[1][1]; aimBall.z=poseMatrixFix[1][2]; }else { aimBall.x=poseMatrixFix[2][0]; aimBall.y=poseMatrixFix[2][1]; aimBall.z=poseMatrixFix[2][2]; } //***************************************************************** // Initialize opengl and draw //***************************************************************** view.beginGL(); glPushAttrib( GL_ALL_ATTRIB_BITS ); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glLineWidth(2); if(status == M3dView::kLead) glColor4f(0.0,1.0,0.0,0.3f); else glColor4f(1.0,1.0,0.0,0.3f); MVector baseV(0,0,0); MVector xp(1*sizeV,0,0); MVector xm(-1*sizeV,0,0); MVector yp(0,1*sizeV,0); MVector ym(0,-1*sizeV,0); MVector zp(0,0,1*sizeV); MVector zm(0,0,-1*sizeV); double * red; red = new double[4]; red[0]=1; red[1]=0; red[2]=0; red[3]=1; double * green; green = new double[4]; green[0]=0; green[1]=1; green[2]=0; green[3]=1; double * blue; blue = new double[4]; blue[0]=0; blue[1]=0; blue[2]=1; blue[3]=1; double * yellow; yellow = new double[4]; yellow[0]=1; yellow[1]=1; yellow[2]=0.2; yellow[3]=0.3; if (readerOnOffV==1) { drawSphere(sizeV,20,20,baseV,yellow); } if (axisOnOffV==1) { drawSphere(sizeV/7,15,15,xp,red); drawSphere(sizeV/7,15,15,xm,red); drawSphere(sizeV/7,15,15,yp,green); drawSphere(sizeV/7,15,15,ym,green); drawSphere(sizeV/7,15,15,zp,blue); drawSphere(sizeV/7,15,15,zm,blue); } if (poseOnOffV==1) { double* color = blendColor(xColor,yColor,zColor,1); drawSphere(sizeV/7,15,15,aimBall*sizeV,color); } glDisable(GL_BLEND); glPopAttrib(); }
//--------------------------------------- void MaterialExporter::setSetParam ( const cgfxShaderNode* shaderNodeCgfx, const cgfxAttrDef* attribute ) { COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter(); String attributeName = attribute->fName.asChar(); cgfxAttrDef::cgfxAttrType attributeType = attribute->fType; switch ( attributeType ) { case cgfxAttrDef::kAttrTypeBool: { COLLADASW::SetParamBool setParam ( streamWriter ); setParam.openParam ( attributeName ); setParam.appendValues ( attribute->fNumericDef && attribute->fNumericDef[0] ); setParam.closeParam (); break; } case cgfxAttrDef::kAttrTypeInt: { COLLADASW::SetParamInt setParam ( streamWriter ); setParam.openParam ( attributeName ); setParam.appendValues ( (int) attribute->fNumericDef[0] ); setParam.closeParam(); break; } case cgfxAttrDef::kAttrTypeString: { COLLADASW::SetParamString setParam ( streamWriter ); setParam.openParam ( attributeName ); if ( attribute->fStringDef != NULL ) setParam.appendValues ( String ( attribute->fStringDef.asChar() ) ); setParam.closeParam(); break; } case cgfxAttrDef::kAttrTypeFloat: { COLLADASW::SetParamFloat setParam ( streamWriter ); setParam.openParam ( attributeName ); if ( attribute->fNumericDef!=NULL /*&& attribute->fNumericDef[0]!=0*/ ) setParam.appendValues ( attribute->fNumericDef[0] ); setParam.closeParam(); break; } case cgfxAttrDef::kAttrTypeVector2: { COLLADASW::SetParamFloat2 setParam ( streamWriter ); setParam.openParam ( attributeName ); for ( int i=0; i<attribute->fSize; ++i ) { if ( attribute->fNumericDef!=NULL /*&& attribute->fNumericDef[i]!=0*/ ) { double val = attribute->fNumericDef[i]; setParam.appendValues( val ); } } setParam.closeParam(); break; } case cgfxAttrDef::kAttrTypeVector3: case cgfxAttrDef::kAttrTypeColor3: { COLLADASW::SetParamFloat3 setParam ( streamWriter ); setParam.openParam ( attributeName ); for ( int i=0; i<attribute->fSize; ++i ) { if ( attribute->fNumericDef!=NULL /*&& attribute->fNumericDef[i]!=0*/ ) { double val = attribute->fNumericDef[i]; setParam.appendValues( val ); } } setParam.closeParam(); break; } case cgfxAttrDef::kAttrTypeVector4: case cgfxAttrDef::kAttrTypeColor4: { COLLADASW::SetParamFloat4 setParam ( streamWriter ); setParam.openParam ( attributeName ); for ( int i=0; i<attribute->fSize; ++i ) { if ( attribute->fNumericDef!=NULL /*&& attribute->fNumericDef[i]!=0*/ ) { double val = attribute->fNumericDef[i]; setParam.appendValues( val ); } } setParam.closeParam(); break; } case cgfxAttrDef::kAttrTypeWorldDir: case cgfxAttrDef::kAttrTypeWorldPos: { // Read the value double tmp[4]; for ( int i=0; i<attribute->fSize; ++i ) { tmp[i] = attribute->fNumericDef[i]; } if (attribute->fSize == 3) tmp[3] = 1.0; // Find the coordinate space, and whether it is a point or a vector int base = cgfxAttrDef::kAttrTypeFirstPos; if (attribute->fType <= cgfxAttrDef::kAttrTypeLastDir) base = cgfxAttrDef::kAttrTypeFirstDir; int space = attribute->fType - base; // Compute the transform matrix MMatrix mat; switch (space) { /* case 0: object space, handled in view dependent method */ case 1: /* world space - do nothing, identity */ break; /* case 2: eye space, unsupported yet */ /* case 3: clip space, unsupported yet */ /* case 4: screen space, unsupported yet */ } if ( base == cgfxAttrDef::kAttrTypeFirstPos ) { MPoint point(tmp[0], tmp[1], tmp[2], tmp[3]); point *= mat; tmp[0] = point.x; tmp[1] = point.y; tmp[2] = point.z; tmp[3] = point.w; } else { MVector vec(tmp[0], tmp[1], tmp[2]); vec *= mat; tmp[0] = vec.x; tmp[1] = vec.y; tmp[2] = vec.z; tmp[3] = 1; } COLLADASW::SetParamFloat4 setParam ( streamWriter ); setParam.openParam ( attributeName ); setParam.appendValues( tmp[0], tmp[1], tmp[2], tmp[3] ); setParam.closeParam(); break; } case cgfxAttrDef::kAttrTypeMatrix: case cgfxAttrDef::kAttrTypeWorldMatrix: case cgfxAttrDef::kAttrTypeViewMatrix: case cgfxAttrDef::kAttrTypeProjectionMatrix: case cgfxAttrDef::kAttrTypeWorldViewMatrix: case cgfxAttrDef::kAttrTypeWorldViewProjectionMatrix: { COLLADASW::SetParamFloat4x4 setParam ( streamWriter ); setParam.openParam ( attributeName ); MMatrix mayaMatrix; double* p = &mayaMatrix.matrix[0][0]; for ( int k=0; k<attribute->fSize; ++k ) { p[k] = attribute->fNumericDef[k]; } MMatrix wMatrix, vMatrix, pMatrix, sMatrix; MMatrix wvMatrix, wvpMatrix, wvpsMatrix; { float tmp[4][4]; wMatrix.setToIdentity(); glGetFloatv(GL_MODELVIEW_MATRIX, &tmp[0][0]); wvMatrix = MMatrix(tmp); vMatrix = wMatrix.inverse() * wvMatrix; glGetFloatv(GL_PROJECTION_MATRIX, &tmp[0][0]); pMatrix = MMatrix(tmp); wvpMatrix = wvMatrix * pMatrix; float vpt[4]; float depth[2]; glGetFloatv(GL_VIEWPORT, vpt); glGetFloatv(GL_DEPTH_RANGE, depth); // Construct the NDC -> screen space matrix // float x0, y0, z0, w, h, d; x0 = vpt[0]; y0 = vpt[1]; z0 = depth[0]; w = vpt[2]; h = vpt[3]; d = depth[1] - z0; // Make a reference to ease the typing // double* s = &sMatrix.matrix[0][0]; s[ 0] = w/2; s[ 1] = 0.0; s[ 2] = 0.0; s[ 3] = 0.0; s[ 4] = 0.0; s[ 5] = h/2; s[ 6] = 0.0; s[ 7] = 0.0; s[ 8] = 0.0; s[ 9] = 0.0; s[10] = d/2; s[11] = 0.0; s[12] = x0+w/2; s[13] = y0+h/2; s[14] = z0+d/2; s[15] = 1.0; wvpsMatrix = wvpMatrix * sMatrix; } switch ( attribute->fType ) { case cgfxAttrDef::kAttrTypeWorldMatrix: mayaMatrix = wMatrix; break; case cgfxAttrDef::kAttrTypeViewMatrix: mayaMatrix = vMatrix; break; case cgfxAttrDef::kAttrTypeProjectionMatrix: mayaMatrix = pMatrix; break; case cgfxAttrDef::kAttrTypeWorldViewMatrix: mayaMatrix = wvMatrix; break; case cgfxAttrDef::kAttrTypeWorldViewProjectionMatrix: mayaMatrix = wvpMatrix; break; default: break; } if (attribute->fInvertMatrix) mayaMatrix = mayaMatrix.inverse(); if (!attribute->fTransposeMatrix) mayaMatrix = mayaMatrix.transpose(); double matrix[4][4]; convertMayaMatrixToTransposedDouble4x4 ( matrix, mayaMatrix, getTolerance () ); setParam.appendValues( matrix ); setParam.closeParam(); break; } case cgfxAttrDef::kAttrTypeColor1DTexture: case cgfxAttrDef::kAttrTypeColor2DTexture: case cgfxAttrDef::kAttrTypeColor3DTexture: case cgfxAttrDef::kAttrTypeColor2DRectTexture: case cgfxAttrDef::kAttrTypeNormalTexture: case cgfxAttrDef::kAttrTypeBumpTexture: case cgfxAttrDef::kAttrTypeCubeTexture: case cgfxAttrDef::kAttrTypeEnvTexture: case cgfxAttrDef::kAttrTypeNormalizationTexture: { CGparameter cgParameter = attribute->fParameterHandle; HwShaderExporter hwShaderExporter ( mDocumentExporter ); hwShaderExporter.setShaderFxFileUri ( getShaderFxFileUri () ); MObject shaderNode = shaderNodeCgfx->thisMObject(); hwShaderExporter.exportSampler ( shaderNode, cgParameter, false ); // ------------------------------- // String imageName = attribute->fStringDef.asChar(); // // MObject oNode = shaderNodeCgfx->thisMObject(); // MFnDependencyNode oNodeFn ( oNode ); // String oNodeName = oNodeFn.name().asChar(); // cgfxShader1 // // MPlug plug; // if ( DagHelper::getPlugConnectedTo( oNode, attributeName, plug ) ) // { // String plugName = plug.name().asChar(); // file1.outColor // MObject textureNode = plug.node(); // // //COLLADASW::Surface::SurfaceType surfaceType; // COLLADASW::Sampler::SamplerType samplerType; // COLLADASW::ValueType::ColladaType samplerValueType; // // switch ( attributeType ) // { // case cgfxAttrDef::kAttrTypeColor1DTexture: // //surfaceType = COLLADASW::Surface::SURFACE_TYPE_1D; // samplerType = COLLADASW::Sampler::SAMPLER_TYPE_1D; // samplerValueType = COLLADASW::ValueType::SAMPLER_1D; // break; // case cgfxAttrDef::kAttrTypeColor2DTexture: // case cgfxAttrDef::kAttrTypeNormalTexture: // case cgfxAttrDef::kAttrTypeBumpTexture: // //surfaceType = COLLADASW::Surface::SURFACE_TYPE_2D; // samplerType = COLLADASW::Sampler::SAMPLER_TYPE_2D; // samplerValueType = COLLADASW::ValueType::SAMPLER_2D; // break; // case cgfxAttrDef::kAttrTypeColor3DTexture: // //surfaceType = COLLADASW::Surface::SURFACE_TYPE_3D; // samplerType = COLLADASW::Sampler::SAMPLER_TYPE_3D; // samplerValueType = COLLADASW::ValueType::SAMPLER_3D; // break; // case cgfxAttrDef::kAttrTypeColor2DRectTexture: // //surfaceType = COLLADASW::Surface::SURFACE_TYPE_RECT; // samplerType = COLLADASW::Sampler::SAMPLER_TYPE_RECT; // samplerValueType = COLLADASW::ValueType::SAMPLER_RECT; // break; // case cgfxAttrDef::kAttrTypeCubeTexture: // case cgfxAttrDef::kAttrTypeEnvTexture: // case cgfxAttrDef::kAttrTypeNormalizationTexture: // //surfaceType = COLLADASW::Surface::SURFACE_TYPE_CUBE; // samplerType = COLLADASW::Sampler::SAMPLER_TYPE_CUBE; // samplerValueType = COLLADASW::ValueType::SAMPLER_CUBE; // break; // default: // //surfaceType = COLLADASW::Surface::SURFACE_TYPE_UNTYPED; // samplerType = COLLADASW::Sampler::SAMPLER_TYPE_UNSPECIFIED; // samplerValueType = COLLADASW::ValueType::VALUE_TYPE_UNSPECIFIED; // } // // // Write the params elements // setSetParamTexture ( attribute, textureNode, samplerType, samplerValueType ); // } } } }
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; }
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; }
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 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 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; }
void MG_poseReader::drawArrowMatrix(const int aimAxis,const double arrowSizeV,const MMatrix poseM ,const MMatrix readerM) { MVector tipV,corner1V,corner2V,corner3V,corner4V; MMatrix tipM,corner1M,corner2M,corner3M,corner4M,baseM; baseM.setToIdentity(); baseM*=poseM; baseM*=readerM.inverse(); switch ( aimAxis ) { case 0: if (aimAxis==0) { tipV.x=1*arrowSizeV; tipV.y=0.0; tipV.z=0.0; tipM=fromVecToMatrix(tipV); tipM*=poseM; tipM*=readerM.inverse(); corner1V.x=0.9*arrowSizeV; corner1V.y=0.05*arrowSizeV; corner1V.z=-0.05*arrowSizeV; corner1M=fromVecToMatrix(corner1V); corner1M*=poseM; corner1M*=readerM.inverse(); corner2V.x=0.9*arrowSizeV; corner2V.y=0.05*arrowSizeV; corner2V.z=0.05*arrowSizeV; corner2M=fromVecToMatrix(corner2V); corner2M*=poseM; corner2M*=readerM.inverse(); corner3V.x=0.9*arrowSizeV; corner3V.y=-0.05*arrowSizeV; corner3V.z=0.05*arrowSizeV; corner3M=fromVecToMatrix(corner3V); corner3M*=poseM; corner3M*=readerM.inverse(); corner4V.x=0.9*arrowSizeV; corner4V.y=-0.05*arrowSizeV; corner4V.z=-0.05*arrowSizeV; corner4M=fromVecToMatrix(corner4V); corner4M*=poseM; corner4M*=readerM.inverse(); } case 1: if (aimAxis==1) { tipV.y=1*arrowSizeV; tipV.x=0.0; tipV.z=0.0; tipM=fromVecToMatrix(tipV); tipM*=poseM; tipM*=readerM.inverse(); corner1V.y=0.9*arrowSizeV; corner1V.x=0.05*arrowSizeV; corner1V.z=-0.05*arrowSizeV; corner1M=fromVecToMatrix(corner1V); corner1M*=poseM; corner1M*=readerM.inverse(); corner2V.y=0.9*arrowSizeV; corner2V.x=0.05*arrowSizeV; corner2V.z=0.05*arrowSizeV; corner2M=fromVecToMatrix(corner2V); corner2M*=poseM; corner2M*=readerM.inverse(); corner3V.y=0.9*arrowSizeV; corner3V.x=-0.05*arrowSizeV; corner3V.z=0.05*arrowSizeV; corner3M=fromVecToMatrix(corner3V); corner3M*=poseM; corner3M*=readerM.inverse(); corner4V.y=0.9*arrowSizeV; corner4V.x=-0.05*arrowSizeV; corner4V.z=-0.05*arrowSizeV; corner4M=fromVecToMatrix(corner4V); corner4M*=poseM; corner4M*=readerM.inverse(); } case 2: if (aimAxis==2) { tipV.z=1*arrowSizeV; tipV.x=0.0; tipV.y=0.0; tipM=fromVecToMatrix(tipV); tipM*=poseM; tipM*=readerM.inverse(); corner1V.z=0.9*arrowSizeV; corner1V.x=0.05*arrowSizeV; corner1V.y=-0.05*arrowSizeV; corner1M=fromVecToMatrix(corner1V); corner1M*=poseM; corner1M*=readerM.inverse(); corner2V.z=0.9*arrowSizeV; corner2V.x=0.05*arrowSizeV; corner2V.y=0.05*arrowSizeV; corner2M=fromVecToMatrix(corner2V); corner2M*=poseM; corner2M*=readerM.inverse(); corner3V.z=0.9*arrowSizeV; corner3V.x=-0.05*arrowSizeV; corner3V.y=0.05*arrowSizeV; corner3M=fromVecToMatrix(corner3V); corner3M*=poseM; corner3M*=readerM.inverse(); corner4V.z=0.9*arrowSizeV; corner4V.x=-0.05*arrowSizeV; corner4V.y=-0.05*arrowSizeV; corner4M=fromVecToMatrix(corner4V); corner4M*=poseM; corner4M*=readerM.inverse(); } } glBegin(GL_LINES); glVertex3d(baseM[3][0],baseM[3][1],baseM[3][2]); glVertex3d(tipM[3][0],tipM[3][1],tipM[3][2]); glEnd(); glBegin(GL_TRIANGLES); glVertex3d(corner1M[3][0],corner1M[3][1],corner1M[3][2]); glVertex3d(corner2M[3][0],corner2M[3][1],corner2M[3][2]); glVertex3d(tipM[3][0],tipM[3][1],tipM[3][2]); glEnd(); glBegin(GL_TRIANGLES); glVertex3d(corner3M[3][0],corner3M[3][1],corner3M[3][2]); glVertex3d(corner2M[3][0],corner2M[3][1],corner2M[3][2]); glVertex3d(tipM[3][0],tipM[3][1],tipM[3][2]); glEnd(); glBegin(GL_TRIANGLES); glVertex3d(corner3M[3][0],corner3M[3][1],corner3M[3][2]); glVertex3d(corner4M[3][0],corner4M[3][1],corner4M[3][2]); glVertex3d(tipM[3][0],tipM[3][1],tipM[3][2]); glEnd(); glBegin(GL_TRIANGLES); glVertex3d(corner1M[3][0],corner1M[3][1],corner1M[3][2]); glVertex3d(corner4M[3][0],corner4M[3][1],corner4M[3][2]); glVertex3d(tipM[3][0],tipM[3][1],tipM[3][2]); glEnd(); }
MStatus sgCurveEditBrush_context::editCurve( MDagPath dagPathCurve, int beforeX, int beforeY, int currentX, int currentY, float radius, const MDoubleArray& dArrLength, MPointArray &points ) { MStatus status; if( radius < 0 ) return MS::kSuccess; MDagPath dagPathCam; M3dView view = M3dView::active3dView( &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); view.getCamera( dagPathCam ); MPoint camPos = dagPathCam.inclusiveMatrix()[3]; MVector vCamUp = dagPathCam.inclusiveMatrix()[1]; vCamUp.normalize(); radius *= .05; MPoint nearClipBefore; MPoint farClipBefore; view.viewToWorld( beforeX, beforeY, nearClipBefore, farClipBefore ); MVector rayBefore = nearClipBefore - camPos; rayBefore.normalize(); rayBefore *= 20; MPoint posBefore = rayBefore + camPos; MPoint nearClipCurrent; MPoint farClipCurrent; view.viewToWorld( currentX, currentY, nearClipCurrent, farClipCurrent ); MVector rayCurrent = nearClipCurrent - camPos; rayCurrent.normalize(); rayCurrent *= 20; MPoint posCurrent = rayCurrent + camPos; MVector vMove = posCurrent - posBefore; MMatrix mtxCurve = dagPathCurve.inclusiveMatrix(); MFnNurbsCurve fnCurve( dagPathCurve ); fnCurve.getCVs( points ); for( int i=0; i< points.length(); i++ ) { points[i] *= mtxCurve; } for( int i=1; i< points.length(); i++ ) { MPoint cuPoint = points[i]; MVector vPoint = cuPoint - camPos; MVector projV = ( vPoint * rayBefore )/( pow( rayBefore.length(), 2 ) )* rayBefore; MVector vertical = vPoint - projV; float radiusForPoint = vertical.length() / projV.length(); if( radius < radiusForPoint ) continue; MPoint parentPoint = points[i-1]; MVector vCurveDirection = cuPoint - parentPoint; double vDirLength = vCurveDirection.length(); MVector vEditDirection = vCurveDirection + vMove/rayBefore.length()*projV.length(); double dotEdit = vCurveDirection.normal() * vEditDirection.normal(); if( dotEdit < 0 ) continue; vEditDirection = vEditDirection * dotEdit + vCurveDirection*( 1-dotEdit ); MVector vEditLength = vEditDirection / vEditDirection.length() * vCurveDirection.length(); MVector vEdit = (vEditLength - vCurveDirection) * pow((double)(1-radiusForPoint/radius), 1 ); points[i] += vEdit; for( int j=i+1; j< points.length(); j++ ) { MPoint beforePoint = points[j]; MPoint pPoint = points[j-1]; MPoint beforePPoint = pPoint - vEdit; MVector vBefore = points[j] - beforePPoint; MVector vAfter = points[j] - pPoint; MVector vCurrent = vAfter.normal() * dArrLength[j]; points[j] = vCurrent + pPoint; vEdit = points[j] - beforePoint; } } MMatrix invMtxCurve = mtxCurve.inverse(); for( int i=0; i< points.length(); i++ ) { points[i] *= invMtxCurve; } fnCurve.setCVs( points ); fnCurve.updateCurve(); return MS::kSuccess; }
//#include "d3dx10.h" //#pragma comment(lib, "d3dx10.lib") void skeleton::loadKeyframe(joint& j,int time,keyframeTranslation& translation,keyframeRotation& rotation,keyframeScale& scale) { MVector position; int parentIdx = j.parentIndex; int DEBUG_TIME = 7; MMatrix matrix; { matrix = j.jointDag.inclusiveMatrix(); MFnIkJoint jn(j.jointDag); if(jn.name() == "L_toe2") { char str[256]; sprintf(str,"%5.5f,%5.5f,%5.5f\n\n",matrix[3][0],matrix[3][1],matrix[3][2]); OutputDebugString(str); } if(time == DEBUG_TIME) { MFnIkJoint jn(j.jointDag); if(jn.name() == "L_knee") { char str[256]; sprintf(str,"%5.5f,%5.5f,%5.5f,%5.5f\n%5.5f,%5.5f,%5.5f,%5.5f\n%5.5f,%5.5f,%5.5f,%5.5f\n%5.5f,%5.5f,%5.5f,%5.5f\n\n", matrix[0][0],matrix[0][1],matrix[0][2],matrix[0][3], matrix[1][0],matrix[1][1],matrix[1][2],matrix[1][3], matrix[2][0],matrix[2][1],matrix[2][2],matrix[2][3], matrix[3][0],matrix[3][1],matrix[3][2],matrix[3][3]); //sprintf(str,"%5.5f,%5.5f,%5.5f\n\n",matrix[3][0],matrix[3][1],matrix[3][2]); OutputDebugString(str); // breakable; } } //printMatrix(matrix); MMatrix worldMatrix = j.worldMatrix; //printMatrix(worldMatrix); MMatrix invWorldMatrix = worldMatrix.inverse(); //matrix = invWorldMatrix * matrix; //MTransformationMatrix mtm = matrix; //double q_x,q_y,q_z,q_w; //mtm.getRotationQuaternion(q_x,q_y,q_z,q_w); //double s_xyz[3]; //mtm.getScale(s_xyz,MSpace::kWorld); //MVector t_xyz = mtm.getTranslation(MSpace::kWorld); //D3DXMATRIX d3dM(matrix[0][0],matrix[0][1],matrix[0][2],matrix[0][3], // matrix[1][0],matrix[1][1],matrix[1][2],matrix[1][3], // matrix[2][0],matrix[2][1],matrix[2][2],matrix[2][3], // matrix[3][0],matrix[3][1],matrix[3][2],matrix[3][3]); //D3DXVECTOR3 d3dS,d3dT; //D3DXQUATERNION d3dQ; //HRESULT hr = D3DXMatrixDecompose(&d3dS,&d3dQ,&d3dT,&d3dM); //MMatrix matrixT = worldMatrix * matrix; //float t[3],q[4],s[3]; //extractTranMatrix(matrix,t,q,s); //Vector3 t1(t[0],t[1],t[2]); //Quaternion q1(q_x,q_y,q_z,q_w);//q[0],q[1],q[2],q[3]); //Vector3 s1(s[0],s[1],s[2]); //Matrix4 m; //m.transform(t1,s1,q1); //printMatrix(matrix); if(j.parentIndex >= 0) { MMatrix pMatrix = m_joints[parentIdx].jointDag.inclusiveMatrix(); //printMatrix(pMatrix); MMatrix pWorldMatrix = m_joints[parentIdx].worldMatrix; //printMatrix(pWorldMatrix); MMatrix invpWorldMatrix = pWorldMatrix.inverse(); //pMatrix = invpWorldMatrix * pMatrix; //printMatrix(pMatrix); MMatrix pInvMatrix = pMatrix.inverse(); matrix = matrix * pInvMatrix; //printMatrix(matrix); } } if(time == DEBUG_TIME) { MFnIkJoint jn(j.jointDag); if(jn.name() == "L_knee") { char str[256]; sprintf(str,"%5.5f,%5.5f,%5.5f,%5.5f\n%5.5f,%5.5f,%5.5f,%5.5f\n%5.5f,%5.5f,%5.5f,%5.5f\n%5.5f,%5.5f,%5.5f,%5.5f\n\n", matrix[0][0],matrix[0][1],matrix[0][2],matrix[0][3], matrix[1][0],matrix[1][1],matrix[1][2],matrix[1][3], matrix[2][0],matrix[2][1],matrix[2][2],matrix[2][3], matrix[3][0],matrix[3][1],matrix[3][2],matrix[3][3]); OutputDebugString(str); // breakable; } } { MMatrix matrix = j.jointDag.inclusiveMatrix() * j.jointDag.exclusiveMatrixInverse(); //printMatrix(matrix); MMatrix worldMatrix = j.localMatrix; //printMatrix(worldMatrix); MMatrix invWorldMatrix = worldMatrix.inverse(); matrix = matrix * invWorldMatrix; if(j.parentIndex >= 0) { matrix = matrix * m_joints[j.parentIndex].localMatrix; } //printMatrix(matrix); } extractTranMatrix(matrix,translation.v,rotation.q,scale.v); if(time >= DEBUG_TIME) { MFnIkJoint jn(j.jointDag); if(jn.name() == "L_leg") { char str[256]; sprintf(str,"%5.5f,%5.5f,%5.5f\n\n",translation.v[0],translation.v[1],translation.v[2]); OutputDebugString(str); sprintf(str,"%5.5f,%5.5f,%5.5f,%5.5f\n\n",rotation.q[0],rotation.q[1],rotation.q[2],rotation.q[3]); OutputDebugString(str); sprintf(str,"%5.5f,%5.5f,%5.5f\n\n",scale.v[0],scale.v[1],scale.v[2]); OutputDebugString(str); /*D3DXMATRIX d3dM(matrix[0][0],matrix[0][1],matrix[0][2],matrix[0][3], matrix[1][0],matrix[1][1],matrix[1][2],matrix[1][3], matrix[2][0],matrix[2][1],matrix[2][2],matrix[2][3], matrix[3][0],matrix[3][1],matrix[3][2],matrix[3][3]); D3DXVECTOR3 d3dS,d3dT; D3DXQUATERNION d3dQ; HRESULT hr = D3DXMatrixDecompose(&d3dS,&d3dQ,&d3dT,&d3dM); hr = hr;*/ //rotation.q[0] = -rotation.q[0]; //rotation.q[1] = -rotation.q[1]; //rotation.q[2] = -rotation.q[2]; //rotation.q[3] = -rotation.q[3]; } } /*D3DXQUATERNION q1 = D3DXQUATERNION(0.14122,0.09228,-0.82219,0.54365); D3DXQUATERNION q2 = D3DXQUATERNION(-0.13556,-0.09684,0.85495,-0.49124); D3DXQUATERNION q3; D3DXQuaternionSlerp(&q3,&q1,&q2,1-0.63636363);*/ translation.time = time; rotation.time = time; scale.time = time; }
MStatus clusterControledCurve::compute( const MPlug& plug, MDataBlock& data ) { //MFnDependencyNode thisNode( thisMObject() ); //cout << thisNode.name() << ", start" << endl; MStatus status; MDataHandle hInputCurve = data.inputValue( aInputCurve, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hInputCurveMatrix = data.inputValue( aInputCurveMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hOutputCurve = data.outputValue( aOutputCurve, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MArrayDataHandle hArrBindPreMatrix = data.inputArrayValue( aBindPreMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MArrayDataHandle hArrMatrix = data.inputArrayValue( aMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MArrayDataHandle hArrWeightList = data.inputArrayValue( aWeightList, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hUpdate = data.inputValue( aUpdate, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MObject oInputCurve = hInputCurve.asNurbsCurve(); int bindPreMatrixLength = hArrBindPreMatrix.elementCount(); int matrixLength = hArrMatrix.elementCount(); MFnNurbsCurve fnInputCurve = oInputCurve; int numCVs = fnInputCurve.numCVs(); int weightListLength = hArrWeightList.elementCount(); if( weightListLength > 100 ) { cout << "WeightList Count Error : " << weightListLength << endl; return MS::kFailure; } MPointArray inputCvPoints; MPointArray outputCvPoints; fnInputCurve.getCVs( inputCvPoints ); outputCvPoints.setLength( numCVs ); MMatrix matrix; MMatrix inputCurveMatrix = hInputCurveMatrix.asMatrix(); MMatrix inputCurveMatrixInverse = inputCurveMatrix.inverse(); if( requireUpdate ) CHECK_MSTATUS_AND_RETURN_IT( updateBindPreMatrix( oInputCurve, inputCurveMatrixInverse, hArrMatrix, hArrBindPreMatrix, hUpdate.asBool() ) ); for( int i=0; i< numCVs; i++ ) { inputCvPoints[i] *= inputCurveMatrix; } for( int i=0; i< numCVs; i++ ) { outputCvPoints[i] = MPoint( 0,0,0 ); double weight; for( int j=0; j< matrixLength; j++ ) { weight = setWeights[i][j]; hArrMatrix.jumpToElement( j ); matrix = hArrMatrix.inputValue().asMatrix(); outputCvPoints[i] += inputCvPoints[i]*bindPreMatrix[j]*matrix*weight; } } for( int i=0; i< numCVs; i++ ) { outputCvPoints[i] *= inputCurveMatrixInverse; } MFnNurbsCurveData outputCurveData; MObject oOutputCurve = outputCurveData.create(); fnInputCurve.copy( oInputCurve, oOutputCurve ); MFnNurbsCurve fnOutputCurve( oOutputCurve, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); fnOutputCurve.setCVs( outputCvPoints ); hOutputCurve.set( oOutputCurve ); data.setClean( plug ); //cout << thisNode.name() << ", end" << endl; return status; }
// // 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; }
bool gpuCacheIsectUtil::getClosestPointOnTri(const MPoint &toThisPoint, const MPoint &pt1, const MPoint &pt2, const MPoint &pt3, MPoint &theClosestPoint, double &currDist) { double sum, a, b, c, len, dist; MMatrix mat; mat.setToIdentity(); mat[2][0] = mat[2][1] = mat[2][2] = 1.; MVector v = toThisPoint - pt1; MVector v12 = pt2 - pt1; MVector v13 = pt3 - pt1; MVector norm = v12 ^ v13; len = norm * norm; if (len < 1.175494351e-38F) return false; len = ( norm * v ) / len; MPoint pnt = toThisPoint - len * norm; // Do a quick test first if (pnt.distanceTo(toThisPoint) >= currDist) return false; int i, j; // Find best plane to project to if (fabs(norm[0]) > fabs(norm[1])) { if (fabs(norm[0]) > fabs(norm[2])) { i = 1; j = 2; } else { i = 0; j = 1; } } else { if (fabs(norm[1]) > fabs(norm[2])) { i = 0; j = 2; // i = 2; j = 0; } else { i = 0; j = 1; } } mat[0][0] = pt1[i]; mat[0][1] = pt2[i]; mat[0][2] = pt3[i]; mat[1][0] = pt1[j]; mat[1][1] = pt2[j]; mat[1][2] = pt3[j]; MMatrix matInv = mat.inverse(); MPoint abc(pnt[i], pnt[j], 1, 0); abc = matInv * abc; // Now abc is the barycentric coordinates of pnt // clip to inside triangle if (abc[0]<0) { // a < 0 if (abc[1]<0) { // b < 0 a = b = 0; c = 1; } else if (abc[2]<0) { // c < 0 a = c = 0; b = 1; } else { a = 0; // c = BP dot BC / BC square; MVector v23 = pt3 - pt2; // BC MVector vp = toThisPoint - pt2; // BP c = ( vp * v23 ) / ( v23[0]*v23[0] + v23[1]*v23[1] + v23[2]*v23[2] ); if (c<0) c = 0; else if (c>1) c = 1; b = 1 - c; } } else if (abc[1]<0) { // b < 0 if (abc[2]<0) { // c < 0 b = c = 0; a = 1; //} else if (abc[0]<0) { // a < 0 // b = a = 0; // commented-code for optimization // c = 1; // leaving it in for readability (cyclic variations) } else { b = 0; // a = CP dot CA / CA square; MVector v31 = pt1 - pt3; // CA MVector vp = toThisPoint - pt3; // CP a = ( vp * v31 ) / ( v31[0]*v31[0] + v31[1]*v31[1] +v31[2]*v31[2] ); if (a<0) a = 0; else if (a>1) a = 1; c = 1 - a; } } else if (abc[2]<0) { // c < 0 //if (abc[1]<0) { // b < 0 // c = b = 0; // a = 1; //} else if (abc[0]<0) { // a < 0 // c = a = 0; // b = 1; // commented-code for optimization //} else { // leaving it in for readability (cyclic variations) c = 0; // b = AP dot AB / AB square; //DIFF(v23, pt3, pt2); // AB MVector vp = toThisPoint - pt1; // AP b = ( vp * v12 ) / ( v12[0]*v12[0] + v12[1]*v12[1] + v12[2]*v12[2] ); if (b<0) b = 0; else if (b>1) b = 1; a = 1 - b; //} } else { if (abc[0]>0) a = abc[0]; else a = 0; if (abc[1]>0) b = abc[1]; else b = 0; if (abc[2]>0) c = abc[2]; else c = 0; } sum = a+b+c; a /= sum ; b /= sum ; c /= sum ; pnt = a * pt1 + b * pt2 + c * pt3; dist = pnt.distanceTo(toThisPoint); if ( dist < currDist) { // Now it's really closer, keep it currDist = dist; theClosestPoint = pnt; return true; } return false; }
// 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; }
MStatus dgTransform::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; MDataHandle hTranslate = data.inputValue( aTranslate, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hRotate = data.inputValue( aRotate, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hScale = data.inputValue( aScale, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hShear = data.inputValue( aShear, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hJointOrient = data.inputValue( aJointOrient, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hInputTranslate = data.inputValue( aInputTranslate, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hInputRotate = data.inputValue( aInputRotate, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hInputScale = data.inputValue( aInputScale, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MDataHandle hInputShear = data.inputValue( aInputShear, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); MPxTransformationMatrix inputMpxTrMtx; MEulerRotation inputEulerRot( hInputRotate.asVector() ); inputMpxTrMtx.translateTo( hInputTranslate.asVector() ); inputMpxTrMtx.rotateTo( inputEulerRot ); inputMpxTrMtx.scaleTo( hInputScale.asVector() ); inputMpxTrMtx.shearTo( hInputShear.asVector() ); MMatrix parentMatrix = inputMpxTrMtx.asMatrix(); MPxTransformationMatrix mpxTrMtx; MEulerRotation eulerRot( hRotate.asVector() ); MEulerRotation joEulerRot( hJointOrient.asVector() ); mpxTrMtx.translateTo( hTranslate.asVector() ); mpxTrMtx.rotateTo( eulerRot ); mpxTrMtx.rotateBy( joEulerRot ); mpxTrMtx.scaleTo( hScale.asVector() ); mpxTrMtx.shearTo( hShear.asVector() ); if( plug == aMatrix ) { //cout <<"matrix"<<endl; MDataHandle hMatrix = data.outputValue( aMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); hMatrix.setMMatrix( mpxTrMtx.asMatrix() ); } if( plug == aInverseMatrix ) { //cout <<"inverseMatrix"<<endl; MDataHandle hInverseMatrix = data.outputValue( aInverseMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); hInverseMatrix.setMMatrix( mpxTrMtx.asMatrix().inverse() ); } if( plug == aWorldMatrix || plug == aWorldInverseMatrix ) { MMatrix worldMatrix = mpxTrMtx.asMatrix()*parentMatrix; if( plug == aWorldMatrix ) { //cout <<"worldMatrix"<<endl; MDataHandle hWorldMatrix = data.outputValue( aWorldMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); hWorldMatrix.setMMatrix( worldMatrix ); } if( plug == aWorldInverseMatrix ) { //cout <<"worldInverseMatrix"<<endl; MDataHandle hWorldInverseMatrix = data.outputValue( aWorldInverseMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); hWorldInverseMatrix.setMMatrix( worldMatrix.inverse() ); } } if( plug == aParentMatrix ) { //cout <<"parentMatrix"<<endl; MDataHandle hParentMatrix = data.outputValue( aParentMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); hParentMatrix.setMMatrix( parentMatrix ); } if( plug == aParentInverseMatrix ) { //cout <<"parentInverseMatrix"<<endl; MDataHandle hParentInverseMatrix = data.outputValue( aParentInverseMatrix, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); hParentInverseMatrix.setMMatrix( parentMatrix.inverse() ); } data.setClean( plug ); return status; }