bool ToMayaMatrixVectorDataConverter<F>::doConversion( IECore::ConstObjectPtr from, MObject &to, IECore::ConstCompoundObjectPtr operands ) const { MStatus s; typename F::ConstPtr data = IECore::runTimeCast<const F>( from ); if( !data ) { return false; } MFnDoubleArrayData fnData; const typename F::ValueType &v = data->readable(); MDoubleArray array; array.setLength( v.size() * 16 ); for ( unsigned i=0; i < v.size(); i++ ) { for ( unsigned j=0; j < 4; j++ ) { for ( unsigned k=0; k < 4; k++ ) { array[ i*16 + j*4 + k ] = (double)v[i][j][k]; } } } to = fnData.create( array, &s ); return s; }
void VertexPolyColourCommand::WriteColoursToNode(MDagPath& dagPath, MColorArray& colors, bool isSource) { MStatus status; // Try to find the colour node attached to the mesh // If it's not found, create it MObject ourNode; if (!FindNodeOnMesh(dagPath,ourNode)) { CreateNodeOnMesh(dagPath, ourNode); } // Send the selection to the node { // Pass the component list down to the node. // To do so, we create/retrieve the current plug // from the uvList attribute on the node and simply // set the value to our component list. // MDoubleArray dcols; dcols.setLength(colors.length()*4); int idx = 0; for (unsigned int i=0; i<colors.length(); i++) { dcols[idx] = (double)colors[i].r; idx++; dcols[idx] = (double)colors[i].g; idx++; dcols[idx] = (double)colors[i].b; idx++; dcols[idx] = (double)colors[i].a; idx++; } MFnDoubleArrayData wrapper; wrapper.create(dcols,&status); MPlug* colourPlug = NULL; if (isSource) { colourPlug = new MPlug(ourNode, PolyColourNode::m_colors); } else { colourPlug = new MPlug(ourNode, PolyColourNode::m_colorsDest); } // Warning, we have to do this as GCC doesn't like to pass by temporary reference MObject wrapperObjRef = wrapper.object(); status = colourPlug->setValue(wrapperObjRef); delete colourPlug; } }
MStatus XmlCacheFormat::readDoubleArray( MDoubleArray& array, unsigned arraySize ) { MStringArray value; readXmlTagValue(doubleArrayTag, value); assert( value.length() == arraySize ); array.setLength( arraySize ); for ( unsigned int i = 0; i < value.length(); i++ ) { array[i] = strtod( value[i].asChar(), NULL ); } return MS::kSuccess; }
void CalculateSampleWeights(const std::map<int, double>& distances, double radius, MIntArray& vertexIds, MDoubleArray& weights) { std::map<int, double>::const_iterator itDistance; std::vector<std::pair<int, double> > samples; for (itDistance = distances.begin(); itDistance != distances.end(); itDistance++) { double x = itDistance->second; double w = 1.0 - (x/radius); samples.push_back(std::pair<int, double>(itDistance->first, w)); } // Make the samples a multiple of 4 so we can use fast intrinsics! int remainder = 4 - ((samples.size()-1) % 4); if (remainder != 4) { for (int i = 0; i < remainder; ++i) { samples.push_back(std::pair<int, double>(0, 0.0)); } } unsigned int length = (unsigned int)samples.size(); weights.setLength(length); vertexIds.setLength(length); std::sort(samples.begin(), samples.end(), SampleSort); std::vector<std::pair<int, double> >::iterator iter; int ii = 0; double sum = 0.0; for (iter = samples.begin(); iter != samples.end(); ++iter, ++ii) { vertexIds[ii] = (*iter).first; weights[ii] = (*iter).second; sum += (*iter).second; } assert(sum > 0.0); // Normalize the weights for (unsigned int i = 0; i < weights.length(); ++i) { weights[i] /= sum; } }
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 ); } } } } }
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; }
MObject readNurbs(double iFrame, Alembic::AbcGeom::INuPatch & iNode, MObject & iObject) { MStatus status; MObject obj; Alembic::AbcGeom::INuPatchSchema schema = iNode.getSchema(); // no interpolation for now Alembic::AbcCoreAbstract::index_t index, ceilIndex; getWeightAndIndex(iFrame, schema.getTimeSampling(), schema.getNumSamples(), index, ceilIndex); Alembic::AbcGeom::INuPatchSchema::Sample samp; schema.get(samp, Alembic::Abc::ISampleSelector(index)); Alembic::Abc::P3fArraySamplePtr pos = samp.getPositions(); Alembic::Abc::FloatArraySamplePtr weights = samp.getPositionWeights(); MString surfaceName(iNode.getName().c_str()); unsigned int degreeU = samp.getUOrder() - 1; unsigned int degreeV = samp.getVOrder() - 1; unsigned int numCVInU = samp.getNumU(); unsigned int numCVInV = samp.getNumV(); // cv points unsigned int numCV = numCVInU*numCVInV; unsigned int curPos = 0; MPointArray controlVertices; controlVertices.setLength(numCV); for (unsigned int v = 0; v < numCVInV; ++v) { for (unsigned int u = 0; u < numCVInU; ++u, ++curPos) { unsigned int mayaIndex = u * numCVInV + (numCVInV - v - 1); MPoint pt((*pos)[curPos].x, (*pos)[curPos].y, (*pos)[curPos].z); if (weights) { pt.w = (*weights)[curPos]; } // go from u,v order to reversed v, u order controlVertices.set(pt, mayaIndex); } } // Nurbs form // Alemblic file does not record the form of nurb surface, we get the form // by checking the CV data. If the first degree number CV overlap the last // degree number CV, then the form is kPeriodic. If only the first CV overlaps // the last CV, then the form is kClosed. MFnNurbsSurface::Form formU = MFnNurbsSurface::kPeriodic; MFnNurbsSurface::Form formV = MFnNurbsSurface::kPeriodic; // Check all curves bool notOpen = true; for (unsigned int v = 0; notOpen && v < numCVInV; v++) { for (unsigned int u = 0; u < degreeU; u++) { unsigned int firstIndex = u * numCVInV + (numCVInV - v - 1); unsigned int lastPeriodicIndex = (numCVInU - degreeU + u) * numCVInV + (numCVInV - v - 1); if (!controlVertices[firstIndex].isEquivalent(controlVertices[lastPeriodicIndex])) { formU = MFnNurbsSurface::kOpen; notOpen = false; break; } } } if (formU == MFnNurbsSurface::kOpen) { formU = MFnNurbsSurface::kClosed; for (unsigned int v = 0; v < numCVInV; v++) { unsigned int lastUIndex = (numCVInU - 1) * numCVInV + (numCVInV - v - 1); if (! controlVertices[numCVInV-v-1].isEquivalent(controlVertices[lastUIndex])) { formU = MFnNurbsSurface::kOpen; break; } } } notOpen = true; for (unsigned int u = 0; notOpen && u < numCVInU; u++) { for (unsigned int v = 0; v < degreeV; v++) { unsigned int firstIndex = u * numCVInV + (numCVInV - v - 1); unsigned int lastPeriodicIndex = u * numCVInV + (degreeV - v - 1); //numV - (numV - vDegree + v) - 1; if (!controlVertices[firstIndex].isEquivalent(controlVertices[lastPeriodicIndex])) { formV = MFnNurbsSurface::kOpen; notOpen = false; break; } } } if (formV == MFnNurbsSurface::kOpen) { formV = MFnNurbsSurface::kClosed; for (unsigned int u = 0; u < numCVInU; u++) { if (! controlVertices[u * numCVInV + (numCVInV-1)].isEquivalent(controlVertices[u * numCVInV])) { formV = MFnNurbsSurface::kOpen; break; } } } Alembic::Abc::FloatArraySamplePtr uKnot = samp.getUKnot(); Alembic::Abc::FloatArraySamplePtr vKnot = samp.getVKnot(); unsigned int numKnotsInU = static_cast<unsigned int>(uKnot->size() - 2); MDoubleArray uKnotSequences; uKnotSequences.setLength(numKnotsInU); for (unsigned int i = 0; i < numKnotsInU; ++i) { uKnotSequences.set((*uKnot)[i+1], i); } unsigned int numKnotsInV = static_cast<unsigned int>(vKnot->size() - 2); MDoubleArray vKnotSequences; vKnotSequences.setLength(numKnotsInV); for (unsigned int i = 0; i < numKnotsInV; i++) { vKnotSequences.set((*vKnot)[i+1], i); } // Node creation try the API first MFnNurbsSurface mFn; obj = mFn.create(controlVertices, uKnotSequences, vKnotSequences, degreeU, degreeV, formU, formV, true, iObject, &status); // something went wrong, try open/open create if (status != MS::kSuccess && (formU != MFnNurbsSurface::kOpen || formV != MFnNurbsSurface::kOpen)) { obj = mFn.create(controlVertices, uKnotSequences, vKnotSequences, degreeU, degreeV, MFnNurbsSurface::kOpen, MFnNurbsSurface::kOpen, true, iObject, &status); } if (status == MS::kSuccess) { mFn.setName(surfaceName); } else { MString errorMsg = "Could not create Nurbs Surface: "; errorMsg += surfaceName; MGlobal::displayError(errorMsg); } trimSurface(samp, mFn); return obj; }
void OutputHelper::addRSLVariable(const MString& inputQualifier, MString rslType, const MString& rslName, const MString& mayaName, const MString& mayaNode) { MString cmd; // If the user specified that the type was an array of floats // (eg "float2"), extract the size and set the type to float. int rslTypeSize = 1; MString matchedStr; IfMErrorWarn(MGlobal::executeCommand("match(\"float[0-9]+$\",\""+rslType+"\")", matchedStr)); if(matchedStr != "") { IfMErrorWarn(MGlobal::executeCommand("match(\"[0-9]+$\",\""+rslType+"\")", matchedStr)); rslTypeSize = matchedStr.asInt(); rslType = "float"; } // Create the plug's name, and check for convertible connections. MString plug(mayaNode+"."+mayaName); int connected = liquidmaya::ShaderMgr::getSingletonPtr()->convertibleConnection(plug.asChar()); // If there are no convertible connections, then we have to // write out the variable into the shader's body. if( connected == 0 ) { //rslTypeSize(int) --> rslTypeSizeStr(string) MString rslTypeSizeStr; rslTypeSizeStr.set(rslTypeSize); // Write out the description of the variable. rslShaderBody += (" "+inputQualifier + " " + rslType + " " + rslName); rslShaderBody += ( rslTypeSize != 1 )? ( "[" + rslTypeSizeStr + "] = " ) :( " = " + rslType + " " ); // Write out the value of the variable. if( rslType=="color" ||rslType=="point" ||rslType=="normal" ||rslType=="vector") { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr \""+plug+"\"", val)); //val(double) --> valStr(string) MStringArray valStr; valStr.setLength(3); valStr[0].set(val[0]); valStr[1].set(val[1]); valStr[2].set(val[2]); rslShaderBody +="("+valStr[0]+","+valStr[1]+","+valStr[2]+")"; }else if(rslType=="string"){ MString val; IfMErrorWarn(MGlobal::executeCommand("getAttr \""+plug+"\"", val)); rslShaderBody +="\""+val+"\""; }else if(rslType=="float"){ if(rslTypeSize == 1){ double val; IfMErrorWarn(MGlobal::executeCommand("getAttr \""+plug+"\"", val)); //val(double) --> valStr(string) MString valStr; valStr.set(val); rslShaderBody += valStr; }else{ rslShaderBody += "{ "; MDoubleArray val; val.setLength(rslTypeSize); IfMErrorWarn(MGlobal::executeCommand("getAttr \""+plug+"\"", val)); for(int i=0; i<rslTypeSize; ++i){ if( i != 0 ){ rslShaderBody += ", "; } //val[i](double) --> valStr(string) MString valStr; valStr.set(val[i]); rslShaderBody += valStr; } rslShaderBody += " }"; } } rslShaderBody += ";\n"; }//if( $connected == 0 ) // Otherwise, we have a convertible connection, so we'll be // adding the variable to the block's header. else{ rslShaderHeader += " "; // Note if it's connected as an output. if(connected == 2){ rslShaderHeader += "output "; } // Write out the description. rslShaderHeader += ( rslType + " " + rslName ); if( rslTypeSize != 1 ) { rslShaderHeader += "[]"; } rslShaderHeader += ";\n"; // if(connected == 1) { MStringArray srcPlug; IfMErrorWarn(MGlobal::executeCommand("listConnections -source true -plugs true \""+plug+"\"", srcPlug)); assert(srcPlug.length()==1); rslShaderBody +="//"+plug+" <-- "+srcPlug[0]+"\n"; } }//else }
MStatus puttyNode::deform( MDataBlock& block, MItGeometry& iter, const MMatrix& worldMatrix, unsigned int multiIndex) { // MGlobal::displayInfo("deform"); MStatus status = MS::kSuccess; ///////////////////////////////////////////////////////////////////////////////////////////////// // // get inputs // // get the node ready flag MDataHandle dh = block.inputValue(aScriptSourced,&status); SYS_ERROR_CHECK(status, "Error getting aScriptSourced data handle\n"); bool scriptSourced = dh.asBool(); if (!scriptSourced) return MS::kSuccess; dh = block.inputValue(aNodeReady,&status); SYS_ERROR_CHECK(status, "Error getting node ready data handle\n"); bool nodeReady = dh.asBool(); // if it's not ready, don't do anything if (!nodeReady) return MS::kSuccess; dh = block.inputValue(aDefSpace,&status); SYS_ERROR_CHECK(status, "Error getting defSpace data handle\n"); short defSpace = dh.asShort(); dh = block.inputValue(aDefWeights,&status); SYS_ERROR_CHECK(status, "Error getting defWeights data handle\n"); short defWeights = dh.asShort(); dh = block.inputValue(aDefEnvelope,&status); SYS_ERROR_CHECK(status, "Error getting defEnvelope data handle\n"); short defEnvelope = dh.asShort(); // get the command dh = block.inputValue(aCmdBaseName,&status); SYS_ERROR_CHECK(status, "Error getting aCmdBaseName handle\n"); MString script = dh.asString(); /* if (script == "") { status = MS::kFailure; USER_ERROR_CHECK(status, "no script provided!\n"); } */ ///////////////////////////////////////////////////////////////////////////////////////////////// // // build mel cmd string // // check if it's a valid cmd // get the envelope // double env = 1; if (defEnvelope == MSD_ENVELOPE_AUTO) { dh = block.inputValue(envelope,&status); SYS_ERROR_CHECK(status, "Error getting envelope data handle\n"); env = double(dh.asFloat()); // early stop 'cause there is nothing more to do if (env == 0.0) return MS::kSuccess; } // get the points, transform them into the right space if needed // int count = iter.count(); MVectorArray points(count); for ( ; !iter.isDone(); iter.next()) points[iter.index()] = iter.position(); if ( defSpace == MSD_SPACE_WORLD ) { for (int i = 0;i<count;i++) points[i] = MPoint(points[i]) * worldMatrix; } // get the weights // MDoubleArray weights; if ( defWeights == MSD_WEIGHTS_AUTO) { weights.setLength(count); for (int i = 0;i<count;i++) weights[i] = weightValue(block,multiIndex,i); } // get the object name and type // get the input geometry, traverse through the data handles MArrayDataHandle adh = block.outputArrayValue( input, &status ); SYS_ERROR_CHECK(status,"error getting input array data handle.\n"); status = adh.jumpToElement( multiIndex ); SYS_ERROR_CHECK(status, "input jumpToElement failed.\n"); // compound data MDataHandle cdh = adh.inputValue( &status ); SYS_ERROR_CHECK(status, "error getting input inputValue\n"); // input geometry child dh = cdh.child( inputGeom ); MObject dInputGeometry = dh.data(); // get the type MString geometryType = dInputGeometry.apiTypeStr(); // get the name // MFnDagNode dagFn( dInputGeometry, &status); // SYS_ERROR_CHECK(status, "error converting geometry obj to dag node\n"); // MString geometryName = dagFn.fullPathName(&status); // SYS_ERROR_CHECK(status, "error getting full path name \n"); // MString geometryType = ""; // MString geometryName = ""; ///////////////////////////////////////////////////////////////////////////////////////////////// // // set the current values on the temp plugs for the script to be picked up // // the position MObject thisNode = thisMObject(); MPlug currPlug(thisNode,aCurrPosition); MFnVectorArrayData vecD; MObject currObj = vecD.create(points,&status); currPlug.setValue(currObj); SYS_ERROR_CHECK(status, "error setting currPosPlug value\n"); // the weights currPlug =MPlug(thisNode,aCurrWeight); MFnDoubleArrayData dblD; currObj = dblD.create(weights,&status); currPlug.setValue(currObj); SYS_ERROR_CHECK(status, "error setting currWeightsPlug value\n"); // world matrix currPlug =MPlug(thisNode,aCurrWorldMatrix); MFnMatrixData matD; currObj = matD.create(worldMatrix,&status); currPlug.setValue(currObj); SYS_ERROR_CHECK(status, "error setting currWorldMatrixPlug value\n"); // the multi index currPlug =MPlug(thisNode,aCurrMultiIndex); currPlug.setValue(int(multiIndex)); SYS_ERROR_CHECK(status, "error setting currMultiIndexPlug value\n"); // geometry name/type // currPlug =MPlug(thisNode,aCurrGeometryName); // currPlug.setValue(geometryName); // SYS_ERROR_CHECK(status, "error setting aCurrGeometryName value\n"); currPlug =MPlug(thisNode,aCurrGeometryType); currPlug.setValue(geometryType); SYS_ERROR_CHECK(status, "error setting aCurrGeometryType value\n"); ///////////////////////////////////////////////////////////////////////////////////////////////// // // execute the mel script // MString melCmd = script+"(\"" +name()+"\","+count+")"; MCommandResult melResult; status = MGlobal::executeCommand(melCmd,melResult); // if the command did not work, then try to resource the script // (might have been that we were in a fresh scene and nothing was ready yet if (status != MS::kSuccess) { dh = block.inputValue(aScript,&status); SYS_ERROR_CHECK(status, "Error getting aCmdBaseName handle\n"); MString scriptFile = dh.asString(); // try to source the script MString cmd = "source \"" + scriptFile+"\""; MCommandResult melResult; status = MGlobal::executeCommand(cmd,melResult); // if successfull, retry the command if (!status.error()) { status = MGlobal::executeCommand(melCmd,melResult); } } USER_ERROR_CHECK(status, "Error executing mel command, please check the function you provided is valid, error free and has the appropriate parameters!"); // check the result type if ((melResult.resultType()) != (MCommandResult::kDoubleArray)) { USER_ERROR_CHECK(MS::kFailure, "result of mel command has wrong type, should be doubleArray (which will be interpreted as vectorArray)!"); } // get the result as a double array MDoubleArray newP; status = melResult.getResult(newP); USER_ERROR_CHECK(status, "Error getting result of mel command!"); int newCount = newP.length()/3; // size check if (newCount != count) { USER_ERROR_CHECK(MS::kFailure, "the size of the result does not match the size of the input!"); } // convert the double array into a vector array MPointArray newPoints(newCount); for(int i=0;i<newCount;i++) newPoints[i]=MPoint(newP[i*3],newP[i*3+1],newP[i*3+2]); ///////////////////////////////////////////////////////////////////////////////////////////////// // // interprete and apply the result // // do the envelope and weights if ((defEnvelope == MSD_ENVELOPE_AUTO)||((defWeights == MSD_WEIGHTS_AUTO))) { MDoubleArray envPP(count, env); if (defWeights == MSD_WEIGHTS_AUTO) { for (int i = 0;i<count;i++) envPP[i] *= weights[i]; } // linear interpolation between old and new points for (int i = 0;i<count;i++) newPoints[i] = (points[i] * (1-envPP[i])) + (newPoints[i] * envPP[i]); } // retransform the result if it was in world space if ( defSpace == MSD_SPACE_WORLD ) { MMatrix worldMatrixInv = worldMatrix.inverse(); for (int i = 0;i<count;i++) newPoints[i] *= worldMatrixInv; } // set the points iter.reset(); for ( ; !iter.isDone(); iter.next()) iter.setPosition(newPoints[iter.index()]); return status; }
void Helper4::addVariableBSDF( const std::string& param_name_as, const std::string& param_type_as, const std::string& param_name_maya ) { std::string param_value; const std::string plugName(param_name_maya); MString fullPlugName((m_nodename+"."+plugName).c_str()); int connected = liquidmaya::ShaderMgr::getSingletonPtr()->convertibleConnection(fullPlugName.asChar()); if( connected == 0 ) { if( isType("color", param_type_as) ) { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); param_value = m_nodename+"_"+plugName; createColor3(m_assembly->colors(), param_value.c_str(), val[0], val[1], val[2]); } else if( isType("scalar", param_type_as) ) { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); //val contains (r,b,g) value, but I only use val[0] for 'scalar' MString strVal0; strVal0.set(val[0]); param_value = strVal0.asChar(); } else { liquidMessage2(messageWarning,"only [color],[scalar] are handled for an unconnected plug in BSDF. " "the plug of %s is unhandled.", fullPlugName.asChar()); param_value = "unhandled"; } } else if(connected == 1)//the color plug is linked in. { if( isType("texture_instance", param_type_as) ) { MStringArray srcPlug; IfMErrorWarn(MGlobal::executeCommand("listConnections -source true -plugs true \""+fullPlugName+"\"", srcPlug)); assert(srcPlug.length()==1); MStringArray src; srcPlug[0].split('.',src); MString srcNode(src[0]); if( is2DTexture(srcNode) || is3DTexture(srcNode) ) { //visitFile(srcNode.asChar()); param_value = getTextureInstanceName(srcNode.asChar()); }else{ liquidMessage2(messageWarning,"type of [%s] is unhandled.(not 2Dtexture and 3Dtexture). [%s]", srcNode.asChar(), fullPlugName.asChar()); param_value = "unhandled"; } } else if( isType("bsdf", param_type_as) ) { //bsdf0 value MString srcBSDFModel; IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", srcBSDFModel)); MStringArray srcPlug; IfMErrorWarn(MGlobal::executeCommand("listConnections -source true -plugs true \""+fullPlugName+"\"", srcPlug)); assert(srcPlug.length()==1); MStringArray src; srcPlug[0].split('.',src); MString srcNode(src[0]); param_value = srcNode.asChar(); } else{ liquidMessage2(messageWarning,"only [texture_instance],[bsdf] are handled for a connected-in plug in BSDF." "the plug of %s is unhandled.", fullPlugName.asChar()); param_value = "unhandled"; } }else{// $(fullPlugName) is connected out // if $(fullPlugName) plug is connected out to "bsdf0"/"bsdf1" of a "bsdf_mix" node, // we also need to create this plug for appleseed // get destination node(s) MStringArray desNodePlug; IfMErrorWarn(MGlobal::executeCommand("listConnections -destination true -plugs true \""+fullPlugName+"\"", desNodePlug)); // check whether $(fullPlugName) is connected to a BSDF node bool isConnectedToA_BSDFMixNode = false; MString desPlug; for(std::size_t i = 0; i< desNodePlug.length(); ++i) { MStringArray des; desNodePlug[i].split('.',des); MString desNode(des[0]); //destination node BSDF type MString desNodeBSDFType; IfMErrorWarn(MGlobal::executeCommand( "getAttr \""+desNode+".rmanShaderType\"", desNodeBSDFType)); if(desNodeBSDFType == "bsdf_mix") { isConnectedToA_BSDFMixNode = true; desPlug = des[1]; } } // if $(fullPlugName) is connected out to "bsdf0"/"bsdf1" of a "bsdf_mix" node // we also need to create this plug for appleseed if( isConnectedToA_BSDFMixNode && (desPlug=="bsdf0" ||desPlug=="bsdf1") ) { if( isType("color", param_type_as) ) { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); param_value = m_nodename+"_"+plugName; createColor3(m_assembly->colors(), param_value.c_str(), val[0], val[1], val[2]); } else if( isType("scalar", param_type_as) ) { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); //val contains (r,b,g) value, but I only use val[0] for 'scalar' MString strVal0; strVal0.set(val[0]); param_value = strVal0.asChar(); } else if( isType("texture_instance", param_type_as) ) { MStringArray srcPlug; IfMErrorWarn(MGlobal::executeCommand("listConnections -source true -plugs true \""+fullPlugName+"\"", srcPlug)); assert(srcPlug.length()==1); MStringArray src; srcPlug[0].split('.',src); MString srcNode(src[0]); if( is2DTexture(srcNode) || is3DTexture(srcNode) ) { //visitFile(srcNode.asChar()); param_value = getTextureInstanceName(srcNode.asChar()); }else{ liquidMessage2(messageWarning,"type of [%s] is unhandled.(not 2Dtexture and 3Dtexture). [%s]", srcNode.asChar(), fullPlugName.asChar()); param_value = "unhandled"; } } else { liquidMessage2(messageWarning,"only [color],[scalar],[texture_instance] are handled for an connected-out plug in BSDF. " "the plug of %s is unhandled.", fullPlugName.asChar()); param_value = "unhandled"; } }//if( nodetype=="bsdf_mix" && (desPlug=="bsdf0" ||desPlug=="bsdf1") ) else { liquidMessage2(messageWarning,"[%s] is connected out. But not connected to brdf node, or not brdf0/brdf1 of a brdf node." " So I don't create the value for this plug.", fullPlugName.asChar()); } } // addVariableBSDF(param_name_as, param_value); }
void Helper4::addVariableSS(const std::string& param_name_as, const std::string& param_type_as, const std::string& param_name_maya ) { //std::string ss_name(getSurfaceShaderName(m_nodename,m_ss_model)); asr::ParamArray ss_params; { std::string param_value; const std::string plugName(param_name_maya); MString fullPlugName((m_nodename+"."+plugName).c_str()); int connected = liquidmaya::ShaderMgr::getSingletonPtr()->convertibleConnection(fullPlugName.asChar()); if(connected ==0) { if( isType("color", param_type_as) ) { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); param_value = m_nodename+"_"+plugName; createColor3(m_assembly->colors(), param_value.c_str(), val[0], val[1], val[2]); } else if( isType("scalar", param_type_as) ) { MDoubleArray val; val.setLength(3); IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); //val contains (r,b,g) value, but I only use val[0] for 'scalar' MString strVal0; strVal0.set(val[0]); param_value = strVal0.asChar(); } else if( isType("string", param_type_as)) { MString val; IfMErrorWarn(MGlobal::executeCommand("getAttr (\""+fullPlugName+"\")", val)); param_value = val.asChar(); } else { liquidMessage2(messageWarning,"only [color],[scalar],[string] are handled for an unconnected plug in Surface Shader. " "the plug of %s is unhandled.", fullPlugName.asChar()); param_value = "unhandled"; } } else if(connected == 1)//the plug is linked in. { if( isType("texture_instance", param_type_as) ) { MStringArray srcPlug; IfMErrorWarn(MGlobal::executeCommand("listConnections -source true -plugs true \""+fullPlugName+"\"", srcPlug)); assert(srcPlug.length()==1); MStringArray src; srcPlug[0].split('.',src); MString srcNode(src[0]); if( is2DTexture(srcNode) || is3DTexture(srcNode) ) { //visitFile(srcNode.asChar()); param_value = getTextureInstanceName(srcNode.asChar()); }else{ liquidMessage2(messageWarning,"only [texture2D],[texture3D] are handled for a texture_instance connected-in plug in Surface Shader." "the plug of %s is unhandled.", fullPlugName.asChar()); param_value = "unhandled"; } } else{ liquidMessage2(messageWarning,"only [texture_instance] is handled for a connected-in plug in Surface Shader." "the plug of %s is unhandled.", fullPlugName.asChar()); param_value = "unhandled"; } }else{ liquidMessage2(messageWarning,"[%s] is connected out.", fullPlugName.asChar()); } // addVariableSS(param_name_as, param_value); } }
MStatus grabUVContext::doDrag ( MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context) { if (event.mouseButton() != MEvent::kLeftMouse || !event.isModifierNone() ) return MS::kFailure; MPxTexContext::doDrag(event, drawMgr, context); short x, y; event.getPosition( x, y ); fLastScreenPoint = fCurrentScreenPoint; fCurrentScreenPoint = MPoint( x, y ); double xView, yView; portToView(x, y, xView, yView); // pos at viewrect coordinate fLastPoint = fCurrentPoint; fCurrentPoint = MPoint( xView, yView, 0.0 ); if( fDragMode == kBrushSize ) { double dis = fCurrentScreenPoint.distanceTo( fLastScreenPoint ); if ( fCurrentScreenPoint[0] > fLastScreenPoint[0] ) setSize( size() + float(dis) ); else setSize( std::max( size() - float(dis), 0.01f ) ); } else { fBrushCenterScreenPoint = MPoint( x, y ); MFloatArray uUVsExported; MFloatArray vUVsExported; const MVector vec = fCurrentPoint - fLastPoint; if (!fCommand) { fCommand = (UVUpdateCommand *)(newToolCommand()); } if (fCommand) { MFnMesh mesh(fDagPath); MString currentUVSetName; mesh.getCurrentUVSetName(currentUVSetName); int nbUVs = mesh.numUVs(currentUVSetName); MDoubleArray pinData; MUintArray uvPinIds; MDoubleArray fullPinData; mesh.getPinUVs(uvPinIds, pinData, ¤tUVSetName); int len = pinData.length(); fullPinData.setLength(nbUVs); for (unsigned int i = 0; i < nbUVs; i++) { fullPinData[i] = 0.0; } while( len-- > 0 ) { fullPinData[uvPinIds[len]] = pinData[len]; } MFloatArray uValues; MFloatArray vValues; float pinWeight = 0; for (unsigned int i = 0; i < fCollectedUVs.length(); ++i) { float u, v; MStatus bGetUV = mesh.getUV(fCollectedUVs[i], u, v, ¤tUVSetName); if (bGetUV == MS::kSuccess) { pinWeight = fullPinData[fCollectedUVs[i]]; u += (float)vec[0]*(1-pinWeight); v += (float)vec[1]*(1-pinWeight); uValues.append( u ); vValues.append( v ); } } fCommand->setUVs( mesh.object(), fCollectedUVs, uValues, vValues, ¤tUVSetName ); } } return MS::kSuccess; }