void rigidBodyNode::updateShape(const MPlug& plug, MDataBlock& data, float& collisionMarginOffset) { MObject thisObject(thisMObject()); MPlug plgCollisionShape(thisObject, ia_collisionShape); MObject update; //force evaluation of the shape plgCollisionShape.getValue(update); /* vec3f prevCenter(0, 0, 0); quatf prevRotation(qidentity<float>()); if(m_rigid_body) { prevCenter = m_rigid_body->collision_shape()->center(); prevRotation = m_rigid_body->collision_shape()->rotation(); }*/ collision_shape_t::pointer collision_shape; if(plgCollisionShape.isConnected()) { MPlugArray connections; plgCollisionShape.connectedTo(connections, true, true); if(connections.length() != 0) { MFnDependencyNode fnNode(connections[0].node()); if(fnNode.typeId() == collisionShapeNode::typeId) { collisionShapeNode *pCollisionShapeNode = static_cast<collisionShapeNode*>(fnNode.userNode()); pCollisionShapeNode->setCollisionMarginOffset(collisionMarginOffset); //mb collision_shape = pCollisionShapeNode->collisionShape(); } else { std::cout << "rigidBodyNode connected to a non-collision shape node!" << std::endl; } } } data.outputValue(ca_rigidBody).set(true); data.setClean(plug); }
MStatus sgBDataCmd_key::readData( MString nameFilePath ) { MStatus status; std::ifstream inFile( nameFilePath.asChar(), ios::binary ); MString nameTarget; readString( nameTarget, inFile ); MSelectionList selList; nameTarget.substitute( ":", "_" ); MGlobal::getSelectionListByName( nameTarget, selList ); MObject oTarget; selList.getDependNode( 0, oTarget ); MFnDagNode fnNode( oTarget ); m_objectKeyDataImport.oTargetNode = oTarget; readUnsignedInt( m_objectKeyDataImport.unit, inFile ); readStringArray( m_objectKeyDataImport.namesAttribute, inFile ); readDoubleArray( m_objectKeyDataImport.dArrTime, inFile ); unsigned int lengthValues = m_objectKeyDataImport.namesAttribute.length() * m_objectKeyDataImport.dArrTime.length(); m_objectKeyDataImport.dArrValuesArray.setLength( lengthValues ); for( unsigned int j=0; j<lengthValues; j++ ) inFile.read( ( char* )&m_objectKeyDataImport.dArrValuesArray[j], sizeof( double ) ); inFile.close(); return MS::kSuccess; }
MStatus sgCurveEditBrush_context::getShapeNode( MDagPath& path ) { MStatus status; if ( path.apiType() == MFn::kNurbsCurve ) { return MS::kSuccess; } unsigned int numShapes; status = path.numberOfShapesDirectlyBelow( numShapes ); CHECK_MSTATUS_AND_RETURN_IT( status ); for ( unsigned int i = 0; i < numShapes; ++i ) { status = path.extendToShapeDirectlyBelow( i ); CHECK_MSTATUS_AND_RETURN_IT( status ); if ( !path.hasFn( MFn::kNurbsCurve ) ) { path.pop(); continue; } MFnDagNode fnNode( path, &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); if ( !fnNode.isIntermediateObject() ) { return MS::kSuccess; } path.pop(); } return MS::kFailure; }
MStatus GetShapeNode(MDagPath& path, bool intermediate) { MStatus status; if (IsShapeNode(path)) { // Start at the transform so we can honor the intermediate flag. path.pop(); } if (path.hasFn(MFn::kTransform)) { unsigned int shapeCount = path.childCount(); for (unsigned int i = 0; i < shapeCount; ++i) { status = path.push(path.child(i)); CHECK_MSTATUS_AND_RETURN_IT(status); if (!IsShapeNode(path)) { path.pop(); continue; } MFnDagNode fnNode(path, &status); CHECK_MSTATUS_AND_RETURN_IT(status); if ((!fnNode.isIntermediateObject() && !intermediate) || (fnNode.isIntermediateObject() && intermediate)) { return MS::kSuccess; } // Go to the next shape path.pop(); } } // No valid shape node found. return MS::kFailure; }
MObject findShader(MObject& setNode, SXRShaderData& d) // // Description: // Find the shading node for the given shading group set node. // { MFnDependencyNode fnNode(setNode); d.name = fnNode.name(); // cout << "looking for shader in node " << fnNode.name().asChar() << "\n"; MPlug shaderPlug = fnNode.findPlug("surfaceShader"); if (!shaderPlug.isNull()) { MPlugArray connectedPlugs; bool asSrc = false; bool asDst = true; shaderPlug.connectedTo( connectedPlugs, asDst, asSrc ); if (connectedPlugs.length() != 1) Msg("!Error getting shader"); else return connectedPlugs[0].node(); } Msg("!Error finding surface shader for node '%s'",fnNode.name().asChar()); return MObject::kNullObj; }
void exportShadingInputs() { MObject proceduralNode = m_dagPath.node(); MPlug nullPlug; MIteratorType filter; MIntArray filterTypes; filterTypes.append( MFn::kShadingEngine ); filterTypes.append( MFn::kDisplacementShader ); filter.setFilterList( filterTypes ); MItDependencyGraph itDG( proceduralNode, nullPlug, filter, MItDependencyGraph::kUpstream ); while( !itDG.isDone() ) { MObject node = itDG.currentItem(); MFnDependencyNode fnNode( node ); MPlug plug; if( fnNode.typeName() == "displacementShader" ) { plug = fnNode.findPlug( "displacement" ); } else { plug = fnNode.findPlug( "dsm" ); } ExportNode( plug ); itDG.next(); } }
/** Create a RIB compatible representation of a Maya coordinate system. */ liqRibClipPlaneData::liqRibClipPlaneData( MObject coord ) { LIQDEBUGPRINTF("-> creating clipPlane\n"); MFnDependencyNode fnNode( coord ); this->name = fnNode.name(); //cout <<"created clipPlane "<<this->name.asChar()<<endl; }
void BasicLocator::postConstructor() { //rename the locator shape post construction MObject oThis = thisMObject(); MFnDependencyNode fnNode(oThis); fnNode.setName("basicLocator#"); }
void nailConstraintNode::nodeRemoved(MObject& node, void *clientData) { // std::cout << "nailConstraintNode::nodeRemoved" << std::endl; MFnDependencyNode fnNode(node); nailConstraintNode *pNode = static_cast<nailConstraintNode*>(fnNode.userNode()); constraint_t::pointer constraint = static_cast<constraint_t::pointer>(pNode->m_constraint); solver_t::remove_constraint(constraint); }
AtNode* CScriptedShapeTranslator::CreateArnoldNodes() { std::map<std::string, CScriptedTranslator>::iterator translatorIt; MFnDependencyNode fnNode(GetMayaObject()); translatorIt = gTranslators.find(fnNode.typeName().asChar()); if (translatorIt == gTranslators.end()) { AiMsgError("[mtoa.scriptedTranslators] No command to export node \"%s\" of type %s.", fnNode.name().asChar(), fnNode.typeName().asChar()); return NULL; } float step = FindMayaPlug("aiStepSize").asFloat(); bool asVolume = (step > AI_EPSILON); m_masterNode = 0; if (!IsMasterInstance()) { MDagPath masterPath = GetMasterInstance(); CNodeAttrHandle handle(masterPath); std::vector<CNodeTranslator*> translators; unsigned int n = m_session->GetActiveTranslators(handle, translators); for (unsigned int i=0; i<n; ++i) { m_masterNode = translators[i]->GetArnoldRootNode(); if (m_masterNode) { break; } } } if (!m_masterNode) { if (asVolume && !translatorIt->second.supportVolumes) { return AddArnoldNode("box"); } else { return AddArnoldNode("procedural"); } } else { if (asVolume && !translatorIt->second.supportVolumes) { return AddArnoldNode("ginstance"); } else { return AddArnoldNode(translatorIt->second.supportInstances ? "ginstance" : "procedural"); } } }
bool atomImport::replaceNameAndFindPlug(const MString& origName, atomNodeNameReplacer& replacer, MPlug& replacedPlug) { bool rtn = false; // get the node name // MStringArray nameParts; origName.split('.', nameParts); // Perform any necessary replacement // MString tmpName(nameParts[0]); // TODO: type & hierarchy info -- does the replacer store enough info // to help us find that out since in the case of export edits we don't // have that info for sources // if (replacer.findNode(atomNodeNameReplacer::eDag,tmpName,0,0)) { MString newName(tmpName); newName += ("."); // add the attribute name(s) back on again // unsigned int ii; MString attrName; for (ii = 1; ii < nameParts.length(); ++ii) { if (ii > 1) { attrName += ("."); } attrName += nameParts[ii]; } newName += attrName; MSelectionList tmpList; if (MS::kSuccess == tmpList.add(newName)) { tmpList.getPlug(0,replacedPlug); rtn = !replacedPlug.isNull(); if (!rtn) { // test for the special case of the pivot component // MDagPath path; MObject component; if (MS::kSuccess == tmpList.getDagPath(0,path,component) && component.apiType() == MFn::kPivotComponent) { MObject node; tmpList.getDependNode(0,node); MFnDependencyNode fnNode(node); replacedPlug = fnNode.findPlug(attrName,false); rtn = !replacedPlug.isNull(); } } } } return rtn; }
void TransformNode::createInstance(Core::SmartPtr<Model::IInstanceCreator> model, Core::SmartPtr<Core::SceneGraphNode> &sceneGraph) { Core::SmartPtr<Instances::Instance> instance = model->createInstance(); MFnDagNode fnNode(node); MDagPath dagPath; fnNode.getPath(dagPath); MMatrix worldTransform = dagPath.inclusiveMatrix(); Maya::set(instance->worldTransform, worldTransform); sceneGraph->insert(instance); }
MStatus pbdSolverCmd::redoIt() { //create solver node MStatus stat; MObject transform = dgMod.createNode("transform"); MObject solver= dgMod.createNode(pbdSolverNode::typeId, transform, &stat); //connect time attribute MPlug plgInTime(solver,pbdSolverNode::time); MItDependencyNodes dnTime(MFn::kTime); MObject time = dnTime.thisNode(); MPlug plgOutTime = MFnDependencyNode(time).findPlug("outTime", false); dgMod.connect(plgOutTime, plgInTime); //connect msattr MSelectionList activeSelect; MGlobal::getActiveSelectionList(activeSelect); int pnum = 0, mnum = 0; for(int i = 0;i < activeSelect.length(); ++i) { MObject tNode; activeSelect.getDependNode(i,tNode); MFnDagNode fnDagNode(tNode); MObject pNode=fnDagNode.child(0); MFnDependencyNode fnNode(pNode); //MString name=fnNode1.name().asChar(); if(fnNode.typeId() == OParticleNode::typeId) { //get solver message attribute from particleNode MPlug s_msg(pNode,OParticleNode::pbd_solver); //get particle message attribute from solverNode MPlug o_msg(solver,pbdSolverNode::orientedParticle); dgMod.connect(o_msg,s_msg); ++pnum; } else if(pNode.apiType()==MFn::kMesh) { MString name=MFnDependencyNode(pNode).name().asChar(); MPlug m_vs=fnNode.findPlug("ogc",false); MPlug s_vs(solver,pbdSolverNode::inMesh); dgMod.connect(m_vs,s_vs); ++mnum; } } if( pnum == 0 ) MGlobal::displayError(" No oriented particles are selected"); if( mnum == 0 ) MGlobal::displayError(" No mesh is selected"); MGlobal::displayInfo("PBD solver is created"); return dgMod.doIt(); }
//init the rigid bodies to it's first frame configuration void dSolverNode::initRigidBodies(MPlugArray &rbConnections) { for(size_t i = 0; i < rbConnections.length(); ++i) { MObject node = rbConnections[i].node(); MFnDependencyNode fnNode(node); if(fnNode.typeId() == rigidBodyNode::typeId) { initRigidBody(node); } else if(fnNode.typeId() == rigidBodyArrayNode::typeId) { initRigidBodyArray(node); } } }
MObject exportJointClusterData::jointForCluster(MObject& jointCluster) const // // Given a jointCluster, return the joint that drives it // { MObject result; MFnDependencyNode fnNode(jointCluster); MObject attrJoint = fnNode.attribute("matrix"); MPlug pJointPlug(jointCluster,attrJoint); MPlugArray conns; if (pJointPlug.connectedTo(conns,true,false)) { result = conns[0].node(); } return result; }
MStatus tm_randPoint::undoIt() { if(helpMode) return MS::kSuccess; if(selVtxMode) { MSelectionList curSel; MGlobal::getActiveSelectionList( curSel); MItSelectionList iter( curSel, MFn::kMeshVertComponent); MObject component; MDagPath selVtx_dagPath; int vtxCount = 0; for ( ; !iter.isDone(); iter.next() ) { iter.getDagPath(selVtx_dagPath, component); MItMeshVertex vertexIter( selVtx_dagPath, component ); for ( ; !vertexIter.isDone(); vertexIter.next() ) { vertexIter.setPosition( oldPointsArrays[0][vtxCount], MSpace::kObject ); vtxCount++; } } } else { int num_meshes = res_MDagPathArray.length(); for( int i = 0; i < num_meshes; i++ ) { MDagPath dagPath = res_MDagPathArray[i]; MObject node; node = dagPath.node(); MFnDependencyNode fnNode( node ); MStatus polyStatus; MFnMesh fnMesh( node, &polyStatus ); if( polyStatus == MS::kSuccess ) { MStatus status; status = fnMesh.setPoints( oldPointsArrays[i]); if (!status){status.perror("### error setting point ::undoIt()");return status;} } } } return MS::kSuccess; }
MObject Material::findShader(MObject &setNode) { MFnDependencyNode fnNode(setNode); MPlug shaderPlug = fnNode.findPlug("surfaceShader"); if (!shaderPlug.isNull()) { MPlugArray connectedPlugs; bool asSrc = false; bool asDst = true; shaderPlug.connectedTo( connectedPlugs, asDst, asSrc ); if (connectedPlugs.length() != 1) cerr << "Error getting shader\n"; else return connectedPlugs[0].node(); } return MObject::kNullObj; }
MStatus cgfxShaderCmd::redoIt() { #ifdef KH_DEBUG MString ss = " .. Redo "; ss += fArgString; ss += "\n"; ::OutputDebugString( ss.asChar() ); #endif MStatus stat; try { // Get the node object from the selection list. MObject oNode; stat = fNodeSelection.getDependNode( 0, oNode ); M_CHECK( stat ); MFnDependencyNode fnNode( oNode, &stat ); M_CHECK( stat && fnNode.typeId() == cgfxShaderNode::sId ); cgfxShaderNode* pNode = (cgfxShaderNode*)fnNode.userNode(); M_CHECK( pNode ); // Re-create or re-edit the node. stat = redoCmd( oNode, fnNode, pNode ); } catch ( cgfxShaderCommon::InternalError* e ) { reportInternalError( __FILE__, (size_t)e ); stat = MS::kFailure; } catch ( ... ) { reportInternalError( __FILE__, __LINE__ ); stat = MS::kFailure; } #ifdef KH_DEBUG ss = " .. redone\n"; ::OutputDebugString( ss.asChar() ); #endif return stat; } // MStatus cgfxShaderCmd::redoIt
void sixdofConstraintNode::nodeRemoved(MObject& node, void *clientData) { // std::cout << "sixdofConstraintNode::nodeRemoved" << std::endl; MFnDependencyNode fnNode(node); sixdofConstraintNode *pNode = static_cast<sixdofConstraintNode*>(fnNode.userNode()); if (pNode->m_constraint) { bt_sixdof_constraint_t* hinge_impl = dynamic_cast<bt_sixdof_constraint_t*>(pNode->m_constraint->pubImpl()); rigid_body_t::pointer rigid_bodyA = pNode->m_constraint->rigid_bodyA(); if(rigid_bodyA) { rigid_bodyA->remove_constraint(hinge_impl); } rigid_body_t::pointer rigid_bodyB = pNode->m_constraint->rigid_bodyB(); if(rigid_bodyB) { rigid_bodyB->remove_constraint(hinge_impl); } } constraint_t::pointer constraint = static_cast<constraint_t::pointer>(pNode->m_constraint); solver_t::remove_constraint(constraint); }
MObject findShader( MObject& setNode ) // // Description: // Find the shading node for the given shading group set node. // { MFnDependencyNode fnNode(setNode); MPlug shaderPlug = fnNode.findPlug("surfaceShader"); if (!shaderPlug.isNull()) { MPlugArray connectedPlugs; bool asSrc = false; bool asDst = true; shaderPlug.connectedTo( connectedPlugs, asDst, asSrc ); if (connectedPlugs.length() != 1) MGlobal::displayError("Error getting shader"); else return connectedPlugs[0].node(); } return MObject::kNullObj; }
//standard attributes void nailConstraintNode::computeConstraint(const MPlug& plug, MDataBlock& data) { // std::cout << "nailConstraintNode::computeConstraint" << std::endl; MObject thisObject(thisMObject()); MPlug plgRigidBody(thisObject, ia_rigidBody); MObject update; //force evaluation of the rigidBody plgRigidBody.getValue(update); rigid_body_t::pointer rigid_body; if(plgRigidBody.isConnected()) { MPlugArray connections; plgRigidBody.connectedTo(connections, true, true); if(connections.length() != 0) { MFnDependencyNode fnNode(connections[0].node()); if(fnNode.typeId() == rigidBodyNode::typeId) { rigidBodyNode *pRigidBodyNode = static_cast<rigidBodyNode*>(fnNode.userNode()); rigid_body = pRigidBodyNode->rigid_body(); } else { std::cout << "nailConstraintNode connected to a non-rigidbody node!" << std::endl; } } } if(rigid_body) { //not connected to a rigid body, put a default one constraint_t::pointer constraint = static_cast<constraint_t::pointer>(m_constraint); solver_t::remove_constraint(constraint); m_constraint = solver_t::create_nail_constraint(rigid_body); constraint = static_cast<constraint_t::pointer>(m_constraint); solver_t::add_constraint(constraint); } data.outputValue(ca_constraint).set(true); data.setClean(plug); }
MCallbackId lockEvent::installCallback( MItSelectionList &iter ) // // Description: // Uses given iterator and callback type to attach a new callback on // a node, dag path, or plug. The selection iterator must contain a // valid selection item for the target callback type (fAttach). That is, // if the callback type is three, then the iterator must contain // a dependency node on it the next list item. // { MStatus status; MCallbackId id = 0; MObject node, component; MDagPath path; switch (fAttach) { case 1: { status = iter.getDependNode( node ); if ( status ) { // Try to set the callback. Note: we check the status // flag at the end of the switch statement. // id = MLM::setNodeLockQueryCallback( node, lockDecision, NULL, &status ); } } break; case 2: { status = iter.getDagPath( path, component ); if ( status ) { // Try to set the callback. Note: we check the status // flag at the end of the switch statement. // id = MLM::setNodeLockDAGQueryCallback( path, lockDagDecision, NULL, &status ); } } break; case 3: { status = iter.getDependNode( node ); MStringArray plugName; iter.getStrings( plugName ); // Now we have to parse the plug string. // if ( status && plugName.length() > 0 ) { MFnDependencyNode depNode( node ); MStringArray attrName; plugName[0].split( '.', attrName ); MPlug plug = depNode.findPlug( attrName[1], &status ); if ( status ) { // Try to set the callback. Note: we check the status // flag at the end of the switch statement. // id = MLM::setPlugLockQueryCallback( plug, plugDecision, NULL,&status ); } } else { status = MS::kFailure; } } break; case 4: { status = iter.getDependNode( node ); if ( status ) { // Try to set the callback. Note: we check the status // flag at the end of the switch statement. // id = MLM::setPlugLockQueryCallback( node, nodePlugDecision, NULL, &status ); } } break; default: MGlobal::displayError( "Invalid callback attach type" ); status = MS::kFailure; }; MFnDependencyNode fnNode( node ); // Check the status flag here and report any particular problems // encountered. It is possible for the callback attach routines // to fail. // // This typically occurs when a callback has already been attached // to the node or plug. // if ( !status || !id ) { MString msg; msg = "Unable to add callback for node "; msg += fnNode.name(); MGlobal::displayError( msg ); status.perror( msg ); } else { // Store the result -- so we can clean up later -- and // echo some useful information. // cerr << "Callback attached to " << fnNode.name(); cerr << "; attachment type = " << fAttach << endl; callbackIds.append( (int)id ); } return id; }
MStatus sgBDataCmd_key::writeData( bool exportByMatrix ) { MStatus status; double dTime = MAnimControl::currentTime().value(); if( exportByMatrix ) { for( unsigned int i=0; i<m_pathArrExport.length(); i++ ) { m_objectKeyDatasExport[i].lengthTime++; m_objectKeyDatasExport[i].dArrTime.append( dTime ); MFnDependencyNode fnNode( m_objectKeyDatasExport[i].oTargetNode ); if( m_objectKeyDatasExport[i].numAttr == 0 ) { continue; } if( m_objectKeyDatasExport[i].numAttr == 1 ) { MPlug plug = fnNode.findPlug( m_objectKeyDatasExport[i].namesAttribute[0] ); m_objectKeyDatasExport[i].dArrValuesArray.append( plug.asDouble() ); } else { if( m_objectKeyDatasExport[i].numAttr == 10 ) { MPlug plug = fnNode.findPlug( m_objectKeyDatasExport[i].namesAttribute[0] ); m_objectKeyDatasExport[i].dArrValuesArray.append( plug.asDouble() ); } MDagPath dagPath; dagPath.getAPathTo( m_objectKeyDatasExport[i].oTargetNode, dagPath ); MTransformationMatrix trMtx = dagPath.inclusiveMatrix() * dagPath.exclusiveMatrixInverse(); MVector trans = trMtx.translation( MSpace::kTransform ); double rotValues[3] ={0,0,0}; MTransformationMatrix::RotationOrder order = MTransformationMatrix::kZXY; trMtx.getRotation( rotValues, order, MSpace::kTransform ); double scales[3]; trMtx.getScale( scales, MSpace::kTransform ); m_objectKeyDatasExport[i].dArrValuesArray.append( trans.x ); m_objectKeyDatasExport[i].dArrValuesArray.append( trans.y ); m_objectKeyDatasExport[i].dArrValuesArray.append( trans.z ); m_objectKeyDatasExport[i].dArrValuesArray.append( rotValues[0] ); m_objectKeyDatasExport[i].dArrValuesArray.append( rotValues[1] ); m_objectKeyDatasExport[i].dArrValuesArray.append( rotValues[2] ); m_objectKeyDatasExport[i].dArrValuesArray.append( scales[0] ); m_objectKeyDatasExport[i].dArrValuesArray.append( scales[1] ); m_objectKeyDatasExport[i].dArrValuesArray.append( scales[2] ); } } } else { for( unsigned int i=0; i<m_pathArrExport.length(); i++ ) { m_objectKeyDatasExport[i].lengthTime++; m_objectKeyDatasExport[i].dArrTime.append( dTime ); MFnDependencyNode fnNode( m_objectKeyDatasExport[i].oTargetNode ); for( unsigned int j=0; j< m_objectKeyDatasExport[i].numAttr; j++ ) { MPlug plug = fnNode.findPlug( m_objectKeyDatasExport[i].namesAttribute[j] ); m_objectKeyDatasExport[i].dArrValuesArray.append( plug.asDouble() ); } } } return MS::kSuccess; }
void retargetLocator::postConstructor() { MObject oThis = thisMObject(); MFnDependencyNode fnNode( oThis ); fnNode.setName( "retargetLocatorShape#" ); }
MStatus tm_randPoint::doIt( const MArgList& args ) { MStatus stat = MS::kSuccess; double amp = 1.0; double amp_x = 1.0; double amp_y = 1.0; double amp_z = 1.0; unsigned int seed = 0; bool useAxisAmp = false; bool exactObject = false; unsigned int num_meshes; MString objMString; helpMode = false; MArgDatabase argData( syntax(), args); if(argData.isFlagSet( help_Flag)) { helpMode = true; appendToResult( "\n// tm_polygon randPoint usage:\n"); appendToResult( "// Command operates with specified object with \"-obj\" flag,\n"); appendToResult( "// if this flag is not set, command use selected poly objects or poly vertices.\n"); appendToResult( "// Synopsis: tm_polygon [flags].\n"); appendToResult( "// Type \"help tm_randPoint\" to query flags.\n"); return MS::kSuccess; } if(argData.isFlagSet( amp_Flag)) argData.getFlagArgument( amp_Flag, 0, amp); if(argData.isFlagSet( ampX_Flag)) { argData.getFlagArgument( ampX_Flag, 0, amp_x); useAxisAmp = true; } if(argData.isFlagSet( ampY_Flag)) { argData.getFlagArgument( ampY_Flag, 0, amp_y); useAxisAmp = true; } if(argData.isFlagSet( ampZ_Flag)) { argData.getFlagArgument( ampZ_Flag, 0, amp_z); useAxisAmp = true; } if(argData.isFlagSet( seed_Flag)) argData.getFlagArgument( seed_Flag, 0, seed); if(argData.isFlagSet( obj_Flag)) { exactObject = true; argData.getFlagArgument( obj_Flag, 0, objMString); } double randMax = (double)RAND_MAX; double halfRandMax = 0.5 * randMax; unsigned i; if( exactObject) { selVtxMode = false; MSelectionList m_selList; MDagPath m_dagPath; stat = m_selList.add( objMString); if (!stat){stat.perror("###1 invalid obect path string");return stat;} stat = m_selList.getDagPath( 0, m_dagPath); if (!stat){stat.perror("###2 invalid obect path string");return stat;} stat = res_MDagPathArray.append( m_dagPath); if (!stat){stat.perror("###3 invalid obect path string");return stat;} } else { MSelectionList curSel; MGlobal::getActiveSelectionList( curSel); unsigned int numSelected = curSel.length(); MItSelectionList iter( curSel, MFn::kMeshVertComponent); if (iter.isDone()) { selVtxMode = false; MItDag::TraversalType traversalType = MItDag::kBreadthFirst; MFn::Type filter = MFn::kMesh; MItDag mit_dag( traversalType, filter, &stat); for( i = 0; i < numSelected; i++ ) { MDagPath sel_dagPath; curSel.getDagPath( i, sel_dagPath); stat = mit_dag.reset( sel_dagPath, traversalType, filter); if ( !stat) { stat.perror("MItDag constructor");return stat;} for ( ; !mit_dag.isDone(); mit_dag.next() ) { MDagPath m_dagPath; stat = mit_dag.getPath(m_dagPath); if ( !stat ) { stat.perror("MItDag::getPath error"); continue;} stat = res_MDagPathArray.append( m_dagPath); if ( !stat ) { stat.perror("MDagPathArray.append error"); continue;} } } } else { newPointsArrays = new MPointArray[1]; oldPointsArrays = new MPointArray[1]; selVtxMode = true; MObject component; MDagPath selVtx_dagPath; for ( ; !iter.isDone(); iter.next() ) { iter.getDagPath(selVtx_dagPath, component); MItMeshVertex vertexIter( selVtx_dagPath, component ); for ( ; !vertexIter.isDone(); vertexIter.next() ) { MPoint oldPoint = vertexIter.position(MSpace::kObject ); MPoint newPoint; newPoint.x = oldPoint.x + ((halfRandMax - (double)rand()) / randMax) * amp * amp_x; newPoint.y = oldPoint.y + ((halfRandMax - (double)rand()) / randMax) * amp * amp_y; newPoint.z = oldPoint.z + ((halfRandMax - (double)rand()) / randMax) * amp * amp_z; oldPointsArrays[0].append( oldPoint); newPointsArrays[0].append( newPoint); } } } } if(!selVtxMode) { num_meshes = res_MDagPathArray.length(); newPointsArrays = new MPointArray[num_meshes]; oldPointsArrays = new MPointArray[num_meshes]; for( i = 0; i < num_meshes; i++ ) { MDagPath dagPath = res_MDagPathArray[i]; MObject node; node = dagPath.node(); MFnDependencyNode fnNode( node ); MStatus polyStatus; MFnMesh fnMesh( node, &polyStatus ); if( polyStatus == MS::kSuccess ) { MStatus status; status = fnMesh.getPoints( oldPointsArrays[i]); if (!status){status.perror("### error getting mesh points");return stat;} unsigned int numVertices = oldPointsArrays[i].length(); newPointsArrays[i].setLength(numVertices); oldPointsArrays[i].setLength(numVertices); if(seed != 0) srand(seed); if(useAxisAmp) { for( unsigned int v = 0; v < numVertices; v++) { newPointsArrays[i][v].x = oldPointsArrays[i][v].x + ((halfRandMax - (double)rand()) / randMax) * amp * amp_x; newPointsArrays[i][v].y = oldPointsArrays[i][v].y + ((halfRandMax - (double)rand()) / randMax) * amp * amp_y; newPointsArrays[i][v].z = oldPointsArrays[i][v].z + ((halfRandMax - (double)rand()) / randMax) * amp * amp_z; } } else { for( unsigned int v = 0; v < numVertices; v++) { newPointsArrays[i][v].x = oldPointsArrays[i][v].x + ((halfRandMax - (double)rand()) / randMax) * amp; newPointsArrays[i][v].y = oldPointsArrays[i][v].y + ((halfRandMax - (double)rand()) / randMax) * amp; newPointsArrays[i][v].z = oldPointsArrays[i][v].z + ((halfRandMax - (double)rand()) / randMax) * amp; } } } else stat = MS::kFailure; } } return redoIt(); }
//--------------------------------------------------------------- void LightExporter::exportExtraAttributes(const SceneElement* sceneElement, COLLADASW::Light* light) { class ExtraAttributeExporter : public AttributeParser { public: ExtraAttributeExporter(COLLADASW::Light& light) : mLight(light) {} private: COLLADASW::Light& mLight; protected: virtual bool onBeforePlug(MPlug & plug) override { MStatus status; MObject attr = plug.attribute(&status); if (!status) return false; MFnAttribute fnAttr(attr, &status); if (!status) return false; MString attrName = fnAttr.name(&status); if (!status) return false; bool isDynamic = fnAttr.isDynamic(&status); if (!status) return false; if (!isDynamic) return false; bool isHidden = fnAttr.isHidden(&status); if (!status) return false; if (isHidden) return false; return true; } virtual void onBoolean(MPlug & plug, const MString & name, bool value) override { mLight.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value, "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } virtual void onInteger(MPlug & plug, const MString & name, int value) override { mLight.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value, "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } virtual void onInteger2(MPlug & plug, const MString & name, int value[2]) override { mLight.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } virtual void onInteger3(MPlug & plug, const MString & name, int value[3]) override { mLight.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], value[2], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } virtual void onFloat(MPlug & plug, const MString & name, float value) override { mLight.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value, "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } virtual void onFloat2(MPlug & plug, const MString & name, float value[2]) override { mLight.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } virtual void onFloat3(MPlug & plug, const MString & name, float value[3]) override { mLight.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], value[2], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } virtual void onDouble(MPlug & plug, const MString & name, double value) override { mLight.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value, "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } virtual void onDouble2(MPlug & plug, const MString & name, double value[2]) override { mLight.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } virtual void onDouble3(MPlug & plug, const MString & name, double value[3]) override { mLight.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], value[2], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } virtual void onDouble4(MPlug & plug, const MString & name, double value[4]) override { mLight.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], value[2], value[3], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } virtual void onString(MPlug & plug, const MString & name, const MString & value) override { mLight.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), COLLADABU::StringUtils::translateToXML(String(value.asChar())), "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } virtual void onEnum(MPlug & plug, const MString & name, int enumValue, const MString & enumName) override { // TODO export all possible enum values to be able to re-import them? mLight.addExtraTechniqueEnumParameter(PROFILE_MAYA, name.asChar(), COLLADABU::StringUtils::translateToXML(String(enumName.asChar())), "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); } }; MObject nodeObject = sceneElement->getNode(); MStatus status; MFnDependencyNode fnNode(nodeObject, &status); if (!status) return; ExtraAttributeExporter extraAttributeExporter(*light); AttributeParser::parseAttributes(fnNode, extraAttributeExporter); }
void sixdofConstraintNode::computeWorldMatrix(const MPlug& plug, MDataBlock& data) { MObject thisObject(thisMObject()); MFnDagNode fnDagNode(thisObject); MObject update; MPlug(thisObject, ca_constraint).getValue(update); MPlug(thisObject, ca_constraintParam).getValue(update); MStatus status; MFnTransform fnParentTransform(fnDagNode.parent(0, &status)); double fixScale[3] = { 1., 1., 1. }; // lock scale fnParentTransform.setScale(fixScale); MVector mtranslation = fnParentTransform.getTranslation(MSpace::kTransform, &status); if(bSolverNode::isStartTime) { // allow to edit pivots MPlug plgRigidBodyA(thisObject, ia_rigidBodyA); MPlug plgRigidBodyB(thisObject, ia_rigidBodyB); MObject update; //force evaluation of the rigidBody plgRigidBodyA.getValue(update); if(plgRigidBodyA.isConnected()) { MPlugArray connections; plgRigidBodyA.connectedTo(connections, true, true); if(connections.length() != 0) { MFnDependencyNode fnNode(connections[0].node()); if(fnNode.typeId() == boingRBNode::typeId) { MObject rbAObj = fnNode.object(); boingRBNode *pRigidBodyNodeA = static_cast<boingRBNode*>(fnNode.userNode()); MPlug(rbAObj, pRigidBodyNodeA->worldMatrix).elementByLogicalIndex(0).getValue(update); } } } plgRigidBodyB.getValue(update); if(plgRigidBodyB.isConnected()) { MPlugArray connections; plgRigidBodyB.connectedTo(connections, true, true); if(connections.length() != 0) { MFnDependencyNode fnNode(connections[0].node()); if(fnNode.typeId() == boingRBNode::typeId) { MObject rbBObj = fnNode.object(); boingRBNode *pRigidBodyNodeB = static_cast<boingRBNode*>(fnNode.userNode()); MPlug(rbBObj, pRigidBodyNodeB->worldMatrix).elementByLogicalIndex(0).getValue(update); } } } if(m_constraint) { MQuaternion mrotation; fnParentTransform.getRotation(mrotation, MSpace::kTransform); bool doUpdatePivot = m_constraint->getPivotChanged(); if(!doUpdatePivot) { vec3f worldP; quatf worldR; m_constraint->get_world(worldP, worldR); float deltaPX = worldP[0] - float(mtranslation.x); float deltaPY = worldP[1] - float(mtranslation.y); float deltaPZ = worldP[2] - float(mtranslation.z); float deltaRX = (float)mrotation.x - worldR[1]; float deltaRY = (float)mrotation.y - worldR[2]; float deltaRZ = (float)mrotation.z - worldR[3]; float deltaRW = (float)mrotation.w - worldR[0]; float deltaSq = deltaPX * deltaPX + deltaPY * deltaPY + deltaPZ * deltaPZ + deltaRX * deltaRX + deltaRY * deltaRY + deltaRZ * deltaRZ + deltaRW * deltaRW; doUpdatePivot = (deltaSq > FLT_EPSILON); } if(doUpdatePivot) { m_constraint->set_world(vec3f((float) mtranslation[0], (float) mtranslation[1], (float) mtranslation[2]), quatf((float)mrotation.w, (float)mrotation.x, (float)mrotation.y, (float)mrotation.z)); vec3f pivInA, pivInB; quatf rotInA, rotInB; m_constraint->get_frameA(pivInA, rotInA); m_constraint->get_frameB(pivInB, rotInB); MDataHandle hPivInA = data.outputValue(ia_pivotInA); float3 &ihPivInA = hPivInA.asFloat3(); MDataHandle hPivInB = data.outputValue(ia_pivotInB); float3 &ihPivInB = hPivInB.asFloat3(); for(int i = 0; i < 3; i++) { ihPivInA[i] = pivInA[i]; ihPivInB[i] = pivInB[i]; } MDataHandle hRotInA = data.outputValue(ia_rotationInA); float3 &hrotInA = hRotInA.asFloat3(); MQuaternion mrotA(rotInA[1], rotInA[2], rotInA[3], rotInA[0]); MEulerRotation newrotA(mrotA.asEulerRotation()); hrotInA[0] = rad2deg((float)newrotA.x); hrotInA[1] = rad2deg((float)newrotA.y); hrotInA[2] = rad2deg((float)newrotA.z); MDataHandle hRotInB = data.outputValue(ia_rotationInB); float3 &hrotInB = hRotInB.asFloat3(); MQuaternion mrotB(rotInB[1], rotInB[2], rotInB[3], rotInB[0]); MEulerRotation newrotB(mrotB.asEulerRotation()); hrotInB[0] = rad2deg((float)newrotB.x); hrotInB[1] = rad2deg((float)newrotB.y); hrotInB[2] = rad2deg((float)newrotB.z); m_constraint->setPivotChanged(false); m_constraint->get_local_frameA(m_PivInA, m_RotInA); m_constraint->get_local_frameB(m_PivInB, m_RotInB); } } } else { // if not start time, lock position and rotation if(m_constraint) { vec3f worldP; quatf worldR; m_constraint->get_world(worldP, worldR); fnParentTransform.setTranslation(MVector(worldP[0], worldP[1], worldP[2]), MSpace::kTransform); fnParentTransform.setRotation(MQuaternion(worldR[1], worldR[2], worldR[3], worldR[0])); } } m_initialized = true; data.setClean(plug); }
MStatus cgfxShaderCmd::undoCmd() // // Description: // implements undo for the MEL cgfxShader command. // // This method is called to undo a previous command of this type. The // system should be returned to the exact state that it was it previous // to this command being executed. That includes the selection state. // // Return Value: // MS::kSuccess - command succeeded // MS::kFailure - undo failed. this is a serious problem that will // likely cause the undo queue to be purged // { MStatus status; // Find the node // MObject oNode; status = fNodeSelection.getDependNode(0, oNode); M_CHECK( status ); MFnDependencyNode fnNode( oNode, &status ); M_CHECK( status && fnNode.typeId() == cgfxShaderNode::sId ); cgfxShaderNode* pNode = (cgfxShaderNode*)fnNode.userNode(); M_CHECK( pNode ); if (!fNewAttrDefList.empty()) { // Release the textures from the innactive attribute list to // save memory. NodeAttrDefList::iterator it = fNewAttrDefList.begin(); NodeAttrDefList::iterator itEnd = fNewAttrDefList.end(); for(; it != itEnd; ++it) { cgfxRCPtr<cgfxAttrDefList> &attrDefList = it->second; if(!attrDefList.isNull()) attrDefList->releaseTextures(); } } if (fFxFile) { // cgfxAttrDef list may contain MObject references to dynamic attrs // that are about to disappear. Clean up those references before // they become invalid, so they don't cause an exception later. pNode->setAttrDefList( cgfxRCPtr<cgfxAttrDefList>() ); } // Now put the node back the way it used to be. // status = fDagMod->undoIt(); M_CHECK( status ); if ( fIsEdit ) { if (fFxFile) { cgfxRCPtr<cgfxAttrDefList> currNodeAttrDefList; cgfxShaderNode::NodeList nodes; // getNodesToUpdate will return the list of nodes that will need to be updated : // if the new fx file is the same as the old fx file, the action is considered a reload, // we'll gather all the nodes that are using the nex effect (it's an undo) and reload them all. // else the effect file is different and only the current node will be updated. getNodesToUpdate(fNewEffect, pNode, nodes); cgfxShaderNode::NodeList::const_iterator it = nodes.begin(); cgfxShaderNode::NodeList::const_iterator itEnd = nodes.end(); for(; it != itEnd; ++it) { cgfxShaderNode* node = *it; MStringArray &attributeList = fOldAttributeList[node]; cgfxRCPtr<cgfxAttrDefList> &attrDefList = fOldAttrDefList[node]; if(node == pNode) currNodeAttrDefList = attrDefList; node->setAttributeList(attributeList); node->setAttrDefList(attrDefList); // Notice: Must setShaderFxFileChanged before setEffect node->setShaderFxFileChanged(true); node->setEffect(fOldEffect); } cgfxAttrDef::initializeAttributes( oNode, currNodeAttrDefList, true, fDagMod); fnNode.findPlug( cgfxShaderNode::sShader ).setValue( fOldFxFile ); } if (fTechnique) { fnNode.findPlug( cgfxShaderNode::sTechnique ).setValue( fOldTechnique ); } if (fProfile) { fnNode.findPlug( cgfxShaderNode::sProfile ).setValue( fOldProfile ); } } else { MGlobal::setActiveSelectionList( fOldSelection ); } return MS::kSuccess; } // cgfxShaderCmd::undoCmd
const SceneElement::Type SceneElement::determineType() const { if (mType != UNDETERMINED) return mType; MFn::Type mayaType = mDagPath.apiType(); MStatus status; MObject node = mDagPath.node(); MFnDependencyNode fnNode(node, &status); MString nodeTypeName = fnNode.typeName(); if (nodeTypeName == BULLET_PHYSIKS_NODE) return PHYSIK_BULLET; if (nodeTypeName == NX_RIGID_SOLVER) return PHYSX_RIGID_SOLVER; if (nodeTypeName == NX_RIGID_BODY) return PHYSX_RIGID_BODY; if (nodeTypeName == NX_RIGID_CONSTRAINT) return PHYSX_RIGID_CONSTRAINT; if (nodeTypeName == NX_SHAPE) return PHYSX_SHAPE; bool isLightProbe = false; DagHelper::getPlugValue(node, ATTR_LIGHT_PROBE, isLightProbe); if (isLightProbe) { return LIGHT_PROBE; } switch ( mayaType ) { case MFn::kLookAt: case MFn::kParentConstraint: case MFn::kOrientConstraint: case MFn::kConstraint: case MFn::kAimConstraint: case MFn::kPoleVectorConstraint: case MFn::kPointConstraint: case MFn::kNormalConstraint: return CONSTRAINT; break; case MFn::kAmbientLight: case MFn::kSpotLight: case MFn::kPointLight: case MFn::kDirectionalLight: return LIGHT; break; case MFn::kMesh: return MESH; break; case MFn::kIkHandle: return IKHANDLE; break; case MFn::kCamera: return CAMERA; break; case MFn::kRigid: return PHYSIK; break; case MFn::kNurbsCurve: return SPLINE; break; case MFn::kNurbsSurface: return NURBS; break; case MFn::kEmitter: return EMITTER; break; case MFn::kAir: case MFn::kDrag: case MFn::kField: case MFn::kGravity: case MFn::kNewton: case MFn::kRadial: case MFn::kTurbulence: case MFn::kUniform: case MFn::kVortex: case MFn::kVolumeAxis: return UNKNOWN; break; case MFn::kTransform: return TRANSFORM; break; case MFn::kLodGroup: return LOD; break; default: return UNKNOWN; break; } }
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 ); } } } } }