Exemplo 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);
}
Exemplo n.º 2
0
void rigidBodyNode::clearContactInfo()
{
	MObject thisObject(thisMObject());

	// contactCount
	m_contactCount = 0;
	MPlug plugContactCount(thisObject, rigidBodyNode::oa_contactCount);
	plugContactCount.setValue(m_contactCount);
	
	// contactName
	MStringArray stringArray;
	stringArray.clear();
	MFnStringArrayData stringArrayData;
	MObject strArrObject = stringArrayData.create(stringArray);

	MPlug plugContactName(thisObject, rigidBodyNode::oa_contactName);

	if ( !plugContactName.isNull() )
		plugContactName.setValue(strArrObject);

	// contactPosition
	MPlug plugContactPosition(thisObject, rigidBodyNode::oa_contactPosition);
	bool isArray = plugContactPosition.isArray();
				
	MVectorArray vectorArray;
	vectorArray.clear();

	MFnVectorArrayData vectorArrayData;
	MObject arrObject = vectorArrayData.create(vectorArray);		

	if ( !plugContactPosition.isNull() )
		plugContactPosition.setValue(arrObject);
}
Exemplo n.º 3
0
bool
PxrUsdMayaWriteUtil::ReadMayaAttribute(
        const MFnDependencyNode& depNode,
        const MString& name,
        VtVec3fArray* val)
{
    MStatus status;
    depNode.attribute(name, &status);

    if (status == MS::kSuccess) {
        MPlug plug = depNode.findPlug(name);
        MObject dataObj;

        if ( (plug.getValue(dataObj) == MS::kSuccess) &&
             (dataObj.hasFn(MFn::kVectorArrayData)) ) {

            MFnVectorArrayData dData(dataObj, &status);
            if (status == MS::kSuccess) {
                MVectorArray arrayValues = dData.array();
                size_t numValues = arrayValues.length();
                val->resize(numValues);
                for (size_t i = 0; i < numValues; ++i) {
                    (*val)[i].Set(
                            arrayValues[i][0],
                            arrayValues[i][1],
                            arrayValues[i][2]);
                }
                return true;
            }
        }
    }

    return false;
}
MStatus metro_model_translator::create_shape( const m2033::mesh_ptr m )
{
	MFloatPointArray v;
	MVectorArray norm;
	MIntArray p;
	MIntArray idx;

	MFnTransform transform_fn;
	MObject transform_obj = transform_fn.create( MObject::kNullObj );
	transform_fn.setName( m->get_name().c_str() );

	m2033::mesh::vertices mv = m->get_vertices();
	m2033::mesh::indices mi = m->get_indices();
	m2033::mesh::texcoords mt = m->get_tex_coords();
	m2033::mesh::normals mn = m->get_normals();

	for( unsigned i = 0; i < mv.size(); i++ ) {
		v.append( -mv[i].x, mv[i].y, mv[i].z );
		norm.append( MVector( -mn[i].x, mn[i].y, mn[i].z ) );
	}

	for( unsigned i = 0; i < mi.size() / 3; i++ ) {
		idx.append( mi[i*3+2] );
		idx.append( mi[i*3+1] );
		idx.append( mi[i*3] );
		p.append( 3 );
	}

	MFloatArray u_values, v_values;
	for( unsigned i = 0; i < mt.size(); i++ ) {
		u_values.append( mt[i].x );
		v_values.append( -mt[i].y );
	}

	MFnMesh meshFn;
	MObject mesh = meshFn.create( v.length(), p.length(), v, p, idx, u_values, v_values, transform_obj );
	MString name = m->get_name().c_str();
	meshFn.setName( name + MString("_shape") );

	MStatus s = meshFn.assignUVs( p, idx, 0 );
	if( !s ) {
		return s;
	}

	s = meshFn.unlockVertexNormals( idx );
	if( !s ) {
		return s;
	}
	meshFn.setVertexNormals( norm, idx );

	MObject mat = create_material( m->get_texture_name(), &s );
	if( !s ) {
		return s;
	}
	MFnSet mat_fn(mat);
	mat_fn.addMember(mesh);

	return MS::kSuccess;
}
Exemplo n.º 5
0
void liqRibData::parseVectorAttributes( MFnDependencyNode & nodeFn, MStringArray & strArray, ParameterType pType )
{
  int i;
  MStatus status;
  if ( strArray.length() > 0 ) {
    for ( i = 0; i < strArray.length(); i++ ) {
      liqTokenPointer tokenPointerPair;
      MString cutString = strArray[i].substring(5, strArray[i].length());
      MPlug vPlug = nodeFn.findPlug( strArray[i] );
      MObject plugObj;
      status = vPlug.getValue( plugObj );
      if ( plugObj.apiType() == MFn::kVectorArrayData ) {
        MFnVectorArrayData  fnVectorArrayData( plugObj );
        MVectorArray vectorArrayData = fnVectorArrayData.array( &status );
        tokenPointerPair.set(   cutString.asChar(),
                                pType,
                                ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false,
                                true,
                                false,
                                vectorArrayData.length() );
        for ( int kk = 0; kk < vectorArrayData.length(); kk++ ) {
          tokenPointerPair.setTokenFloat( kk, vectorArrayData[kk].x, vectorArrayData[kk].y, vectorArrayData[kk].z );
        }

        // should it be per vertex or face-varying
        if ( ( ( type() == MRT_Mesh ) || ( type() == MRT_Subdivision ) ) && ( vectorArrayData.length() == faceVaryingCount ) ) {
          tokenPointerPair.setDetailType( rFaceVarying);
        } else {
          tokenPointerPair.setDetailType( rVertex );
        }

        // store it all
        tokenPointerArray.push_back( tokenPointerPair );

      } else {
        // Hmmmm float ? double ?
        float x, y, z;
          tokenPointerPair.set( cutString.asChar(),
                                pType,
                                ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false,
                                false,
                                false,
                                0 );
        vPlug.child(0).getValue( x );
        vPlug.child(1).getValue( y );
        vPlug.child(2).getValue( z );
        tokenPointerPair.setTokenFloat( 0, x, y, z );
        tokenPointerPair.setDetailType( rConstant );
        tokenPointerArray.push_back( tokenPointerPair );
      }
    }
  }
}
Exemplo n.º 6
0
void dynExprField::apply(
MDataBlock         &block,
int                 receptorSize,
const MDoubleArray &magnitudeArray,
const MDoubleArray &magnitudeOwnerArray,
const MVectorArray &directionArray,
const MVectorArray &directionOwnerArray,
MVectorArray       &outputForce
)
//
//      Compute output force for each particle.  If there exists the 
//      corresponding per particle attribute, use the data passed from
//      particle shape (stored in magnitudeArray and directionArray).  
//      Otherwise, use the attribute value from the field.
//
{
        // get the default values
	MVector defaultDir = direction(block);
	double  defaultMag = magnitude(block);
	int magArraySize = magnitudeArray.length();
	int dirArraySize = directionArray.length();
	int magOwnerArraySize = magnitudeOwnerArray.length();
	int dirOwnerArraySize = directionOwnerArray.length();
	int numOfOwner = magOwnerArraySize;
	if( dirOwnerArraySize > numOfOwner )
	    numOfOwner = dirOwnerArraySize;

	double  magnitude = defaultMag;
	MVector direction = defaultDir;

	for (int ptIndex = 0; ptIndex < receptorSize; ptIndex ++ ) {
	    if(receptorSize == magArraySize)
	        magnitude = magnitudeArray[ptIndex];
	    if(receptorSize == dirArraySize)
	        direction = directionArray[ptIndex];
	    if( numOfOwner > 0) {
	        for( int nthOwner = 0; nthOwner < numOfOwner; nthOwner++ ) {
		    if(magOwnerArraySize == numOfOwner)
		        magnitude = magnitudeOwnerArray[nthOwner];
		    if(dirOwnerArraySize == numOfOwner)
		        direction = directionOwnerArray[nthOwner];
		    outputForce.append( direction * magnitude );
		}
	    } else {
	        outputForce.append( direction * magnitude );
	    }
	}
}
Exemplo n.º 7
0
void rigidBodyNode::addContactInfo(const MString& contactObjectName, const MVector& point)
{
	MObject thisObject(thisMObject());

	// contactCount
	m_contactCount++;
	MPlug plugContactCount(thisObject, rigidBodyNode::oa_contactCount);
	plugContactCount.setValue(m_contactCount);
	
	// contactName
	MPlug plugContactName(thisObject, rigidBodyNode::oa_contactName);

	if ( !plugContactName.isNull() )
	{
		MObject strArrObject;
		plugContactName.getValue(strArrObject);

		MFnStringArrayData stringArrayData(strArrObject);
		MStringArray stringArray = stringArrayData.array();

		stringArray.append(contactObjectName);

		MFnStringArrayData newStringArrayData;
		MObject newStrArrObject = newStringArrayData.create(stringArray);
	
		plugContactName.setValue(newStrArrObject);
	}

	// contactPosition
	MPlug plugContactPosition(thisObject, rigidBodyNode::oa_contactPosition);

	if ( !plugContactPosition.isNull() )
	{
		MObject arrObject;
		plugContactPosition.getValue(arrObject);	

		MFnVectorArrayData vectorArrayData(arrObject);
		MVectorArray vectorArray = vectorArrayData.array();

		vectorArray.append(point);
	
		MFnVectorArrayData newVectorArrayData;
		MObject newArrObject = newVectorArrayData.create(vectorArray);	
	
		plugContactPosition.setValue(newArrObject);
	}
}
Exemplo n.º 8
0
MStatus
XmlCacheFormat::readDoubleVectorArray( MVectorArray& array, unsigned arraySize )
{
	MStringArray value;
	if( !readXmlTagValue(doubleVectorArrayTag, value) )
	{
		return MS::kFailure;
	}

	assert( value.length() == arraySize * 3 );
	array.setLength( arraySize );
	for (unsigned i = 0; i < arraySize; i++ )
	{
		double v[3];
		v[0] = strtod( value[i*3].asChar(), NULL );
		v[1] = strtod( value[i*3+1].asChar(), NULL );
		v[2] = strtod( value[i*3+2].asChar(), NULL );

		array.set( v, i );
	}
	
	return MS::kSuccess;
}
Exemplo n.º 9
0
MStatus
XmlCacheFormat::writeDoubleVectorArray( const MVectorArray& array )
{
	int size = array.length();
	assert(size != 0);

	writeXmlTagValue(sizeTag,size);

	startXmlBlock( doubleVectorArrayTag );
	for(int i = 0; i < size; i++)
	{
	    writeXmlValue(array[i][0]);
	    writeXmlValue(array[i][1]);
	    writeXmlValue(array[i][2]);
	    string endl("\n");
	    writeXmlValue(endl);
	}
	endXmlBlock();
	return MS::kSuccess;
}
Exemplo n.º 10
0
void CylinderMesh::transform(MPointArray& points, MVectorArray& normals)
{
    MVector forward = mEnd - mStart;
    double s = forward.length();
    forward.normalize();

    MVector left = MVector(0,0,1)^forward;
    MVector up;
    if (left.length() < 0.0001)
    {
        up = forward^MVector(0,1,0);
        left = up^forward;
    }
    else
    {
        up = forward^left;
    }

    MMatrix mat;
    mat[0][0] = forward[0]; mat[0][1] = left[0]; mat[0][2] = up[0]; mat[0][3] = 0;
    mat[1][0] = forward[1];   mat[1][1] = left[1]; mat[1][2] = up[1]; mat[1][3] = 0;
    mat[2][0] = forward[2];   mat[2][1] = left[2]; mat[2][2] = up[2]; mat[2][3] = 0;
    mat[3][0] = 0;            mat[3][1] = 0;       mat[3][2] = 0;     mat[3][3] = 1;
    mat = mat.transpose();

    for (int i = 0; i < gPoints.length(); i++)
    {
        MPoint p = gPoints[i];
        p.x = p.x * s; // scale
        p = p * mat + mStart; // transform
        points.append(p);

        MVector n = gNormals[i] * mat;
        normals.append(n);
    }
}
Exemplo n.º 11
0
MString CBPoseSpaceCmd::cacheResult(const MPointArray& bindPoints, const MPointArray& posePoints, const MVectorArray& dx, const MVectorArray& dy, const MVectorArray& dz)
{
    MDGModifier modif;
    MObject opose = modif.createNode("sculptSpaceRecord");
    modif.doIt();

    unsigned count = dx.length();

    MVectorArray row0Array;
    row0Array.setLength(count);
    MVectorArray row1Array;
    row1Array.setLength(count);
    MVectorArray row2Array;
    row2Array.setLength(count);
    MVectorArray row3Array;
    row3Array.setLength(count);

    MVectorArray bndArray;
    bndArray.setLength(count);

    MVectorArray posArray;
    posArray.setLength(count);

    float m[4][4];

    for(unsigned i=0; i < count; i++) {
        m[0][0] = dx[i].x;
        m[0][1] = dx[i].y;
        m[0][2] = dx[i].z;
        m[0][3] = 0.f;
        m[1][0] = dy[i].x;
        m[1][1] = dy[i].y;
        m[1][2] = dy[i].z;
        m[1][3] = 0.f;
        m[2][0] = dz[i].x;
        m[2][1] = dz[i].y;
        m[2][2] = dz[i].z;
        m[2][3] = 0.f;
        m[3][0] = 0.f;
        m[3][1] = 0.f;
        m[3][2] = 0.f;
        m[3][3] = 1.f;

        MMatrix tm(m);
        tm = tm.inverse();

        tm.get(m);

        row0Array[i].x = m[0][0];
        row0Array[i].y = m[0][1];
        row0Array[i].z = m[0][2];
        row1Array[i].x = m[1][0];
        row1Array[i].y = m[1][1];
        row1Array[i].z = m[1][2];
        row2Array[i].x = m[2][0];
        row2Array[i].y = m[2][1];
        row2Array[i].z = m[2][2];
        row3Array[i].x = m[3][0];
        row3Array[i].y = m[3][1];
        row3Array[i].z = m[3][2];

        bndArray[i] = bindPoints[i];
        posArray[i] = posePoints[i];
    }

    MFnDependencyNode fposec(opose);

    MStatus stat;
    MPlug pspacerow0 = fposec.findPlug("poseSpaceRow0", false, &stat);
    MPlug pspacerow1 = fposec.findPlug("poseSpaceRow1", false, &stat);
    MPlug pspacerow2 = fposec.findPlug("poseSpaceRow2", false, &stat);
    MPlug pspacerow3 = fposec.findPlug("poseSpaceRow3", false, &stat);
    MPlug pbind = fposec.findPlug("bpnt", false, &stat);
    MPlug ppose = fposec.findPlug("ppnt", false, &stat);

    MFnVectorArrayData frow0;
    MObject orow0 = frow0.create(row0Array);
    pspacerow0.setMObject(orow0);

    MFnVectorArrayData frow1;
    MObject orow1 = frow1.create(row1Array);
    pspacerow1.setMObject(orow1);

    MFnVectorArrayData frow2;
    MObject orow2 = frow2.create(row2Array);
    pspacerow2.setMObject(orow2);

    MFnVectorArrayData frow3;
    MObject orow3 = frow3.create(row3Array);
    pspacerow3.setMObject(orow3);

    MFnVectorArrayData fbind;
    MObject obind = fbind.create(bndArray);
    pbind.setMObject(obind);

    MFnVectorArrayData fpose;
    MObject oposed = fpose.create(posArray);
    ppose.setMObject(oposed);

    return fposec.name();
}
Exemplo n.º 12
0
void CBPoseSpaceCmd::calculateVertexPoseSpace(const MObject& poseMesh, const MObject& bindMesh)
{
    MStatus status;
    MFnMesh poseFn(poseMesh, &status);
    MPointArray originalPoseVertex;
    poseFn.getPoints ( originalPoseVertex, MSpace::kObject );

    unsigned numVert = originalPoseVertex.length();

    MFnMesh bindFn(bindMesh, &status);
    MPointArray originalbindVertex;
    bindFn.getPoints ( originalbindVertex, MSpace::kObject );

    MPointArray movedVertex(originalbindVertex);
    for(unsigned i=0; i < numVert; i++)
    {
        movedVertex[i].x =  originalbindVertex[i].x + 1.0;
    }

    bindFn.setPoints(movedVertex, MSpace::kObject );
    bindFn.updateSurface();
    poseFn.updateSurface();

    MPointArray xPoseVertex;
    poseFn.getPoints ( xPoseVertex, MSpace::kObject );

    MVectorArray dirx;
    dirx.setLength(numVert);

    for(unsigned i=0; i < numVert; i++) {
        dirx[i] = xPoseVertex[i] - originalPoseVertex[i];
    }

    for(unsigned i=0; i < numVert; i++) {
        movedVertex[i].x =  originalbindVertex[i].x;
        movedVertex[i].y =  originalbindVertex[i].y + 1.0;
    }

    bindFn.setPoints(movedVertex, MSpace::kObject );
    bindFn.updateSurface();
    poseFn.updateSurface();

    poseFn.getPoints ( xPoseVertex, MSpace::kObject );

    MVectorArray diry;
    diry.setLength(numVert);

    for(unsigned i=0; i < numVert; i++) {
        diry[i] = xPoseVertex[i] - originalPoseVertex[i];
    }

    for(unsigned i=0; i < numVert; i++) {
        movedVertex[i].y =  originalbindVertex[i].y;
        movedVertex[i].z =  originalbindVertex[i].z + 1.0;
    }

    bindFn.setPoints(movedVertex, MSpace::kObject );
    bindFn.updateSurface();
    poseFn.updateSurface();

    poseFn.getPoints ( xPoseVertex, MSpace::kObject );

    MVectorArray dirz;
    dirz.setLength(numVert);

    for(unsigned i=0; i < numVert; i++) {
        dirz[i] = xPoseVertex[i] - originalPoseVertex[i];
    }

    bindFn.setPoints(originalbindVertex, MSpace::kObject );
    bindFn.updateSurface();

    const MString cacheNodeName = cacheResult(originalbindVertex, originalPoseVertex, dirx, diry, dirz);

    MGlobal::displayInfo(MString("correct shape recordes ") + numVert + " points in " + cacheNodeName);

    setResult(cacheNodeName);
}
Exemplo n.º 13
0
MString CBPoseSpaceCmd::saveResult(const MPointArray& bindPoints, const MPointArray& posePoints, const MVectorArray& dx, const MVectorArray& dy, const MVectorArray& dz)
{
    unsigned count = dx.length();
    float* data = new float[count * (3 + 3 + 16)];

    for(unsigned i=0; i < count; i++)
    {
        data[i*3] = bindPoints[i].x;
        data[i*3+1] = bindPoints[i].y;
        data[i*3+2] = bindPoints[i].z;
    }

    unsigned offset = count * 3;

    for(unsigned i=0; i < count; i++)
    {
        data[offset+i*3] = posePoints[i].x;
        data[offset+i*3+1] = posePoints[i].y;
        data[offset+i*3+2] = posePoints[i].z;
    }

    offset = count * 6;

    for(unsigned i=0; i < count; i++)
    {
        float m[4][4];

        m[0][0] = dx[i].x;
        m[0][1] = dx[i].y;
        m[0][2] = dx[i].z;
        m[0][3] = 0.f;
        m[1][0] = dy[i].x;
        m[1][1] = dy[i].y;
        m[1][2] = dy[i].z;
        m[1][3] = 0.f;
        m[2][0] = dz[i].x;
        m[2][1] = dz[i].y;
        m[2][2] = dz[i].z;
        m[2][3] = 0.f;
        m[3][0] = 0.f;
        m[3][1] = 0.f;
        m[3][2] = 0.f;
        m[3][3] = 1.f;

        MMatrix tm(m);
        tm = tm.inverse();

        tm.get(m);

        unsigned ivx = offset+i*16;

        data[ivx]    = m[0][0];
        data[ivx+1]  = m[0][1];
        data[ivx+2]  = m[0][2];
        data[ivx+3]  = m[0][3];
        data[ivx+4]  = m[1][0];
        data[ivx+5]  = m[1][1];
        data[ivx+6]  = m[1][2];
        data[ivx+7]  = m[1][3];
        data[ivx+8]  = m[2][0];
        data[ivx+9]  = m[2][1];
        data[ivx+10] = m[2][2];
        data[ivx+11] = m[2][3];
        data[ivx+12] = m[3][0];
        data[ivx+13] = m[3][1];
        data[ivx+14] = m[3][2];
        data[ivx+15] = m[3][3];
    }

    io::filtering_ostream out;
    out.push(boost::iostreams::gzip_compressor());

    MString filename = _cacheName;

    if(filename == "") {

        MString projRoot;
        MGlobal::executeCommand(MString("workspace -q -dir"), projRoot, 0, 0);

        projRoot = projRoot + "/poses/";
        if(!exists( projRoot.asChar() )) {
            create_directory(projRoot.asChar());
        }

        const ptime now = second_clock::local_time();
        std::string file_time = to_iso_string(now);

        filename = projRoot+file_time.c_str()+".pos";
    }

    out.push(io::file_sink(filename.asChar(), ios::binary));

    out.write((char*)data, count*(3 + 3 + 16)*4);
    out.flush();

    delete[] data;

    MGlobal::displayInfo(MString("corrective blendshape writes pose cache to ") + filename);
    return filename;
}
Exemplo n.º 14
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 );		
				}
			}
		}
	}
}
Exemplo n.º 15
0
void sweptEmitter::emit
	(
		const MVectorArray &inPosAry,	// points where new particles from
		const MVectorArray &inVelAry,	// initial velocity of new particles
		const MIntArray &emitCountPP,	// # of new particles per point
		double dt,						// elapsed time
		double speed,					// speed factor
		double inheritFactor,			// for inherit velocity
		MVector dirV,					// emit direction
		MVectorArray &outPosAry,		// holding new particles position
		MVectorArray &outVelAry			// holding new particles velocity
	)
