Esempio n. 1
0
bool ProxyViz::loadInternal(MDataBlock& block)
{
	MDataHandle tmH = block.inputValue(aplantTransformCache);
	MFnPointArrayData tmFn(tmH.data());
	MPointArray plantTms = tmFn.array();
	if(plantTms.length() < 1) return false;
	
	MDataHandle idH = block.inputValue(aplantIdCache);
	MFnIntArrayData idFn(idH.data());
	MIntArray plantIds = idFn.array();
	if(plantIds.length() < 1) return false;
	
	MDataHandle triH = block.inputValue(aplantTriangleIdCache);
	MFnIntArrayData triFn(triH.data());
	MIntArray plantTris = triFn.array();
	if(plantTris.length() < 1) return false;
	
	MDataHandle crdH = block.inputValue(aplantTriangleCoordCache);
	MFnVectorArrayData crdFn(crdH.data());
	MVectorArray plantCoords = crdFn.array();
	if(plantCoords.length() < 1) return false;
	
	MDataHandle cotH = block.inputValue(aplantOffsetCache);
	MFnVectorArrayData cotFn(cotH.data());
	MVectorArray plantOffsets = cotFn.array();
		
	return loadPlants(plantTms, plantIds, plantTris, plantCoords, plantOffsets);
}
Esempio n. 2
0
MStatus VoxelShape::compute( const MPlug& plug, MDataBlock& data ) {
	MStatus stat;

	// 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 == outData )
	{
		// 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.
		// 
		MDataHandle inputDataHandle = data.inputValue( voxelData, &stat );

		MObject inputDataObj = inputDataHandle.data();
		
		MFnPluginData fnDataCreator;
		MTypeId tmpid( VoxelPreviewDataWrapper::id );
		VoxelPreviewDataWrapper * newData = NULL;

		MDataHandle outHandle = data.outputValue( outData );	
		newData = (VoxelPreviewDataWrapper*)outHandle.asPluginData();

		if ( newData == NULL ) {
			// Create some output data
			fnDataCreator.create( tmpid, &stat );
			MCHECKERROR( stat, "compute : error creating VoxelPreviewDataWrapper")
				newData = (VoxelPreviewDataWrapper*)fnDataCreator.data( &stat );
			MCHECKERROR( stat, "compute : error getting proxy VoxelPreviewDataWrapper object")
		}
Esempio n. 3
0
MStatus cvColor::compute( const MPlug& plug, MDataBlock& data )
{ 
	MStatus stat;

	// cout << "cvColor::compute\n";

	if ( plug == cvLocations ) {
		MDataHandle inputData = data.inputValue ( inputSurface, &stat );
		if (!stat) {
			stat.perror("cvColor::compute get inputSurface");
			return stat;
		}

		MObject surf = inputData.asNurbsSurface();
		MFnNurbsSurface surfFn (surf, &stat);
		if (!stat) {
			stat.perror("cvColor::compute surface creator");
			return stat;
		}

		MDataHandle outputData = data.outputValue ( cvLocations, &stat );
		if (!stat) {
			stat.perror("cvColor::compute get cvLocations");
			return stat;
		}
		
		MObject cvs = outputData.data();
		MFnPointArrayData cvData(cvs, &stat);
		if (!stat) {
			stat.perror("cvColor::compute point array data creator");
			return stat;
		}

		MPointArray cvArray;
		stat = surfFn.getCVs( cvArray, MSpace::kObject);
		if (!stat) {
			stat.perror("cvColor::compute getCVs");
			return stat;
		}

		stat = cvData.set ( cvArray );
		if (!stat) {
			stat.perror("cvColor::compute setCVs");
			return stat;
		}

		outputData.set ( cvs );

		stat = data.setClean ( plug );
		if (!stat) {
			stat.perror("cvColor::compute setClean");
			return stat;
		}
	} else {
		return MS::kUnknownParameter;
	}

	return MS::kSuccess;
}
Esempio n. 4
0
MStatus setMDoubleArray(MObject &node, MString attrString, MDoubleArray &arr)
{
    MStatus stat; 
    MFnDependencyNode nodeFn(node);
    
    MObject attr = nodeFn.attribute( attrString, &stat );  MCheckStatus(stat,"ERROR node.attribute()"); 
    MPlug plug( node, attr );
    MDataHandle handle; plug.getValue( handle );
    MFnDoubleArrayData(handle.data()).array().copy(arr);
    plug.destructHandle(handle);
    
    return MS::kSuccess;
}
Esempio n. 5
0
MStatus ReduceArrayNode::compute(const MPlug& plug, MDataBlock& data)
{
    if (plug != aOutput)
        return MS::kUnknownParameter;

    MStatus status;

    MDataHandle inputHandle = data.inputValue(aInput, &status);
    CHECK_MSTATUS_AND_RETURN_IT(status);

    MFnDoubleArrayData inputArrayData(inputHandle.data());
    MDoubleArray inputArray = inputArrayData.array();
    int numInputs = inputArray.length();

    short operation = data.inputValue(aOperation).asShort();

    double output = numInputs > 0 ? inputArray[0] : 0.0;

    if (operation == kLENGTH)
    {
        output = double(numInputs);
    } else {
        for (int i = 1; i < numInputs; i++)
        {
            output = computeOutput(output, inputArray[i], operation, status);

            if (!status)
            {
                reportComputeError(this, operation);
                break;
            }
        }
    }

    MDataHandle outputHandle = data.outputValue(this->aOutput);
    outputHandle.setDouble(output);
    outputHandle.setClean();

    return MS::kSuccess;
}
Esempio n. 6
0
MStatus ProxyViz::compute( const MPlug& plug, MDataBlock& block )
{
	if(!m_enableCompute) return MS::kSuccess;
	if( plug == outValue ) {
		
		updateWorldSpace(thisMObject() );
		
		MStatus status;

		ExampVox * defBox = plantExample(0);
		
		defBox->setGeomSizeMult(block.inputValue(aradiusMult).asFloat() );
		
		defBox->setGeomBox(block.inputValue(abboxminx).asFloat(),
			block.inputValue(abboxminy).asFloat(), 
			block.inputValue(abboxminz).asFloat(), 
			block.inputValue(abboxmaxx).asFloat(), 
			block.inputValue(abboxmaxy).asFloat(), 
			block.inputValue(abboxmaxz).asFloat());
		
		float grdsz = defBox->geomExtent() * 32.f ;
		if(grdsz < 32.f) {
			AHelper::Info<float>(" ProxyViz input box is too small", grdsz);
			grdsz = 32.f;
			AHelper::Info<float>(" trancated to", grdsz);
		}
		
		if(m_toSetGrid) {
			m_toSetGrid = false;
			resetGrid(grdsz);
		}
		
		if(_firstLoad) {
/// internal cache only, initializing from external cache is obsolete 
			if(!loadInternal(block) )
				std::cout<<"\n ERROR proxviz cannot load internal cache";

			_firstLoad = 0;
		}
        
		if(!m_toCheckVisibility) {
			MArrayDataHandle groundMeshArray = block.inputArrayValue(agroundMesh );
			MArrayDataHandle groundSpaceArray = block.inputArrayValue(agroundSpace );
/// in case no ground is connected
            if(updateGround(groundMeshArray, groundSpaceArray )) {
                moveWithGround();
                AHelper::Info<std::string>(" ProxyViz ground ", groundBuildLog() );
            }
		}
		
		if(!m_hasParticle) {
			block.setClean(plug);
            return MS::kSuccess;
		}
		
		const int ngroups = block.inputValue(agroupcount).asInt();
		
		MDataHandle hdata = block.inputValue(outPositionPP, &status);
        MFnVectorArrayData farray(hdata.data(), &status);
        if(!status) {
            MGlobal::displayInfo("proxy viz is not properly connected to a particle system");
			block.setClean(plug);
            return MS::kSuccess;
        }
    
        MDataHandle scaledata = block.inputValue(outScalePP, &status);
        MFnVectorArrayData scalearray(scaledata.data(), &status);
        if(!status) {
            MGlobal::displayInfo("proxy viz is not properly connected to a particle system");
			block.setClean(plug);
            return MS::kSuccess;
        }
		
		MDataHandle rotatedata = block.inputValue(outRotationPP, &status);
        MFnVectorArrayData rotatearray(rotatedata.data(), &status);
        if(!status) {
            MGlobal::displayInfo("proxy viz is not properly connected to a particle system");
			block.setClean(plug);
            return MS::kSuccess;
        }
		
		MDataHandle replaceData = block.inputValue(outReplacePP, &status);
        MFnDoubleArrayData replaceArrayFn(replaceData.data(), &status);
        if(!status) {
            MGlobal::displayInfo("proxy viz is not properly connected to a particle system, needs userScalarPP");
			block.setClean(plug);
            return MS::kSuccess;
        }
		
		MVectorArray outPosArray = farray.array();	
        MVectorArray outScaleArray = scalearray.array();
		MVectorArray outRotateArray = rotatearray.array();
		MDoubleArray outReplaceArray = replaceArrayFn.array();
		
		if( outPosArray.length() < 1) {
			block.setClean(plug);
			return MS::kSuccess;
		}
		
		computePPAttribs(outPosArray, outRotateArray, outScaleArray, outReplaceArray,
						ngroups);

        float result = outPosArray.length();

		MDataHandle outputHandle = block.outputValue( outValue );
		outputHandle.set( result );
		block.setClean(plug);
    }
	if(plug == outValue1) {
		
		MArrayDataHandle hArray = block.inputArrayValue(ainexamp);
		updateExamples(hArray);

		float result = 91.f;

		MDataHandle outputHandle = block.outputValue( outValue1 );
		outputHandle.set( result );
		block.setClean(plug);
	}

	return MS::kSuccess;
}
Esempio n. 7
0
MStatus LSSolverNode::compute(const MPlug& plug, MDataBlock& data)
{
	MStatus stat;
	
	if( plug == deformed)
	{
		MDataHandle tetWorldMatrixData = data.inputValue(tetWorldMatrix, &returnStatus);
		McheckErr(returnStatus, "Error getting tetWorldMatrix data handle\n");

		MDataHandle restShapeData = data.inputValue(restShape, &returnStatus);
		McheckErr(returnStatus, "Error getting step data handle\n");

		MDataHandle restVerticesData = data.inputValue(restVertices, &returnStatus);
		McheckErr(returnStatus, "Error getting step data handle\n");

		MDataHandle restElementsData = data.inputValue(restElements, &returnStatus);
		McheckErr(returnStatus, "Error getting step data handle\n");

		MDataHandle selectedConstraintVertsData = data.inputValue(selectedConstraintVerts, &returnStatus);
		McheckErr(returnStatus, "Error getting step data handle\n");

		MDataHandle selectedForceVertsData = data.inputValue(selectedForceVerts, &returnStatus);
		McheckErr(returnStatus, "Error getting step data handle\n");

		MDataHandle timeData = data.inputValue(time, &returnStatus);
		McheckErr(returnStatus, "Error getting step data handle\n");

		MDataHandle outputMeshData = data.outputValue(deformed, &returnStatus);
		McheckErr(returnStatus, "Error getting outputMesh data handle\n");
		
		MMatrix twmat = tetWorldMatrixData.asMatrix();
		MObject rs = restShapeData.asMesh();
		double t = timeData.asDouble();

		MDataHandle poissonRatioData = data.inputValue(poissonRatio, &returnStatus);
		McheckErr(returnStatus, "Error getting poissonRatio data handle\n");

		MDataHandle youngsModulusData = data.inputValue(youngsModulus, &returnStatus);
		McheckErr(returnStatus, "Error getting youngsmodulus data handle\n");

		MDataHandle objectDensityData = data.inputValue(objectDensity, &returnStatus);
		McheckErr(returnStatus, "Error getting objectDensity data handle\n");

		MDataHandle frictionData = data.inputValue(friction, &returnStatus);
		McheckErr(returnStatus, "Error getting friction data handle\n");

		MDataHandle restitutionData = data.inputValue(restitution, &returnStatus);
		McheckErr(returnStatus, "Error getting restitution data handle\n");

		MDataHandle dampingData = data.inputValue(damping, &returnStatus);
		McheckErr(returnStatus, "Error getting damping data handle\n");

		MDataHandle userSuppliedDtData = data.inputValue(userSuppliedDt, &returnStatus);
		McheckErr(returnStatus, "Error getting user supplied dt data handle\n");


		MDataHandle integrationTypeData = data.inputValue(integrationType, &returnStatus);
		McheckErr(returnStatus, "Error getting user integrationTypeData\n");

		MDataHandle forceModelTypeData = data.inputValue(forceModelType, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceModelTypeData\n");

		MDataHandle forceApplicationTimeData = data.inputValue(forceApplicationTime, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceApplicationTime\n");
	
		MDataHandle forceReleasedTimeData = data.inputValue(forceReleasedTime, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceReleasedTime\n");

		MDataHandle forceIncrementTimeData = data.inputValue(forceIncrementTime, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceIncrementTime\n");

		MDataHandle forceStartTimeData = data.inputValue(forceStartTime, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceStartTime\n");

		MDataHandle forceStopTimeData = data.inputValue(forceStopTime, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceStopTime\n");

		MDataHandle forceMagnitudeData = data.inputValue(forceMagnitude, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceIdleTime\n");

		MDataHandle useSuppliedForceData = data.inputValue(useSuppliedForce, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceIdleTime\n");

		MDataHandle useSuppliedConstraintsData = data.inputValue(useSuppliedConstraints, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceIdleTime\n");

		MDataHandle forceDirectionData = data.inputValue(forceDirection, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceDirection\n");

		MDataHandle contactKsData = data.inputValue(contactKs, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceDirection\n");	

		MDataHandle contactKdData = data.inputValue(contactKd, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceDirection\n");

		MTime currentTime, maxTime;
		currentTime = MAnimControl::currentTime();
		maxTime = MAnimControl::maxTime();
					
		if (currentTime == MAnimControl::minTime())
		{
			// retrive restVertices and restElements
			sTime=0;

			MFnDoubleArrayData restVertArrayData(restVerticesData.data());
			MDoubleArray verts = restVertArrayData.array();
			int vertArrayLen = verts.length();
			double *vertArray = new double[vertArrayLen];
			verts.get(vertArray);

			for(int v=0;v<vertArrayLen;v=v+3)
			{
				MPoint mpoint = MPoint(vertArray[v],vertArray[v+1],vertArray[v+2])*twmat;
				vertArray[v] = mpoint.x;
				vertArray[v+1] = mpoint.y;
				vertArray[v+2] = mpoint.z;
			}

			MFnIntArrayData restEleArrayData(restElementsData.data());
			MIntArray ele = restEleArrayData.array();
			int eleArrayLen = ele.length();
			int *eleArray = new int[eleArrayLen];
			ele.get(eleArray);

			MFnIntArrayData selectedConstraintVertsArrayData(selectedConstraintVertsData.data());
			MIntArray sv = selectedConstraintVertsArrayData.array();

			// building selectedConstraintVerts
			vector<int> selectedConstraintVertIndices;
			for (int i = 0 ; i < sv.length() ; i++)
			{
				selectedConstraintVertIndices.push_back(sv[i]);
			}
			MGlobal::displayInfo("!!!!!");
			//std::string tmp=std::to_string((long double)selectedConstraintVertIndices.size());
			//MGlobal::displayInfo(MString(tmp.c_str()));
			//std::cout<<currentConstriant<<" up"<<std::endl;
			for(int i=0;i<constraintIndex[currentConstriant].size();i++){
				if(domainParentIndex[currentConstriant]==-1)
					selectedConstraintVertIndices.push_back(constraintIndex[currentConstriant][i]);
				//std::cout<<constraintIndex[currentConstriant][i]<<std::endl;
			}
			//std::cout<<currentConstriant<<" up"<<std::endl;

			/*for(int i=0;i<10;i++){
				selectedConstraintVertIndices.push_back(i+1);
			}*/

			MFnIntArrayData selectedForceVertsArrayData(selectedForceVertsData.data());
			MIntArray sf = selectedForceVertsArrayData.array();

			vector<int> selectedForceVertIndices;
			for (int i = 0 ; i < sf.length() ; i++)
			{
				selectedForceVertIndices.push_back(sf[i]);
			}


			// temporarily create force direction vector
			double *forceDir = forceDirectionData.asDouble3();

	
			vector<double> dir;
			dir.push_back(forceDir[0]); dir.push_back(forceDir[1]);dir.push_back(forceDir[2]);

			prevDeformed = 0;
			double youngsModulusDouble = youngsModulusData.asDouble();
			double poissonRatioDouble = poissonRatioData.asDouble();
			double objectDensityDouble = objectDensityData.asDouble();
			double frictionDouble = frictionData.asDouble();
			double restitutionDouble = restitutionData.asDouble();
			double dampingDouble = dampingData.asDouble();
			double userSuppliedDtDouble = userSuppliedDtData.asDouble();
			double forceMagnitudeDouble = forceMagnitudeData.asDouble();
			int fAppT = forceApplicationTimeData.asInt();
			int fReleasedT = forceReleasedTimeData.asInt();
			int fIncT = forceIncrementTimeData.asInt();
			int fStartT = forceStartTimeData.asInt();
			int fStopT = forceStopTimeData.asInt();
			int integrationTypeInt = integrationTypeData.asShort();
			int forceModelTypeInt = forceModelTypeData.asShort();

			bool useSuppliedForceBool = useSuppliedForceData.asBool();
			bool useSuppliedConstraintsBool = useSuppliedConstraintsData.asBool();

			double contactKs = contactKsData.asDouble();
			double contactKd = contactKdData.asDouble();

			if( sm)
			{
				delete sm;
			}
			sm = new SoftBodySim(youngsModulusDouble,poissonRatioDouble,objectDensityDouble,
				frictionDouble,restitutionDouble,dampingDouble, eleArrayLen, eleArray, vertArrayLen, vertArray,integrationTypeInt,forceModelTypeInt);
			sm->setContactAttributes(contactKs,contactKd);
			if (useSuppliedConstraintsBool)
				sm->initialize("",userSuppliedDtDouble, selectedConstraintVertIndices);
			else
			{
				vector<int> empty;
				sm->initialize("",userSuppliedDtDouble, empty);
			}
			
			if (useSuppliedForceBool)
				sm->setUserForceAttributes(forceMagnitudeDouble, dir,selectedForceVertIndices,fAppT,fReleasedT,fIncT,fStartT,fStopT);

			std::vector<int> childList=fdg.GetDomainChild(currentConstriant);
			if(childList.size()!=0){//not the root
				for(int i=0;i<childList.size();i++){
					int childIndex=-1;
					for(int j=0;j<fdomain_list.size();j++){
						if(fdomain_list[j]->index==childList[i]){
							childIndex=j;
						}
					}//j
					glm::dvec3 oldPos=glm::dvec3(0,0,0);
					for(int j=0;j<parentConstraintIndex[childIndex].size();j++){
						int index=3*parentConstraintIndex[childIndex][j];
						oldPos.x+=sm->m_vertices[index];
						oldPos.y+=sm->m_vertices[index+1];
						oldPos.z+=sm->m_vertices[index+2];
					}
					oldPos=oldPos*(1.0/parentConstraintIndex[childIndex].size());
					parentLastPosOld[childIndex]=oldPos;
					parentLastPosNew[childIndex]=oldPos;
				}//i
			}
			domainID=currentConstriant;
			currentConstriant++;
			if(currentConstriant==fdomain_list.size()) currentConstriant=0;
		}

		else
		{
			std::vector<int> childList=fdg.GetDomainChild(domainID);
			if(childList.size()!=0){//not the root
				for(int i=0;i<childList.size();i++){
					int childIndex=-1;
					for(int j=0;j<fdomain_list.size();j++){
						if(fdomain_list[j]->index==childList[i]){
							childIndex=j;
						}
					}//j
					glm::dvec3 newPos=glm::dvec3(0,0,0);
					for(int j=0;j<parentConstraintIndex[childIndex].size();j++){
						int index=3*parentConstraintIndex[childIndex][j];
						newPos.x+=sm->m_vertices[index];
						newPos.y+=sm->m_vertices[index+1];
						newPos.z+=sm->m_vertices[index+2];
					}
					//std::cout<<newPos.x<<","<<newPos.y<<","<<newPos.z<<std::endl;
					newPos=newPos*(1.0/parentConstraintIndex[childIndex].size());
					parentLastPosOld[childIndex]=parentLastPosNew[childIndex];
					parentLastPosNew[childIndex]=newPos;
				}//i
			}
			//update the parents' fixed point moving distance
			std::vector<float> pos;
			int num=0;
			if(domainParentIndex[domainID]!=-1){//has parent
				for(int i=0;i<constraintIndex[domainID].size();i++){
					int index=3*constraintIndex[domainID][i];
					pos.push_back(sm->m_vertices[index]);
					pos.push_back(sm->m_vertices[index+1]);
					pos.push_back(sm->m_vertices[index+2]);
				}
			}
			sm->update(sTime);
			sTime++;
			if(domainParentIndex[domainID]!=-1){//has parent
				//std::cout<<sm->numOfVertices<<std::endl;
				for(int i=0;i<constraintIndex[domainID].size();i++){
					int index=3*constraintIndex[domainID][i];
					if(index>3*sm->numOfVertices) std::cout<<index-3*sm->numOfVertices<<"big "<<currentConstriant<<std::endl;
					glm::dvec3 movePos=parentLastPosNew[domainID]-parentLastPosOld[domainID];
					//std::cout<<sm->m_vertices[index]<<","<<sm->m_vertices[index+1]<<","<<sm->m_vertices[index+2]<<std::endl;
					sm->m_vertices[index]=pos[num++]+movePos.x;
					sm->m_vertices[index+1]=pos[num++]+movePos.y;
					sm->m_vertices[index+2]=pos[num++]+movePos.z;
					//std::cout<<sm->m_vertices[index]<<","<<sm->m_vertices[index+1]<<","<<sm->m_vertices[index+2]<<"end"<<std::endl;
					//std::cout<<constraintIndex[domainID][i]<<std::endl;
				}
			}
		}

		MFnMesh surfFn(rs,&stat);
		McheckErr( stat, "compute - MFnMesh error" );

		MFnMeshData ouputMeshDataCreator;
		MObject oMesh = ouputMeshDataCreator.create(&stat);
		buildOutputMesh(surfFn, sm->m_vertices,oMesh);
		outputMeshData.set(oMesh);
		data.setClean(plug);

	}

	else
		stat = MS::kUnknownParameter;

	return stat;
}
MStatus geometrySurfaceConstraint::compute( const MPlug& plug, MDataBlock& block )
{	
	MStatus returnStatus;
 
    if(plug == constraintTranslateX || plug == constraintTranslateY || plug == constraintTranslateZ) {
        if(!m_isInitd) {
// read rest position
            MDataHandle htgo = block.inputValue(targetRestP);
            double3 & tgo = htgo.asDouble3();
            MGlobal::displayInfo(MString("target rest p ")+tgo[0]+" "+tgo[1]+" "+tgo[2]);
            m_restPos = MPoint(tgo[0],tgo[1],tgo[2]);
			m_isInitd = true;
		}
		
		MArrayDataHandle targetArray = block.inputArrayValue( compoundTarget );
		const unsigned int targetArrayCount = targetArray.elementCount();
        MMatrix tm;
        tm.setToIdentity();
        unsigned int i;
		for ( i = 0; i < targetArrayCount; i++ ) {
            MDataHandle targetElement = targetArray.inputValue(&returnStatus);
            if(!returnStatus) {
                MGlobal::displayInfo("failed to get input value target element");
            }
            MDataHandle htm = targetElement.child(targetTransform);
            MFnMatrixData ftm(htm.data(), &returnStatus);
            if(!returnStatus) {
                MGlobal::displayInfo("failed to get matrix data");
            }
            tm = ftm.matrix();
            targetArray.next();
        }
		
		MDataHandle hparentInvMat = block.inputValue(constraintParentInverseMatrix);
		MMatrix parentInvMat = hparentInvMat.asMatrix();

// world position
        MPoint curPos(tm(3,0), tm(3,1), tm(3,2));
// offset in local space
		m_offsetToRest = m_restPos - curPos;
// object position in world space
		MPoint localP = m_offsetToRest * tm + curPos;
// in local space
		localP *= parentInvMat;

        MDataHandle hout;
        if(plug == constraintTranslateX) {
            hout = block.outputValue(constraintTranslateX);
			hout.set(localP.x);
        }
        else if(plug == constraintTranslateY) {
            hout = block.outputValue(constraintTranslateY);
			hout.set(localP.y);
        }
        else if(plug == constraintTranslateZ) {
            hout = block.outputValue(constraintTranslateZ);
			hout.set(localP.z);
        }
		
		//MPlug pgTx(thisMObject(), constraintTargetX);
		//pgTx.setValue(m_lastPos.x);
		//MPlug pgTy(thisMObject(), constraintTargetY);
		//pgTy.setValue(m_lastPos.y);
		//MPlug pgTz(thisMObject(), constraintTargetZ);
		//pgTz.setValue(m_lastPos.z);
		
		MPlug pgOx(thisMObject(), constraintObjectX);
		pgOx.setValue(m_offsetToRest.x);
		MPlug pgOy(thisMObject(), constraintObjectY);
		pgOy.setValue(m_offsetToRest.y);
		MPlug pgOz(thisMObject(), constraintObjectZ);
		pgOz.setValue(m_offsetToRest.z);
        
       // MFnNumericData nd;
		//MObject offsetData = nd.create( MFnNumericData::k3Double);
        //nd.setData3Double(m_lastPos.x, m_lastPos.y, m_lastPos.z);
        //MPlug pgTgo(thisMObject(), targetOffset);
        //pgTgo.setValue(offsetData); 
    }
	else
		return MS::kUnknownParameter;

	return MS::kSuccess;
}
Esempio n. 9
0
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 );		
				}
			}
		}
	}
}
Esempio n. 10
0
//----------------------------------------------------------------------------
MStatus		BPT_InsertVtx::doCompleteCompute( MDataBlock& data )
//----------------------------------------------------------------------------
{

				SPEED("Berechne EdgeSplit neu: ");

				MStatus status;

				MPRINT("MACHE KOMPLETTE BERECHNUNG")



				MDataHandle inMeshHandle = data.inputValue(IVinMesh);
				MDataHandle outMeshHandle = data.outputValue(IVoutMesh);


					//splitCount setzen
				
				MDataHandle countHandle	= data.inputValue(IVcount);			
				fIVfty.setCount(countHandle.asInt());
			
				

				MDataHandle spinHandle = data.inputValue(IVspin);

				fIVfty.setSpin(spinHandle.asInt());
				

				int initialVtxCount;	//wird spueueter benueuetigt, um das ValidIndicesArray gleich in der rictigen grueueueuee zu erstellen und zu schreiben


				//gleich zu beginn muss der MeshPath initialisiert werden, damit der MeshPath an die fty ueuebergeben werden kann
				// Dies geschieht besser durch die STE - sie ist darauf ausgelegt
				softTransformationEngine::gatherAttributeObjects(thisMObject());
				softTransformationEngine::saveMeshPathes();

				

				fIVfty.setMeshPath(meshPath);
				
				
			
				MDataHandle	rHandle = data.inputValue(IVslideRelative);
				fIVfty.setRelative(rHandle.asInt());
				
				
				MDataHandle nRelativeHandle = data.inputValue(IVnormalRelative);
				fIVfty.setNormalRelative(nRelativeHandle.asInt());
				
				
				//selection setzen
				MFnIntArrayData		intDataArray;	
				
				MDataHandle arrayHandle = data.inputValue(IVselEdgeIDs);
				intDataArray.setObject(arrayHandle.data());
				
				fIVfty.setEdgeIDs( intDataArray.array() );

				arrayHandle = data.inputValue(IVselVertIDs);
				intDataArray.setObject(arrayHandle.data());

				fIVfty.setVertIDs(intDataArray.array());
				

				//				optionen holen
				
				arrayHandle = data.inputValue(IVoptions);
				intDataArray.setObject(arrayHandle.data());
				MIntArray optionsArray(intDataArray.array());
				

				fIVfty.setOptions(optionsArray);
				
				
				
				
				MDataHandle slideHandle = data.inputValue(IVslide);
				fIVfty.setSlide(slideHandle.asDouble());

				
				//whichSide attribute wird nur fueuer SLide selbst verwendet und kann nicht bereits beim command gestetzt werden
				
				


				MObject inMeshRef = inMeshHandle.asMesh();
				fIVfty.setMesh(inMeshRef);


				MFnMesh meshFn(inMeshHandle.asMesh());
				initialVtxCount = meshFn.numVertices();
				

				

				//ACTION
				try
				{
					status = fIVfty.doIt();
				}
				
				catch(...)
				{
					MGlobal::displayError(" An unknown, severe, error occoured.\nIf it happens again in this situation, please write a bug report.\nPlease undo the operation and save your work!");
					return MS::kUnknownParameter;
				}

				
				MObject newOutMesh = fIVfty.getMesh();

				
				outMeshHandle.set(newOutMesh);

				
				// ---------------------
				// SOFT TRANSFORMATION
				// ---------------------
				// VtxSet setzen - hier reicht es, wenn er einfach die neuen Vtx nimmt


				softTransformationEngine::setVtxSet(data);

		

				//------------SELECTION ROUTINE----------------------


			
				//nur wenn sich spin nicht verueuendert hat, darf ne neue selection gemacht werden - dies wird auch von der IV berueuecksichtigt
				//die selection wird nur noch einmal ausgefueuehrt, weshalb scriptJobInitiated nicht mehr gesetzt wird vom scriptjob
				if( optionsArray[6] && !scriptJobInitated && !(meshPath.apiType() == MFn::kInvalid) )
				{
						
						//auf jeden Fall erstmal die neuen Vertizen holen, damit die anderen prozeduren auch darauf arbeiten kueuennen

						//alles neuen Vertces sollen gewueuehlt werden, also einfach alle Indices eintragen vom initialVtxCount
						//bis zum jetzigen VtxCount
						MIntArray validEdges, validFaces;
						componentConverter CC(newOutMesh);

						int i = 0;


						meshFn.setObject(newOutMesh);
						int newCount = meshFn.numVertices();
						
						validIndices.clear();
						validIndices.setLength(newCount - initialVtxCount);
						
						

						for(; initialVtxCount < newCount; initialVtxCount++)
							validIndices[i++] = initialVtxCount;
						
						

					
					if(optionsArray[6] == 1 || optionsArray[6] == 2) //select edges
					{
						
						CC.getContainedEdges(validIndices,validEdges);
					}


					BPT_Helpers helper;


					if(optionsArray[6] == 2) //select Faces
					{
						CC.getConnectedFaces(validEdges,validFaces);

						//jetzt kann gleich alles beendet werden, da hiernach keine componente mehr kommt, in die man faces umwandeln mueuesste
						validIndices.clear();
						validIndices.append(2);

						
						helper.addIntArrayToLHS(validIndices,validFaces);

					}

					if(optionsArray[6] == 1)
					{//edges fertigmachen
						
						validIndices.clear();
						validIndices.append(1);

						helper.addIntArrayToLHS(validIndices,validEdges);

					}
					else if(optionsArray[6] == 5)
						validIndices.insert(3,0);


					//component Mode umschalten bei bedarf
					if(optionsArray[5])
					{
						MSelectionMask::SelectionType type = MSelectionMask::kSelectMeshVerts;
						
						if(optionsArray[6] == 5)
						{
							type = MSelectionMask::kSelectMeshVerts;
						}
						else if(optionsArray[6] == 2)
						{
							type = MSelectionMask::kSelectMeshFaces;
						}
						else if(optionsArray[6] == 1)
						{
							type = MSelectionMask::kSelectMeshEdges;
						}
						
						
						MSelectionMask mask(type);
						
						
						MGlobal:: setComponentSelectionMask(mask);
					}


					eID = MEventMessage::addEventCallback("idle",IV_makeSelection,this);

					scriptJobInitated = true;

				}
				else
				{//ansonsten muss die SelectionList neu aufgebaut werden, allerdings ohne komponenten
					//diese Aktion solte auch nur einmal ausgefueuehrt werden

					//gegenwueuertige selection holen
					MSelectionList currentList;
					MSelectionList newList;
					MGlobal::getActiveSelectionList(currentList);

					//durch die Liste iterieren und Komponenten Filtern
					MItSelectionList selIter(currentList);
					MObject currentObj;
					for( ; !selIter.isDone();selIter.next() )
					{
						
						selIter.getDependNode(currentObj);
						
						newList.add(currentObj);
					}

					MGlobal::setActiveSelectionList(newList, MGlobal::kAddToList);


		


				}


				



				return status;

}
MStatus LSSolverNode::compute(const MPlug& plug, MDataBlock& data)
{
	MStatus stat;
	
	if( plug == deformed)
	{
		MDataHandle tetWorldMatrixData = data.inputValue(tetWorldMatrix, &returnStatus);
		McheckErr(returnStatus, "Error getting tetWorldMatrix data handle\n");

		MDataHandle restShapeData = data.inputValue(restShape, &returnStatus);
		McheckErr(returnStatus, "Error getting step data handle\n");

		MDataHandle restVerticesData = data.inputValue(restVertices, &returnStatus);
		McheckErr(returnStatus, "Error getting step data handle\n");

		MDataHandle restElementsData = data.inputValue(restElements, &returnStatus);
		McheckErr(returnStatus, "Error getting step data handle\n");

		MDataHandle selectedConstraintVertsData = data.inputValue(selectedConstraintVerts, &returnStatus);
		McheckErr(returnStatus, "Error getting step data handle\n");

		MDataHandle selectedForceVertsData = data.inputValue(selectedForceVerts, &returnStatus);
		McheckErr(returnStatus, "Error getting step data handle\n");

		MDataHandle timeData = data.inputValue(time, &returnStatus);
		McheckErr(returnStatus, "Error getting step data handle\n");

		MDataHandle outputMeshData = data.outputValue(deformed, &returnStatus);
		McheckErr(returnStatus, "Error getting outputMesh data handle\n");
		
		MMatrix twmat = tetWorldMatrixData.asMatrix();
		MObject rs = restShapeData.asMesh();
		double t = timeData.asDouble();

		MDataHandle poissonRatioData = data.inputValue(poissonRatio, &returnStatus);
		McheckErr(returnStatus, "Error getting poissonRatio data handle\n");

		MDataHandle youngsModulusData = data.inputValue(youngsModulus, &returnStatus);
		McheckErr(returnStatus, "Error getting youngsmodulus data handle\n");

		MDataHandle objectDensityData = data.inputValue(objectDensity, &returnStatus);
		McheckErr(returnStatus, "Error getting objectDensity data handle\n");

		MDataHandle frictionData = data.inputValue(friction, &returnStatus);
		McheckErr(returnStatus, "Error getting friction data handle\n");

		MDataHandle restitutionData = data.inputValue(restitution, &returnStatus);
		McheckErr(returnStatus, "Error getting restitution data handle\n");

		MDataHandle dampingData = data.inputValue(damping, &returnStatus);
		McheckErr(returnStatus, "Error getting damping data handle\n");

		MDataHandle userSuppliedDtData = data.inputValue(userSuppliedDt, &returnStatus);
		McheckErr(returnStatus, "Error getting user supplied dt data handle\n");


		MDataHandle integrationTypeData = data.inputValue(integrationType, &returnStatus);
		McheckErr(returnStatus, "Error getting user integrationTypeData\n");

		MDataHandle forceModelTypeData = data.inputValue(forceModelType, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceModelTypeData\n");

		MDataHandle forceApplicationTimeData = data.inputValue(forceApplicationTime, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceApplicationTime\n");
	
		MDataHandle forceReleasedTimeData = data.inputValue(forceReleasedTime, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceReleasedTime\n");

		MDataHandle forceIncrementTimeData = data.inputValue(forceIncrementTime, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceIncrementTime\n");

		MDataHandle forceStartTimeData = data.inputValue(forceStartTime, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceStartTime\n");

		MDataHandle forceStopTimeData = data.inputValue(forceStopTime, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceStopTime\n");

		MDataHandle forceMagnitudeData = data.inputValue(forceMagnitude, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceIdleTime\n");

		MDataHandle useSuppliedForceData = data.inputValue(useSuppliedForce, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceIdleTime\n");

		MDataHandle useSuppliedConstraintsData = data.inputValue(useSuppliedConstraints, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceIdleTime\n");

		MDataHandle forceDirectionData = data.inputValue(forceDirection, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceDirection\n");

		MDataHandle contactKsData = data.inputValue(contactKs, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceDirection\n");	

		MDataHandle contactKdData = data.inputValue(contactKd, &returnStatus);
		McheckErr(returnStatus, "Error getting user forceDirection\n");

		MTime currentTime, maxTime;
		currentTime = MAnimControl::currentTime();
		maxTime = MAnimControl::maxTime();
					
		if (currentTime == MAnimControl::minTime())
		{
			// retrive restVertices and restElements
			MFnDoubleArrayData restVertArrayData(restVerticesData.data());
			MDoubleArray verts = restVertArrayData.array();
			int vertArrayLen = verts.length();
			double *vertArray = new double[vertArrayLen];
			verts.get(vertArray);

			for(int v=0;v<vertArrayLen;v=v+3)
			{
				MPoint mpoint = MPoint(vertArray[v],vertArray[v+1],vertArray[v+2])*twmat;
				vertArray[v] = mpoint.x;
				vertArray[v+1] = mpoint.y;
				vertArray[v+2] = mpoint.z;
			}

			MFnIntArrayData restEleArrayData(restElementsData.data());
			MIntArray ele = restEleArrayData.array();
			int eleArrayLen = ele.length();
			int *eleArray = new int[eleArrayLen];
			ele.get(eleArray);

			MFnIntArrayData selectedConstraintVertsArrayData(selectedConstraintVertsData.data());
			MIntArray sv = selectedConstraintVertsArrayData.array();

			// building selectedConstraintVerts
			vector<int> selectedConstraintVertIndices;
			for (int i = 0 ; i < sv.length() ; i++)
			{
				selectedConstraintVertIndices.push_back(sv[i]);
			}

			MFnIntArrayData selectedForceVertsArrayData(selectedForceVertsData.data());
			MIntArray sf = selectedForceVertsArrayData.array();

			vector<int> selectedForceVertIndices;
			for (int i = 0 ; i < sf.length() ; i++)
			{
				selectedForceVertIndices.push_back(sf[i]);
			}


			// temporarily create force direction vector
			double *forceDir = forceDirectionData.asDouble3();

	
			vector<double> dir;
			dir.push_back(forceDir[0]); dir.push_back(forceDir[1]);dir.push_back(forceDir[2]);

			prevDeformed = 0;
			double youngsModulusDouble = youngsModulusData.asDouble();
			double poissonRatioDouble = poissonRatioData.asDouble();
			double objectDensityDouble = objectDensityData.asDouble();
			double frictionDouble = frictionData.asDouble();
			double restitutionDouble = restitutionData.asDouble();
			double dampingDouble = dampingData.asDouble();
			double userSuppliedDtDouble = userSuppliedDtData.asDouble();
			double forceMagnitudeDouble = forceMagnitudeData.asDouble();
			int fAppT = forceApplicationTimeData.asInt();
			int fReleasedT = forceReleasedTimeData.asInt();
			int fIncT = forceIncrementTimeData.asInt();
			int fStartT = forceStartTimeData.asInt();
			int fStopT = forceStopTimeData.asInt();
			int integrationTypeInt = integrationTypeData.asShort();
			int forceModelTypeInt = forceModelTypeData.asShort();

			bool useSuppliedForceBool = useSuppliedForceData.asBool();
			bool useSuppliedConstraintsBool = useSuppliedConstraintsData.asBool();

			double contactKs = contactKsData.asDouble();
			double contactKd = contactKdData.asDouble();

			if( sm)
			{
				delete sm;
			}
			sm = new SoftBodySim(youngsModulusDouble,poissonRatioDouble,objectDensityDouble,
				frictionDouble,restitutionDouble,dampingDouble, eleArrayLen, eleArray, vertArrayLen, vertArray,integrationTypeInt,forceModelTypeInt);
			sm->setContactAttributes(contactKs,contactKd);
			if (useSuppliedConstraintsBool)
				sm->initialize("",userSuppliedDtDouble, selectedConstraintVertIndices);
			else
			{
				vector<int> empty;
				sm->initialize("",userSuppliedDtDouble, empty);
			}
			
			if (useSuppliedForceBool)
				sm->setUserForceAttributes(forceMagnitudeDouble, dir,selectedForceVertIndices,fAppT,fReleasedT,fIncT,fStartT,fStopT);
		}

		else
		{
			sm->update();
		}

		MFnMesh surfFn(rs,&stat);
		McheckErr( stat, "compute - MFnMesh error" );

		MFnMeshData ouputMeshDataCreator;
		MObject oMesh = ouputMeshDataCreator.create(&stat);
		buildOutputMesh(surfFn, sm->m_vertices,oMesh);
		outputMeshData.set(oMesh);
		data.setClean(plug);

	}

	else
		stat = MS::kUnknownParameter;

	return stat;
}
Esempio n. 12
0
void 
simpleFluidEmitter::omniFluidEmitter(
	MFnFluid& 		fluid,
	const MMatrix&	fluidWorldMatrix,
	int 			plugIndex,
	MDataBlock& 	block,
	double 			dt,
	double			conversion,
	double			dropoff
)
//==============================================================================
//
//	Method:	
//
//		simpleFluidEmitter::omniFluidEmitter
//
//	Description:
//
//		Emits fluid from a point, or from a set of object control points.
//
//	Parameters:
//
//		fluid:				fluid into which we are emitting
//		fluidWorldMatrix:	object->world matrix for the fluid
//		plugIndex:			identifies which fluid connected to the emitter
//							we are emitting into
//		block:				datablock for the emitter, to retrieve attribute
//							values
//		dt:					time delta for this frame
//		conversion:			mapping from UI emission rates to internal units
//		dropoff:			specifies how much emission rate drops off as
//							we move away from each emission point.
//
//	Notes:
//
//		If no owner object is present for the emitter, we simply emit from
//		the emitter position.  If an owner object is present, then we emit
//		from each control point of that object in an identical fashion.
//		
//		To associate an owner object with an emitter, use the
//		addDynamic MEL command, e.g. "addDynamic simpleFluidEmitter1 pPlane1".
//
//==============================================================================
{
	//	find the positions that we need to emit from
	//
	MVectorArray emitterPositions;
	
	//	first, try to get them from an owner object, which will have its
	//	"ownerPositionData" attribute feeding into the emitter.  These
	//	values are in worldspace
	//
	bool gotOwnerPositions = false;
	MObject ownerShape = getOwnerShape();
	if( ownerShape != MObject::kNullObj )
	{
		MStatus status;
		MDataHandle hOwnerPos = block.inputValue( mOwnerPosData, &status );
		if( status == MS::kSuccess )
		{
			MObject dOwnerPos = hOwnerPos.data();
			MFnVectorArrayData fnOwnerPos( dOwnerPos );
			MVectorArray posArray = fnOwnerPos.array( &status );
			if( status == MS::kSuccess )
			{
				// assign vectors from block to ownerPosArray.
				//
				for( unsigned int i = 0; i < posArray.length(); i ++ )
				{
					emitterPositions.append( posArray[i] );
				}
				
				gotOwnerPositions = true;
			}
		}
	}
	
	//	there was no owner object, so we just use the emitter position for
	//	emission.
	//
	if( !gotOwnerPositions )
	{
		MPoint emitterPos = getWorldPosition();
		emitterPositions.append( emitterPos );
	}

	//	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;	

	//	emission will only happen for voxels whose centers lie within
	//	"minDist" and "maxDist" of an emitter position
	//
	double minDist = getMinDistance( block );
	double maxDist = getMaxDistance( block );

	//	bump up the min/max distance values so that they
	//	are both > 0, and there is at least about a half
	//	voxel between the min and max values, to prevent aliasing
	//	artifacts caused by emitters missing most voxel centers
	//
	MTransformationMatrix fluidXform( fluidWorldMatrix );
	double fluidScale[3];
	fluidXform.getScale( fluidScale, MSpace::kWorld );
	
	//	compute smallest voxel diagonal length
	double wsX =  fabs(fluidScale[0]*dx);
	double wsY = fabs(fluidScale[1]*dy);
	double wsZ = fabs(fluidScale[2]*dz);
	double wsMin = MIN( MIN( wsX, wsY), wsZ );
	double wsMax = MAX( MAX( wsX, wsY), wsZ );
	double wsDiag  = wsMin * sqrt(3.0);

	//	make sure emission range is bigger than 0.5 voxels
	if ( maxDist <= minDist || maxDist <= (wsDiag/2.0) ) {
		if ( minDist < 0 ) minDist = 0;

		maxDist = minDist + wsDiag/2.0;
		dropoff = 0;
	}

	//	Now, it's time to actually emit into the fluid:
	//	
	//	foreach emitter point
	//		foreach voxel
	//			- select some points in the voxel
	//			- compute a dropoff function from the emitter point
	//			- emit an appropriate amount of fluid into the voxel
	//
	//	Since we've already expanded the min/max distances to cover
	//	the smallest voxel dimension, we should only need 1 sample per
	//	voxel, unless the voxels are highly non-square.  We increase the
	//	number of samples in these cases.
	//
	//	If the "jitter" flag is enabled, we jitter each sample position,
	//	using the rangen() function, which keeps track of independent 
	//	random states for each fluid, to make sure that results are
	//	repeatable for multiple simulation runs.
	//	

	// basic sample count
	int numSamples = 1;

	// increase samples if necessary for non-square voxels
	if(wsMin >.00001) 
	{
		numSamples = (int)(wsMax/wsMin + .5);
		if(numSamples > 8) 
			numSamples = 8;
		if(numSamples < 1)
			numSamples = 1;
	}
	
	bool jitter =  fluidJitter(block);
	if( !jitter )
	{
		//	I don't have a good uniform sample generator for an 
		//	arbitrary number of samples.  It would be a good idea to use
		//	one here.  For now, just use 1 sample for the non-jittered case.
		//
		numSamples = 1;
	}

	for( unsigned int p = 0; p < emitterPositions.length(); p++ )
	{
		MPoint emitterWorldPos = emitterPositions[p];

		//	loop through all voxels, looking for ones that lie at least
		//	partially within the dropoff field around this emitter point
		//
		for( unsigned int i = 0; i < res[0]; i++ )
		{
			double x = Ox + i*dx;
			
			for( unsigned int j = 0; j < res[1]; j++ )
			{
				double y = Oy + j*dy;
				
				for( unsigned int k = 0; k < res[2]; k++ )
				{
					double z = Oz + k*dz;
	
					int si;
					for( si = 0; si < numSamples; si++ )
					{
						//	compute sample point (fluid object space)
						//
						double rx, ry, rz;
						if( jitter )
						{
							rx = x + randgen()*dx;
							ry = y + randgen()*dy;
							rz = z + randgen()*dz;
						}
						else
						{
							rx = x + 0.5*dx;
							ry = y + 0.5*dy;
							rz = z + 0.5*dz;
						}

						//	compute distance from sample to emitter point
						//	
						MPoint point( rx, ry, rz );
						point *= fluidWorldMatrix;
						MVector diff = point - emitterWorldPos;
						double distSquared = diff * diff;
						double dist = diff.length();
					
						//	discard if outside min/max range
						//
						if( (dist < minDist) || (dist > maxDist) )
						{
							continue;
						}
						
						//	drop off the emission rate according to the falloff
						//	parameter, and divide to accound for multiple samples
						//	in the voxel
						//
						double distDrop = dropoff * distSquared;
						double newVal = theRate * exp( -distDrop ) / (double)numSamples;

						//	emit density/heat/fuel/color into the current voxel
						//
						if( newVal != 0 )
						{
							fluid.emitIntoArrays( (float) newVal, i, j, k, (float)densityEmit, (float)heatEmit, (float)fuelEmit, doEmitColor, emitColor );
						}

						float *fArray = fluid.falloff();
						if( fArray != NULL )
						{
							MPoint midPoint( x+0.5*dx, y+0.5*dy, z+0.5*dz );
							midPoint.x *= 0.2;
							midPoint.y *= 0.2;
							midPoint.z *= 0.2;

							float fdist = (float) sqrt( midPoint.x*midPoint.x + midPoint.y*midPoint.y + midPoint.z*midPoint.z );
							fdist /= sqrtf(3.0f);
							fArray[fluid.index(i,j,k)] = 1.0f-fdist;
						}
					}
				}
			}
		}
	}
}
Esempio n. 13
0
MObject VoxelShape::geometryData() const {
	VoxelShape* nonConstThis = const_cast<VoxelShape*>(this);
	MDataBlock datablock = nonConstThis->forceCache();
	MDataHandle handle = datablock.inputValue( outData );
	return handle.data();
}
Esempio n. 14
0
MStatus meshOpNode::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 status = MS::kSuccess;
 
	MDataHandle stateData = data.outputValue( state, &status );
	MCheckStatus( status, "ERROR getting state" );

	// Check for the HasNoEffect/PassThrough flag on the node.
	//
	// (stateData is an enumeration standard in all depend nodes)
	// 
	// (0 = Normal)
	// (1 = HasNoEffect/PassThrough)
	// (2 = Blocking)
	// ...
	//
	if( stateData.asShort() == 1 )
	{
		MDataHandle inputData = data.inputValue( inMesh, &status );
		MCheckStatus(status,"ERROR getting inMesh");

		MDataHandle outputData = data.outputValue( outMesh, &status );
		MCheckStatus(status,"ERROR getting outMesh");

		// Simply redirect the inMesh to the outMesh for the PassThrough effect
		//
		outputData.set(inputData.asMesh());
	}
	else
	{
		// 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 == outMesh)
		{
			MDataHandle inputData = data.inputValue( inMesh, &status );
			MCheckStatus(status,"ERROR getting inMesh");

			MDataHandle outputData = data.outputValue( outMesh, &status );
			MCheckStatus(status,"ERROR getting outMesh"); 

			// Now, we get the value of the component list and the operation
			// type and use it to perform the mesh operation on this mesh
			//
			MDataHandle inputIDs = data.inputValue( cpList, &status);
			MCheckStatus(status,"ERROR getting componentList"); 
			
			MDataHandle opTypeData = data.inputValue( opType, &status);
			MCheckStatus(status,"ERROR getting opType"); 

			// Copy the inMesh to the outMesh, so you can
			// perform operations directly on outMesh
			//
			outputData.set(inputData.asMesh());
			MObject mesh = outputData.asMesh();

			// Retrieve the ID list from the component list.
			//
			// Note, we use a component list to store the components
			// because it is more compact memory wise. (ie. comp[81:85]
			// is smaller than comp[81], comp[82],...,comp[85])
			//
			MObject compList = inputIDs.data();
			MFnComponentListData compListFn( compList );

			// Get what operation is requested and 
			// what type of component is expected for this operation.
			MeshOperation operationType = (MeshOperation) opTypeData.asShort();
			MFn::Type componentType =
				meshOpFty::getExpectedComponentType(operationType);

			unsigned i;
			int j;
			MIntArray cpIds;

			for( i = 0; i < compListFn.length(); i++ )
			{
				MObject comp = compListFn[i];
				if( comp.apiType() == componentType )
				{
					MFnSingleIndexedComponent siComp( comp );
					for( j = 0; j < siComp.elementCount(); j++ )
						cpIds.append( siComp.element(j) );
				}
			}

			// Set the mesh object and component List on the factory
			//
			fmeshOpFactory.setMesh( mesh );
			fmeshOpFactory.setComponentList( compList );
			fmeshOpFactory.setComponentIDs( cpIds );
			fmeshOpFactory.setMeshOperation( operationType );

			// Now, perform the meshOp
			//
			status = fmeshOpFactory.doIt();

			// Mark the output mesh as clean
			//
			outputData.setClean();
		}
		else
		{
			status = MS::kUnknownParameter;
		}
	}

	return status;
}
Esempio n. 15
0
MStatus dynExprField::compute(const MPlug& plug, MDataBlock& block)
//
//	Descriptions:
//		compute output force.
//
{
	MStatus status;

	if( !(plug == mOutputForce) )
        return( MS::kUnknownParameter );

	// get the logical index of the element this plug refers to.
	//
	int multiIndex = plug.logicalIndex( &status );
	McheckErr(status, "ERROR in plug.logicalIndex.\n");

	// Get input data handle, use outputArrayValue since we do not
	// want to evaluate both inputs, only the one related to the
	// requested multiIndex. Evaluating both inputs at once would cause
	// a dependency graph loop.
	
	MArrayDataHandle hInputArray = block.outputArrayValue( mInputData, &status );
	McheckErr(status,"ERROR in hInputArray = block.outputArrayValue().\n");
	
	status = hInputArray.jumpToElement( multiIndex );
	McheckErr(status, "ERROR: hInputArray.jumpToElement failed.\n");
	
	// get children of aInputData.
	
	MDataHandle hCompond = hInputArray.inputValue( &status );
	McheckErr(status, "ERROR in hCompond=hInputArray.inputValue\n");
	
	MDataHandle hPosition = hCompond.child( mInputPositions );
	MObject dPosition = hPosition.data();
	MFnVectorArrayData fnPosition( dPosition );
	MVectorArray points = fnPosition.array( &status );
	McheckErr(status, "ERROR in fnPosition.array(), not find points.\n");
	
	// Comment out the following since velocity, and mass are 
	// not needed in this field.
	//
	// MDataHandle hVelocity = hCompond.child( mInputVelocities );
	// MObject dVelocity = hVelocity.data();
	// MFnVectorArrayData fnVelocity( dVelocity );
	// MVectorArray velocities = fnVelocity.array( &status );
	// McheckErr(status, "ERROR in fnVelocity.array(), not find velocities.\n");
	//
	// MDataHandle hMass = hCompond.child( mInputMass );
	// MObject dMass = hMass.data();
	// MFnDoubleArrayData fnMass( dMass );
	// MDoubleArray masses = fnMass.array( &status );
	// McheckErr(status, "ERROR in fnMass.array(), not find masses.\n");

	// The attribute mInputPPData contains the attribute in an array form 
	// parpared by the particleShape if the particleShape has per particle 
	// attribute fieldName_attrName.  
	//
	// Suppose a field with the name dynExprField1 is connecting to 
	// particleShape1, and the particleShape1 has per particle float attribute
	// dynExprField1_magnitude and vector attribute dynExprField1_direction,
	// then hInputPPArray will contains a MdoubleArray with the corresponding
	// name "magnitude" and a MvectorArray with the name "direction".  This 
	// is a mechanism to allow the field attributes being driven by dynamic 
	// expression.
	MArrayDataHandle mhInputPPData = block.inputArrayValue( mInputPPData, &status );
	McheckErr(status,"ERROR in mhInputPPData = block.inputArrayValue().\n");

	status = mhInputPPData.jumpToElement( multiIndex );
	McheckErr(status, "ERROR: mhInputPPArray.jumpToElement failed.\n");

	MDataHandle hInputPPData = mhInputPPData.inputValue( &status );
	McheckErr(status, "ERROR in hInputPPData = mhInputPPData.inputValue\n");

	MObject dInputPPData = hInputPPData.data();
	MFnArrayAttrsData inputPPArray( dInputPPData );

	MDataHandle hOwnerPPData = block.inputValue( mOwnerPPData, &status );
	McheckErr(status, "ERROR in hOwnerPPData = block.inputValue\n");

	MObject dOwnerPPData = hOwnerPPData.data();
	MFnArrayAttrsData ownerPPArray( dOwnerPPData );

	const MString magString("magnitude");
	MFnArrayAttrsData::Type doubleType(MFnArrayAttrsData::kDoubleArray);

	bool arrayExist;
	MDoubleArray magnitudeArray;
	arrayExist = inputPPArray.checkArrayExist(magString, doubleType, &status);
	// McheckErr(status, "ERROR in checkArrayExist(magnitude)\n");
	if(arrayExist) {
	    magnitudeArray = inputPPArray.getDoubleData(magString, &status);
	    // McheckErr(status, "ERROR in inputPPArray.doubleArray(magnitude)\n");
	}

	MDoubleArray magnitudeOwnerArray;
	arrayExist = ownerPPArray.checkArrayExist(magString, doubleType, &status);
	// McheckErr(status, "ERROR in checkArrayExist(magnitude)\n");
	if(arrayExist) {
	    magnitudeOwnerArray = ownerPPArray.getDoubleData(magString, &status);
	    // McheckErr(status, "ERROR in ownerPPArray.doubleArray(magnitude)\n");
	}

	const MString dirString("direction");
	MFnArrayAttrsData::Type vectorType(MFnArrayAttrsData::kVectorArray);

	arrayExist = inputPPArray.checkArrayExist(dirString, vectorType, &status);
        MVectorArray directionArray;
	// McheckErr(status, "ERROR in checkArrayExist(direction)\n");
	if(arrayExist) {
	    directionArray = inputPPArray.getVectorData(dirString, &status);
	    // McheckErr(status, "ERROR in inputPPArray.vectorArray(direction)\n");
	}

	arrayExist = ownerPPArray.checkArrayExist(dirString, vectorType, &status);
        MVectorArray directionOwnerArray;
	// McheckErr(status, "ERROR in checkArrayExist(direction)\n");
	if(arrayExist) {
	    directionOwnerArray = ownerPPArray.getVectorData(dirString, &status);
	    // McheckErr(status, "ERROR in ownerPPArray.vectorArray(direction)\n");
	}

	// Compute the output force.
	//
	MVectorArray forceArray;

	apply( block, points.length(), magnitudeArray, magnitudeOwnerArray, 
	       directionArray, directionOwnerArray, forceArray );

	// get output data handle
	//
	MArrayDataHandle hOutArray = block.outputArrayValue( mOutputForce, &status);
	McheckErr(status, "ERROR in hOutArray = block.outputArrayValue.\n");
	MArrayDataBuilder bOutArray = hOutArray.builder( &status );
	McheckErr(status, "ERROR in bOutArray = hOutArray.builder.\n");

	// get output force array from block.
	//
	MDataHandle hOut = bOutArray.addElement(multiIndex, &status);
	McheckErr(status, "ERROR in hOut = bOutArray.addElement.\n");

	MFnVectorArrayData fnOutputForce;
	MObject dOutputForce = fnOutputForce.create( forceArray, &status );
	McheckErr(status, "ERROR in dOutputForce = fnOutputForce.create\n");

	// update data block with new output force data.
	//
	hOut.set( dOutputForce );
	block.setClean( plug );

	return( MS::kSuccess );
}
Esempio n. 16
0
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;
}
Esempio n. 17
0
MStatus latticeNoiseNode::compute( const MPlug& plug, MDataBlock& data )
{ 
	MStatus returnStatus;

	float noiseAmplitude;
	float noiseFreq;
 
	if( plug == output )
	{
		// Get the lattice data from the input attribute.  First get the 
		// data object, and then use the lattice data function set to extract
		// the actual lattice.
		//

		// Get the data handle
		//
		MDataHandle inputData = data.inputValue( input, &returnStatus );
		McheckErr( returnStatus, "ERROR getting lattice data handle\n" ); 
		// Get the data object
		//
		MObject latticeData = inputData.data(); 
		MFnLatticeData dataFn( latticeData );
		// Get the actual geometry
		// 
		MObject lattice = dataFn.lattice();
		MFnLattice lattFn( lattice, &returnStatus );
		McheckErr( returnStatus, "ERROR getting lattice geometry\n" );  


		// Do the same for the output lattice
		//
		MDataHandle outputData = data.outputValue( output, &returnStatus ); 
		McheckErr( returnStatus, "ERROR getting lattice data handle\n" );
		// Get the data object
		//
		latticeData = outputData.data(); 
		if ( latticeData.isNull() ) { 
			// The data object for this attribute has not been created yet, so
			// we'll create it
			//
			latticeData = dataFn.create();
		} else {
			// Use the data object that is already there
			// 
			dataFn.setObject( latticeData );
		}
		// Get the actual geometry
		// 
		MObject outLattice = dataFn.lattice();
		MFnLattice outLattFn( outLattice, &returnStatus );
		McheckErr( returnStatus, "ERROR getting lattice geometry\n" );  

		// Get the amplitude and frequency
		//
		MDataHandle ampData = data.inputValue( amplitude, &returnStatus );
		McheckErr( returnStatus, "ERROR getting amplitude\n" );
		noiseAmplitude = ampData.asFloat(); 

		MDataHandle freqData = data.inputValue( frequency, &returnStatus );
		McheckErr( returnStatus, "ERROR getting frequency\n" );
		noiseFreq = freqData.asFloat(); 

		// Get the time.  
		//
		MDataHandle timeData = data.inputValue( time, &returnStatus ); 
		McheckErr( returnStatus, "ERROR getting time data handle\n" );
		MTime time = timeData.asTime();
		float seconds = (float)time.as( MTime::kSeconds );

		// Easiest way to modify frequency is by modifying the time
		//
		seconds = seconds * noiseFreq;

		// We have the information we need now.  We'll apply noise to the
		// points upon the lattice
		//
		unsigned s, t, u;
		lattFn.getDivisions( s, t, u );
		// match up the divisions in the lattices
		//
		outLattFn.setDivisions( s, t, u );   

		for ( unsigned i = 0; i < s; i++ ) {
			for ( unsigned j = 0; j < t; j++ ) {
				for ( unsigned k = 0; k < u; k++ ) {
					MPoint & point = lattFn.point( i, j, k );
					MPoint & outPoint = outLattFn.point( i, j, k );
					pnt noisePnt = noise::atPointAndTime( (float)point.x, (float)point.y, 
														  (float)point.z, seconds );
					// Make noise between -1 and 1 instead of 0 and 1
					//
					noisePnt.x =  ( noisePnt.x * 2.0F ) - 1.0F;
					noisePnt.y =  ( noisePnt.y * 2.0F ) - 1.0F;
					noisePnt.z =  ( noisePnt.z * 2.0F ) - 1.0F;

 					outPoint.x = point.x + ( noisePnt.x * noiseAmplitude );
 					outPoint.y = point.y + ( noisePnt.y * noiseAmplitude );
 					outPoint.z = point.z + ( noisePnt.z * noiseAmplitude );  
				}
			}
		} 
		outputData.set( latticeData );
		data.setClean(plug); 
	} 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;
}
Esempio n. 19
0
MStatus splitUVNode::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 status = MS::kSuccess;
 
	MDataHandle stateData = data.outputValue( state, &status );
	MCheckStatus( status, "ERROR getting state" );

	// Check for the HasNoEffect/PassThrough flag on the node.
	//
	// (stateData is an enumeration standard in all depend nodes - stored as short)
	// 
	// (0 = Normal)
	// (1 = HasNoEffect/PassThrough)
	// (2 = Blocking)
	// ...
	//
	if( stateData.asShort() == 1 )
	{
		MDataHandle inputData = data.inputValue( inMesh, &status );
		MCheckStatus(status,"ERROR getting inMesh");

		MDataHandle outputData = data.outputValue( outMesh, &status );
		MCheckStatus(status,"ERROR getting outMesh");

		// Simply redirect the inMesh to the outMesh for the PassThrough effect
		//
		outputData.set(inputData.asMesh());
	}
	else
	{
		// 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 == outMesh)
		{
			MDataHandle inputData = data.inputValue( inMesh, &status );
			MCheckStatus(status,"ERROR getting inMesh");

			MDataHandle outputData = data.outputValue( outMesh, &status );
			MCheckStatus(status,"ERROR getting outMesh"); 

			// Now, we get the value of the uvList and use it to perform
			// the operation on this mesh
			//
			MDataHandle inputUVs = data.inputValue( uvList, &status);
			MCheckStatus(status,"ERROR getting uvList"); 
			
			// Copy the inMesh to the outMesh, and now you can
			// perform operations in-place on the outMesh
			//
			outputData.set(inputData.asMesh());
			MObject mesh = outputData.asMesh();

			// Retrieve the UV list from the component list.
			//
			// Note, we use a component list to store the components
			// because it is more compact memory wise. (ie. comp[81:85]
			// is smaller than comp[81], comp[82],...,comp[85])
			//
			MObject compList = inputUVs.data();
			MFnComponentListData compListFn( compList );

			unsigned i;
			int j;
			MIntArray uvIds;

			for( i = 0; i < compListFn.length(); i++ )
			{
				MObject comp = compListFn[i];
				if( comp.apiType() == MFn::kMeshMapComponent )
				{
					MFnSingleIndexedComponent uvComp( comp );
					for( j = 0; j < uvComp.elementCount(); j++ )
					{
						int uvId = uvComp.element(j);
						uvIds.append( uvId );
					}
				}
			}

			// Set the mesh object and uvList on the factory
			//
			fSplitUVFactory.setMesh( mesh );
			fSplitUVFactory.setUVIds( uvIds );

			// Now, perform the splitUV
			//
			status = fSplitUVFactory.doIt();

			// Mark the output mesh as clean
			//
			outputData.setClean();
		}
		else
		{
			status = MS::kUnknownParameter;
		}
	}

	return status;
}
Esempio n. 20
0
MStatus AlembicNode::compute(const MPlug & plug, MDataBlock & dataBlock)
{
    MStatus status;

    // update the frame number to be imported
    MDataHandle speedHandle = dataBlock.inputValue(mSpeedAttr, &status);
    double speed = speedHandle.asDouble();

    MDataHandle offsetHandle = dataBlock.inputValue(mOffsetAttr, &status);
    double offset = offsetHandle.asDouble();

    MDataHandle timeHandle = dataBlock.inputValue(mTimeAttr, &status);
    MTime t = timeHandle.asTime();
    double inputTime = t.as(MTime::kSeconds);

    double fps = getFPS();

    // scale and offset inputTime.
    inputTime = computeAdjustedTime(inputTime, speed, offset/fps);

    // this should be done only once per file
    if (mFileInitialized == false)
    {
        mFileInitialized = true;

        MDataHandle dataHandle = dataBlock.inputValue(mAbcFileNameAttr);
        MFileObject fileObject;
        fileObject.setRawFullName(dataHandle.asString());
        MString fileName = fileObject.resolvedFullName();

        // TODO, make sure the file name, or list of files create a valid
        // Alembic IArchive

        // initialize some flags for plug update
        mSubDInitialized = false;
        mPolyInitialized = false;

        // When an alembic cache will be imported at the first time using
        // AbcImport, we need to set mIncludeFilterAttr (filterHandle) to be
        // mIncludeFilterString for later use. When we save a maya scene(.ma)
        // mIncludeFilterAttr will be saved. Then when we load the saved
        // .ma file, mIncludeFilterString will be set to be mIncludeFilterAttr.
        MDataHandle includeFilterHandle =
                        dataBlock.inputValue(mIncludeFilterAttr, &status);
        MString& includeFilterString = includeFilterHandle.asString();

       if (mIncludeFilterString.length() > 0)
        {
            includeFilterHandle.set(mIncludeFilterString);
            dataBlock.setClean(mIncludeFilterAttr);
        }
        else if (includeFilterString.length() > 0)
        {
            mIncludeFilterString = includeFilterString;
        }

        MDataHandle excludeFilterHandle =
                        dataBlock.inputValue(mExcludeFilterAttr, &status);
        MString& excludeFilterString = excludeFilterHandle.asString();

       if (mExcludeFilterString.length() > 0)
        {
            excludeFilterHandle.set(mExcludeFilterString);
            dataBlock.setClean(mExcludeFilterAttr);
        }
        else if (excludeFilterString.length() > 0)
        {
            mExcludeFilterString = excludeFilterString;
        }


        MFnDependencyNode dep(thisMObject());
        MPlug allSetsPlug = dep.findPlug("allColorSets");
        CreateSceneVisitor visitor(inputTime, !allSetsPlug.isNull(),
            MObject::kNullObj, CreateSceneVisitor::NONE, "",
            mIncludeFilterString, mExcludeFilterString);

        {
           mData.getFrameRange(mSequenceStartTime, mSequenceEndTime);
            MDataHandle startFrameHandle = dataBlock.inputValue(mStartFrameAttr,
                                                                &status);
            startFrameHandle.set(mSequenceStartTime*fps);
            MDataHandle endFrameHandle = dataBlock.inputValue(mEndFrameAttr,
                                                                &status);
            endFrameHandle.set(mSequenceEndTime*fps);
        }
    }

    // Retime
    MDataHandle cycleHandle = dataBlock.inputValue(mCycleTypeAttr, &status);
    short playType = cycleHandle.asShort();
    inputTime = computeRetime(inputTime, mSequenceStartTime, mSequenceEndTime,
                              playType);

    clamp<double>(mSequenceStartTime, mSequenceEndTime, inputTime);

    // update only when the time lapse is big enough
    if (fabs(inputTime - mCurTime) > 0.00001)
    {
        mOutRead = std::vector<bool>(mOutRead.size(), false);
        mCurTime = inputTime;
    }

    if (plug == mOutPropArrayAttr)
    {

        if (mOutRead[0])
        {
            dataBlock.setClean(plug);
            return MS::kSuccess;
        }

        mOutRead[0] = true;

        unsigned int propSize =
            static_cast<unsigned int>(mData.mPropList.size());

        if (propSize > 0)
        {
            MArrayDataHandle outArrayHandle = dataBlock.outputValue(
                mOutPropArrayAttr, &status);

            unsigned int outHandleIndex = 0;
            MDataHandle outHandle;

            // for all of the nodes with sampled attributes
            for (unsigned int i = 0; i < propSize; i++)
            {
                // only use the handle if it matches the index.
                // The index wont line up in the sparse case so we
                // can just skip that element.
                if (outArrayHandle.elementIndex() == outHandleIndex++)
                {
                    outHandle = outArrayHandle.outputValue();
                }
                else
                {
                    continue;
                }

                if (mData.mPropList[i].mArray.valid())
                {
                    readProp(mCurTime, mData.mPropList[i].mArray, outHandle);
                }
                else if (mData.mPropList[i].mScalar.valid())
                {
                    // for visibility only
                    if (mData.mPropList[i].mScalar.getName() ==
                        Alembic::AbcGeom::kVisibilityPropertyName)
                    {
                        Alembic::Util::int8_t visVal = 1;
                        mData.mPropList[i].mScalar.get(&visVal,
                            Alembic::Abc::ISampleSelector(mCurTime,
                                Alembic::Abc::ISampleSelector::kNearIndex ));
                        outHandle.setGenericBool(visVal != 0, false);
                    }
                    else
                    {
                        // for all scalar props
                        readProp(mCurTime, mData.mPropList[i].mScalar, outHandle);
                    }
                }
                outArrayHandle.next();
            }
            outArrayHandle.setAllClean();
        }

    }
    else if (plug == mOutTransOpArrayAttr )
    {
        if (mOutRead[1])
        {
            dataBlock.setClean(plug);
            return MS::kSuccess;
        }

        mOutRead[1] = true;

        unsigned int xformSize =
            static_cast<unsigned int>(mData.mXformList.size());

        if (xformSize > 0)
        {
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutTransOpArrayAttr, &status);

            MPlug arrayPlug(thisMObject(), mOutTransOpArrayAttr);

            MDataHandle outHandle;
            unsigned int outHandleIndex = 0;

            for (unsigned int i = 0; i < xformSize; i++)
            {
                std::vector<double> sampleList;

                if (mData.mIsComplexXform[i])
                {
                    readComplex(mCurTime, mData.mXformList[i], sampleList);
                }
                else
                {
                    Alembic::AbcGeom::XformSample samp;
                    read(mCurTime, mData.mXformList[i], sampleList, samp);
                }

                unsigned int sampleSize = (unsigned int)sampleList.size();

                for (unsigned int j = 0; j < sampleSize; j++)
                {
                    // only use the handle if it matches the index.
                    // The index wont line up in the sparse case so we
                    // can just skip that element.
                    if (outArrayHandle.elementIndex() == outHandleIndex++)
                    {
                        outHandle = outArrayHandle.outputValue(&status);
                    }
                    else
                        continue;

                    outArrayHandle.next();
                    outHandle.set(sampleList[j]);
                }
            }
            outArrayHandle.setAllClean();
        }
    }
    else if (plug == mOutLocatorPosScaleArrayAttr )
    {
        if (mOutRead[8])
        {
            dataBlock.setClean(plug);
            return MS::kSuccess;
        }

        mOutRead[8] = true;

        unsigned int locSize =
            static_cast<unsigned int>(mData.mLocList.size());

        if (locSize > 0)
        {
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutLocatorPosScaleArrayAttr, &status);

            MPlug arrayPlug(thisMObject(), mOutLocatorPosScaleArrayAttr);

            MDataHandle outHandle;
            unsigned int outHandleIndex = 0;

            for (unsigned int i = 0; i < locSize; i++)
            {
                std::vector< double > sampleList;
                read(mCurTime, mData.mLocList[i], sampleList);

                unsigned int sampleSize = (unsigned int)sampleList.size();
                for (unsigned int j = 0; j < sampleSize; j++)
                {
                    // only use the handle if it matches the index.
                    // The index wont line up in the sparse case so we
                    // can just skip that element.
                    if (outArrayHandle.elementIndex() == outHandleIndex++)
                    {
                        outHandle = outArrayHandle.outputValue(&status);
                    }
                    else
                        continue;

                    outArrayHandle.next();
                    outHandle.set(sampleList[j]);
                }
            }
            outArrayHandle.setAllClean();
        }
    }
    else if (plug == mOutSubDArrayAttr)
    {
        if (mOutRead[2])
        {
            // Reference the output to let EM know we are the writer
            // of the data. EM sets the output to holder and causes
            // race condition when evaluating fan-out destinations.
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutSubDArrayAttr, &status);
            const unsigned int elementCount = outArrayHandle.elementCount();
            for (unsigned int j = 0; j < elementCount; j++)
            {
                outArrayHandle.outputValue().data();
                outArrayHandle.next();
            }
            outArrayHandle.setAllClean();
            return MS::kSuccess;
        }

        mOutRead[2] = true;

        unsigned int subDSize =
            static_cast<unsigned int>(mData.mSubDList.size());

        if (subDSize > 0)
        {
            MArrayDataHandle outArrayHandle = dataBlock.outputValue(
                mOutSubDArrayAttr, &status);

            MDataHandle outHandle;

            for (unsigned int j = 0; j < subDSize; j++)
            {
                // these elements can be sparse if they have been deleted
                if (outArrayHandle.elementIndex() != j)
                {
                    continue;
                }

                outHandle = outArrayHandle.outputValue(&status);
                outArrayHandle.next();

                MObject obj = outHandle.data();
                if (obj.hasFn(MFn::kMesh))
                {
                    MFnMesh fnMesh(obj);
                    readSubD(mCurTime, fnMesh, obj, mData.mSubDList[j],
                        mSubDInitialized);
                    outHandle.set(obj);
                }
            }
            mSubDInitialized = true;
            outArrayHandle.setAllClean();
        }
        // for the case where we don't have any nodes, we want to make sure
        // to push out empty meshes on our connections, this can happen if
        // the input file was offlined, currently we only need to do this for
        // meshes as Nurbs, curves, and the other channels don't crash Maya
        else
        {
            MArrayDataHandle outArrayHandle = dataBlock.outputValue(
                mOutSubDArrayAttr, &status);

            if (outArrayHandle.elementCount() > 0)
            {
                do
                {
                    MDataHandle outHandle = outArrayHandle.outputValue();
                    MObject obj = outHandle.data();
                    if (obj.hasFn(MFn::kMesh))
                    {
                        MFloatPointArray emptyVerts;
                        MIntArray emptyCounts;
                        MIntArray emptyConnects;
                        MFnMesh emptyMesh;
                        emptyMesh.create(0, 0, emptyVerts, emptyCounts,
                            emptyConnects, obj);
                        outHandle.set(obj);
                    }
                }
                while (outArrayHandle.next() == MS::kSuccess);
            }
            mSubDInitialized = true;
            outArrayHandle.setAllClean();
        }
    }
    else if (plug == mOutPolyArrayAttr)
    {
        if (mOutRead[3])
        {
            // Reference the output to let EM know we are the writer
            // of the data. EM sets the output to holder and causes
            // race condition when evaluating fan-out destinations.
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutPolyArrayAttr, &status);
            const unsigned int elementCount = outArrayHandle.elementCount();
            for (unsigned int j = 0; j < elementCount; j++)
            {
                outArrayHandle.outputValue().data();
                outArrayHandle.next();
            }
            outArrayHandle.setAllClean();
            return MS::kSuccess;
        }

        mOutRead[3] = true;

        unsigned int polySize =
            static_cast<unsigned int>(mData.mPolyMeshList.size());

        if (polySize > 0)
        {
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutPolyArrayAttr, &status);

            MDataHandle outHandle;

            for (unsigned int j = 0; j < polySize; j++)
            {
                // these elements can be sparse if they have been deleted
                if (outArrayHandle.elementIndex() != j)
                {
                    continue;
                }

                outHandle = outArrayHandle.outputValue(&status);
                outArrayHandle.next();

                MObject obj = outHandle.data();
                if (obj.hasFn(MFn::kMesh))
                {
                    MFnMesh fnMesh(obj);
                    readPoly(mCurTime, fnMesh, obj, mData.mPolyMeshList[j],
                        mPolyInitialized);
                    outHandle.set(obj);
                }
            }
            mPolyInitialized = true;
            outArrayHandle.setAllClean();
        }
        // for the case where we don't have any nodes, we want to make sure
        // to push out empty meshes on our connections, this can happen if
        // the input file was offlined, currently we only need to do this for
        // meshes as Nurbs, curves, and the other channels don't crash Maya
        else
        {
            MArrayDataHandle outArrayHandle = dataBlock.outputValue(
                mOutPolyArrayAttr, &status);

            if (outArrayHandle.elementCount() > 0)
            {
                do
                {
                    MDataHandle outHandle = outArrayHandle.outputValue(&status);
                    MObject obj = outHandle.data();
                    if (obj.hasFn(MFn::kMesh))
                    {
                        MFloatPointArray emptyVerts;
                        MIntArray emptyCounts;
                        MIntArray emptyConnects;
                        MFnMesh emptyMesh;
                        emptyMesh.create(0, 0, emptyVerts, emptyCounts,
                            emptyConnects, obj);
                        outHandle.set(obj);
                    }
                }
                while (outArrayHandle.next() == MS::kSuccess);
            }
            mPolyInitialized = true;
            outArrayHandle.setAllClean();
        }
    }
    else if (plug == mOutCameraArrayAttr)
    {
        if (mOutRead[4])
        {
            dataBlock.setClean(plug);
            return MS::kSuccess;
        }

        mOutRead[4] = true;

        unsigned int cameraSize =
            static_cast<unsigned int>(mData.mCameraList.size());

        if (cameraSize > 0)
        {
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutCameraArrayAttr, &status);
            MPlug arrayPlug(thisMObject(), mOutCameraArrayAttr);
            double angleConversion = 1.0;

            switch (MAngle::uiUnit())
            {
                case MAngle::kRadians:
                    angleConversion = 0.017453292519943295;
                break;
                case MAngle::kAngMinutes:
                    angleConversion = 60.0;
                break;
                case MAngle::kAngSeconds:
                    angleConversion = 3600.0;
                break;
                default:
                break;
            }

            MDataHandle outHandle;
            unsigned int index = 0;

            for (unsigned int cameraIndex = 0; cameraIndex < cameraSize;
                cameraIndex++)
            {
                Alembic::AbcGeom::ICamera & cam =
                    mData.mCameraList[cameraIndex];
                std::vector<double> array;

                read(mCurTime, cam, array);

                for (unsigned int dataIndex = 0; dataIndex < array.size();
                    dataIndex++, index++)
                {
                    // skip over sparse elements
                    if (index != outArrayHandle.elementIndex())
                    {
                        continue;
                    }

                    outHandle = outArrayHandle.outputValue(&status);
                    outArrayHandle.next();

                    // not shutter angle index, so not an angle
                    if (dataIndex != 11)
                    {
                        outHandle.set(array[dataIndex]);
                    }
                    else
                    {
                        outHandle.set(array[dataIndex] * angleConversion);
                    }
                }  // for the per camera data handles
            }  // for each camera
            outArrayHandle.setAllClean();
        }
    }
    else if (plug == mOutNurbsSurfaceArrayAttr)
    {
        if (mOutRead[5])
        {
            // Reference the output to let EM know we are the writer
            // of the data. EM sets the output to holder and causes
            // race condition when evaluating fan-out destinations.
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status);
            const unsigned int elementCount = outArrayHandle.elementCount();
            for (unsigned int j = 0; j < elementCount; j++)
            {
                outArrayHandle.outputValue().data();
                outArrayHandle.next();
            }
            outArrayHandle.setAllClean();
            return MS::kSuccess;
        }

        mOutRead[5] = true;

        unsigned int nSurfaceSize =
            static_cast<unsigned int>(mData.mNurbsList.size());

        if (nSurfaceSize > 0)
        {
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutNurbsSurfaceArrayAttr, &status);

            MDataHandle outHandle;

            for (unsigned int j = 0; j < nSurfaceSize; j++)
            {
                // these elements can be sparse if they have been deleted
                if (outArrayHandle.elementIndex() != j)
                    continue;

                outHandle = outArrayHandle.outputValue(&status);
                outArrayHandle.next();

                MObject obj = outHandle.data();
                if (obj.hasFn(MFn::kNurbsSurface))
                {
                    readNurbs(mCurTime, mData.mNurbsList[j], obj);
                    outHandle.set(obj);
                }
            }
            outArrayHandle.setAllClean();
        }
    }
    else if (plug == mOutNurbsCurveGrpArrayAttr)
    {
        if (mOutRead[6])
        {
            // Reference the output to let EM know we are the writer
            // of the data. EM sets the output to holder and causes
            // race condition when evaluating fan-out destinations.
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status);
            const unsigned int elementCount = outArrayHandle.elementCount();
            for (unsigned int j = 0; j < elementCount; j++)
            {
                outArrayHandle.outputValue().data();
                outArrayHandle.next();
            }
            outArrayHandle.setAllClean();
            return MS::kSuccess;
        }

        mOutRead[6] = true;

        unsigned int nCurveGrpSize =
            static_cast<unsigned int>(mData.mCurvesList.size());

        if (nCurveGrpSize > 0)
        {
            MArrayDataHandle outArrayHandle =
                dataBlock.outputValue(mOutNurbsCurveGrpArrayAttr, &status);
            MDataHandle outHandle;

            std::vector<MObject> curvesObj;
            for (unsigned int i = 0; i < nCurveGrpSize; ++i)
            {
                readCurves(mCurTime, mData.mCurvesList[i],
                    mData.mNumCurves[i], curvesObj);
            }

            std::size_t numChild = curvesObj.size();

            // not the best way to do this
            // only reading bunches of curves based on the connections would be
            // more efficient when there is a bunch of broken connections
            for (unsigned int i = 0; i < numChild; i++)
            {
                if (outArrayHandle.elementIndex() != i)
                {
                    continue;
                }

                outHandle = outArrayHandle.outputValue(&status);
                outArrayHandle.next();
                status = outHandle.set(curvesObj[i]);
            }

            outArrayHandle.setAllClean();
        }
    }
    else
    {
        return MS::kUnknownParameter;
    }

    dataBlock.setClean(plug);
    return status;
}
Esempio n. 21
0
MStatus NBuddyEMPSaverNode::compute( const MPlug& plug, MDataBlock& data )
{
    MStatus status;
    if (plug == _outTrigger)
    {
	MDataHandle outputPathHdl = data.inputValue( _empOutputPath, &status );
        NM_CheckMStatus( status, "Failed to get the output path handle");
	MString outputPath = outputPathHdl.asString();

       	// Get the input time
	MDataHandle timeHdl = data.inputValue( _time, &status );
	NM_CheckMStatus( status, "Failed to get time handle");
	MTime time = timeHdl.asTime();

        // Get the frame padding
        MDataHandle framePaddingHdl = data.inputValue( _framePadding, &status );
        NM_CheckMStatus( status, "Failed to get the framePadding handle");
        int numPad = framePaddingHdl.asInt();

      // Get the frame padding
        MDataHandle timeStepHdl = data.inputValue( _timeStep, &status );
        NM_CheckMStatus( status, "Failed to get the timeStep handle");
        int timeStep = timeStepHdl.asInt();
  
        // Get the time in frames
        int frameNr = (int)floor( time.as( time.uiUnit() ) );

        //Create the writer, givin it the time index in seconds
        Nb::EmpWriter* writer = 
            new Nb::EmpWriter( 
                "",
                outputPath.asChar(),       // absolute fullpath of emp
                frameNr,                   // frame
                timeStep,                  // timestep
                numPad,                    // zero-padding                
                time.as( MTime::kSeconds ) // emp timestamp
                );

        // Then get the inputBodies
        MArrayDataHandle inBodyArrayData = data.inputArrayValue( _inBodies, &status );
        NM_CheckMStatus( status, "Failed to create get inBodyArrayData handle");

        // Loop the input in the inBody multi plug
        unsigned int numBodies = inBodyArrayData.elementCount();
        if ( numBodies > 0 )
        {
            //Jump to the first element in the array
            inBodyArrayData.jumpToArrayElement(0);

            //Loop all the body inputs and add them to the empWriter
            for ( unsigned int i(0); i < numBodies; ++i)
            {
                MDataHandle bodyDataHnd = inBodyArrayData.inputValue( &status );
                MFnPluginData dataFn(bodyDataHnd.data());

                //Get naiad body from datatype
                naiadBodyData * bodyData = (naiadBodyData*)dataFn.data( &status );
                if ( bodyData && bodyData->nBody() )
                {
                    //Add body to writer
                    try{
                        Nb::String channels("*.*");
                        writer->write(bodyData->nBody(),channels);
                    }
                    catch(std::exception& e) {
                        std::cerr << "NBuddyEMPSaverNode::compute() " << e.what() << std::endl;
                    }
                }
                else
                    std::cerr << "NBuddyEMPSaverNode::compute() :: No body in input " << inBodyArrayData.elementIndex() << std::endl;

                //Next body in the input multi
                inBodyArrayData.next();
            }
        }

        try{
            writer->close();
            // Get rid of the writer object
            delete writer;
        }
        catch(std::exception& e) {
            std::cerr << "NBuddyEMPSaverNode::compute() " << e.what() << std::endl;
        }

        //Set the output to be clean indicating that we have saved out the file
        MDataHandle outTriggerHnd = data.outputValue( _outTrigger, &status );
        outTriggerHnd.set(true);
        data.setClean( plug );
    }

    return status;
}
Esempio n. 22
0
/* virtual */
MStatus cgfxVector::compute( const MPlug& plug, MDataBlock& data )
{
	MStatus status;

	MFnData::Type dataType = MFnData::kInvalid;
 
	if( plug == sWorldVector ||
		plug == sWorldVectorX ||
		plug == sWorldVectorY ||
		plug == sWorldVectorZ ||
		plug == sWorldVectorW)
	{
		// We do isDirection first simply because if there is an
		// error, the isDirection error is more legible than the
		// vector or matrix error.
		//
		MDataHandle dhIsDirection = data.inputValue(sIsDirection, &status);
		if (!status)
		{
			status.perror("cgfxVector: isDirection handle");
			return status;
		}

		dataType = dhIsDirection.type();

		MDataHandle dhVector = data.inputValue(sVector, &status);
		if (!status)
		{
			status.perror("cgfxVector: vector handle");
			return status;
		}

		dataType = dhVector.type();

		MMatrix matrix;

		MPlug matrixPlug(thisMObject(), sMatrix);
		if (matrixPlug.isNull())
		{
			OutputDebugString("matrixPlug is NULL!\n");
		}

		// TODO: Fix this kludge.
		//
		// We should not have to do this but for some reason, 
		// using data.inputValue() fails for the sMatrix attribute.
		// Instead, we get a plug to the attribute and then get
		// the value directly.
		//
		MObject oMatrix;

		matrixPlug.getValue(oMatrix);

		MFnMatrixData fndMatrix(oMatrix, &status);
		if (!status)
		{
			status.perror("cgfxVector: matrix data");
		}

		matrix= fndMatrix.matrix(&status);
		if (!status)
		{
			status.perror("cgfxVector: get matrix");
		}

#if 0
		// TODO: This is how we are supposed to do it.  (I think).
		//
		MDataHandle dhMatrix = data.inputValue(sMatrix, &status);
		if (!status)
		{
			status.perror("cgfxVector: matrix handle");
		}

		dataType = dhMatrix.type();

		oMatrix			= dhMatrix.data();
		MFnMatrixData fnMatrix(oMatrix, &status);
		if (!status)
		{
			status.perror("cgfxVector: matrix function set");
		}

		matrix = fnMatrix.matrix();
#endif /* 0 */

		bool	 isDirection	= dhIsDirection.asBool();
		double3& vector			= dhVector.asDouble3();

		double mat[4][4];
		matrix.get(mat);

		double ix, iy, iz, iw;	// Input vector
		float  ox, oy, oz, ow;	// Output vector

		ix = vector[0];
		iy = vector[1];
		iz = vector[2];
		iw = isDirection ? 0.0 : 1.0;

		ox = (float)(mat[0][0] * ix +
					 mat[1][0] * iy +
					 mat[2][0] * iz +
					 mat[3][0] * iw);

		oy = (float)(mat[0][1] * ix +
					 mat[1][1] * iy +
					 mat[2][1] * iz +
					 mat[3][1] * iw);

		oz = (float)(mat[0][2] * ix +
					 mat[1][2] * iy +
					 mat[2][2] * iz +
					 mat[3][2] * iw);

		ow = (float)(mat[0][3] * ix +
					 mat[1][3] * iy +
					 mat[2][3] * iz +
					 mat[3][3] * iw);

		MDataHandle dhWVector = data.outputValue(sWorldVector, &status);
		if (!status)
		{
			status.perror("cgfxVector: worldVector handle");
			return status;
		}

		MDataHandle dhWVectorW = data.outputValue(sWorldVectorW, &status);
		if (!status)
		{
			status.perror("cgfxVector: worldVectorW handle");
			return status;
		}

		dhWVector.set(ox, oy, oz);
		dhWVectorW.set(ow);
		data.setClean(sWorldVector);
		data.setClean(sWorldVectorW);
	}
	else
	{
		return MS::kUnknownParameter;
	}

	return MS::kSuccess;
}
Esempio n. 23
0
MStatus sweptEmitter::compute(const MPlug& plug, MDataBlock& block)
//
//	Descriptions:
//		Call emit emit method to generate new particles.
//
{
	MStatus status;

	// Determine if we are requesting the output plug for this emitter node.
	//
	if( !(plug == mOutput) )
        return( MS::kUnknownParameter );

	// Get the logical index of the element this plug refers to,
	// because the node can be emitting particles into more 
    // than one particle shape.
	//
	int multiIndex = plug.logicalIndex( &status );
	McheckErr(status, "ERROR in plug.logicalIndex.\n");

	// Get output data arrays (position, velocity, or parentId)
	// that the particle shape is holding from the previous frame.
	//
	MArrayDataHandle hOutArray = block.outputArrayValue(mOutput, &status);
	McheckErr(status, "ERROR in hOutArray = block.outputArrayValue.\n");

	// Create a builder to aid in the array construction efficiently.
	//
	MArrayDataBuilder bOutArray = hOutArray.builder( &status );
	McheckErr(status, "ERROR in bOutArray = hOutArray.builder.\n");

	// Get the appropriate data array that is being currently evaluated.
	//
	MDataHandle hOut = bOutArray.addElement(multiIndex, &status);
	McheckErr(status, "ERROR in hOut = bOutArray.addElement.\n");

    // Get the data and apply the function set.
    //
    MFnArrayAttrsData fnOutput;
    MObject dOutput = fnOutput.create ( &status );
    McheckErr(status, "ERROR in fnOutput.create.\n");

	// Check if the particle object has reached it's maximum,
	// hence is full. If it is full then just return with zero particles.
	//
	bool beenFull = isFullValue( multiIndex, block );
	if( beenFull )
	{
		return( MS::kSuccess );
	}

	// Get deltaTime, currentTime and startTime.
	// If deltaTime <= 0.0, or currentTime <= startTime,
	// do not emit new pariticles and return.
	//
	MTime cT = currentTimeValue( block );
	MTime sT = startTimeValue( multiIndex, block );
	MTime dT = deltaTimeValue( multiIndex, block );
	if( (cT <= sT) || (dT <= 0.0) )
	{
		// We do not emit particles before the start time, 
		// and do not emit particles when moving backwards in time.
		// 

		// This code is necessary primarily the first time to 
		// establish the new data arrays allocated, and since we have 
		// already set the data array to length zero it does 
		// not generate any new particles.
		// 
		hOut.set( dOutput );
		block.setClean( plug );

		return( MS::kSuccess );
	}

	// Get speed, direction vector, and inheritFactor attributes.
	//
	double speed = speedValue( block );
	MVector dirV = directionVector( block );
	double inheritFactor = inheritFactorValue( multiIndex, block );

	// Get the position and velocity arrays to append new particle data.
	//
	MVectorArray fnOutPos = fnOutput.vectorArray("position", &status);
	MVectorArray fnOutVel = fnOutput.vectorArray("velocity", &status);

	// Convert deltaTime into seconds.
	//
	double dt = dT.as( MTime::kSeconds );
	
	// Apply rotation to the direction vector
	MVector rotatedV = useRotation ( dirV );


	// position,
	MVectorArray inPosAry;
	// velocity
	MVectorArray inVelAry;
	// emission rate
	MIntArray emitCountPP;


	// Get the swept geometry data
	//
	MObject thisObj = this->thisMObject();
	MPlug sweptPlug( thisObj, mSweptGeometry );

	if ( sweptPlug.isConnected() ) 
	{
		MDataHandle sweptHandle = block.inputValue( mSweptGeometry );
		// MObject sweptData = sweptHandle.asSweptGeometry();
		MObject sweptData = sweptHandle.data();
		MFnDynSweptGeometryData fnSweptData( sweptData );


		// Curve emission
		//
		if (fnSweptData.lineCount() > 0) {
			int numLines = fnSweptData.lineCount();
		
			for ( int i=0; i<numLines; i++ )
			{
				inPosAry.clear();
				inVelAry.clear();
				emitCountPP.clear();

				MDynSweptLine line = fnSweptData.sweptLine( i );

				// ... process current line ...
				MVector p1 = line.vertex( 0 );
				MVector p2 = line.vertex( 1 );

				inPosAry.append( p1 );
				inPosAry.append( p2 );

				inVelAry.append( MVector( 0,0,0 ) );
				inVelAry.append( MVector( 0,0,0 ) );

				// emit Rate for two points on line
				emitCountPP.clear();
				status = emitCountPerPoint( plug, block, 2, emitCountPP );

				emit( inPosAry, inVelAry, emitCountPP,
					dt, speed, inheritFactor, rotatedV, fnOutPos, fnOutVel );

			}
		}

		// Surface emission (nurb or polygon)
		//
		if (fnSweptData.triangleCount() > 0) {
			int numTriangles = fnSweptData.triangleCount();
		
			for ( int i=0; i<numTriangles; i++ )
			{
				inPosAry.clear();
				inVelAry.clear();
				emitCountPP.clear();

				MDynSweptTriangle tri = fnSweptData.sweptTriangle( i );

				// ... process current triangle ...
				MVector p1 = tri.vertex( 0 );
				MVector p2 = tri.vertex( 1 );
				MVector p3 = tri.vertex( 2 );

				MVector center = p1 + p2 + p3;
				center /= 3.0;

				inPosAry.append( center );

				inVelAry.append( MVector( 0,0,0 ) );

				// emit Rate for two points on line
				emitCountPP.clear();
				status = emitCountPerPoint( plug, block, 1, emitCountPP );

				emit( inPosAry, inVelAry, emitCountPP,
					dt, speed, inheritFactor, rotatedV, fnOutPos, fnOutVel );

			}
		}
	}

	// Update the data block with new dOutput and set plug clean.
	//
	hOut.set( dOutput );
	block.setClean( plug );

	return( MS::kSuccess );
}