MMatrix MotionSyn::syc() { int subject =0; MMatrix stylemat(1,mFactors[2]->sizeCol()); stylemat.copyRowRow(0,*mFactors[2],0); stylemat.scale(0.5); stylemat.axpyRowRow(0,*mFactors[2],1,0.5); std::cout << stylemat << std::endl; assert(mFactors.size() == 3); //assert(subject < mFactors[1]->sizeRow() && style < mFactors[2]->sizeRow()); MMatrix mat(1,mFactors[1]->sizeCol() * mFactors[2]->sizeCol()); for(size_t t = 0; t < mFactors[1]->sizeCol(); t++) { for(size_t k = 0; k < mFactors[2]->sizeCol(); k++) { double val = mFactors[1]->get(subject,t) * stylemat.get(0,k); mat.assign(val,t * stylemat.sizeCol() + k); } } MMatrix val = mGPM->predict(mat); double step = val.get(0); int length = int(2*3.141592653589/step); std::vector<MMatrix> X(3); X[0].resize(length,2); X[1].resize(length, mFactors[1]->sizeCol()); X[2].resize(length, mFactors[2]->sizeCol()); for(int i = 0; i < length; i++) { X[0].assign(cos(double(i * step)), i, 0); X[0].assign(sin(double(i * step)), i, 1); X[1].copyRowRow(i, *mFactors[1], subject); X[2].copyRowRow(i, stylemat, 0); } return meanPrediction(X,CVector3D<double>(0,mInitY.get(subject,1),0)); }
//--------------------------------------------------- // 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 getUVFromConnectedTexturePlacementNode(MObject fileTextureNode, float inU, float inV, float& outU, float& outV) { MObject texPlaceObj = getConnectedInNode(fileTextureNode, "uvCoord"); outU = inU; outV = outV; if( texPlaceObj == MObject::kNullObj ) return; double offsetU = 0.0; double offsetV = 0.0; MFnDependencyNode texPlaceNode(texPlaceObj); getDouble(MString("offsetU"), texPlaceNode, offsetU); getDouble(MString("offsetV"), texPlaceNode, offsetV); float repeatU = 1.0f, repeatV = 1.0f, rotateUV = 0.0f; getFloat("repeatU", texPlaceNode, repeatU); getFloat("repeatV", texPlaceNode, repeatV); getFloat("rotateUV", texPlaceNode, rotateUV); MMatrix rotationMatrix; rotationMatrix.setToIdentity(); rotationMatrix[0][0] = cos(rotateUV) * repeatU; rotationMatrix[1][0] = -sin(rotateUV) * repeatU; rotationMatrix[0][1] = sin(rotateUV) * repeatV; rotationMatrix[1][1] = cos(rotateUV) * repeatV; MVector uv(inU - 0.5, inV - 0.5, 0.0); uv = uv * rotationMatrix; uv.x += 0.5; uv.y += 0.5; uv.x *= repeatU; uv.y *= repeatV; uv.x += offsetU; uv.y += offsetV; outU = uv.x; outV = uv.y; }
void FujiRenderer::setTransform(mtfu_MayaObject *obj) { if( obj->objectID == SI_BADID) { logger.error(MString("Object ") + obj->shortName + " has bad ID"); return; } MMatrix rotMatrix; rotMatrix.setToIdentity(); if( obj->mobject.hasFn(MFn::kAreaLight)) { MTransformationMatrix tm(rotMatrix); double areaScale[3] = {2,2,2}; tm.setScale(areaScale, MSpace::kWorld); MEulerRotation e(-90.0, 0.0, 0.0); tm.rotateBy(e, MSpace::kWorld); rotMatrix = tm.asMatrix(); } MMatrix transformMatrix = rotMatrix * obj->dagPath.inclusiveMatrix(); MTransformationMatrix objTMatrix(transformMatrix); double rot[3]; double scale[3]; MTransformationMatrix::RotationOrder rotOrder = MTransformationMatrix::kXYZ; objTMatrix.getRotation(rot, rotOrder, MSpace::kWorld); MVector pos = objTMatrix.getTranslation(MSpace::kWorld); objTMatrix.getScale(scale, MSpace::kWorld); SiSetProperty3(obj->objectID, "translate", pos[0], pos[1], pos[2]); SiSetProperty3(obj->objectID, "rotate", RadToDeg(rot[0]), RadToDeg(rot[1]), RadToDeg(rot[2])); SiSetProperty3(obj->objectID, "scale", scale[0], scale[1], scale[2]); //logger.debug(MString("SetProperty3 ") + obj->shortName + " translate " + pos[0] + " " + pos[1] + " " + pos[2]); //logger.debug(MString("SetProperty3 ") + obj->shortName + " rotate " + RadToDeg(rot[0]) + " " + RadToDeg(rot[1]) + " " + RadToDeg(rot[2])); }
void CylinderMesh::transform(MPointArray& points, MVectorArray& normals) { MVector forward = mEnd - mStart; double s = forward.length(); forward.normalize(); MVector left = MVector(0,0,1)^forward; MVector up; if (left.length() < 0.0001) { up = forward^MVector(0,1,0); left = up^forward; } else { up = forward^left; } MMatrix mat; mat[0][0] = forward[0]; mat[0][1] = left[0]; mat[0][2] = up[0]; mat[0][3] = 0; mat[1][0] = forward[1]; mat[1][1] = left[1]; mat[1][2] = up[1]; mat[1][3] = 0; mat[2][0] = forward[2]; mat[2][1] = left[2]; mat[2][2] = up[2]; mat[2][3] = 0; mat[3][0] = 0; mat[3][1] = 0; mat[3][2] = 0; mat[3][3] = 1; mat = mat.transpose(); for (int i = 0; i < gPoints.length(); i++) { MPoint p = gPoints[i]; p.x = p.x * s; // scale p = p * mat + mStart; // transform points.append(p); MVector n = gNormals[i] * mat; normals.append(n); } }
void Kernel::computeKernel(MMatrix &K, const MMatrix &X, const MMatrix &X2) const { assert(K.rowsMatch(X) && K.sizeCol() == X2.sizeRow()); for(size_t i = 0; i < K.sizeRow(); i++) { for(size_t j = 0; j < K.sizeCol(); j++) { K.assign(computeElement(X, i, X2, j), i, j); } } }
// 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 Kernel::computeKernel(MMatrix &K, const MMatrix &X) const { assert(K.rowsMatch(X) && K.isSquare()); for(size_t i = 0; i < K.sizeRow(); i++) { for(size_t j = 0; j < i; j++) { double k = computeElement(X, i, X, j); K.assign(k,i,j); K.assign(k,j,i); } K.assign(computeDiagElement(X,i), i, i); } }
void MotionSyn::toCircle(MMatrix & mat) const { for (size_t i = 1; i < mSegments.size(); i++) { double theta = mFactors[0]->get(i-1, 0); double delta = mFactors[0]->get(i-1, 1); for (size_t j = mSegments[i-1]; j < mSegments[i]; j++) { double cosTheta = cos(theta + (j - mSegments[i-1]) * delta); double sinTheta = sin(theta + (j - mSegments[i-1]) * delta); mat.assign(cosTheta, j, 0); mat.assign(sinTheta, j, 1); //precompute for saving time //mGradTs[0]->assign(-sinTheta, j, 0); //mGradTs[0]->assign( cosTheta, j, 1); //mGradTs[1]->assign(-sinTheta*(j - mSegments[i-1]), j, 0); //mGradTs[1]->assign( cosTheta*(j - mSegments[i-1]), j, 1); } } }
MStatus geometrySurfaceConstraint::compute( const MPlug& plug, MDataBlock& block ) { MStatus returnStatus; if(plug == constraintTranslateX || plug == constraintTranslateY || plug == constraintTranslateZ) { if(!m_isInitd) { // read rest position MDataHandle htgo = block.inputValue(targetRestP); double3 & tgo = htgo.asDouble3(); MGlobal::displayInfo(MString("target rest p ")+tgo[0]+" "+tgo[1]+" "+tgo[2]); m_restPos = MPoint(tgo[0],tgo[1],tgo[2]); m_isInitd = true; } MArrayDataHandle targetArray = block.inputArrayValue( compoundTarget ); const unsigned int targetArrayCount = targetArray.elementCount(); MMatrix tm; tm.setToIdentity(); unsigned int i; for ( i = 0; i < targetArrayCount; i++ ) { MDataHandle targetElement = targetArray.inputValue(&returnStatus); if(!returnStatus) { MGlobal::displayInfo("failed to get input value target element"); } MDataHandle htm = targetElement.child(targetTransform); MFnMatrixData ftm(htm.data(), &returnStatus); if(!returnStatus) { MGlobal::displayInfo("failed to get matrix data"); } tm = ftm.matrix(); targetArray.next(); } MDataHandle hparentInvMat = block.inputValue(constraintParentInverseMatrix); MMatrix parentInvMat = hparentInvMat.asMatrix(); // world position MPoint curPos(tm(3,0), tm(3,1), tm(3,2)); // offset in local space m_offsetToRest = m_restPos - curPos; // object position in world space MPoint localP = m_offsetToRest * tm + curPos; // in local space localP *= parentInvMat; MDataHandle hout; if(plug == constraintTranslateX) { hout = block.outputValue(constraintTranslateX); hout.set(localP.x); } else if(plug == constraintTranslateY) { hout = block.outputValue(constraintTranslateY); hout.set(localP.y); } else if(plug == constraintTranslateZ) { hout = block.outputValue(constraintTranslateZ); hout.set(localP.z); } //MPlug pgTx(thisMObject(), constraintTargetX); //pgTx.setValue(m_lastPos.x); //MPlug pgTy(thisMObject(), constraintTargetY); //pgTy.setValue(m_lastPos.y); //MPlug pgTz(thisMObject(), constraintTargetZ); //pgTz.setValue(m_lastPos.z); MPlug pgOx(thisMObject(), constraintObjectX); pgOx.setValue(m_offsetToRest.x); MPlug pgOy(thisMObject(), constraintObjectY); pgOy.setValue(m_offsetToRest.y); MPlug pgOz(thisMObject(), constraintObjectZ); pgOz.setValue(m_offsetToRest.z); // MFnNumericData nd; //MObject offsetData = nd.create( MFnNumericData::k3Double); //nd.setData3Double(m_lastPos.x, m_lastPos.y, m_lastPos.z); //MPlug pgTgo(thisMObject(), targetOffset); //pgTgo.setValue(offsetData); } else return MS::kUnknownParameter; 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 }
// ========== DtCameraGetMatrix ========== // // SYNOPSIS // Return the camera transformation matrix. This matrix // includes the camera rotation, translation, and scale // transforms. This function also sets the valid bits // for DT_CAMERA_POSITION and DT_CAMERA_ORIENTATION. // The matrix is in row-major order. // // From PA DT: // Not implemented: returns a pointer to an identity matrix // under the OpenModel implementation. // // For Maya DT: // This fuction returns the camera's global transformation matrix. // int DtCameraGetMatrix( int cameraID, float** matrix ) { // static float mtx[4][4]; static float globalMtx[4][4]; static float localMtx[4][4]; // Check for error. // if( ( cameraID < 0) || ( cameraID >= local->camera_ct ) ) { *matrix = NULL; return( 0 ); } // Set the valid flag. // // local->cameras[cameraID].valid_bits|=(DT_VALID_BIT_MASK&DT_CAMERA_MATRIX); // Get transformations. // #if 0 mtx[0][0]=1.0;mtx[0][1]=0.0;mtx[0][2]=0.0;mtx[0][3]=0.0; mtx[1][0]=0.0;mtx[1][1]=1.0;mtx[1][2]=0.0;mtx[1][3]=0.0; mtx[2][0]=0.0;mtx[2][1]=0.0;mtx[2][2]=1.0;mtx[2][3]=0.0; mtx[3][0]=0.0;mtx[3][1]=0.0;mtx[3][2]=0.0;mtx[3][3]=1.0; #endif // Camera transformation matrix is set on the transform node. // MStatus returnStatus = MS::kSuccess; MFnDagNode fnTransNode( local->cameras[cameraID].transformNode, &returnStatus ); MDagPath dagPath; returnStatus = fnTransNode.getPath( dagPath ); if( MS::kSuccess == returnStatus ) { if( DtExt_Debug() & DEBUG_CAMERA ) { cerr << "Got the dagPath\n"; cerr << "length of the dagpath is " << dagPath.length() << endl; } } MFnDagNode fnDagPath( dagPath, &returnStatus ); MMatrix localMatrix; MMatrix globalMatrix; localMatrix = fnTransNode.transformationMatrix ( &returnStatus ); globalMatrix = dagPath.inclusiveMatrix(); localMatrix.get( localMtx ); globalMatrix.get( globalMtx ); if( DtExt_Debug() & DEBUG_CAMERA ) { int i = 0; int j = 0; cerr << "camera's global transformation matrix:\n"; for( i = 0; i < 4; i++ ) { for( j = 0; j < 4; j++ ) { cerr << globalMtx[i][j] << " "; } cerr << endl; } cerr << "camera's local transformation matrix:\n"; for( i = 0; i < 4; i++ ) { for( j = 0; j < 4; j++ ) { cerr << localMtx[i][j] << " "; } cerr << endl; } } // *matrix = (float*)&mtx; *matrix = (float*)&globalMtx; return(1); } // DtCameraGetMatrix //
MStatus viewRenderUserOperation::execute( const MHWRender::MDrawContext & drawContext ) { // Sample code to debug pass information static const bool debugPassInformation = false; if (debugPassInformation) { const MHWRender::MPassContext & passCtx = drawContext.getPassContext(); const MString & passId = passCtx.passIdentifier(); const MStringArray & passSem = passCtx.passSemantics(); printf("viewRenderUserOperation: drawing in pass[%s], semantic[", passId.asChar()); for (unsigned int i=0; i<passSem.length(); i++) printf(" %s", passSem[i].asChar()); printf("\n"); } // Example code to find the active override. // This is not necessary if the operations just keep a reference // to the override, but this demonstrates how this // contextual information can be extracted. // MHWRender::MRenderer *theRenderer = MHWRender::MRenderer::theRenderer(); const MHWRender::MRenderOverride *overridePtr = NULL; if (theRenderer) { const MString & overrideName = theRenderer->activeRenderOverride(); overridePtr = theRenderer->findRenderOverride( overrideName ); } // Some sample code to debug lighting information in the MDrawContext // if (fDebugLightingInfo) { viewRenderOverrideUtilities::printDrawContextLightInfo( drawContext ); } // Some sample code to debug other MDrawContext information // if (fDebugDrawContext) { MStatus status; MMatrix matrix = drawContext.getMatrix(MHWRender::MFrameContext::kWorldMtx, &status); double dest[4][4]; status = matrix.get(dest); printf("World matrix is:\n"); printf("\t%f, %f, %f, %f\n", dest[0][0], dest[0][1], dest[0][2], dest[0][3]); printf("\t%f, %f, %f, %f\n", dest[1][0], dest[1][1], dest[1][2], dest[1][3]); printf("\t%f, %f, %f, %f\n", dest[2][0], dest[2][1], dest[2][2], dest[2][3]); printf("\t%f, %f, %f, %f\n", dest[3][0], dest[3][1], dest[3][2], dest[3][3]); MDoubleArray viewDirection = drawContext.getTuple(MHWRender::MFrameContext::kViewDirection, &status); printf("Viewdirection is: %f, %f, %f\n", viewDirection[0], viewDirection[1], viewDirection[2]); MBoundingBox box = drawContext.getSceneBox(&status); printf("Screen box is:\n"); printf("\twidth=%f, height=%f, depth=%f\n", box.width(), box.height(), box.depth()); float center[4]; box.center().get(center); printf("\tcenter=(%f, %f, %f, %f)\n", center[0], center[1], center[2], center[3]); int originX, originY, width, height; status = drawContext.getViewportDimensions(originX, originY, width, height); printf("Viewport dimension: center(%d, %d), width=%d, heigh=%d\n", originX, originY, width, height); } // Draw some addition things for scene draw // M3dView mView; if (mPanelName.length() && (M3dView::getM3dViewFromModelPanel(mPanelName, mView) == MStatus::kSuccess)) { // Get the current viewport and scale it relative to that // int targetW, targetH; drawContext.getRenderTargetSize( targetW, targetH ); if (fDrawLabel) { MString testString("Drawing with override: "); testString += overridePtr->name(); MPoint pos(0.0,0.0,0.0); glColor3f( 1.0f, 1.0f, 1.0f ); mView.drawText( testString, pos); } // Some user drawing of scene bounding boxes // if (fDrawBoundingBoxes) { MDagPath cameraPath; mView.getCamera( cameraPath); MCustomSceneDraw userDraw; userDraw.draw( cameraPath, targetW, targetH ); } } return MStatus::kSuccess; }
MStatus CXRayCameraExport::ExportCamera(const MFileObject& file) { MDagPath node; MObject component; MSelectionList list; MFnDagNode nodeFn; MFnCamera C; MStatus st ; MGlobal::getActiveSelectionList( list ); for ( u32 index = 0; index < list.length(); ++index ) { list.getDagPath ( index, node, component ); nodeFn.setObject ( node ); st = C.setObject (node); if(st!=MStatus::kSuccess) { Msg ("Selected object is not a camera"); return MStatus::kInvalidParameter; } } Msg("exporting camera named [%s]", C.name().asChar()); MTime tmTemp,tmTemp2; MTime tmQuant; // Remember the frame the scene was at so we can restore it later. MTime storedFrame = MAnimControl::currentTime(); MTime startFrame = MAnimControl::minTime(); MTime endFrame = MAnimControl::maxTime(); tmTemp.setUnit (MTime::uiUnit()); tmTemp2.setUnit (MTime::uiUnit()); tmQuant.setUnit (MTime::uiUnit()); tmQuant = 10.0; //3 time in sec. temporary COMotion M; M.SetParam (0, (int)(endFrame-startFrame).as(MTime::uiUnit()), 30); Fvector P,R; tmTemp = startFrame; MObject cam_parent = C.parent(0); MFnTransform parentTransform(cam_parent); MDistance dist; while(tmTemp <= endFrame) { MAnimControl::setCurrentTime( tmTemp ); MMatrix parentMatrix = parentTransform.transformation().asMatrix(); MMatrix cv; cv.setToIdentity (); cv[2][2] = -1.0; MMatrix TM; TM = (cv*parentMatrix)*cv; TM = cv*TM; parentMatrix = TM; Msg ("frame[%d]",(int)tmTemp.as(MTime::uiUnit())); dist.setValue (parentMatrix[3][0]); P.x = (float)dist.asMeters(); dist.setValue (parentMatrix[3][1]); P.y = (float)dist.asMeters(); dist.setValue (parentMatrix[3][2]); P.z = (float)dist.asMeters(); Msg ("P %3.3f,%3.3f,%3.3f",P.x,P.y,P.z); double rot[3]; MTransformationMatrix::RotationOrder rot_order = MTransformationMatrix::kXYZ; st = parentTransform.getRotation( rot, rot_order ); R.x = -(float)rot[0]; R.y = -(float)rot[1]; R.z = -(float)rot[2]; //. Msg ("rt %3.3f,%3.3f,%3.3f kWorld",R.x,R.y,R.z); tmTemp2 = tmTemp-startFrame; M.CreateKey (float(tmTemp2.as(MTime::uiUnit()))/30.0f,P,R); if(tmTemp==endFrame) break; tmTemp += tmQuant; if(tmTemp>endFrame) tmTemp=endFrame; }; MString fn_save_to = file.fullName(); fn_save_to += ".anm"; Msg("file full name [%s]", fn_save_to); M.SaveMotion (fn_save_to.asChar()); MAnimControl::setCurrentTime( storedFrame ); return MS::kSuccess; }
// write the frame ranges and statistic string on the root // Also call the post callbacks void AbcWriteJob::postCallback(double iFrame) { std::string statsStr = ""; addToString(statsStr, "SubDStaticNum", mStats.mSubDStaticNum); addToString(statsStr, "SubDAnimNum", mStats.mSubDAnimNum); addToString(statsStr, "SubDStaticCVs", mStats.mSubDStaticCVs); addToString(statsStr, "SubDAnimCVs", mStats.mSubDAnimCVs); addToString(statsStr, "SubDStaticFaces", mStats.mSubDStaticFaces); addToString(statsStr, "SubDAnimFaces", mStats.mSubDAnimFaces); addToString(statsStr, "PolyStaticNum", mStats.mPolyStaticNum); addToString(statsStr, "PolyAnimNum", mStats.mPolyAnimNum); addToString(statsStr, "PolyStaticCVs", mStats.mPolyStaticCVs); addToString(statsStr, "PolyAnimCVs", mStats.mPolyAnimCVs); addToString(statsStr, "PolyStaticFaces", mStats.mPolyStaticFaces); addToString(statsStr, "PolyAnimFaces", mStats.mPolyAnimFaces); addToString(statsStr, "CurveStaticNum", mStats.mCurveStaticNum); addToString(statsStr, "CurveStaticCurves", mStats.mCurveStaticCurves); addToString(statsStr, "CurveAnimNum", mStats.mCurveAnimNum); addToString(statsStr, "CurveAnimCurves", mStats.mCurveAnimCurves); addToString(statsStr, "CurveStaticCVs", mStats.mCurveStaticCVs); addToString(statsStr, "CurveAnimCVs", mStats.mCurveAnimCVs); addToString(statsStr, "PointStaticNum", mStats.mPointStaticNum); addToString(statsStr, "PointAnimNum", mStats.mPointAnimNum); addToString(statsStr, "PointStaticCVs", mStats.mPointStaticCVs); addToString(statsStr, "PointAnimCVs", mStats.mPointAnimCVs); addToString(statsStr, "NurbsStaticNum", mStats.mNurbsStaticNum); addToString(statsStr, "NurbsAnimNum", mStats.mNurbsAnimNum); addToString(statsStr, "NurbsStaticCVs", mStats.mNurbsStaticCVs); addToString(statsStr, "NurbsAnimCVs", mStats.mNurbsAnimCVs); addToString(statsStr, "TransStaticNum", mStats.mTransStaticNum); addToString(statsStr, "TransAnimNum", mStats.mTransAnimNum); addToString(statsStr, "LocatorStaticNum", mStats.mLocatorStaticNum); addToString(statsStr, "LocatorAnimNum", mStats.mLocatorAnimNum); addToString(statsStr, "CameraStaticNum", mStats.mCameraStaticNum); addToString(statsStr, "CameraAnimNum", mStats.mCameraAnimNum); if (statsStr.length() > 0) { Alembic::Abc::OStringProperty stats(mRoot.getTop().getProperties(), "statistics"); stats.set(statsStr); } if (mTransTimeIndex != 0) { MString propName; propName += static_cast<int>(mTransTimeIndex); propName += ".samples"; Alembic::Abc::OUInt32Property samp(mRoot.getTop().getProperties(), propName.asChar()); samp.set(mTransSamples); } if (mShapeTimeIndex != 0 && mShapeTimeIndex != mTransTimeIndex) { MString propName; propName += static_cast<int>(mShapeTimeIndex); propName += ".samples"; Alembic::Abc::OUInt32Property samp(mRoot.getTop().getProperties(), propName.asChar()); samp.set(mShapeSamples); } MBoundingBox bbox; if (mArgs.melPostCallback.find("#BOUNDS#") != std::string::npos || mArgs.pythonPostCallback.find("#BOUNDS#") != std::string::npos || mArgs.melPostCallback.find("#BOUNDSARRAY#") != std::string::npos || mArgs.pythonPostCallback.find("#BOUNDSARRAY#") != std::string::npos) { util::ShapeSet::const_iterator it = mArgs.dagPaths.begin(); const util::ShapeSet::const_iterator end = mArgs.dagPaths.end(); for (; it != end; it ++) { mCurDag = *it; MMatrix eMInvMat; if (mArgs.worldSpace) { eMInvMat.setToIdentity(); } else { eMInvMat = mCurDag.exclusiveMatrixInverse(); } bbox.expand(getBoundingBox(iFrame, eMInvMat)); } } processCallback(mArgs.melPostCallback, true, iFrame, bbox); processCallback(mArgs.pythonPostCallback, false, iFrame, bbox); }
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; }
MMatrix MotionSyn::meanPrediction(const std::vector<MMatrix> &X ,CVector3D<double> initPos) { std::vector<const MMatrix*> tempX; for(std::size_t t = 0; t < X.size(); t++) tempX.push_back(&X[t]); std::size_t motionLen = X[0].sizeRow(); MMatrix Kx(motionLen, mNumData); mKernel->computeKernel(Kx, tempX, mFakeFactors); MMatrix &Ymean = Kx * mInvK * mCentredY; for(std::size_t i = 0; i < Ymean.sizeCol(); i++) { Ymean.scaleCol(i, sqrt(mVarY.get(i))); } MMatrix meanData; meanData.repmat(mMeanY, motionLen, 1); Ymean += meanData; MMatrix motion(Ymean.sizeRow(), mInitY.sizeCol()); motion.copyMMatrix(0, 0, Ymean, 0, Ymean.sizeRow(), 0, mInitY.sizeCol()); //TODO motion.assign(initPos.x, 0, 0); motion.assign(initPos.y, 0, 1); motion.assign(initPos.z, 0, 2); for (std::size_t i = 1; i < motionLen; i++) { /* motion.assign(motion.get(i, 0), i, 0); motion.assign(motion.get(i, 1), i, 1); motion.assign(motion.get(i, 2), i, 2);*/ motion.add(motion.get(i-1, 0), i, 0); motion.add(motion.get(i-1, 1), i, 1); motion.add(motion.get(i-1, 2), i, 2); } mocapToEulerAngle(motion); for(std::size_t i = 3; i < motion.sizeCol(); i++) { motion.scaleCol(i, 180.0/M_PI); } //for(std::size_t i = 0; i < motion.sizeRow(); i++) //{ // std::cout << motion.get(i,0) << " ,"; // std::cout << motion.get(i,1) << " ,"; // std::cout << motion.get(i,2) << " ,"; // std::cout << motion.get(i,3) << " ,"; // std::cout << motion.get(i,4) << " ,"; // std::cout << motion.get(i,5) << std::endl; // } // return motion; }
MMatrix MotionSyn::generate(std::size_t identity,vector<std::size_t> contents,std::size_t interval) { std::size_t state_size = contents.size() * 2 - 1; std::size_t length = interval * state_size; MMatrix motion(length,mInitY.sizeCol()); std::vector<MMatrix> xStar(3); xStar[0].resize(length, 2); xStar[1].resize(length, mFactors[1]->sizeCol()); xStar[2].resize(length, mFactors[2]->sizeCol()); double current_state = 0; for (std::size_t i = 0; i < state_size; i++) { MMatrix kron(1,mFactors[1]->sizeCol() * mFactors[2]->sizeCol()); if (i % 2 == 0) { MMatrix mat1 = mFactors[1]->subMMatrix(identity, 0, 1, mFactors[1]->sizeCol()); MMatrix mat2 = mFactors[2]->subMMatrix(contents[i/2], 0, 1, mFactors[2]->sizeCol()); kron = mat1.kron(mat2); MMatrix val = mGPM->predict(kron); double step = val.get(0); for (std::size_t t = 0; t < interval; t++) { xStar[0].assign(cos(current_state + double(t*step)), t + i * interval, 0); xStar[0].assign(sin(current_state + double(t*step)), t + i * interval, 1); xStar[1].copyRowRow(t + i * interval, *mFactors[1], identity); xStar[2].copyRowRow(t + i * interval, *mFactors[2], contents[i/2]); } current_state += step * interval; } else { for (std::size_t t = 0; t < interval; t++) { MMatrix linearIpconent(1,mFactors[2]->sizeCol()); for (std::size_t k = 0; k < linearIpconent.sizeCol(); k++) { double val = (1 - double(t) / interval) * mFactors[2]->get(contents[(i-1)/2], k) + (double(t) / interval) * mFactors[2]->get(contents[(i+1)/2], k); linearIpconent.assign(val, 0, k); } MMatrix mat = mFactors[1]->subMMatrix(identity, 0, 1, mFactors[1]->sizeCol()); kron = mat.kron(linearIpconent); MMatrix val = mGPM->predict(kron); double step = val.get(0); current_state += step; xStar[0].assign(cos(current_state), t + i * interval, 0); xStar[0].assign(sin(current_state), t + i * interval, 1); xStar[1].copyRowRow(t + i * interval, *mFactors[1], identity); xStar[2].copyRowRow(t + i * interval, linearIpconent, 0); } } } return meanPrediction(xStar,CVector3D<double>(0,mInitY.get(identity,1),0)); }
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; }
void Kernel::getGradientX(std::vector<MMatrix*>&gX, const MMatrix &X,const MMatrix &X2,bool addG) const { for(size_t t = 0; t < X.sizeRow(); t++) getGradientX(*gX[t],X,t,X2,addG); }
MMatrix MotionSyn::synTrainsiton(const std::size_t identity, const std::size_t content1,const std::size_t content2, const std::size_t length, CVector3D<double> initPos, double &curState) { std::vector<MMatrix> xStar(3); xStar[0].resize(length,2); xStar[1].resize(length, mFactors[1]->sizeCol()); xStar[2].resize(length, mFactors[2]->sizeCol()); MMatrix actor = mFactors[1]->subMMatrix(identity,0,1,mFactors[1]->sizeCol()); /*std::vector<double> steps; double total = 0.0; for (std::size_t i = 0; i < length; i++) { MMatrix newContent(1,mFactors[2]->sizeCol()); for(std::size_t t = 0; t < newContent.sizeCol(); t++) { double val = (1 - double(t)/length) * mFactors[2]->get(content1,t) + double(t)/length * mFactors[2]->get(content2,t); newContent.assign(val,t); } MMatrix kron = actor.kron(newContent); MMatrix val = mGPM->predict(kron); total += val.get(0); steps.push_back(val.get(0)); xStar[1].copyRowRow(i,*mFactors[1],identity); xStar[2].copyRowRow(i,newContent,0); } total = 6.28 - total; for (std::size_t i = 0; i < length; i++) { total += steps[i]; xStar[0].assign(cos(6.28-steps[i]*(length-i)), i, 0); xStar[0].assign(sin(6.28-steps[i]*(length-i)), i, 1); }*/ for (std::size_t i = 0; i < length; i++) { if(i < 50) { MMatrix newContent(1,mFactors[2]->sizeCol()); for(std::size_t t = 0; t < newContent.sizeCol(); t++) { double val = (1 - double(t)/50) * mFactors[2]->get(content1,t) + double(t)/50 * mFactors[2]->get(content2,t); newContent.assign(val,t); } MMatrix kron = actor.kron(newContent); MMatrix val = mGPM->predict(kron); double step = val.get(0); curState += step; xStar[2].copyRowRow(i,newContent,0); /* MMatrix content = mFactors[2]->subMMatrix(content1,0,1,mFactors[2]->sizeCol()); MMatrix kron = actor.kron(content); MMatrix val = mGPM->predict(kron); double step = val.get(0); curState += step; xStar[2].copyRowRow(i,content,0);*/ } else { MMatrix content = mFactors[2]->subMMatrix(content2,0,1,mFactors[2]->sizeCol()); MMatrix kron = actor.kron(content); MMatrix val = mGPM->predict(kron); double step = val.get(0); curState += step; xStar[2].copyRowRow(i,content,0); } xStar[0].assign(cos(curState), i, 0); xStar[0].assign(sin(curState), i, 1); xStar[1].copyRowRow(i,*mFactors[1],identity); } return meanPrediction(xStar,initPos); }
/** Create a RIB compatible representation of a Maya polygon mesh. */ liqRibMeshData::liqRibMeshData( MObject mesh ) : numFaces( 0 ), numPoints ( 0 ), numNormals ( 0 ), nverts(), verts(), vertexParam(NULL), normalParam(NULL) { CM_TRACE_FUNC("liqRibMeshData::liqRibMeshData("<<MFnDagNode(mesh).fullPathName().asChar()<<")"); unsigned int i; unsigned int j; areaLight = false; LIQDEBUGPRINTF( "-> creating mesh\n" ); MFnMesh fnMesh( mesh ); objDagPath = fnMesh.dagPath(); MStatus astatus; name = fnMesh.name(); areaLight =( liquidGetPlugValue( fnMesh, "areaIntensity", areaIntensity, astatus ) == MS::kSuccess )? true : false ; if ( areaLight ) { MDagPath meshDagPath; meshDagPath = fnMesh.dagPath(); MTransformationMatrix worldMatrix = meshDagPath.inclusiveMatrix(); MMatrix worldMatrixM = worldMatrix.asMatrix(); worldMatrixM.get( transformationMatrix ); } numPoints = fnMesh.numVertices(); numNormals = fnMesh.numNormals(); // UV sets ------------------- // //const unsigned numSTs( fnMesh.numUVs() ); const unsigned numUVSets( fnMesh.numUVSets() ); MString currentUVSetName; MStringArray extraUVSetNames; fnMesh.getCurrentUVSetName( currentUVSetName ); { MStringArray UVSetNames; fnMesh.getUVSetNames( UVSetNames ); for ( unsigned i( 0 ); i<numUVSets; i++ ) if ( UVSetNames[i] != currentUVSetName ) extraUVSetNames.append( UVSetNames[i] ); } numFaces = fnMesh.numPolygons(); const unsigned numFaceVertices( fnMesh.numFaceVertices() ); if ( numPoints < 1 ) { // MGlobal::displayInfo( MString( "fnMesh: " ) + fnMesh.name() ); // cerr << "Liquid : Could not export degenerate mesh '"<< fnMesh.fullPathName( &astatus ).asChar() << "'" << endl << flush; return; } unsigned face = 0; unsigned faceVertex = 0; unsigned count; unsigned vertex; unsigned normal; float S; float T; MPoint point; liqTokenPointer pointsPointerPair; liqTokenPointer normalsPointerPair; liqTokenPointer pFaceVertexSPointer; liqTokenPointer pFaceVertexTPointer; // Allocate memory and tokens numFaces = numFaces; nverts = shared_array< liqInt >( new liqInt[ numFaces ] ); verts = shared_array< liqInt >( new liqInt[ numFaceVertices ] ); pointsPointerPair.set( "P", rPoint, numPoints ); pointsPointerPair.setDetailType( rVertex ); if ( numNormals == numPoints ) { normalsPointerPair.set( "N", rNormal, numPoints ); normalsPointerPair.setDetailType( rVertex ); } else { normalsPointerPair.set( "N", rNormal, numFaceVertices ); normalsPointerPair.setDetailType( rFaceVarying ); } // uv std::vector<liqTokenPointer> UVSetsArray; UVSetsArray.reserve( 1 + extraUVSetNames.length() ); liqTokenPointer currentUVSetUPtr; liqTokenPointer currentUVSetVPtr; liqTokenPointer currentUVSetNamePtr; liqTokenPointer extraUVSetsUPtr; liqTokenPointer extraUVSetsVPtr; liqTokenPointer extraUVSetsNamePtr; if(liqglo.liqglo_outputMeshAsRMSArrays) { currentUVSetUPtr.set( "s", rFloat, numFaceVertices ); currentUVSetUPtr.setDetailType( rFaceVarying ); currentUVSetVPtr.set( "t", rFloat, numFaceVertices ); currentUVSetVPtr.setDetailType( rFaceVarying ); currentUVSetNamePtr.set( "currentUVSet", rString, 1 ); currentUVSetNamePtr.setDetailType( rConstant ); if( numUVSets > 1 ) { extraUVSetsUPtr.set( "u_uvSet", rFloat, numFaceVertices, numUVSets-1 ); extraUVSetsUPtr.setDetailType( rFaceVarying ); extraUVSetsVPtr.set( "v_uvSet", rFloat, numFaceVertices, numUVSets-1 ); extraUVSetsVPtr.setDetailType( rFaceVarying ); extraUVSetsNamePtr.set( "extraUVSets", rString, numUVSets-1 ); extraUVSetsNamePtr.setDetailType( rConstant ); } } else { if ( numUVSets > 0 ) { liqTokenPointer pFaceVertexPointerPair; pFaceVertexPointerPair.set( "st", rFloat, numFaceVertices, 2 ); pFaceVertexPointerPair.setDetailType( rFaceVarying ); UVSetsArray.push_back( pFaceVertexPointerPair ); for ( unsigned j( 0 ); j<extraUVSetNames.length(); j++) { liqTokenPointer pFaceVertexPointerPair; pFaceVertexPointerPair.set( extraUVSetNames[j].asChar(), rFloat, numFaceVertices, 2 ); pFaceVertexPointerPair.setDetailType( rFaceVarying ); UVSetsArray.push_back( pFaceVertexPointerPair ); } if( liqglo.liqglo_outputMeshUVs ) { // Match MTOR, which also outputs face-varying STs as well for some reason - Paul // not anymore - Philippe pFaceVertexSPointer.set( "u", rFloat, numFaceVertices ); pFaceVertexSPointer.setDetailType( rFaceVarying ); pFaceVertexTPointer.set( "v", rFloat, numFaceVertices ); pFaceVertexTPointer.setDetailType( rFaceVarying ); } } } vertexParam = pointsPointerPair.getTokenFloatArray(); normalParam = normalsPointerPair.getTokenFloatArray(); // Read the mesh from Maya MFloatVectorArray normals; fnMesh.getNormals( normals ); for ( MItMeshPolygon polyIt ( mesh ); polyIt.isDone() == false; polyIt.next() ) { count = polyIt.polygonVertexCount(); nverts[face] = count; for( i=0; i<count; i++ ) // boucle sur les vertex de la face { vertex = polyIt.vertexIndex( i ); verts[faceVertex] = vertex; point = polyIt.point( i, MSpace::kObject ); pointsPointerPair.setTokenFloat( vertex, point.x, point.y, point.z ); normal = polyIt.normalIndex( i ); if( numNormals == numPoints ) normalsPointerPair.setTokenFloat( vertex, normals[normal].x, normals[normal].y, normals[normal].z ); else normalsPointerPair.setTokenFloat( faceVertex, normals[normal].x, normals[normal].y, normals[normal].z ); if( liqglo.liqglo_outputMeshAsRMSArrays ) { for( j=0; j<numUVSets; j++ ) { if(j==0) { MString uvSetName = currentUVSetName; // set uvSet name currentUVSetNamePtr.setTokenString( 0, currentUVSetName.asChar() ); // set uv values fnMesh.getPolygonUV( face, i, S, T, &uvSetName ); currentUVSetUPtr.setTokenFloat( faceVertex, S ); currentUVSetVPtr.setTokenFloat( faceVertex, 1-T ); } else { MString uvSetName = extraUVSetNames[j-1]; // set uvSet name extraUVSetsNamePtr.setTokenString( j-1, extraUVSetNames[j-1].asChar() ); // set uv values fnMesh.getPolygonUV( face, i, S, T, &uvSetName ); extraUVSetsUPtr.setTokenFloat( (numFaceVertices*(j-1)) + faceVertex, S ); extraUVSetsVPtr.setTokenFloat( (numFaceVertices*(j-1)) + faceVertex, 1-T ); } } } else { if ( numUVSets ) { for( j=0; j<numUVSets; j++ ) { MString uvSetName; if(j==0) { uvSetName = currentUVSetName; } else { uvSetName = extraUVSetNames[j-1]; } fnMesh.getPolygonUV( face, i, S, T, &uvSetName ); UVSetsArray[j].setTokenFloat( faceVertex, 0, S ); UVSetsArray[j].setTokenFloat( faceVertex, 1, 1-T ); //printf("V%d %s : %f %f => %f %f \n", i, uvSetName.asChar(), S, T, S, 1-T); if( liqglo.liqglo_outputMeshUVs && j==0) { // Match MTOR, which always outputs face-varying STs as well for some reason - Paul pFaceVertexSPointer.setTokenFloat( faceVertex, S ); pFaceVertexTPointer.setTokenFloat( faceVertex, 1-T ); } } } } // printf( "[%d] faceVertex = %d vertex = %d\n", i, faceVertex, vertex ); ++faceVertex; } ++face; } // Add tokens to array and clean up after tokenPointerArray.push_back( pointsPointerPair ); tokenPointerArray.push_back( normalsPointerPair ); if(liqglo.liqglo_outputMeshAsRMSArrays) { tokenPointerArray.push_back( currentUVSetNamePtr ); tokenPointerArray.push_back( currentUVSetUPtr ); tokenPointerArray.push_back( currentUVSetVPtr ); if( numUVSets > 1 ) { tokenPointerArray.push_back( extraUVSetsNamePtr ); tokenPointerArray.push_back( extraUVSetsUPtr ); tokenPointerArray.push_back( extraUVSetsVPtr ); } } else { if( UVSetsArray.size() ) tokenPointerArray.insert( tokenPointerArray.end(), UVSetsArray.begin(), UVSetsArray.end() ); if( liqglo.liqglo_outputMeshUVs ) { tokenPointerArray.push_back( pFaceVertexSPointer ); tokenPointerArray.push_back( pFaceVertexTPointer ); } } addAdditionalSurfaceParameters( mesh ); }
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; }
// 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 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; }
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 ); } } } } } } }
// // 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; }
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 ); } } } } }
/* virtual */ MStatus cgfxVector::compute( const MPlug& plug, MDataBlock& data ) { MStatus status; MFnData::Type dataType = MFnData::kInvalid; if( plug == sWorldVector || plug == sWorldVectorX || plug == sWorldVectorY || plug == sWorldVectorZ || plug == sWorldVectorW) { // We do isDirection first simply because if there is an // error, the isDirection error is more legible than the // vector or matrix error. // MDataHandle dhIsDirection = data.inputValue(sIsDirection, &status); if (!status) { status.perror("cgfxVector: isDirection handle"); return status; } dataType = dhIsDirection.type(); MDataHandle dhVector = data.inputValue(sVector, &status); if (!status) { status.perror("cgfxVector: vector handle"); return status; } dataType = dhVector.type(); MMatrix matrix; MPlug matrixPlug(thisMObject(), sMatrix); if (matrixPlug.isNull()) { OutputDebugString("matrixPlug is NULL!\n"); } // TODO: Fix this kludge. // // We should not have to do this but for some reason, // using data.inputValue() fails for the sMatrix attribute. // Instead, we get a plug to the attribute and then get // the value directly. // MObject oMatrix; matrixPlug.getValue(oMatrix); MFnMatrixData fndMatrix(oMatrix, &status); if (!status) { status.perror("cgfxVector: matrix data"); } matrix= fndMatrix.matrix(&status); if (!status) { status.perror("cgfxVector: get matrix"); } #if 0 // TODO: This is how we are supposed to do it. (I think). // MDataHandle dhMatrix = data.inputValue(sMatrix, &status); if (!status) { status.perror("cgfxVector: matrix handle"); } dataType = dhMatrix.type(); oMatrix = dhMatrix.data(); MFnMatrixData fnMatrix(oMatrix, &status); if (!status) { status.perror("cgfxVector: matrix function set"); } matrix = fnMatrix.matrix(); #endif /* 0 */ bool isDirection = dhIsDirection.asBool(); double3& vector = dhVector.asDouble3(); double mat[4][4]; matrix.get(mat); double ix, iy, iz, iw; // Input vector float ox, oy, oz, ow; // Output vector ix = vector[0]; iy = vector[1]; iz = vector[2]; iw = isDirection ? 0.0 : 1.0; ox = (float)(mat[0][0] * ix + mat[1][0] * iy + mat[2][0] * iz + mat[3][0] * iw); oy = (float)(mat[0][1] * ix + mat[1][1] * iy + mat[2][1] * iz + mat[3][1] * iw); oz = (float)(mat[0][2] * ix + mat[1][2] * iy + mat[2][2] * iz + mat[3][2] * iw); ow = (float)(mat[0][3] * ix + mat[1][3] * iy + mat[2][3] * iz + mat[3][3] * iw); MDataHandle dhWVector = data.outputValue(sWorldVector, &status); if (!status) { status.perror("cgfxVector: worldVector handle"); return status; } MDataHandle dhWVectorW = data.outputValue(sWorldVectorW, &status); if (!status) { status.perror("cgfxVector: worldVectorW handle"); return status; } dhWVector.set(ox, oy, oz); dhWVectorW.set(ow); data.setClean(sWorldVector); data.setClean(sWorldVectorW); } else { return MS::kUnknownParameter; } return MS::kSuccess; }
// ========== DtCameraGetOrientation ========== // // SYNOPSIS // Return the camera orientation as x,y,z // Euler angles. // int DtCameraGetOrientation( int cameraID, float* xRot, float* yRot, float* zRot ) { float LRotX, LRotY, LRotZ; double LX = 0.0; double LY = 0.0; double LZ = 0.0; double LXV = 0.0; double LYV = 0.0; double LZV = 0.0; double LXUp = 0.0; double LYUp = 0.0; double LZUp = 0.0; MMatrix LMatrix; // Check for error. // if( (cameraID<0) || (cameraID>=local->camera_ct) ) { *xRot=0.0; *yRot=0.0; *zRot=0.0; return( 0 ); } MStatus returnStatus = MS::kSuccess; MFnCamera fnCamera( local->cameras[cameraID].cameraShapeNode, &returnStatus ); if( MS::kSuccess == returnStatus ) { MPoint eyePt = fnCamera.eyePoint( MSpace::kObject, &returnStatus ); LX = eyePt.x; LY = eyePt.y; LZ = eyePt.z; if( DtExt_Debug() & DEBUG_CAMERA ) { cerr << "eye point is at " << LX << " " << LY << " " << LZ << endl; } MVector upDir = fnCamera.upDirection( MSpace::kObject, &returnStatus ); if( DtExt_Debug() & DEBUG_CAMERA ) { cerr << "up direction is " << upDir.x << " " << upDir.y << " " << upDir.z << endl; } LXUp = upDir.x; LYUp = upDir.y; LZUp = upDir.z; MVector viewDir = fnCamera.viewDirection( MSpace::kObject, &returnStatus ); if( DtExt_Debug() & DEBUG_CAMERA ) { cerr << "view direction is " << viewDir.x << " " << viewDir.y << " " << viewDir.z << endl; } LXV = -viewDir.x; LYV = -viewDir.y; LZV = -viewDir.z; } else { DtExt_Err( "Error in getting the camera function set\n" ); return 0; } // If the up-vector is a null-vector (a problem), set it to 0,1,0 if ( (LXUp == 0) && (LYUp == 0) && (LZUp == 0) ) { LXUp=0.0; LYUp=1.0; LZUp=0.0; } // Compute camera orbital angles LXV, LYV, LZV: direction vector of the camera LRotX = DtGetAngle2D( LYV, sqrt(LXV*LXV + LZV*LZV) ); LRotY = DtGetAngle2D(LZV, LXV); if ( LRotY < 0.0 ) LRotY += 360.0; LX=0.0; LY=1.0; LZ=0.0; // Unit-length up-vector // Create the inverse camera rotation matrix and transform the // default up-vector with it MVector vec( LX, LY, LZ ); vec.rotateBy( MVector::kXaxis, LRotX-90.0 ); vec.rotateBy( MVector::kYaxis, LRotY ); LX = vec.x; LY = vec.y; LZ = vec.z; #if 0 LMatrix = LMatrix.rotateX((LRotX-90.0)*DEGREE_TO_RADIAN); LMatrix *= LMatrix.rotateY(LRotY*DEGREE_TO_RADIAN); LMatrix.transVector(LX,LY,LZ); #endif LRotZ = acos((LXUp*LX + LYUp*LY + LZUp*LZ) / sqrt(LXUp*LXUp + LYUp*LYUp + LZUp*LZUp)) * RADIAN_TO_DEGREE; *xRot = LRotX; *yRot = LRotY; *zRot = LRotZ; return(1); } // DtCameraGetOrientation //