//
//	Descriptions:
//
{
	// check the length of input arrays.
	//
	int posLength = inPosAry.length();
	int velLength = inVelAry.length();
	int countLength = emitCountPP.length();
	if( (posLength != velLength) || (posLength != countLength) )
		return;

	// Compute total emit count.
	//
	int index;
	int totalCount = 0;
	for( index = 0; index < countLength; index ++ )
		totalCount += emitCountPP[index];

	if( totalCount <= 0 )
		return;

	// Map direction vector into world space and normalize it.
	//
	dirV.normalize();

	// Start emission.
	//
	int emitCount;
	MVector newPos, newVel;
	MVector prePos, sPos, sVel;
	for( index = 0; index < posLength; index++ )
	{
		emitCount = emitCountPP[index];
		if( emitCount <= 0 )
			continue;

		sPos = inPosAry[index];
		sVel = inVelAry[index];
		prePos = sPos - sVel * dt;

		for( int i = 0; i < emitCount; i++ )
		{
			double alpha = ( (double)i + drand48() ) / (double)emitCount;
			newPos = (1 - alpha) * prePos + alpha * sPos;
			newVel = dirV * speed;

			newPos += newVel * ( dt * (1 - alpha) );
			newVel += sVel * inheritFactor;

			// Add new data into output arrays.
			//
			outPosAry.append( newPos );
			outVelAry.append( newVel );
		}
	}

}
Exemplo n.º 16
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 );
}
Exemplo n.º 17
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;
						}
					}
				}
			}
		}
	}
}
Exemplo n.º 18
0
MStatus particlePathsCmd::doIt( const MArgList& args )
{
	MStatus stat = parseArgs( args );
	if( stat != MS::kSuccess ) 
	{
		return stat;
	}

	MFnParticleSystem cloud( particleNode );

	if( ! cloud.isValid() )
	{
		MGlobal::displayError( "The function set is invalid!" );
		return MS::kFailure;
	}

	//
	// Create curves from the particle system in two stages.  First, sample 
	// all particle positions from the start time to the end time.  Then,
	// use the data that was collected to create curves.
	//

	// Create the particle hash table at a fixed size.  This should work fine
	// for small particle systems, but may become inefficient for larger ones.
	// If the plugin is running very slow, increase the size.  The value should
	// be roughly the number of particles that are expected to be emitted
	// within the time period.
	//
	ParticleIdHash hash(1024);
	MIntArray idList;

	//
	// Stage 1
	//

	MVectorArray positions;
	MIntArray ids;
	int i = 0;
	for (double time = start; time <= finish + TOLERANCE; time += increment)
	{
		MTime timeSeconds(time,MTime::kSeconds);

		// It is necessary to query the worldPosition attribute to force the 
		// particle positions to update.
		//
		cloud.evaluateDynamics(timeSeconds,false);
//		MGlobal::executeCommand(MString("getAttr ") + cloud.name() + 
//			MString(".worldPosition"));

		if (!cloud.isValid())
		{
			MGlobal::displayError( "Particle system has become invalid." );
			return MS::kFailure;
		}

		MGlobal::displayInfo( MString("Received ") + (int)(cloud.count()) + 
			" particles, at time " + time);

		// Request position and ID data for particles
		//
		cloud.position( positions );
		cloud.particleIds( ids );

		if (ids.length() != cloud.count() || positions.length() != cloud.count())
		{
			MGlobal::displayError( "Invalid array sizes." );
			return MS::kFailure;
		}

		for (int j = 0; j < (int)cloud.count(); j++)
		{
			// Uncomment to show particle positions as the plugin accumulates
			// samples.
			/*
			MGlobal::displayInfo(MString("(") + (positions[j])[0] + MString(",") + 
				(positions[j])[1] + MString(",") + (positions[j])[2] + MString(")"));
			*/

			MPoint pt(positions[j]);
			if (hash.getPoints(ids[j]).length() == 0)
			{
				idList.append(ids[j]);
			}
			hash.insert(ids[j],pt);
		}

		i++;
	}
	
	//
	// Stage 2
	//

	for (i = 0; i < (int)(idList.length()); i++)
	{
		MPointArray points = hash.getPoints(idList[i]);

		// Don't bother with single samples
		if (points.length() <= 1)
		{
			continue;
		}

		// Add two additional points, so that the curve covers all sampled
		// values.
		//
		MPoint p1 = points[0]*2 - points[1];
		MPoint p2 = points[points.length()-1]*2 - points[points.length()-2];
		points.insert(p1,0);
		points.append(p2);

		// Uncomment to show information about the generated curves
		/*
		MGlobal::displayInfo( MString("ID ") + (int)(idList[i]) + " has " + (int)(points.length()) + " curve points.");
		for (int j = 0; j < (int)(points.length()); j++)
		{
			MGlobal::displayInfo(MString("(") + points[j][0] + MString(",") + points[j][1] + MString(",") + points[j][2] + MString(")"));
		}
		*/

		MDoubleArray knots;
		knots.insert(0.0,0);
		for (int j = 0; j < (int)(points.length()); j++)
		{
			knots.append((double)j);
		}
		knots.append(points.length()-1);

		MStatus status;
		MObject dummy;
		MFnNurbsCurve curve;
		curve.create(points,knots,3,MFnNurbsCurve::kOpen,false,false,dummy,&status);
		if (!status)
		{
			MGlobal::displayError("Failed to create nurbs curve.");
			return MS::kFailure;
		}
	}

	return MS::kSuccess;
}
Exemplo n.º 19
0
bool SargassoNode::creatRestShape(const MObject & m)
{
    MStatus stat;
    MFnMesh fmesh(m, &stat);
    if(!stat) {
        MGlobal::displayInfo("val is not mesh");
        return false;
    }
    MObject thisObj = thisMObject();
    MPlug pnv(thisObj, atargetNv);
    const int restNv = pnv.asInt();
    
    if(restNv != fmesh.numVertices()) {
        MGlobal::displayInfo("target nv not match");
        return false;
    }
    
    MPlug pntriv(thisObj, atargetNt);
    const int restNtriv = pntriv.asInt();
    
    MIntArray triangleCounts, triangleVertices;
	fmesh.getTriangles(triangleCounts, triangleVertices);
	
    if(restNtriv != triangleVertices.length()) {
        MGlobal::displayInfo("target ntri not match");
        return false;
    }
    
    m_mesh->create(restNv, restNtriv/3);
    
    MPlug prestp(thisObj, atargetRestP);
    MObject orestp;
    prestp.getValue(orestp);
    MFnPointArrayData frestp(orestp);
    MPointArray restPArray = frestp.array();	
    
    if(restPArray.length() != restNv) {
        MGlobal::displayInfo("cached target nv not match");
        return false;
    }
    
    Vector3F * p = m_mesh->points();
    unsigned i=0;
    for(;i<restNv;i++) p[i].set(restPArray[i].x, restPArray[i].y, restPArray[i].z);
    
    MPlug presttri(thisObj, atargetTri);
    MObject oresttri;
    presttri.getValue(oresttri);
    MFnIntArrayData fresttri(oresttri);
    MIntArray restTriArray = fresttri.array();	
    
    if(restTriArray.length() != restNtriv) {
        MGlobal::displayInfo("cached target ntri not match");
        return false;
    }
    
    unsigned * ind = m_mesh->indices();
    for(i=0;i<restNtriv;i++) ind[i] = restTriArray[i];
    
    const BoundingBox box = ((AGenericMesh *)m_mesh)->calculateBBox();
    AHelper::Info<BoundingBox>("target mesh box", box);
    
    m_diff = new TriangleDifference(m_mesh);
    
    MPlug ptargetbind(thisObj, atargetBind);
    MObject otargetbind;
    ptargetbind.getValue(otargetbind);
    MFnIntArrayData ftargetbind(otargetbind);
    MIntArray targetBindArray = ftargetbind.array();
    const unsigned nbind = targetBindArray.length();
    AHelper::Info<unsigned>("n binded triangles", nbind);
    
    std::vector<unsigned> vbind;
    for(i=0;i<nbind;i++) vbind.push_back(targetBindArray[i]);
    m_diff->requireQ(vbind);
    vbind.clear();
    
    MPlug pobjLocal(thisObj, aobjLocal);
    MObject oobjLocal;
    pobjLocal.getValue(oobjLocal);
    MFnVectorArrayData fobjLocal(oobjLocal);
    MVectorArray localPArray = fobjLocal.array();
    m_numObjects = localPArray.length();
    AHelper::Info<unsigned>("n constrained objects", m_numObjects);
    
    m_localP->create(m_numObjects * 12);
    
    Vector3F * lp = localP();
    for(i=0;i<m_numObjects;i++) lp[i].set(localPArray[i].x, localPArray[i].y, localPArray[i].z);
    
    m_triId->create(m_numObjects * 4);
    
    MPlug pobjtri(thisObj, aobjTri);
    MObject oobjtri;
    pobjtri.getValue(oobjtri);
    MFnIntArrayData fobjtri(oobjtri);
    MIntArray objtriArray = fobjtri.array();
    
    unsigned * tri = objectTriangleInd();
    for(i=0;i<m_numObjects;i++) tri[i] = objtriArray[i];
        
    return true;
}
Exemplo n.º 20
0
MStatus PTCMapCmd::doIt( const MArgList& args)
{
    MStatus status = parseArgs( args );

    if( status != MS::kSuccess ) return status;

    MArgDatabase argData(syntax(), args);

    MAnimControl timeControl;
    MTime time = timeControl.currentTime();
    int frame =int(time.value());
    MString proj;
    MGlobal::executeCommand( MString ("string $p = `workspace -q -fn`"), proj );

    MString cache_path = proj + "/data";
    MString cache_name = "foo";
    MString cache_attrib;
    double cache_mindist = 0.1;
    int max_level = 3;
    double root_size = 32;
    MString dem_trans = "nil";
    double cloud_os = 0.05;
    MString key_trans = "nil";
    MString eye_trans = "nil";

    if (argData.isFlagSet("-p")) argData.getFlagArgument("-p", 0, cache_path);
    if (argData.isFlagSet("-n")) argData.getFlagArgument("-n", 0, cache_name);
    if (argData.isFlagSet("-a")) argData.getFlagArgument("-a", 0, cache_attrib);
    if (argData.isFlagSet("-mnd")) argData.getFlagArgument("-mnd", 0, cache_mindist);
    if (argData.isFlagSet("-ml")) argData.getFlagArgument("-ml", 0, max_level);
    if (argData.isFlagSet("-rs")) argData.getFlagArgument("-rs", 0, root_size);
    if (argData.isFlagSet("-t")) argData.getFlagArgument("-t", 0, dem_trans);
    if(argData.isFlagSet("-o")) argData.getFlagArgument("-o", 0, cloud_os);
    if(argData.isFlagSet("-tk")) argData.getFlagArgument("-tk", 0, key_trans);
    if(argData.isFlagSet("-te")) argData.getFlagArgument("-te", 0, eye_trans);

    float def_area = root_size;
    int last = 0;
    while(last < max_level-2) {
        def_area /= 2;
        last++;
    }

    def_area = 1.0f;

    //def_area *= def_area;

// get bounding box center
    MDagPath p_bbox;

    zWorks::getTypedPathByName(MFn::kTransform, dem_trans, p_bbox);
    MObject o_bbox = p_bbox.transform();

    float m_space[4][4];
    m_space[0][0]=1;
    m_space[0][1]=0;
    m_space[0][2]=0;
    m_space[1][0]=0;
    m_space[1][1]=1;
    m_space[1][2]=0;
    m_space[2][0]=0;
    m_space[2][1]=0;
    m_space[2][2]=1;
    m_space[3][0]=0;
    m_space[3][1]=0;
    m_space[3][2]=0;

    if(o_bbox.isNull()) MGlobal::displayWarning("Cannot find pmap dimension, use default space.");
    else zWorks::getTransformWorldNoScale(p_bbox.partialPathName(), m_space);

    XYZ root_center(m_space[3][0], m_space[3][1], m_space[3][2]);

// get key light dir
    MDagPath p_key;

    zWorks::getTypedPathByName(MFn::kTransform, key_trans, p_key);
    MObject o_key = p_key.transform();

    m_space[0][0]=1;
    m_space[0][1]=0;
    m_space[0][2]=0;
    m_space[1][0]=0;
    m_space[1][1]=1;
    m_space[1][2]=0;
    m_space[2][0]=0;
    m_space[2][1]=0;
    m_space[2][2]=1;
    m_space[3][0]=0;
    m_space[3][1]=0;
    m_space[3][2]=0;

    if(o_key.isNull()) MGlobal::displayWarning("Cannot find key camera, use default space.");
    else zWorks::getTransformWorldNoScale(p_key.partialPathName(), m_space);

    XYZ key_dir(m_space[2][0], m_space[2][1], m_space[2][2]);
    key_dir.normalize();

// get view dir
    MDagPath p_eye;

    zWorks::getTypedPathByName(MFn::kTransform, eye_trans, p_eye);
    MObject o_eye = p_eye.transform();

    m_space[0][0]=1;
    m_space[0][1]=0;
    m_space[0][2]=0;
    m_space[1][0]=0;
    m_space[1][1]=1;
    m_space[1][2]=0;
    m_space[2][0]=0;
    m_space[2][1]=0;
    m_space[2][2]=1;
    m_space[3][0]=0;
    m_space[3][1]=0;
    m_space[3][2]=0;

    if(o_eye.isNull()) MGlobal::displayWarning("Cannot find render camera, use default space.");
    else zWorks::getTransformWorldNoScale(p_eye.partialPathName(), m_space);

    XYZ view_dir(-m_space[2][0], -m_space[2][1], -m_space[2][2]);
    view_dir.normalize();

// additional attribs
    MStringArray attribArray;
    cache_attrib.split('.', attribArray);

    MSelectionList slist;
    MGlobal::getActiveSelectionList( slist );
    MItSelectionList list( slist, MFn::kParticle, &status );
    if (MS::kSuccess != status) {
        displayError( "Could not create selection list iterator");
        return status;
    }

    if (list.isDone()) {
        displayError( "No particles selected" );
        return MS::kSuccess;
    }

    MDagPath fDagPath;
    MObject component;
    unsigned npt = 0,acc = 0;
    for(; !list.isDone(); list.next()) {
        list.getDagPath (fDagPath, component);
        MFnParticleSystem ps( fDagPath );
        npt += ps.count();
    }

    if(npt < 1) {
        MGlobal::displayInfo(" zero particle: do nothing ");
        return MS::kSuccess;
    }

    std::list<AParticle *> particles;

    RGRID *buf = new RGRID[npt];
    unsigned *idxb = new unsigned[npt];
    float *opab = new float[npt];
    float *ageb = new float[npt];

    list.reset();
    for(; !list.isDone(); list.next()) {
        list.getDagPath (fDagPath, component);
        MFnParticleSystem ps( fDagPath );

        MVectorArray positions;
        ps.position( positions );

        MVectorArray velarr;
        ps.velocity( velarr );

        MIntArray ids;
        ps.particleIds(ids);

        MVectorArray cols;
        ps.rgb(cols);

        MDoubleArray opas;
        ps.opacity(opas);

        MDoubleArray ages;
        ps.opacity(ages);

        for(unsigned i=0; i<positions.length(); i++,acc++ ) {
            buf[acc].pos.x = positions[i].x;
            buf[acc].pos.y = positions[i].y;
            buf[acc].pos.z = positions[i].z;
            buf[acc].nor.x = velarr[i].x;
            buf[acc].nor.y = velarr[i].y;
            buf[acc].nor.z = velarr[i].z;
            buf[acc].area = def_area;

            if(ps.hasRgb()) {
                buf[acc].col.x = cols[i].x;
                buf[acc].col.y = cols[i].y;
                buf[acc].col.z = cols[i].z;
            }
            else buf[acc].col = XYZ(1,1,1);

            idxb[acc] = ids[i];

            if(ps.hasOpacity ()) opab[acc] = opas[i];
            else opab[acc] = 1.f;

            ageb[acc] = ages[i];

            AParticle *pt = new AParticle();
            pt->pos.x = positions[i].x;
            pt->pos.y = positions[i].y;
            pt->pos.z = positions[i].z;
            pt->r = def_area;

            particles.push_back(pt);
        }
    }
    /*
    	Z3DTexture* tree = new Z3DTexture();
    	tree->setGrid(buf, npt);
    	tree->constructTree(root_center, root_size, max_level);
    	tree->setGridIdData(idxb, npt);
    	tree->setGridOpacityData(opab, npt);
    	tree->setGridAgeData(ageb, npt);
    	MGlobal::displayInfo(MString(" num grid ")+ tree->getNumGrid());
    	MGlobal::displayInfo(MString(" num voxel ")+ tree->getNumVoxel());
    	MGlobal::displayInfo(MString(" num leaf ")+ tree->getNumLeaf());
    	MGlobal::displayInfo(MString(" max level ")+ tree->getMaxLevel());
    	MGlobal::displayInfo(" calculating voxel volume occlusion...");
    	tree->occlusionVolume(cloud_os, key_dir, view_dir);
    	MGlobal::displayInfo(" done");
    	MGlobal::displayInfo(" updating grid distance to neighbour...");
    	tree->distanceToNeighbour(cache_mindist);
    	MGlobal::displayInfo(" done");

    	char filename[512];
    	sprintf( filename, "%s/%s.%d.pmap", cache_path.asChar(), cache_name.asChar(), frame );
    	MGlobal::displayInfo(MString("PTCMap saved ") + filename);
    	tree->save(filename);

    	delete tree;
    	*/
    if(!particles.empty()) {
        GPUOctree *data = new GPUOctree();
        data->create(root_center, root_size, 8, particles);
        MGlobal::displayInfo(MString(" num voxel ")+ data->getNumVoxel()+ MString(" minvar ")+ data->getMinVariation()+ MString(" max level ")+ data->getMaxLevel()+ MString(" filter size ")+ def_area);

        char filename[512];
        sprintf( filename, "%s/%s.%d", cache_path.asChar(), cache_name.asChar(), frame );

        data->dumpIndirection(filename);

        delete data;
        particles.clear();
    }

    return MS::kSuccess;
}
Exemplo n.º 21
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 );
}
Exemplo n.º 22
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;
}
Exemplo n.º 23
0
void apiSimpleShapeUI::drawVertices( const MDrawRequest & request,
							  M3dView & view ) const
