bool OpenSubdivShader::setInternalValueInContext(const MPlug &plug, const MDataHandle &handle, MDGContext &) { if (plug == aLevel) { _hbrMeshDirty = true; _level = handle.asLong(); } else if (plug == aTessFactor) { _tessFactor = handle.asLong(); } else if (plug == aScheme) { _hbrMeshDirty = true; _scheme = (OsdMeshData::SchemeType)handle.asShort(); } else if (plug == aKernel) { _hbrMeshDirty = true; _kernel = (OsdMeshData::KernelType)handle.asShort(); } else if (plug == aInterpolateBoundary) { _hbrMeshDirty = true; _interpolateBoundary = (OsdMeshData::InterpolateBoundaryType)handle.asShort(); } else if (plug == aAdaptive) { _hbrMeshDirty = true; _adaptiveDirty = true; _adaptive = handle.asBool(); } else if (plug == aDiffuseMapFile) { _diffuseMapDirty = true; _diffuseMapFile = handle.asString(); } else if (plug == aUVSet) { _hbrMeshDirty = true; _uvSet = handle.asString(); } else if (plug == aInterpolateUVBoundary) { _hbrMeshDirty = true; _interpolateUVBoundary = (OsdMeshData::InterpolateBoundaryType)handle.asShort(); } else if (plug == aShaderSource) { _shaderSourceFilename = handle.asString(); std::ifstream ifs; ifs.open(_shaderSourceFilename.asChar()); if (ifs.fail()) { printf("Using default shader\n"); _shaderSource.clear(); _shaderSourceFilename.clear(); } else { printf("Using %s shader\n", _shaderSourceFilename.asChar()); std::stringstream buffer; buffer << ifs.rdbuf(); _shaderSource = buffer.str(); } ifs.close(); _shaderSourceDirty = true; } return false; }
//------------------------------------------------------------------------------ bool OpenSubdivShader::setInternalValueInContext(const MPlug &plug, const MDataHandle &handle, MDGContext &) { if(plug == aLevel) { _level = handle.asLong(); } else if(plug == aScheme) { _scheme = handle.asShort(); } else if(plug == aKernel) { _kernel = handle.asShort(); } return false; }
MStatus blindDataMesh::compute(const MPlug& plug, MDataBlock& data) { MStatus returnStatus; if (plug == outputMesh) { // Get the given random number generator seed. We need to use a // seed, because a pseudo-random number generator will always give // the same random numbers for a constant seed. This means that the // mesh will not change when it is recalculated. // MDataHandle seedHandle = data.inputValue(seed, &returnStatus); McheckErr(returnStatus,"ERROR getting random number generator seed\n"); long seed = seedHandle.asLong(); // Get the handle to the output mesh. The creation of the output mesh // is done in two steps. First, the mesh is created. That involves // calculating the position of the vertices and their connectivity. // // Second, blind data is associated to the vertices on the mesh. // For this example, three double blind data values is associated // to each vertex: "red", "green" and "blue". // MFnMeshData dataCreator; MDataHandle outputHandle = data.outputValue(outputMesh, &returnStatus); McheckErr(returnStatus, "ERROR getting polygon data handle\n"); MObject newOutputData = dataCreator.create(&returnStatus); McheckErr(returnStatus, "ERROR creating outputData"); createMesh(seed, newOutputData, returnStatus); McheckErr(returnStatus, "ERROR creating new plane"); returnStatus = setMeshBlindData(newOutputData); McheckErr(returnStatus, "ERROR setting the blind Data on the plane"); outputHandle.set(newOutputData); data.setClean( plug ); } else return MS::kUnknownParameter; return MS::kSuccess; }
bool OpenSubdivPtexShader::setInternalValueInContext(const MPlug &plug, const MDataHandle &handle, MDGContext &) { if (plug == aLevel) { _hbrMeshDirty = true; _level = handle.asLong(); } else if (plug == aTessFactor) { _tessFactor = handle.asLong(); } else if (plug == aScheme) { _hbrMeshDirty = true; _scheme = (OsdPtexMeshData::SchemeType)handle.asShort(); } else if (plug == aKernel) { _hbrMeshDirty = true; _kernel = (OsdPtexMeshData::KernelType)handle.asShort(); } else if (plug == aInterpolateBoundary) { _hbrMeshDirty = true; _interpolateBoundary = (OsdPtexMeshData::InterpolateBoundaryType)handle.asShort(); } else if (plug == aAdaptive) { _hbrMeshDirty = true; _adaptiveDirty = true; _adaptive = handle.asBool(); } else if (plug == aShaderSource) { _shaderSourceFilename = handle.asString(); std::ifstream ifs; ifs.open(_shaderSourceFilename.asChar()); if (ifs.fail()) { printf("Using default shader\n"); _shaderSource.clear(); _shaderSourceFilename.clear(); } else { printf("Using %s shader\n", _shaderSourceFilename.asChar()); std::stringstream buffer; buffer << ifs.rdbuf(); _shaderSource = buffer.str(); } ifs.close(); _shaderSourceDirty = true; } else if (plug == aDiffuseEnvironmentMapFile) { _diffEnvMapDirty = true; _diffEnvMapFile = handle.asString(); } else if (plug == aSpecularEnvironmentMapFile) { _specEnvMapDirty = true; _specEnvMapFile = handle.asString(); } else if (plug == aColorFile) { _ptexColorDirty = true; _colorFile = handle.asString(); } else if (plug == aDisplacementFile) { _ptexDisplacementDirty = true; _displacementFile = handle.asString(); } else if (plug == aOcclusionFile) { _ptexOcclusionDirty = true; _occlusionFile = handle.asString(); } else if (plug == aEnableColor) { _enableColor = handle.asBool(); } else if (plug == aEnableDisplacement) { _enableDisplacement = handle.asBool(); } else if (plug == aEnableOcclusion) { _enableOcclusion = handle.asBool(); } else if (plug == aEnableNormal) { _enableNormal = handle.asBool(); } return false; }
MStatus pointOnSubd::compute( const MPlug& plug, MDataBlock& data ) // // Description: // This method computes the value of the given output plug based // on the values of the input attributes. // // Arguments: // plug - the plug to compute // data - object that provides access to the attributes for this node // { MStatus returnStatus; // Check which output attribute we have been asked to compute. If this // node doesn't know how to compute it, we must return // MS::kUnknownParameter. // if( (plug == aPoint) || (plug == aNormal) || (plug == aPointX) || (plug == aNormalX) || (plug == aPointY) || (plug == aNormalY) || (plug == aPointZ) || (plug == aNormalZ) ) { // Get a handle to the input attribute that we will need for the // computation. If the value is being supplied via a connection // in the dependency graph, then this call will cause all upstream // connections to be evaluated so that the correct value is supplied. // do { MDataHandle subdHandle = data.inputValue( aSubd, &returnStatus ); if( returnStatus != MS::kSuccess ) { MGlobal::displayError( "ERROR: cannot get subd\n" ); break; } MDataHandle faceFirstHandle = data.inputValue( aFaceFirst, &returnStatus ); if( returnStatus != MS::kSuccess ) { MGlobal::displayError( "ERROR: cannot get face first\n" ); break; } MDataHandle faceSecondHandle = data.inputValue( aFaceSecond, &returnStatus ); if( returnStatus != MS::kSuccess ) { MGlobal::displayError( "ERROR: cannot get face2\n" ); break; } MDataHandle uHandle = data.inputValue( aU, &returnStatus ); if( returnStatus != MS::kSuccess ) { MGlobal::displayError( "ERROR: cannot get u\n" ); break; } MDataHandle vHandle = data.inputValue( aV, &returnStatus ); if( returnStatus != MS::kSuccess ) { MGlobal::displayError( "ERROR: cannot get v\n" ); break; } MDataHandle relHandle = data.inputValue( aRelativeUV, &returnStatus ); if( returnStatus != MS::kSuccess ) { MGlobal::displayError( "ERROR: cannot get relative UV\n" ); break; } // Read the input value from the handle. // MStatus stat; MObject subdValue = subdHandle.asSubdSurface(); MFnSubd subdFn( subdValue, &stat ); McheckErr(stat,"ERROR creating subd function set"); int faceFirstValue = faceFirstHandle.asLong(); int faceSecondValue = faceSecondHandle.asLong(); double uValue = uHandle.asDouble(); double vValue = vHandle.asDouble(); bool relUV = relHandle.asBool(); MPoint point; MVector normal; MUint64 polyId; stat = MFnSubdNames::fromSelectionIndices( polyId, faceFirstValue, faceSecondValue ); McheckErr(stat,"ERROR converting indices"); stat = subdFn.evaluatePositionAndNormal( polyId, uValue, vValue, relUV, point, normal ); normal.normalize(); McheckErr(stat,"ERROR evaluating the position and the normal"); // Get handles to the output attributes. This is similar to the // "inputValue" call above except that no dependency graph // computation will be done as a result of this call. // MDataHandle pointHandle = data.outputValue( aPoint ); pointHandle.set( point.x, point.y, point.z ); data.setClean(plug); MDataHandle normalHandle = data.outputValue( aNormal ); normalHandle.set( normal.x, normal.y, normal.z ); data.setClean(plug); } while( false ); } else { return MS::kUnknownParameter; } return MS::kSuccess; }
MStatus proWater::compute(const MPlug& plug, MDataBlock& dataBlock) { MStatus status = MStatus::kUnknownParameter; if (plug.attribute() == outputGeom) { // get the input corresponding to this output // unsigned int index = plug.logicalIndex(); MObject thisNode = this->thisMObject(); MPlug inPlug(thisNode,input); inPlug.selectAncestorLogicalIndex(index,input); MDataHandle hInput = dataBlock.inputValue(inPlug); // get the input geometry and input groupId // MDataHandle hGeom = hInput.child(inputGeom); MDataHandle hGroup = hInput.child(groupId); unsigned int groupId = hGroup.asLong(); MDataHandle hOutput = dataBlock.outputValue(plug); hOutput.copy(hGeom); MStatus returnStatus; MDataHandle envData = dataBlock.inputValue(envelope, &returnStatus); if (MS::kSuccess != returnStatus) return returnStatus; float env = envData.asFloat(); MDataHandle timeData = dataBlock.inputValue(time, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double t = timeData.asDouble(); MDataHandle dirData = dataBlock.inputValue(dir, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double dirDeg = dirData.asDouble(); MDataHandle bigData = dataBlock.inputValue(bigFreq, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double bigFreqAmp = bigData.asDouble(); MDataHandle ampData = dataBlock.inputValue(amplitude1, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double amp1 = ampData.asDouble(); MDataHandle freqData = dataBlock.inputValue(frequency1, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double freq1 = freqData.asDouble(); MDataHandle ampData2 = dataBlock.inputValue(amplitude2, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double amp2 = ampData2.asDouble(); MDataHandle freqData2 = dataBlock.inputValue(frequency2, &returnStatus); if(MS::kSuccess != returnStatus) return returnStatus; double freq2 = freqData2.asDouble(); // Get the MFnMesh MStatus stat; MObject inputObj = hOutput.data(); MFnMesh * meshFn = new MFnMesh(inputObj, &stat); // do the deformation // MItGeometry iter(hOutput,groupId,false); for ( ; !iter.isDone(); iter.next()) { MPoint pt = iter.position(); //float2 uvPoint; //float u,v; //uvPoint[0] = u; //uvPoint[1] = v; //meshFn->getUVAtPoint(pt, uvPoint, MSpace::kObject); float u = pt.x; //uvPoint[0]*100; float v = pt.z; //uvPoint[1]*100; float degDir = dirDeg; float dir = degDir* M_PI/180; float dirX = cos(dir); float dirY = sin(dir); float bigFreq = 0.01; float bigWaves = scaled_raw_noise_3d(0, 1, (u + 3*t*dirX)*bigFreq*dirX, (v + 3*t*dirY)*bigFreq*dirY*2, t*0.01); float frequency1 = freq1/10;//0.2; float amplitude1 = amp1;//1.3; float firstOctave = -(std::abs(scaled_raw_noise_3d(-amplitude1, amplitude1, (float)(u + 0.7*t*dirX)*frequency1*0.4, (float)(v + 0.7*t*dirY)*frequency1*0.6, 0.05*t))-amplitude1); float frequency2 = freq2/10; float amplitude2 = amp2; float secondOctave = - (std::abs(scaled_raw_noise_3d(-amplitude2, amplitude2, (float)(u + 0.7*t*dirX)*frequency2*0.35, (float)(v + 0.7*t*dirY)*frequency2*0.65, 0.005*t))-amplitude2); float frequency3 = freq1/10; float amplitude3 = amp1/1.5; float thirdOctave = - (std::abs(scaled_raw_noise_3d(-amplitude3, amplitude3, (float)(u + t*0.5*dirX)*frequency3*0.4, (float)(v + t*0.5*dirY)*frequency3*0.6, 30))-amplitude3); float frequency4 = freq2/10; float amplitude4 = amp2/1.5; float fourthOctave = scaled_raw_noise_3d(-amplitude4, amplitude4, (float)(u + t*0.5*dirX)*frequency4*0.4, (float)(v + t*0.5*dirY)*frequency4*0.6, 50); float frequency5 = freq2; float amplitude5 = amp2/2; float fifthOctave = scaled_raw_noise_3d(-amplitude5, amplitude5, (float)(u + t*0.5*dirX)*frequency5*0.15, (float)(v + t*0.5*dirY)*frequency5*0.85, 0.001*t); float disp = bigFreqAmp*bigWaves + 7*(bigWaves)*firstOctave + secondOctave + thirdOctave*thirdOctave + fourthOctave + std::abs(bigWaves-1)*fifthOctave; pt = pt + iter.normal()*disp; iter.setPosition(pt); } delete meshFn; status = MStatus::kSuccess; } return status; }
MStatus VmIslandNode::compute( const MPlug& i_plug, MDataBlock& io_dataBlock ) { MStatus status; fprintf( stderr, "VmIslandNode::compute()...\n" ); //Check plugs if( i_plug == oa_update ) { //Make sure all internal structures are up to date with attributes fprintf( stderr, "VmIslandNode::compute(oa_update)\n" ); MDataHandle seedHandle = io_dataBlock.inputValue( ia_seed, & status); const long seed = seedHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle roughnessHandle = io_dataBlock.inputValue( ia_roughness, & status); const float roughness = roughnessHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle planeHeightHandle = io_dataBlock.inputValue( ia_planeHeight, & status); const long planeHeight = planeHeightHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle smoothHandle = io_dataBlock.inputValue( ia_smooth, & status); const long smooth = smoothHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle resolutionHandle = io_dataBlock.inputValue( ia_resolution, & status); const long resolution = resolutionHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle planeSizeHandle = io_dataBlock.inputValue( ia_planeSize, & status); const long planeSize = planeSizeHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle gridSizeHandle = io_dataBlock.inputValue( ia_gridSize, & status); const long gridSize = gridSizeHandle.asLong(); m_gridSize = (int) gridSize; CHECK_MSTATUS( status ); //Grass //-------------- MDataHandle baseWidthHandle = io_dataBlock.inputValue( ia_baseWidth, & status); const float baseWidth = baseWidthHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle grassMultiplierHandle = io_dataBlock.inputValue( ia_grassMultiplier, & status); const long grassMultiplier = grassMultiplierHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle grassSegmentLengthHandle = io_dataBlock.inputValue( ia_grassSegmentLength, & status); const float grassSegmentLength = grassSegmentLengthHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle grassNumSegmentsHandle = io_dataBlock.inputValue( ia_grassNumSegments, & status); const long grassNumSegments = grassNumSegmentsHandle.asLong(); CHECK_MSTATUS( status ); //MDataHandle windDirectionHandle = io_dataBlock.inputValue( ia_windDirection, & status); MFloatVector& windDirVec = io_dataBlock.inputValue( ia_windDirection, & status).asFloatVector(); const Vcore::Vec3 windDirection = Vec3(windDirVec.x, windDirVec.y, windDirVec.z); CHECK_MSTATUS( status ); MDataHandle grassBendAmountHandle = io_dataBlock.inputValue( ia_grassBendAmount, & status); const float grassBendAmount = grassBendAmountHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle windSpreadHandle = io_dataBlock.inputValue( ia_windSpread, & status); const float windSpread = windSpreadHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle clockHandle = io_dataBlock.inputValue( ia_clock, & status); const float clock = clockHandle.asLong(); CHECK_MSTATUS( status ); //Colours //----------------- MFloatVector& grassBaseColour1Vec = io_dataBlock.inputValue( ia_grassBaseColour1, & status).asFloatVector(); const Vcore::Vec3 grassBaseColour1 = Vec3(grassBaseColour1Vec.x, grassBaseColour1Vec.y, grassBaseColour1Vec.z); CHECK_MSTATUS( status ); MFloatVector& grassTipColour1Vec = io_dataBlock.inputValue( ia_grassTipColour1, & status).asFloatVector(); const Vcore::Vec3 grassTipColour1 = Vec3(grassTipColour1Vec.x, grassTipColour1Vec.y, grassTipColour1Vec.z); CHECK_MSTATUS( status ); MFloatVector& grassBaseColour2Vec = io_dataBlock.inputValue( ia_grassBaseColour2, & status).asFloatVector(); const Vcore::Vec3 grassBaseColour2 = Vec3(grassBaseColour2Vec.x, grassBaseColour2Vec.y, grassBaseColour2Vec.z); CHECK_MSTATUS( status ); MFloatVector& grassTipColour2Vec = io_dataBlock.inputValue( ia_grassTipColour2, & status).asFloatVector(); const Vcore::Vec3 grassTipColour2 = Vec3(grassTipColour2Vec.x, grassTipColour2Vec.y, grassTipColour2Vec.z); CHECK_MSTATUS( status ); //Update paramters of external lib system and rebuild m_island.setPlaneParameters( planeSize, planeHeight, seed, roughness, resolution, gridSize, grassMultiplier, baseWidth, grassSegmentLength, grassNumSegments, windDirection, grassBendAmount, windSpread, clock, smooth, grassBaseColour1, grassTipColour1, grassBaseColour2, grassTipColour2 ); //Rebuild object and check for success const bool updateOK = m_island.build(); m_cachedVertices = m_island.getComponents( Vcore::Visland::VERTICES ); m_cachedColours = m_island.getComponents( Vcore::Visland::COLOURS ); m_cachedNormals = m_island.getComponents( Vcore::Visland::NORMALS ); m_cachedIndices = m_island.getAllIndices(); m_geomInstances = m_island.getAllGeometryInstances(); // We must set a value for the plug we have been asked to evaluate, // even if we are not going to use it. We set it in the data-block, // and to set it we use outputValue(). // // Here we usually set the result to true. The caller who triggered the // computation for this attribute might not look at the value that // we are setting this plug to. But they do ask for the value of this plug, // only to trigger an update of the internal structures. See the draw() // and boundingBox() methods to see how this is done. MDataHandle updateHandle = io_dataBlock.outputValue( i_plug ); updateHandle.set( updateOK ); //Need to set plug to clean to refresh it io_dataBlock.setClean( i_plug ); } else if( i_plug == oa_rib ) { //Set up rib system to ready renderman values fprintf( stderr, "VmIslandNode::compute(oa_rib)\n" ); MDataHandle seedHandle = io_dataBlock.inputValue( ia_seed, & status); const long seed = seedHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle smoothHandle = io_dataBlock.inputValue( ia_smooth, & status); const float smooth = smoothHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle roughnessHandle = io_dataBlock.inputValue( ia_roughness, & status); const float roughness = roughnessHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle rmanResolutionHandle = io_dataBlock.inputValue( ia_rmanResolution, & status); const long rmanResolution = rmanResolutionHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle planeHeightHandle = io_dataBlock.inputValue( ia_planeHeight, & status); const long planeHeight = planeHeightHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle planeSizeHandle = io_dataBlock.inputValue( ia_planeSize, & status); const long planeSize = planeSizeHandle.asLong(); CHECK_MSTATUS( status ); //Grass //---------------- MDataHandle gridSizeHandle = io_dataBlock.inputValue( ia_gridSize, & status); const long gridSize = gridSizeHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle grassMultiplierHandle = io_dataBlock.inputValue( ia_grassMultiplier, & status); const long grassMultiplier = grassMultiplierHandle.asLong(); CHECK_MSTATUS( status ); MDataHandle baseWidthHandle = io_dataBlock.inputValue( ia_baseWidth, & status); const float baseWidth = baseWidthHandle.asFloat(); m_gridSize = (int) baseWidth; CHECK_MSTATUS( status ); MDataHandle grassSegmentLengthHandle = io_dataBlock.inputValue( ia_grassSegmentLength, & status); const float grassSegmentLength = grassSegmentLengthHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle grassNumSegmentsHandle = io_dataBlock.inputValue( ia_grassNumSegments, & status); const long grassNumSegments = grassNumSegmentsHandle.asLong(); CHECK_MSTATUS( status ); MFloatVector& windDirVec = io_dataBlock.inputValue( ia_windDirection, & status).asFloatVector(); const Vcore::Vec3 windDirection = Vec3(windDirVec.x, windDirVec.y, windDirVec.z); CHECK_MSTATUS( status ); MDataHandle grassBendAmountHandle = io_dataBlock.inputValue( ia_grassBendAmount, & status); const float grassBendAmount = grassBendAmountHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle windSpreadHandle = io_dataBlock.inputValue( ia_windSpread, & status); const float windSpread = windSpreadHandle.asFloat(); CHECK_MSTATUS( status ); MDataHandle clockHandle = io_dataBlock.inputValue( ia_clock, & status); const float clock = clockHandle.asLong(); CHECK_MSTATUS( status ); //Colours //------------------- MFloatVector& grassBaseColour1Vec = io_dataBlock.inputValue( ia_grassBaseColour1, & status).asFloatVector(); const Vcore::Vec3 grassBaseColour1 = Vec3(grassBaseColour1Vec.x, grassBaseColour1Vec.y, grassBaseColour1Vec.z); CHECK_MSTATUS( status ); MFloatVector& grassTipColour1Vec = io_dataBlock.inputValue( ia_grassTipColour1, & status).asFloatVector(); const Vcore::Vec3 grassTipColour1 = Vec3(grassTipColour1Vec.x, grassTipColour1Vec.y, grassTipColour1Vec.z); CHECK_MSTATUS( status ); MFloatVector& grassBaseColour2Vec = io_dataBlock.inputValue( ia_grassBaseColour2, & status).asFloatVector(); const Vcore::Vec3 grassBaseColour2 = Vec3(grassBaseColour2Vec.x, grassBaseColour2Vec.y, grassBaseColour2Vec.z); CHECK_MSTATUS( status ); MFloatVector& grassTipColour2Vec = io_dataBlock.inputValue( ia_grassTipColour2, & status).asFloatVector(); const Vcore::Vec3 grassTipColour2 = Vec3(grassTipColour2Vec.x, grassTipColour2Vec.y, grassTipColour2Vec.z); CHECK_MSTATUS( status ); char rib[4096]; sprintf( rib, "seed=%d;roughness=%f;planeHeight=%d;planeSize=%d;resolution=%d;gridSize=%d;grassMultiplier=%d;baseWidth=%f;grassSegmentLength=%f;grassNumSegments=%d;windDirectionX=%f;windDirectionY=%f;windDirectionZ=%f;grassBendAmount=%f;windSpread=%f;clock=%d;smooth=%d;grassBaseColour1X=%f;grassBaseColour1Y=%f;grassBaseColour1Z=%f;grassTipColour1X=%f;grassTipColour1Y=%f;grassTipColour1Z=%f;grassBaseColour2X=%f;grassBaseColour2Y=%f;grassBaseColour2Z=%f;grassTipColour2X=%f;grassTipColour2Y=%f;grassTipColour2Z=%f;", (int) seed, (float) roughness, (int) planeHeight, (int) planeSize, (int) rmanResolution , (int) gridSize, (int) grassMultiplier, (float) baseWidth, (float) grassSegmentLength, (int) grassNumSegments, (float) windDirection.x, (float) windDirection.y, (float) windDirection.z, (float) grassBendAmount, (float) windSpread, (int) clock, (int) smooth, (float) grassBaseColour1.x, (float) grassBaseColour1.y, (float) grassBaseColour1.z, (float) grassTipColour1.x, (float) grassTipColour1.y, (float) grassTipColour1.z, (float) grassBaseColour2.x, (float) grassBaseColour2.y, (float) grassBaseColour2.z, (float) grassTipColour2.x, (float) grassTipColour2.y, (float) grassTipColour2.z ); // We must set a value for the plug we have been asked to evaluate, // even if we are not going to use it. We set it in the data-block, // and to set it we use outputValue(). // // Here we are calculating a string value, and that value will // be used by the caller in a "rib-gen" operation - a process in // which a RIB file is generated for Renderman. // // Notice also that strings in Maya or more complicated than numbers. // We need to make a data object for the string data. MFnStringData stringDataFn; MObject stringDataObj = stringDataFn.create( rib, & status ); CHECK_MSTATUS( status ); MDataHandle ribHandle = io_dataBlock.outputValue( i_plug ); ribHandle.set( stringDataObj ); io_dataBlock.setClean( i_plug ); } else { //Shouldn't be here. return MStatus::kSuccess; } }
MStatus splatDeformer::compute(const MPlug& plug, MDataBlock& data) { // do this if we are using an OpenMP implementation that is not the same as Maya's. // Even if it is the same, it does no harm to make this call. MThreadUtils::syncNumOpenMPThreads(); MStatus status = MStatus::kUnknownParameter; if (plug.attribute() != outputGeom) { return status; } unsigned int index = plug.logicalIndex(); MObject thisNode = this->thisMObject(); // get input value MPlug inPlug(thisNode,input); inPlug.selectAncestorLogicalIndex(index,input); MDataHandle hInput = data.inputValue(inPlug, &status); MCheckStatus(status, "ERROR getting input mesh\n"); // get the input geometry MDataHandle inputData = hInput.child(inputGeom); if (inputData.type() != MFnData::kMesh) { printf("Incorrect input geometry type\n"); return MStatus::kFailure; } // get the input groupId - ignored for now... MDataHandle hGroup = inputData.child(groupId); unsigned int groupId = hGroup.asLong(); // get deforming mesh MDataHandle deformData = data.inputValue(deformingMesh, &status); MCheckStatus(status, "ERROR getting deforming mesh\n"); if (deformData.type() != MFnData::kMesh) { printf("Incorrect deformer geometry type %d\n", deformData.type()); return MStatus::kFailure; } MObject dSurf = deformData.asMeshTransformed(); MFnMesh fnDeformingMesh; fnDeformingMesh.setObject( dSurf ) ; MDataHandle outputData = data.outputValue(plug); outputData.copy(inputData); if (outputData.type() != MFnData::kMesh) { printf("Incorrect output mesh type\n"); return MStatus::kFailure; } MItGeometry iter(outputData, groupId, false); // create fast intersector structure MMeshIntersector intersector; intersector.create(dSurf); // get all points at once. Faster to query, and also better for // threading than using iterator MPointArray verts; iter.allPositions(verts); int nPoints = verts.length(); // use bool variable as lightweight object for failure check in loop below bool failed = false; MTimer timer; timer.beginTimer(); #ifdef _OPENMP #pragma omp parallel for #endif for(int i=0; i<nPoints; i++) { // Cannot break out of an OpenMP loop, so if one of the // intersections failed, skip the rest if(failed) continue; // mesh point object must be in loop-local scope to avoid race conditions MPointOnMesh meshPoint; // Do intersection. Need to use per-thread status value as // MStatus has internal state and may trigger race conditions // if set from multiple threads. Probably benign in this case, // but worth being careful. MStatus localStatus = intersector.getClosestPoint(verts[i], meshPoint); if(localStatus != MStatus::kSuccess) { // NOTE - we cannot break out of an OpenMP region, so set // bad status and skip remaining iterations failed = true; continue; } // default OpenMP scheduling breaks traversal into large // chunks, so low risk of false sharing here in array write. verts[i] = meshPoint.getPoint(); } timer.endTimer(); printf("Runtime for threaded loop %f\n", timer.elapsedTime()); // write values back onto output using fast set method on iterator iter.setAllPositions(verts); if(failed) { printf("Closest point failed\n"); return MStatus::kFailure; } return status; }
MStatus multiCurve::compute( const MPlug& plug, MDataBlock& data ) { MStatus stat; if ( plug == outputCurves ) { MDataHandle numCurvesHandle = data.inputValue(numCurves, &stat); PERRORfail(stat, "multiCurve::compute getting numCurves"); int num = numCurvesHandle.asLong(); MDataHandle curveOffsetHandle = data.inputValue(curveOffset, &stat); PERRORfail(stat, "multiCurve::compute getting curveOffset"); double baseOffset = curveOffsetHandle.asDouble(); MDataHandle inputCurveHandle = data.inputValue(inputCurve, &stat); PERRORfail(stat, "multiCurve::compute getting inputCurve"); MObject inputCurveObject ( inputCurveHandle.asNurbsCurveTransformed() ); MFnNurbsCurve inCurveFS ( inputCurveObject ); MArrayDataHandle outputArray = data.outputArrayValue(outputCurves, &stat); PERRORfail(stat, "multiCurve::compute getting output data handle"); // Create an array data build that is preallocated to hold just // the number of curves we plan on creating. When this builder // is set in to the MArrayDataHandle at the end of the compute // method, the new array will replace the existing array in the // scene. // // If the number of elements of the multi does not change between // compute cycles, then one can reuse the space allocated on a // previous cycle by extracting the existing builder from the // MArrayDataHandle: // MArrayDataBuilder builder( outputArray.builder(&stat) ); // this later form of the builder will allow you to rewrite elements // of the array, and to grow it, but the array can only be shrunk by // explicitly removing elements with the method // MArrayDataBuilder::removeElement(unsigned index); // MArrayDataBuilder builder(outputCurves, num, &stat); PERRORfail(stat, "multiCurve::compute creating builder"); for (int curveNum = 0; curveNum < num; curveNum++) { MDataHandle outHandle = builder.addElement(curveNum); MFnNurbsCurveData dataCreator; MObject outCurveData = dataCreator.create(); MObject outputCurve = inCurveFS.copy(inputCurveObject, outCurveData, &stat); PERRORfail(stat, "multiCurve::compute copying curve"); MFnNurbsCurve outCurveFS ( outputCurve ); MPointArray cvs; double offset = baseOffset * (curveNum+1); outCurveFS.getCVs ( cvs, MSpace::kWorld ); int numCVs = cvs.length(); for (int i = 0; i < numCVs; i++) { cvs[i].x += offset; } outCurveFS.setCVs ( cvs ); outHandle.set(outCurveData); } // Set the builder back into the output array. This statement // is always required, no matter what constructor was used to // create the builder. stat = outputArray.set(builder); PERRORfail(stat, "multiCurve::compute setting the builder"); // Since we compute all the elements of the array, instead of // just marking the plug we were asked to compute as clean, mark // every element of the array as clean to prevent further calls // to this compute method during this DG evaluation cycle. stat = outputArray.setAllClean(); PERRORfail(stat, "multiCurve::compute cleaning outputCurves"); } else { return MS::kUnknownParameter; } return stat; }
MStatus finalproject::compute(const MPlug& plug, MDataBlock& data) { // do this if we are using an OpenMP implementation that is not the same as Maya's. // Even if it is the same, it does no harm to make this call. MThreadUtils::syncNumOpenMPThreads(); MStatus status = MStatus::kUnknownParameter; if (plug.attribute() != outputGeom) { return status; } unsigned int index = plug.logicalIndex(); MObject thisNode = this->thisMObject(); // get input value MPlug inPlug(thisNode,input); inPlug.selectAncestorLogicalIndex(index,input); MDataHandle hInput = data.inputValue(inPlug, &status); MCheckStatus(status, "ERROR getting input mesh\n"); // get the input geometry MDataHandle inputData = hInput.child(inputGeom); if (inputData.type() != MFnData::kMesh) { printf("Incorrect input geometry type\n"); return MStatus::kFailure; } // get the input groupId - ignored for now... MDataHandle hGroup = inputData.child(groupId); unsigned int groupId = hGroup.asLong(); // get deforming mesh MDataHandle deformData = data.inputValue(deformingMesh, &status); MCheckStatus(status, "ERROR getting deforming mesh\n"); if (deformData.type() != MFnData::kMesh) { printf("Incorrect deformer geometry type %d\n", deformData.type()); return MStatus::kFailure; } MDataHandle offloadData = data.inputValue(offload, &status); //gathers world space positions of the object and the magnet MObject dSurf = deformData.asMeshTransformed(); MObject iSurf = inputData.asMeshTransformed(); MFnMesh fnDeformingMesh, fnInputMesh; fnDeformingMesh.setObject( dSurf ) ; fnInputMesh.setObject( iSurf ) ; MDataHandle outputData = data.outputValue(plug); outputData.copy(inputData); if (outputData.type() != MFnData::kMesh) { printf("Incorrect output mesh type\n"); return MStatus::kFailure; } MItGeometry iter(outputData, groupId, false); // get all points at once. Faster to query, and also better for // threading than using iterator MPointArray objVerts; iter.allPositions(objVerts); int objNumPoints = objVerts.length(); MPointArray magVerts, tempverts; fnDeformingMesh.getPoints(magVerts); fnInputMesh.getPoints(tempverts); int magNumPoints = magVerts.length(); double min = DBL_MAX, max = -DBL_MAX; //finds min and max z-coordinate values to determine middle point (choice of z-axis was ours) for (int i = 0; i < magNumPoints; i++) { min = magVerts[i].z < min ? magVerts[i].z : min; max = magVerts[i].z > max ? magVerts[i].z : max; } double middle = (min + max) / 2; double polarity[magNumPoints]; //assigns polarity based on middle point of mesh for (int i = 0; i < magNumPoints; i++) { polarity[i] = magVerts[i].z > middle ? max / magVerts[i].z : -min / magVerts[i].z; } double* objdVerts = (double *)malloc(sizeof(double) * objNumPoints * 3); double* magdVerts = (double *)malloc(sizeof(double) * magNumPoints * 3); //creates handles to use attribute data MDataHandle vecX = data.inputValue(transX, &status); MDataHandle vecY = data.inputValue(transY, &status); MDataHandle vecZ = data.inputValue(transZ, &status); //gathers previously stored coordinates of the center of the object double moveX = vecX.asFloat(); double moveY = vecY.asFloat(); double moveZ = vecZ.asFloat(); //translates object based on the position stored in the attribute values for (int i=0; i<objNumPoints; i++) { objdVerts[i * 3] = tempverts[i].x + moveX; objdVerts[i * 3 + 1] = tempverts[i].y + moveY; objdVerts[i * 3 + 2] = tempverts[i].z + moveZ; } for (int i=0; i<magNumPoints; i++) { magdVerts[i * 3] = magVerts[i].x; magdVerts[i * 3 + 1] = magVerts[i].y; magdVerts[i * 3 + 2] = magVerts[i].z; } double teslaData = data.inputValue(tesla, &status).asDouble(); MDataHandle posiData = data.inputValue(positivelycharged, &status); double pivot[6] = {DBL_MAX, -DBL_MAX, DBL_MAX, -DBL_MAX, DBL_MAX, -DBL_MAX}; //finds the pivot point of the object in world space prior to being affected by the magnet for (int i = 0; i < tempverts.length(); i++) { pivot[0] = tempverts[i].x < pivot[0] ? tempverts[i].x : pivot[0]; pivot[1] = tempverts[i].x > pivot[1] ? tempverts[i].x : pivot[1]; pivot[2] = tempverts[i].y < pivot[2] ? tempverts[i].y : pivot[2]; pivot[3] = tempverts[i].y > pivot[3] ? tempverts[i].y : pivot[3]; pivot[4] = tempverts[i].z < pivot[4] ? tempverts[i].z : pivot[4]; pivot[5] = tempverts[i].z > pivot[5] ? tempverts[i].z : pivot[5]; } MTimer timer; timer.beginTimer(); //main function call magnetForce(magNumPoints, objNumPoints, teslaData, magdVerts, objdVerts, polarity, posiData.asBool(), offloadData.asBool()); timer.endTimer(); printf("Runtime for threaded loop %f\n", timer.elapsedTime()); for (int i=0; i<objNumPoints; i++) { objVerts[i].x = objdVerts[i * 3 + 0]; objVerts[i].y = objdVerts[i * 3 + 1]; objVerts[i].z = objdVerts[i * 3 + 2]; } //finds the pivot point of object in world space after being affected by the magnet double objCenter[6] = {DBL_MAX, -DBL_MAX, DBL_MAX, -DBL_MAX, DBL_MAX, -DBL_MAX}; for (int i = 0; i < tempverts.length(); i++) { objCenter[0] = objVerts[i].x < objCenter[0] ? objVerts[i].x : objCenter[0]; objCenter[1] = objVerts[i].x > objCenter[1] ? objVerts[i].x : objCenter[1]; objCenter[2] = objVerts[i].y < objCenter[2] ? objVerts[i].y : objCenter[2]; objCenter[3] = objVerts[i].y > objCenter[3] ? objVerts[i].y : objCenter[3]; objCenter[4] = objVerts[i].z < objCenter[4] ? objVerts[i].z : objCenter[4]; objCenter[5] = objVerts[i].z > objCenter[5] ? objVerts[i].z : objCenter[5]; } //creates vector based on the two calculated pivot points moveX = (objCenter[0] + objCenter[1]) / 2 - (pivot[0] + pivot[1]) / 2; moveY = (objCenter[2] + objCenter[3]) / 2 - (pivot[2] + pivot[3]) / 2; moveZ = (objCenter[4] + objCenter[5]) / 2 - (pivot[4] + pivot[5]) / 2; //stores pivot vector for next computation if (teslaData) { vecX.setFloat(moveX); vecY.setFloat(moveY); vecZ.setFloat(moveZ); } // write values back onto output using fast set method on iterator iter.setAllPositions(objVerts, MSpace::kWorld); free(objdVerts); free(magdVerts); return status; }