//
// Description:
//
//     Component (vertex) drawing routine
//
// Arguments:
//
//     request - request to be drawn
//     view    - view to draw into
//
{
	MDrawData data = request.drawData();
	MVectorArray * geom = (MVectorArray*)data.geometry();

	view.beginGL(); 

	// Query current state so it can be restored
	//
	bool lightingWasOn = glIsEnabled( GL_LIGHTING ) ? true : false;
	if ( lightingWasOn ) {
		glDisable( GL_LIGHTING );
	}
	float lastPointSize;
	glGetFloatv( GL_POINT_SIZE, &lastPointSize );

	// Set the point size of the vertices
	//
	glPointSize( POINT_SIZE );

	// If there is a component specified by the draw request
	// then loop over comp (using an MFnComponent class) and draw the
	// active vertices, otherwise draw all vertices.
	//
	MObject comp = request.component();
	if ( ! comp.isNull() ) {
		MFnSingleIndexedComponent fnComponent( comp );
		for ( int i=0; i<fnComponent.elementCount(); i++ )
		{
			int index = fnComponent.element( i );
			glBegin( GL_POINTS );
			MVector& point = (*geom)[index];
			glVertex3f( (float)point[0], 
						(float)point[1], 
						(float)point[2] );
			glEnd();

			char annotation[32];
			sprintf( annotation, "%d", index );
			view.drawText( annotation, point );
		}
	}
	else {
		for ( unsigned int i=0; i<geom->length(); i++ )
		{
			glBegin( GL_POINTS );
			MVector point = (*geom)[ i ];
			glVertex3f( (float)point[0], (float)point[1], (float)point[2] );
			glEnd();
		}
	}

	// Restore the state
	//
	if ( lightingWasOn ) {
		glEnable( GL_LIGHTING );
	}
	glPointSize( lastPointSize );

	view.endGL(); 
}
Exemplo n.º 24
0
//
// Main routine
///////////////////////////////////////////////////////////////////////////////
MStatus particleSystemInfoCmd::doIt( const MArgList& args )
{
	MStatus stat = parseArgs( args );
	if( stat != MS::kSuccess ) return stat;

	if( particleNode.isNull() ) {
	        MObject parent;
		MFnParticleSystem dummy;
		particleNode = dummy.create(&stat);
		CHECKRESULT(stat,"MFnParticleSystem::create(status) failed!");

		MFnParticleSystem ps( particleNode, &stat );
		CHECKRESULT(stat,"MFnParticleSystem::MFnParticleSystem(MObject,status) failed!");

		MPointArray posArray;
		posArray.append(MPoint(-5,  5, 0));
		posArray.append(MPoint(-5, 10, 0));

		MVectorArray velArray;
		velArray.append(MPoint(1, 1, 0));
		velArray.append(MPoint(1, 1, 0));
		stat = ps.emit(posArray, velArray);
		CHECKRESULT(stat,"MFnParticleSystem::emit(posArray,velArray) failed!");

		stat = ps.emit(MPoint(5,  5, 0));
		CHECKRESULT(stat,"MFnParticleSystem::emit(pos) failed!");
		stat = ps.emit(MPoint(5, 10, 0));
		CHECKRESULT(stat,"MFnParticleSystem::emit(pos) failed!");

		stat = ps.saveInitialState();
		CHECKRESULT(stat,"MFnParticleSystem::saveInitialState() failed!");

		MVectorArray accArray;
		accArray.setLength(4);
		for( unsigned int i=0; i<accArray.length(); i++ )
		{
		        MVector& acc = accArray[i];
			acc.x = acc.y = acc.z = 3.0;
		}
		MString accName("acceleration");
		ps.setPerParticleAttribute( accName, accArray, &stat );
		CHECKRESULT(stat,"MFnParticleSystem::setPerParticleAttribute(vectorArray) failed!");
	} 

	MFnParticleSystem ps( particleNode, &stat );
	CHECKRESULT(stat,"MFnParticleSystem::MFnParticleSystem(MObject,status) failed!");

	if( ! ps.isValid() )
	{
		MGlobal::displayError( "The function set is invalid!" );
		return MS::kFailure;
	}

	const MString name = ps.particleName();
	const MFnParticleSystem::RenderType psType = ps.renderType();
	const unsigned int count = ps.count();

	const char* typeString = NULL;
	switch( psType )
	{
	case MFnParticleSystem::kCloud:
		typeString = "Cloud";
		break;
	case MFnParticleSystem::kTube:
		typeString = "Tube system";
		break;
	case MFnParticleSystem::kBlobby:
		typeString = "Blobby";
		break;
	case MFnParticleSystem::kMultiPoint:
		typeString = "MultiPoint";
		break;
	case MFnParticleSystem::kMultiStreak:
		typeString = "MultiStreak";
		break;
	case MFnParticleSystem::kNumeric:
		typeString = "Numeric";
		break;
	case MFnParticleSystem::kPoints:
		typeString = "Points";
		break;
	case MFnParticleSystem::kSpheres:
		typeString = "Spheres";
		break;
	case MFnParticleSystem::kSprites:
		typeString = "Sprites";
		break;
	case MFnParticleSystem::kStreak:
		typeString = "Streak";
		break;
	default:
		typeString = "Particle system";
		assert( false );
		break;
	}

	char buffer[256];

	sprintf( buffer, "%s \"%s\" has %u primitives.", typeString, name.asChar(), count );
	MGlobal::displayInfo( buffer );

	unsigned i;

	MIntArray ids;
	ps.particleIds( ids );

	sprintf( buffer, "count : %u ", count );
	MGlobal::displayInfo( buffer );
	sprintf( buffer, "%u ids.", ids.length() );
	MGlobal::displayInfo( buffer );

	assert( ids.length() == count );
	for( i=0; i<ids.length(); i++ )
	{
		sprintf( buffer, "id %d  ", ids[i] );
		MGlobal::displayInfo( buffer );
	}

	MVectorArray positions;
	ps.position( positions );
	assert( positions.length() == count );
	for( i=0; i<positions.length(); i++ )
	{
		MVector& p = positions[i];
		sprintf( buffer, "pos %f %f %f  ", p[0], p[1], p[2] );
		MGlobal::displayInfo( buffer );
	}

	MVectorArray vels;
	ps.velocity( vels );
	assert( vels.length() == count );
	for( i=0; i<vels.length(); i++ )
	{
		const MVector& v = vels[i];
		sprintf( buffer, "vel %f %f %f  ", v[0], v[1], v[2] );
		MGlobal::displayInfo( buffer );
	}

	MVectorArray accs;
	ps.acceleration( accs );
	assert( accs.length() == count );
	for( i=0; i<accs.length(); i++ )
	{
		const MVector& a = accs[i];
		sprintf( buffer, "acc %f %f %f  ", a[0], a[1], a[2] );
		MGlobal::displayInfo( buffer );
	}

	bool flag = ps.isDeformedParticleShape(&stat);
	CHECKRESULT(stat,"MFnParticleSystem::isDeformedParticleShape() failed!");
	if( flag ) {
	        MObject obj = ps.originalParticleShape(&stat);
		CHECKRESULT(stat,"MFnParticleSystem::originalParticleShape() failed!");
		if( obj != MObject::kNullObj ) {
		        MFnParticleSystem ps( obj );
			sprintf( buffer, "original particle shape : %s ", ps.particleName().asChar() );
			MGlobal::displayInfo( buffer );
		}
	}

	flag = ps.isDeformedParticleShape(&stat);
	CHECKRESULT(stat,"MFnParticleSystem::isDeformedParticleShape() failed!");
	if( !flag ) {
	        MObject obj = ps.deformedParticleShape(&stat);
		CHECKRESULT(stat,"MFnParticleSystem::deformedParticleShape() failed!");
		if( obj != MObject::kNullObj ) {
		        MFnParticleSystem ps( obj );
			sprintf( buffer, "deformed particle shape : %s ", ps.particleName().asChar() );
			MGlobal::displayInfo( buffer );
		}
	}

	if( ids.length() == positions.length() &&
	    ids.length() == vels.length()      &&
	    ids.length() == accs.length()       ) { 
	        setResult( int(ids.length()) );
	} else {
	        setResult( int(-1) );
	}

	return MS::kSuccess;
}
Exemplo n.º 25
0
bool ToMayaMeshConverter::doConversion( IECore::ConstObjectPtr from, MObject &to, IECore::ConstCompoundObjectPtr operands ) const
{
	MStatus s;

	IECore::ConstMeshPrimitivePtr mesh = IECore::runTimeCast<const IECore::MeshPrimitive>( from );
	assert( mesh );

	if ( !mesh->arePrimitiveVariablesValid() )
	{
		return false;
	}

	MFloatPointArray vertexArray;
	MIntArray polygonCounts;
	MIntArray polygonConnects;

	MFnMesh fnMesh;

	int numVertices = 0;
	IECore::PrimitiveVariableMap::const_iterator it = mesh->variables.find("P");
	if ( it != mesh->variables.end() )
	{
		/// \todo Employ some M*Array converters to simplify this
		IECore::ConstV3fVectorDataPtr p = IECore::runTimeCast<const IECore::V3fVectorData>(it->second.data);
		if (p)
		{
			numVertices = p->readable().size();

			vertexArray.setLength( numVertices );
			for (int i = 0; i < numVertices; i++)
			{
				vertexArray[i] = IECore::convert<MFloatPoint, Imath::V3f>( p->readable()[i] );
			}
		}
		else
		{
			IECore::ConstV3dVectorDataPtr p = IECore::runTimeCast<const IECore::V3dVectorData>(it->second.data);
			if (p)
			{
				numVertices = p->readable().size();

				vertexArray.setLength( numVertices );
				for (int i = 0; i < numVertices; i++)
				{
					vertexArray[i] = IECore::convert<MFloatPoint, Imath::V3d>( p->readable()[i] );
				}
			}
			else
			{
				// "P" is not convertible to an array of "points"
				return false;
			}
		}
	}


	IECore::ConstIntVectorDataPtr verticesPerFace = mesh->verticesPerFace();
	assert( verticesPerFace );
	int numPolygons = verticesPerFace->readable().size();

	polygonCounts.setLength( numPolygons );
	for (int i = 0; i < numPolygons; i++)
	{
		polygonCounts[i] = verticesPerFace->readable()[i];
	}

	IECore::ConstIntVectorDataPtr vertexIds = mesh->vertexIds();
	assert( vertexIds );
	int numPolygonConnects = vertexIds->readable().size();
	polygonConnects.setLength( numPolygonConnects );
	for (int i = 0; i < numPolygonConnects; i++)
	{
		polygonConnects[i] = vertexIds->readable()[i];
	}

	MObject mObj = fnMesh.create( numVertices, numPolygons, vertexArray, polygonCounts, polygonConnects, to, &s );

	if (!s)
	{
		return false;
	}

	it = mesh->variables.find("N");
	if ( it != mesh->variables.end() )
	{
		if (it->second.interpolation == IECore::PrimitiveVariable::FaceVarying )
		{
			/// \todo Employ some M*Array converters to simplify this
			MVectorArray vertexNormalsArray;
			IECore::ConstV3fVectorDataPtr n = IECore::runTimeCast<const IECore::V3fVectorData>(it->second.data);
			if (n)
			{
				int numVertexNormals = n->readable().size();

				vertexNormalsArray.setLength( numVertexNormals );
				for (int i = 0; i < numVertexNormals; i++)
				{
					vertexNormalsArray[i] = IECore::convert<MVector, Imath::V3f>( n->readable()[i] );
				}
			}
			else
			{
				IECore::ConstV3dVectorDataPtr n = IECore::runTimeCast<const IECore::V3dVectorData>(it->second.data);
				if (n)
				{
					int numVertexNormals = n->readable().size();

					vertexNormalsArray.setLength( numVertexNormals );
					for (int i = 0; i < numVertexNormals; i++)
					{
						vertexNormalsArray[i] = IECore::convert<MVector, Imath::V3d>( n->readable()[i] );
					}
				}
				else
				{
					IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"N\" has unsupported type \"%s\"." ) % it->second.data->typeName() );
				}
			}
			
			if ( vertexNormalsArray.length() )
			{
				MStatus status;
				MItMeshPolygon itPolygon( mObj, &status );
				if( status != MS::kSuccess )
				{
					IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "Failed to create mesh iterator" );
				}

				unsigned v = 0;
				MIntArray vertexIds;
				MIntArray faceIds;
				
				for ( ; !itPolygon.isDone(); itPolygon.next() )
				{
					for ( v=0; v < itPolygon.polygonVertexCount(); ++v )
					{
						faceIds.append( itPolygon.index() );
						vertexIds.append( itPolygon.vertexIndex( v ) );
					}
				}

				if( !fnMesh.setFaceVertexNormals( vertexNormalsArray, faceIds, vertexIds ) )
				{
					IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "Setting normals failed" );
				}
			}
		}
		else
		{
			IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "PrimitiveVariable \"N\" has unsupported interpolation (expected FaceVarying)." );
		}
	}

	bool haveDefaultUVs = false;
	IECore::PrimitiveVariableMap::const_iterator sIt = mesh->variables.find( "s" );
	IECore::RefCountedPtr sDataRef = ( sIt == mesh->variables.end() ) ? 0 : static_cast<IECore::RefCountedPtr>( sIt->second.data );

	/// Add named UV sets
	std::set< std::string > uvSets;
	for ( it = mesh->variables.begin(); it != mesh->variables.end(); ++it )
	{
		const std::string &sName = it->first;

		size_t suffixOffset = sName.rfind( "_s" );

		if ( ( suffixOffset != std::string::npos) && ( suffixOffset == sName.length() - 2 ) )
		{
			std::string uvSetNameStr = sName.substr( 0, suffixOffset );

			if ( uvSetNameStr.size() )
			{
				MString uvSetName = uvSetNameStr.c_str();
				std::string tName = uvSetNameStr + "_t";
				std::string stIdName = uvSetNameStr + "Indices";

				addUVSet( fnMesh, polygonCounts, mesh, sName, tName, stIdName, &uvSetName );

				uvSets.insert( uvSetNameStr );
				
				if ( sDataRef == static_cast<IECore::RefCountedPtr>( it->second.data ) )
				{
					haveDefaultUVs = true;
				}
			}
		}
	}

	/// Add default UV set if it isn't just a reference to a named set
	if ( !haveDefaultUVs )
	{
		addUVSet( fnMesh, polygonCounts, mesh, "s", "t", "stIndices" );
	}

	// We do the search again, but looking for primvars ending "_t", so we can catch cases where either "UVSETNAME_s" or "UVSETNAME_t" is present, but not both, taking care
	// not to attempt adding any duplicate sets
	for ( it = mesh->variables.begin(); it != mesh->variables.end(); ++it )
	{
		const std::string &tName = it->first;

		size_t suffixOffset = tName.rfind( "_t" );

		if ( ( suffixOffset != std::string::npos) && ( suffixOffset == tName.length() - 2 ) )
		{
			std::string uvSetNameStr = tName.substr( 0, suffixOffset );

			if ( uvSetNameStr.size() && uvSets.find( uvSetNameStr ) == uvSets.end() )
			{
				MString uvSetName = uvSetNameStr.c_str();
				std::string sName = uvSetNameStr + "_s";
				std::string stIdName = uvSetNameStr + "Indices";
				
				addUVSet( fnMesh, polygonCounts, mesh, sName, tName, stIdName, &uvSetName );
				uvSets.insert( uvSetNameStr );
			}
		}
	}

	/// If we're making a mesh node (rather than a mesh data) then make sure it belongs
	/// to the default shading group and add the ieMeshInterpolation attribute.
	MObject oMesh = fnMesh.object();
	if( oMesh.apiType()==MFn::kMesh )
	{
		assignDefaultShadingGroup( oMesh );
		setMeshInterpolationAttribute( oMesh, mesh->interpolation() );
	}

	/// \todo Other primvars, e.g. vertex color ("Cs")

	return true;
}
Exemplo n.º 26
0
bool	collide(
				const MObject		hairSystem,
				const int			follicleIndex,
				MVectorArray		&hairPositions,
				MVectorArray		&hairPositionsLast,
				const MDoubleArray	&hairWidths,
				const int			startIndex,
				const int			endIndex,
				const double		curTime,
				const double		friction,
				const void			*privateData )
{
	// Get the private data for the collision objects which was returned
	// from preFrame().
	//
	COLLISION_INFO *ci = (COLLISION_INFO *) privateData;
	if ( !ci ) {
		fprintf( stderr,"%s:%d: collide() privateData pointer is NULL\n",
				__FILE__, __LINE__ );
		return( false );
	}

	// If object has no vertices, or hair has no segments, then there is
	// nothing to collide. In our example, we'll return here, but if you
	// want to implement your own hair processing such as smoothing or
	// freeze on the hair, you could proceed and let the processing happen
	// after the object loop so that the data gets processed even if no
	// collisions occur.
	//
	if ( ci->numObjs <= 0 || hairPositions.length() <= 0 ) {
		return( true );
	}

	int		obj;
	for ( obj = 0; obj < ci->numObjs; ++obj ) {
		COLLISION_OBJ *co = &ci->objs[obj];

		// For our plug-in example, we just collide the segments of the
		// hair against the top of the bounding box for the geometry.
		// In an implementation where you only care about hair falling
		// downwards onto flat objects, this might be OK. However, in the
		// most deluxe of implementation, you should do the following:
		//
		//		o  Determine the motion of each face of your collision
		//		   object during the time range.
		//		o  Step through the follicle, and consider each segment
		//		   to be a moving cylinder where the start and end radii
		//		   can differ. The radii come from `hairWidths' and the
		//		   motion comes from the difference between `hairPositions'
		//		   and `hairPositionsLast'.
		//		o  Intersect each moving element (e.g. moving triangle
		//		   if you have a mesh obect) with each hair segment
		//		   e.g. moving cylinder). This intersection may occur
		//		   at a point within the frame. (Remember that the
		//		   hairPositions[] array holds the DESIRED location where
		//		   the hair system wants the hair to go.
		//		o  There can be multiple collisions along a hair segment.
		//		   Use the first location found and the maximal velocity.
		//
		// If a collision is detected, the `hairPositions' array should be
		// updated. `hairPositionsLast' may also be updated to provide a
		// dampening effect only.
		//

		// Loop through the follicle, starting at the root and advancing
		// toward the tip.
		//
		int		numSegments = hairPositions.length() - 1;
		int		seg;
		for ( seg = 0; seg < numSegments; ++seg ) {
			// Get the desired position of the segment (i.e. where the
			// solver is trying to put the hair for the current frame)
			// and the velocity required to get to that desired position.
			//
			// Thus,
			//		P = hairPositions		// Desired pos'n at cur frame.
			//		L = hairPositionsLast	// Position at prev frame.
			//		V = P - L				// Desired velocity of hair.
			//
			MVector pStart = hairPositions[seg];
			MVector pEnd = hairPositions[seg + 1];

			MVector vStart = pStart - hairPositionsLast[seg];
			MVector vEnd = pEnd - hairPositionsLast[seg + 1];

			// The proper way to time sample is to intersect the moving
			// segment of width `hairWidths[seg] to hairWidths[seg + 1]'
			// with the moving collision object. For the purposes of our
			// demo plug-in, we will simply assume the collision object is
			// static, the hair segment has zero width, and instead of
			// intersecting continuously in time, we will sample discrete
			// steps along the segment.
			//
			#define STEPS 4
			int		step;
			for ( step = 0; step < STEPS; ++step ) {
				// Compute the point for this step and its corresponding
				// velocity. This is a "time swept" point:
				//	p1 = desired position at current time
				//	p0 = position at previous time to achieve desired pos
				//
				MVector pCur, pPrev, v;
				double fracAlongSeg = step / ( (double) STEPS );
				v = vStart * ( 1.0 - fracAlongSeg ) + vEnd * fracAlongSeg;
				MVector p1 = pStart * ( 1.0 - fracAlongSeg )
						+ pEnd * fracAlongSeg;
				MVector p0 = p1 - v;

				// See if BOTH endpoints are outside of the bounding box
				// on the same side. If so, then the segment cannot
				// intersect the bounding box. Note that we assume the
				// bounding box is static.
				//
				if (       (p0.x < co->minx && p1.x < co->minx)
						|| (p0.y < co->miny && p1.y < co->miny)
						|| (p0.z < co->minz && p1.z < co->minz)
						|| (p0.x > co->maxx && p1.x > co->maxx)
						|| (p0.y > co->maxy && p1.y > co->maxy)
						|| (p0.z > co->maxz && p1.z > co->maxz) ) {
					continue;
				}

				// For the purposes of this example plug-in, we'll assume
				// the hair always moves downwards (due to gravity and
				// thus in the negative Y direction). As such, we only
				// need to test for collisions with the TOP of the
				// bounding box. Expanding the example to all 6 sides is
				// left as an exercise for the reader.
				//
				// Remember that p1 is the point at current time, and
				// p0 is the point at the previous time. Since we assume
				// the bounding box to be static, this simplifies things.
				//
				MVector	where(-100000,-100000,-100000);	// Loc'n of collision
				double  fracTime;	// Time at which collision happens 0..1

				if ( fabs( v.y ) < EPSILON		// velocity is zero
						&& fabs( p1.y - co->maxy ) < EPSILON ) {	// right on the bbox
					// Velocity is zero and the desired location (p1) is
					// right on top of the bounding box.
					//
					where = p1;
					fracTime = 1.0;		// Collides right at end;
				} else {
					fracTime = ( co->maxy -  p0.y ) / v.y;
					if ( fracTime >= 0.0 && fracTime <= 1.0 ) {
						// Compute the collision of the swept point with the
						// plane defined by the top of the bounding box.
						//
						where = p0 + v * fracTime;
					}
				}

				// If `seg' lies between startIndex and endIndex
				// we can move it. If its <= startIndex, the root is
				// locked and if >= endIndex the tip is locked.
				//
				if ( seg >= startIndex && seg <= endIndex ) {
					// Since we are just colliding with the top of the
					// bounding box, the normal where we hit is (0,1,0).
					// For the object velocity, we SHOULD measure the
					// relative motion of the object during the time
					// interval, but for our example, we'll assume its
					// not moving (0,0,0).
					//
					bool segCollides = false;
					MVector normal(0.0,1.0,0.0);	// normal is always up
					MVector objectVel(0.0,0.0,0.0);	// assume bbox is static

					// If we get the this point, then the intersection
					// point `where' is on the plane of the bounding box
					// top. See if it lies within the actual bounds of the
					// boxtop, and if so compute the position and velocity
					// information and apply to the hair segment.
					//
					if ( where.x >= co->minx && where.x <= co->maxx
							&& where.z >= co->minz && where.z <= co->maxz
							&& fracTime >= 0.0 && fracTime <= 0.0 ) {
						// We have a collision at `where' with the plane.
						// Compute the new velocity for the hair at the
						// point of collision.
						//
						MVector objVelAlongNormal = (objectVel * normal)
								* normal;
						MVector objVelAlongTangent = objectVel
								- objVelAlongNormal;
						MVector pntVelAlongTangent = v - ( v * normal )
								* normal;
						MVector reflectedPntVelAlongTangent
								= pntVelAlongTangent * ( 1.0 - friction )
								+ objVelAlongTangent * friction;
						MVector newVel = objVelAlongNormal
								+ reflectedPntVelAlongTangent;

						// Update the hair position. It actually looks
						// more stable from a simulation standpoint to
						// just move the closest segment endpoint, but
						// you are free to experiment. What we'll do in
						// our example is move the closest segment end-
						// point by the amount the collided point (where)
						// has to move to have velocity `newVel' yet still
						// pass through `where' at time `fracTime'.
						//
						if ( fracAlongSeg > 0.5 ) {
							MVector	deltaPos = -newVel * fracTime;
							hairPositionsLast[seg + 1] += deltaPos;
							hairPositions[seg + 1] = hairPositionsLast[seg]
									+ newVel;
						} else {
							MVector	deltaPos = newVel * fracTime;
							hairPositionsLast[seg] += deltaPos;
							hairPositions[seg] = hairPositionsLast[seg]
									+ newVel;
						}
						segCollides = true;
					}

                    // Check for segment endpoints that may still be
					// inside. Note that segments which started out being
					// totally inside will never collide using the
					// algorithm we use above, so we'll simply clamp them
					// here. One might expect an inside-the-bounding-box
					// test instead. However, this does not work if the
					// collision object is a very thin object.
					//
					bool inside = false;
                    if ( belowCollisionPlane( co, hairPositions[seg] ) ) {
						hairPositions[seg].y = co->maxy + EPSILON;
						hairPositionsLast[seg] = hairPositions[seg] - objectVel;
						inside = true;
                    }
                    if ( belowCollisionPlane( co, hairPositions[seg+1] ) ) {
						hairPositions[seg+1].y = co->maxy + EPSILON;
						hairPositionsLast[seg+1] = hairPositions[seg+1] - objectVel;
						inside = true;
                    }

					// If we collided, go onto the next segment.
					//
					if ( segCollides || inside ) {
						goto nextSeg;
					}
				}
			}
nextSeg:;
    	}
	}

	// You could perform any global filtering that you want on the hair
	// right here. For example: smoothing. This code is independent of
	// whether or not a collision occurred, and note that collide() is
	// called even with zero collision objects, so you will be guaranteed
	// of reaching here once per hair per iteration.
	//

	return( true );
}
Exemplo n.º 27
0
MStatus DA_GridGenerator::compute(const MPlug &plug, MDataBlock &data)
{
    MStatus stat;
    if (plug != aOutDynamicArray)
        return MS::kFailure;

    //
    // Control Inputs
    //
    double dWidth = data.inputValue(aWidth).asDouble();
    double dHeight = data.inputValue(aHeight).asDouble();

    int iResolutionX = data.inputValue(aResolutionX).asInt();
    int iResolutionY = data.inputValue(aResolutionY).asInt();

    short ePattern = data.inputValue(aPattern).asShort();

    // Create output
    MFnArrayAttrsData fnOutDynamicArray;
    fnOutDynamicArray.create();

    // Create position data
    MVectorArray outPositionPP = fnOutDynamicArray.vectorArray("position");

    //
    // Create grid
    //
    double xOffset = dWidth / ((double)iResolutionX - 1);
    double yOffset = dHeight / ((double)iResolutionY - 1);

    // Keep brick pattern in range
    if (ePattern == 1)
        xOffset -= (xOffset/2) / double(iResolutionX);
    if (ePattern == 2)
        yOffset -= (yOffset/2) / double(iResolutionY);

    // Generate grid
    for(int i = 0; i < iResolutionX; i++)
    {
        for(int j = 0; j < iResolutionY; j++)
        {
            MVector position;
            position.x = -dWidth / 2;
            position.y = 0;
            position.z = -dHeight / 2;

            // Pattern offset
            if (ePattern == 1)
                position.x += (xOffset/2) * double(j % 2);
            if (ePattern == 2)
                position.z += (yOffset/2) * double(i % 2);

            position.x += xOffset * i;
            position.z += yOffset * j;

            outPositionPP.append( position );
        }
    }


    //
    // Set output data
    //
    MDataHandle outArray = data.outputValue(aOutDynamicArray);
    outArray.set(fnOutDynamicArray.object());

    // Set plug to clean
    data.setClean(aOutDynamicArray);

    // Done
    return MS::kSuccess;
}
MStatus	liqAttachPrefAttribute::redoIt()
{
  MFnTypedAttribute tAttr;
  MStatus status;

  for ( unsigned i( 0 ); i < objectNames.length(); i++ ) 
  {
    MSelectionList		nodeList;
    nodeList.add( objectNames[i] );
    MObject depNodeObj;
    nodeList.getDependNode( 0, depNodeObj );
    MDagPath dagNode;
    nodeList.getDagPath( 0, dagNode );
    MFnDependencyNode depNode( depNodeObj );
    MObject prefAttr;
    MString attrName, varName;

    // make sure the renderer description is up to date
    liqglo.liquidRenderer.setRenderer();

    // build the name of the attribute
    varName = ( ( exportN && depNodeObj.hasFn( MFn::kMesh ) )? "N":"P" );
    attrName = "rman";
    attrName += varName;
    attrName += ( ( liqglo.liquidRenderer.requires__PREF )? "__":"" );
    attrName += varName + "ref";

    // create the attribute
    prefAttr = tAttr.create( attrName, attrName, MFnData::kPointArray );


    if ( depNodeObj.hasFn( MFn::kNurbsSurface ) ) 
    {
      MFnNurbsSurface nodeFn( depNodeObj );
      MPointArray nodePArray;
      MItSurfaceCV cvs( dagNode, MObject::kNullObj, liqglo.liquidRenderer.requires_SWAPPED_UVS == false, &status );

      while( !cvs.isDone() ) 
      {
        while( !cvs.isRowDone() ) 
        {
          MPoint pt = (worldSpace)? cvs.position( MSpace::kWorld ) : cvs.position( MSpace::kObject );
          nodePArray.append( pt );
          cvs.next();
        }
        cvs.nextRow();
      }

      nodeFn.addAttribute( prefAttr );
      MFnPointArrayData pArrayData;

      MObject prefDefault = pArrayData.create( nodePArray );
      MPlug nodePlug( depNodeObj, prefAttr );
      nodePlug.setValue( prefDefault );
    } 
    else if ( depNodeObj.hasFn( MFn::kNurbsCurve ) ) 
    {
      // Carsten: added support for PREF on nurbs curves
      //
      MFnNurbsCurve nodeFn( depNodeObj );
      MPointArray nodePArray;
      nodeFn.getCVs( nodePArray );

      nodeFn.addAttribute( prefAttr );
      MFnPointArrayData pArrayData;

      MObject prefDefault = pArrayData.create( nodePArray );
      MPlug nodePlug( depNodeObj, prefAttr );
      nodePlug.setValue( prefDefault );
    } 
    else if ( depNodeObj.hasFn( MFn::kMesh ) ) 
    {
      MFnMesh nodeFn( depNodeObj );
      // Moritz: modified this line to dim nodePArray -- otherwise
      // nodePArray.set() in the wile loop below throws an exception
      // which was why __Pref didn't work
      MPointArray nodePArray( MFnMesh( depNodeObj ).numVertices() );
      unsigned count;

      nodeFn.addAttribute( prefAttr );

      if ( exportN ) 
      {
        // export Nref
        unsigned vertex;
        unsigned normal;
        unsigned face = 0;
        unsigned faceVertex = 0;
        unsigned int numNormals = nodeFn.numNormals();
        unsigned int numPoints  = nodeFn.numVertices();
        MFloatVectorArray normals;
        MVectorArray normalAttArray;
        nodeFn.getNormals( normals );

        if ( numNormals > numPoints ) 
        {
          // if we get more than 1 normal per vertex,
          // force the arraysize to the full facevarying size
          unsigned faceVaryingCount( 0 );
          for ( unsigned pOn( 0 ); pOn < nodeFn.numPolygons(); pOn++ ) 
            faceVaryingCount += nodeFn.polygonVertexCount( pOn );
          
          normalAttArray.setLength( faceVaryingCount );
        } 
        else 
          normalAttArray.setLength(normals.length());
        
        for ( MItMeshPolygon polyIt ( depNodeObj ); polyIt.isDone() == false; polyIt.next() ) 
        {
          count = polyIt.polygonVertexCount();
          while ( count > 0 ) 
          {
            --count;
            normal = polyIt.normalIndex( count );
            vertex = polyIt.vertexIndex( count );

            if( numNormals == numPoints )
              normalAttArray.set(normals[normal], vertex);
            else
              normalAttArray.set(normals[normal], faceVertex);

            ++faceVertex;
          }
          ++face;
        }

        MFnVectorArrayData pArrayData;
        MObject prefDefault = pArrayData.create( normalAttArray );
        MPlug nodePlug( depNodeObj, prefAttr );
        nodePlug.setValue( prefDefault );

      } 
      else 
      {
        // TODO: do we need to account for the altMeshExport algo that's
        // used in liquidRibMeshData?
        // Moritz: no, it's basically the same as the algo below
        for ( MItMeshPolygon polyIt( dagNode, MObject::kNullObj ); !polyIt.isDone(); polyIt.next()) 
        {
          count = polyIt.polygonVertexCount();

          while ( count > 0 ) 
          {
            --count;
            unsigned	vertexIndex = polyIt.vertexIndex( count );
            MPoint nodePoint = (worldSpace)? polyIt.point( count, MSpace::kWorld ) : polyIt.point( count, MSpace::kObject );
            // Moritz: this returns MS::kFailure but seems to work?!
            nodePArray.set( nodePoint, vertexIndex );
          }
        }

        MFnPointArrayData pArrayData;
        MObject prefDefault = pArrayData.create( nodePArray );
        MPlug nodePlug( depNodeObj, prefAttr );
        nodePlug.setValue( prefDefault );

      }
    } else cerr << "Neither a Nurbs nor a Mesh !!" << endl;
  }
  return MS::kSuccess;
}
Exemplo n.º 29
0
IECore::DataPtr convert( const MCommandResult &result )
{
	MStatus s;
	switch (result.resultType())
	{
		case MCommandResult::kInvalid:
		{
			// No result
			return 0;
		}
		case MCommandResult::kInt:
		{
			int i;
			s = result.getResult(i);
			assert(s);

			IECore::IntDataPtr data = new IECore::IntData();
			data->writable() = i;

			return data;
		}
		case MCommandResult::kIntArray:
		{
			MIntArray v;
			s = result.getResult(v);
			assert(s);
			unsigned sz = v.length();
			IECore::IntVectorDataPtr data = new IECore::IntVectorData();
			data->writable().resize(sz);
			for (unsigned i = 0; i < sz; i++)
			{
				(data->writable())[i] = v[i];
			}

			return data;
		}
		case MCommandResult::kDouble:
		{
			double d;
			s = result.getResult(d);
			assert(s);

			IECore::FloatDataPtr data = new IECore::FloatData();
			data->writable() = static_cast<float>(d);

			return data;
		}
		case MCommandResult::kDoubleArray:
		{
			MDoubleArray v;
			s = result.getResult(v);
			assert(s);
			unsigned sz = v.length();
			IECore::DoubleVectorDataPtr data = new IECore::DoubleVectorData();
			data->writable().resize(sz);
			for (unsigned i = 0; i < sz; i++)
			{
				data->writable()[i] = v[i];
			}

			return data;
		}
		case MCommandResult::kString:
		{
			MString str;
			s = result.getResult(str);
			assert(s);

			IECore::StringDataPtr data = new IECore::StringData();
			data->writable() = std::string(str.asChar());

			return data;
		}
		case MCommandResult::kStringArray:
		{
			MStringArray v;
			s = result.getResult(v);
			assert(s);
			unsigned sz = v.length();
			IECore::StringVectorDataPtr data = new IECore::StringVectorData();
			data->writable().resize(sz);
			for (unsigned i = 0; i < sz; i++)
			{
				data->writable()[i] = std::string(v[i].asChar());
			}

			return data;
		}
		case MCommandResult::kVector:
		{
			MVector v;
			s = result.getResult(v);
			assert(s);

			IECore::V3fDataPtr data = new IECore::V3fData();
			data->writable() = Imath::V3f(v.x, v.y, v.z);

			return data;
		}
		case MCommandResult::kVectorArray:
		{
			MVectorArray v;
			s = result.getResult(v);
			assert(s);
			unsigned sz = v.length();
			IECore::V3fVectorDataPtr data = new IECore::V3fVectorData();
			data->writable().resize(sz);
			for (unsigned i = 0; i < sz; i++)
			{
				data->writable()[i] = Imath::V3f(v[i].x, v[i].y, v[i].z);
			}

			return data;
		}
		case MCommandResult::kMatrix:
		{
			MDoubleArray v;
			int numRows, numColumns;

			s = result.getResult(v, numRows, numColumns);
			assert(s);

			if (numRows > 4 || numColumns > 4)
			{
				throw IECoreMaya::StatusException( MS::kFailure );
			}

			IECore::M44fDataPtr data = new IECore::M44fData();

			for (int i = 0; i < numColumns; i++)
			{
				for (int j = 0; j < numRows; j++)
				{
					(data->writable())[i][j] = v[i*numRows+j];
				}
			}

			return data;
		}
		case MCommandResult::kMatrixArray:
		{
			return 0;
		}
		default:

			assert( false );
			return 0;
	}
}
Exemplo n.º 30
0
//apply fields in the scene from the rigid body
void dSolverNode::applyFields(MPlugArray &rbConnections, float dt)
{
    MVectorArray position;
    MVectorArray velocity;
    MDoubleArray mass;

    std::vector<rigid_body_t*> rigid_bodies;
    //gather active rigid bodies
    for(size_t i = 0; i < rbConnections.length(); ++i) {
        MObject node = rbConnections[i].node();
        MFnDagNode fnDagNode(node);
        if(fnDagNode.typeId() == rigidBodyNode::typeId) {
            rigidBodyNode *rbNode = static_cast<rigidBodyNode*>(fnDagNode.userNode()); 
            rigid_body_t::pointer rb = rbNode->rigid_body();

            MPlug plgMass(node, rigidBodyNode::ia_mass);
            float mass = 0.f;
            plgMass.getValue(mass);
			bool active = (mass>0.f);
            if(active) {
                rigid_bodies.push_back(rb.get());
            }
        } else if(fnDagNode.typeId() == rigidBodyArrayNode::typeId) {
            rigidBodyArrayNode *rbNode = static_cast<rigidBodyArrayNode*>(fnDagNode.userNode()); 
            std::vector<rigid_body_t::pointer>& rbs = rbNode->rigid_bodies();

            MPlug plgMass(node, rigidBodyArrayNode::ia_mass);
            float mass = 0.f;
			plgMass.getValue(mass);
			bool active = (mass>0.f);
            if(active) {
                for(size_t j = 0; j < rbs.size(); ++j) {
                    rigid_bodies.push_back(rbs[j].get());
                }
            }
        }
    }

    //clear forces and get the properties needed for field computation    
    for(size_t i = 0; i < rigid_bodies.size(); ++i) {
        rigid_bodies[i]->clear_forces();
        vec3f pos, vel;
        quatf rot;
        rigid_bodies[i]->get_transform(pos, rot); 
        rigid_bodies[i]->get_linear_velocity(vel);
        position.append(MVector(pos[0], pos[1], pos[2]));
        velocity.append(MVector(vel[0], vel[1], vel[2]));
        //TODO
        mass.append(1.0);
        //
    }

    //apply the fields to the rigid bodies
    MVectorArray force;
    for(MItDag it(MItDag::kDepthFirst, MFn::kField); !it.isDone(); it.next()) {
        MFnField fnField(it.item());
        fnField.getForceAtPoint(position, velocity, mass, force, dt);
        for(size_t i = 0; i < rigid_bodies.size(); ++i) {
            rigid_bodies[i]->apply_central_force(vec3f(force[i].x, force[i].y, force[i].z));
        }
    }
}