Beispiel #1
0
void retargetLocator::getRadPoints( MPointArray& radPoints )
{
	int    div = discDivision;
	double angle = 360.0/div*0.01745327778;

	radPoints.setLength( div );

	double axisList[3];
	for( int i=0; i<div; i++ )
	{
		axisList[0] = 0.0;
		axisList[1] = sin( angle*i + discAngle );
		axisList[2] = cos( angle*i + discAngle );
		radPoints.set( i, axisList[(discAxis+3)%3]*discSize.x, 
			              axisList[(discAxis+2)%3]*discSize.y, 
						  axisList[(discAxis+1)%3]*discSize.z );
	}
}
Beispiel #2
0
void SGTransformManip::draw(int manipIndex, bool hideMode ) {
	double manipSize = SGMatrix::getManipSizeFromWorldPoint( intersector.center, SGMatrix::getCamMatrix() );
	double centerSize = intersector.centerSize / manipSize;

	GLushort linePattern = 0x5555;

	MColor xColor(1, 0, 0); MColor yColor(0, 1, 0); MColor zColor(0, 0, 1); MColor cColor(100/255.0f, 220/255.0f, 255/255.0f);

	if (intersectType == SGTransformManipIntersector::kCenter)
		cColor = MColor(1, 1, 0);
	else if (intersectType == SGTransformManipIntersector::kX)
		xColor = MColor(1, 1, 0);
	else if (intersectType == SGTransformManipIntersector::kY)
		yColor = MColor(1, 1, 0);
	else if (intersectType == SGTransformManipIntersector::kZ)
		zColor = MColor(1, 1, 0);

	MVector camX = SGMatrix::getCamVector(0).normal() * centerSize;
	MVector camY = SGMatrix::getCamVector(1).normal() * centerSize;
	MPointArray centerManipPoints; centerManipPoints.setLength(5);

	centerManipPoints[0] =  camX + camY + intersector.center;
	centerManipPoints[1] = -camX + camY + intersector.center;
	centerManipPoints[2] = -camX - camY + intersector.center;
	centerManipPoints[3] =  camX - camY + intersector.center;
	centerManipPoints[4] = centerManipPoints[0];

	MPointArray xLine, yLine, zLine;
	xLine.setLength(2);yLine.setLength(2);zLine.setLength(2);

	xLine[0] = intersector.center; xLine[1] = intersector.axisX + xLine[0];
	yLine[0] = intersector.center; yLine[1] = intersector.axisY + yLine[0];
	zLine[0] = intersector.center; zLine[1] = intersector.axisZ + zLine[0];

	manip->pushLine(manipIndex, xLine, xColor, 1, &linePattern);
	manip->pushLine(manipIndex, yLine, yColor, 1, &linePattern);
	manip->pushLine(manipIndex, zLine, zColor, 1, &linePattern);
	if (!hideMode) {
		manip->pushShape(manipIndex, cone.shape, intersector.coneXMatrix, xColor);
		manip->pushShape(manipIndex, cone.shape, intersector.coneYMatrix, yColor);
		manip->pushShape(manipIndex, cone.shape, intersector.coneZMatrix, zColor);
		manip->pushLine(manipIndex, centerManipPoints, cColor, 1, &linePattern);
	}
}
double SGIntersectFunction::getShapeIntersectDist(const SGShape& targetShape, const MMatrix& shapeMatrix, const MMatrix& camMatrix)
{
	MPoint mousePoint(SGMouse::x, SGMouse::y, 0);

	MMatrix worldToView = SGMatrix::getWorldToViewMatrix(camMatrix);
	MPointArray points; points.setLength(targetShape.numPoints);
	for (int i = 0; i < targetShape.numPoints; i++) {
		float x = targetShape.points[i * 3 + 0];
		float y = targetShape.points[i * 3 + 1];
		float z = targetShape.points[i * 3 + 2];
		MPoint point(x, y, z);
		points[i] = SGMatrix::getViewPointFromWorld(point * shapeMatrix, camMatrix, &worldToView );
	}

	MIntArray indices; indices.setLength(targetShape.numPoly * targetShape.interval);
	for (int i = 0; i < targetShape.numPoly * targetShape.interval; i++){
		indices[i] = targetShape.indices[i];
	}

	double closeDist = 10000000.0;

	for (int i = 0; i < targetShape.numPoly; i++){
		int index1 = indices[i*3];
		int index2 = indices[i*3+1];
		int index3 = indices[i*3+2];

		double dist1 = SGMatrix::getLineDist(points[index1], points[index2], mousePoint);
		double dist2 = SGMatrix::getLineDist(points[index2], points[index3], mousePoint);
		double dist3 = SGMatrix::getLineDist(points[index3], points[index1], mousePoint);

		if (dist1 < closeDist) 
			closeDist = dist1;
		if (dist2 < closeDist) 
			closeDist = dist2;
		if (dist3 < closeDist)
			closeDist = dist3;
	}
	return closeDist;
}
Beispiel #4
0
void CBPoseSpaceCmd::loadVertexPosition(MObject& poseMesh)
{
    MStatus status;
    MFnMesh poseFn(poseMesh, &status);
    unsigned numVertex = poseFn.numVertices();

    float* data = new float[numVertex * 3];

    MString filename = _cacheName + ".pose";

    if(!is_regular_file(filename.asChar()))
        return;

    boost::iostreams::filtering_istream in;
    in.push( boost::iostreams::gzip_decompressor());
    in.push( boost::iostreams::file_source(filename.asChar(), ios::binary));
    if(!in.read((char*)data, numVertex * 3  * 4)) {
        MGlobal::displayError(MString("corrective blendshape failed to read enough data from pose cache ") + _cacheName);
        delete[] data;
        return;
    }


    MPointArray poseVertex;
    poseVertex.setLength(numVertex);

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

    poseFn.setPoints ( poseVertex, MSpace::kObject );
    delete[] data;

    MGlobal::displayInfo(MString("corrective blendshape read sculpt pose from ") + filename);
}
Beispiel #5
0
void CBPoseSpaceCmd::setCachedVertexPosition(MObject& poseMesh)
{
    MFnMesh fpose(poseMesh);
    unsigned numVertex = fpose.numVertices();

    float* data = new float[numVertex * (3 + 3 + 16)];

    boost::iostreams::filtering_istream in;
    in.push( boost::iostreams::gzip_decompressor());
    in.push( boost::iostreams::file_source(_cacheName.asChar(), ios::binary));
    if(!in.read((char*)data, numVertex * (3 + 3 + 16) * 4)) {
        MGlobal::displayError(MString("corrective blendshape failed to read enough data from pose cache ") + _cacheName);
        delete[] data;
        return;
    }

    MPointArray sculptVertex;

    sculptVertex.setLength(numVertex);

    unsigned offset = numVertex * 3;

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

    fpose.setPoints(sculptVertex, MSpace::kObject );
    fpose.updateSurface();

    delete[] data;
    MGlobal::displayInfo(MString("corrective blendshape read pose cache from ") + _cacheName);

}
MObject readNurbs(double iFrame, Alembic::AbcGeom::INuPatch & iNode,
    MObject & iObject)
{
    MStatus status;
    MObject obj;

    Alembic::AbcGeom::INuPatchSchema schema = iNode.getSchema();

    // no interpolation for now
    Alembic::AbcCoreAbstract::index_t index, ceilIndex;
    getWeightAndIndex(iFrame, schema.getTimeSampling(),
        schema.getNumSamples(), index, ceilIndex);

    Alembic::AbcGeom::INuPatchSchema::Sample samp;
    schema.get(samp, Alembic::Abc::ISampleSelector(index));

    Alembic::Abc::P3fArraySamplePtr pos = samp.getPositions();
    Alembic::Abc::FloatArraySamplePtr weights = samp.getPositionWeights();

    MString surfaceName(iNode.getName().c_str());

    unsigned int degreeU  = samp.getUOrder() - 1;
    unsigned int degreeV  = samp.getVOrder() - 1;
    unsigned int numCVInU = samp.getNumU();
    unsigned int numCVInV = samp.getNumV();

    // cv points
    unsigned int numCV = numCVInU*numCVInV;
    unsigned int curPos = 0;

    MPointArray controlVertices;
    controlVertices.setLength(numCV);

    for (unsigned int v = 0; v < numCVInV; ++v)
    {
        for (unsigned int u = 0; u < numCVInU; ++u, ++curPos)
        {
            unsigned int mayaIndex = u * numCVInV + (numCVInV - v - 1);
            MPoint pt((*pos)[curPos].x, (*pos)[curPos].y, (*pos)[curPos].z);

            if (weights)
            {
                pt.w = (*weights)[curPos];
            }

            // go from u,v order to reversed v, u order
            controlVertices.set(pt, mayaIndex);
        }
    }

    // Nurbs form
    // Alemblic file does not record the form of nurb surface, we get the form
    // by checking the CV data. If the first degree number CV overlap the last
    // degree number CV, then the form is kPeriodic. If only the first CV overlaps
    // the last CV, then the form is kClosed.
    MFnNurbsSurface::Form formU = MFnNurbsSurface::kPeriodic;
    MFnNurbsSurface::Form formV = MFnNurbsSurface::kPeriodic;
    // Check all curves
    bool notOpen = true;
    for (unsigned int v = 0; notOpen && v < numCVInV; v++) {
        for (unsigned int u = 0; u < degreeU; u++) {
            unsigned int firstIndex = u * numCVInV + (numCVInV - v - 1);
            unsigned int lastPeriodicIndex = (numCVInU - degreeU + u) * numCVInV + (numCVInV - v - 1);
            if (!controlVertices[firstIndex].isEquivalent(controlVertices[lastPeriodicIndex])) {
                formU = MFnNurbsSurface::kOpen;
                notOpen = false;
                break;
            }
        }
    }

    if (formU == MFnNurbsSurface::kOpen) {
        formU = MFnNurbsSurface::kClosed;
        for (unsigned int v = 0; v < numCVInV; v++) {
            unsigned int lastUIndex = (numCVInU - 1) * numCVInV + (numCVInV - v - 1);
            if (! controlVertices[numCVInV-v-1].isEquivalent(controlVertices[lastUIndex])) {
                formU = MFnNurbsSurface::kOpen;
                break;
            }
        }
    }

    notOpen = true;
    for (unsigned int u = 0; notOpen && u < numCVInU; u++) {
        for (unsigned int v = 0; v < degreeV; v++) {
            unsigned int firstIndex = u * numCVInV + (numCVInV - v - 1);
            unsigned int lastPeriodicIndex = u * numCVInV + (degreeV - v - 1); //numV - (numV - vDegree + v) - 1;
            if (!controlVertices[firstIndex].isEquivalent(controlVertices[lastPeriodicIndex])) {
                formV = MFnNurbsSurface::kOpen;
                notOpen = false;
                break;
            }
        }
    }
    if (formV == MFnNurbsSurface::kOpen) {
        formV = MFnNurbsSurface::kClosed;
        for (unsigned int u = 0; u < numCVInU; u++) {
            if (! controlVertices[u * numCVInV + (numCVInV-1)].isEquivalent(controlVertices[u * numCVInV])) {
                formV = MFnNurbsSurface::kOpen;
                break;
            }
        }
    }


    Alembic::Abc::FloatArraySamplePtr uKnot = samp.getUKnot();
    Alembic::Abc::FloatArraySamplePtr vKnot = samp.getVKnot();

    unsigned int numKnotsInU = static_cast<unsigned int>(uKnot->size() - 2);
    MDoubleArray uKnotSequences;
    uKnotSequences.setLength(numKnotsInU);
    for (unsigned int i = 0; i < numKnotsInU; ++i)
    {
        uKnotSequences.set((*uKnot)[i+1], i);
    }

    unsigned int numKnotsInV = static_cast<unsigned int>(vKnot->size() - 2);
    MDoubleArray vKnotSequences;
    vKnotSequences.setLength(numKnotsInV);
    for (unsigned int i = 0; i < numKnotsInV; i++)
    {
        vKnotSequences.set((*vKnot)[i+1], i);
    }

    // Node creation try the API first
    MFnNurbsSurface mFn;
    obj = mFn.create(controlVertices, uKnotSequences, vKnotSequences,
        degreeU, degreeV, formU, formV,
        true, iObject, &status);

    // something went wrong, try open/open create
    if (status != MS::kSuccess && (formU != MFnNurbsSurface::kOpen ||
        formV != MFnNurbsSurface::kOpen))
    {
        obj = mFn.create(controlVertices, uKnotSequences, vKnotSequences,
            degreeU, degreeV,  MFnNurbsSurface::kOpen,  MFnNurbsSurface::kOpen,
            true, iObject, &status);
    }

    if (status == MS::kSuccess)
    {
        mFn.setName(surfaceName);
    }
    else
    {
        MString errorMsg = "Could not create Nurbs Surface: ";
        errorMsg += surfaceName;
        MGlobal::displayError(errorMsg);
    }

    trimSurface(samp, mFn);

    return obj;
}
IECore::PrimitivePtr FromMayaCurveConverter::doPrimitiveConversion( MFnNurbsCurve &fnCurve ) const
{
	// decide on the basis and periodicity
	int mDegree = fnCurve.degree();
	IECore::CubicBasisf basis = IECore::CubicBasisf::linear();
	if( m_linearParameter->getTypedValue()==false && mDegree==3 )
	{
		basis = IECore::CubicBasisf::bSpline();
	}
	bool periodic = false;
	if( fnCurve.form()==MFnNurbsCurve::kPeriodic )
	{
		periodic = true;
	}

	// get the points and convert them
	MPointArray mPoints;
	fnCurve.getCVs( mPoints, space() );
	if( periodic )
	{
		// maya duplicates the first points at the end, whereas we just wrap around.
		// remove the duplicates.
		mPoints.setLength( mPoints.length() - mDegree );
	}

	bool duplicateEnds = false;
	if( !periodic && mDegree==3 )
	{
		// there's an implicit duplication of the end points that we need to make explicit
		duplicateEnds = true;
	}

	IECore::V3fVectorDataPtr pointsData = new IECore::V3fVectorData;
	std::vector<Imath::V3f> &points = pointsData->writable();
	std::vector<Imath::V3f>::iterator transformDst;
	if( duplicateEnds )
	{
		points.resize( mPoints.length() + 4 );
		transformDst = points.begin();
		*transformDst++ = IECore::convert<Imath::V3f>( mPoints[0] );
		*transformDst++ = IECore::convert<Imath::V3f>( mPoints[0] );
	}
	else
	{
		points.resize( mPoints.length() );
		transformDst = points.begin();
	}

	std::transform( MArrayIter<MPointArray>::begin( mPoints ), MArrayIter<MPointArray>::end( mPoints ), transformDst, IECore::VecConvert<MPoint, V3f>() );

	if( duplicateEnds )
	{
		points[points.size()-1] = IECore::convert<Imath::V3f>( mPoints[mPoints.length()-1] );
		points[points.size()-2] = IECore::convert<Imath::V3f>( mPoints[mPoints.length()-1] );
	}

	// make and return the curve
	IECore::IntVectorDataPtr vertsPerCurve = new IECore::IntVectorData;
	vertsPerCurve->writable().push_back( points.size() );

	return new IECore::CurvesPrimitive( vertsPerCurve, basis, periodic, pointsData );
}
MStatus   clusterControledCurve::compute( const MPlug& plug, MDataBlock& data )
{
	//MFnDependencyNode thisNode( thisMObject() );
	//cout << thisNode.name() << ", start" << endl;

	MStatus status;

	MDataHandle hInputCurve = data.inputValue( aInputCurve, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
	MDataHandle hInputCurveMatrix = data.inputValue( aInputCurveMatrix, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
	MDataHandle hOutputCurve = data.outputValue( aOutputCurve, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );

	MArrayDataHandle hArrBindPreMatrix = data.inputArrayValue( aBindPreMatrix, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
	MArrayDataHandle hArrMatrix = data.inputArrayValue( aMatrix, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );

	MArrayDataHandle hArrWeightList = data.inputArrayValue( aWeightList, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );

	MDataHandle hUpdate = data.inputValue( aUpdate, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );

	MObject oInputCurve = hInputCurve.asNurbsCurve();

	int bindPreMatrixLength = hArrBindPreMatrix.elementCount();
	int matrixLength = hArrMatrix.elementCount();

	MFnNurbsCurve fnInputCurve = oInputCurve;
	int numCVs = fnInputCurve.numCVs();
	int weightListLength = hArrWeightList.elementCount();

	if( weightListLength > 100 )
	{
		cout << "WeightList Count Error : " << weightListLength << endl;
		return MS::kFailure;
	}

	MPointArray inputCvPoints;
	MPointArray outputCvPoints;

	fnInputCurve.getCVs( inputCvPoints );
	outputCvPoints.setLength( numCVs );

	MMatrix matrix;
	MMatrix inputCurveMatrix = hInputCurveMatrix.asMatrix();
	MMatrix inputCurveMatrixInverse = inputCurveMatrix.inverse();

	if( requireUpdate )
	CHECK_MSTATUS_AND_RETURN_IT( updateBindPreMatrix( oInputCurve, inputCurveMatrixInverse,
				                                      hArrMatrix, hArrBindPreMatrix, hUpdate.asBool() ) );

	for( int i=0; i< numCVs; i++ )
	{
		inputCvPoints[i] *= inputCurveMatrix;
	}

	for( int i=0; i< numCVs; i++ )
	{
		outputCvPoints[i] = MPoint( 0,0,0 );
		double weight;

		for( int j=0; j< matrixLength; j++ )
		{
			weight = setWeights[i][j];

			hArrMatrix.jumpToElement( j );
			matrix = hArrMatrix.inputValue().asMatrix();
			outputCvPoints[i] += inputCvPoints[i]*bindPreMatrix[j]*matrix*weight;
		}
	}

	for( int i=0; i< numCVs; i++ )
	{
		outputCvPoints[i] *= inputCurveMatrixInverse;
	}

	MFnNurbsCurveData outputCurveData;
	MObject oOutputCurve = outputCurveData.create();

	fnInputCurve.copy( oInputCurve, oOutputCurve );

	MFnNurbsCurve fnOutputCurve( oOutputCurve, &status );
	CHECK_MSTATUS_AND_RETURN_IT( status );
	fnOutputCurve.setCVs( outputCvPoints );

	hOutputCurve.set( oOutputCurve );

	data.setClean( plug );

	//cout << thisNode.name() << ", end" << endl;

	return status;
}
MStatus AlembicCurvesNode::compute(const MPlug &plug, MDataBlock &dataBlock)
{
  ESS_PROFILE_SCOPE("AlembicCurvesNode::compute");
  MStatus status;

  // update the frame number to be imported
  const double inputTime =
      dataBlock.inputValue(mTimeAttr).asTime().as(MTime::kSeconds);
  MString &fileName = dataBlock.inputValue(mFileNameAttr).asString();
  MString &identifier = dataBlock.inputValue(mIdentifierAttr).asString();

  // check if we have the file
  if (fileName != mFileName || identifier != mIdentifier) {
    mSchema.reset();
    if (fileName != mFileName) {
      delRefArchive(mFileName);
      mFileName = fileName;
      addRefArchive(mFileName);
    }
    mIdentifier = identifier;

    // get the object from the archive
    Abc::IObject iObj = getObjectFromArchive(mFileName, identifier);
    if (!iObj.valid()) {
      MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier +
                              "' not found in archive '" + mFileName + "'.");
      return MStatus::kFailure;
    }
    AbcG::ICurves obj(iObj, Abc::kWrapExisting);
    if (!obj.valid()) {
      MGlobal::displayWarning("[ExocortexAlembic] Identifier '" + identifier +
                              "' in archive '" + mFileName +
                              "' is not a Curves.");
      return MStatus::kFailure;
    }
    mObj = obj;
    mSchema = obj.getSchema();
    mCurvesData = MObject::kNullObj;
  }

  if (!mSchema.valid()) {
    return MStatus::kFailure;
  }

  {
    ESS_PROFILE_SCOPE("AlembicCurvesNode::compute readProps");
    Alembic::Abc::ICompoundProperty arbProp = mSchema.getArbGeomParams();
    Alembic::Abc::ICompoundProperty userProp = mSchema.getUserProperties();
    readProps(inputTime, arbProp, dataBlock, thisMObject());
    readProps(inputTime, userProp, dataBlock, thisMObject());

    // Set all plugs as clean
    // Even if one of them failed to get set,
    // trying again in this frame isn't going to help
    for (unsigned int i = 0; i < mGeomParamPlugs.length(); i++) {
      dataBlock.outputValue(mGeomParamPlugs[i]).setClean();
    }

    for (unsigned int i = 0; i < mUserAttrPlugs.length(); i++) {
      dataBlock.outputValue(mUserAttrPlugs[i]).setClean();
    }
  }

  // get the sample
  SampleInfo sampleInfo = getSampleInfo(inputTime, mSchema.getTimeSampling(),
                                        mSchema.getNumSamples());

  // check if we have to do this at all
  if (!mCurvesData.isNull() &&
      mLastSampleInfo.floorIndex == sampleInfo.floorIndex &&
      mLastSampleInfo.ceilIndex == sampleInfo.ceilIndex) {
    return MStatus::kSuccess;
  }

  mLastSampleInfo = sampleInfo;
  const float blend = (float)sampleInfo.alpha;

  // access the camera values
  AbcG::ICurvesSchema::Sample sample;
  AbcG::ICurvesSchema::Sample sample2;
  mSchema.get(sample, sampleInfo.floorIndex);
  if (blend != 0.0f) {
    mSchema.get(sample2, sampleInfo.ceilIndex);
  }

  Abc::P3fArraySamplePtr samplePos = sample.getPositions();
  Abc::P3fArraySamplePtr samplePos2 = sample2.getPositions();
  Abc::Int32ArraySamplePtr nbVertices = sample.getCurvesNumVertices();
  const bool applyBlending =
      (blend == 0.0f) ? false : (samplePos->size() == samplePos2->size());

  Abc::FloatArraySamplePtr pKnotVec = getKnotVector(mObj);
  Abc::UInt16ArraySamplePtr pOrders = getCurveOrders(mObj);

  MArrayDataHandle arrh = dataBlock.outputArrayValue(mOutGeometryAttr);
  MArrayDataBuilder builder = arrh.builder();

  // reference:
  // http://download.autodesk.com/us/maya/2010help/API/multi_curve_node_8cpp-example.html

  const int degree = (sample.getType() == AbcG::kCubic) ? 3 : 1;
  const bool closed = (sample.getWrap() == AbcG::kPeriodic);
  unsigned int pointOffset = 0;
  unsigned int knotOffset = 0;
  for (int ii = 0; ii < nbVertices->size(); ++ii) {
    const unsigned int nbCVs = (unsigned int)nbVertices->get()[ii];
    const int ldegree = (pOrders) ? pOrders->get()[ii] : degree;
    const int nbSpans = (int)nbCVs - ldegree;

    MDoubleArray knots;
    if (pKnotVec) {
      const unsigned int nb_knot = nbCVs + ldegree - 1;
      for (unsigned int i = 0; i < nb_knot; ++i) {
        knots.append(pKnotVec->get()[knotOffset + i]);
      }
      knotOffset += nb_knot;
    }
    else {
      for (int span = 0; span <= nbSpans; ++span) {
        knots.append(double(span));
        if (span == 0 || span == nbSpans) {
          for (int m = 1; m < degree; ++m) {
            knots.append(double(span));
          }
        }
      }
    }

    MPointArray points;
    if (samplePos->size() > 0) {
      points.setLength((unsigned int)nbCVs);
      if (applyBlending) {
        for (unsigned int i = 0; i < nbCVs; ++i) {
          const Abc::P3fArraySample::value_type &vals1 =
              samplePos->get()[pointOffset + i];
          const Abc::P3fArraySample::value_type &vals2 =
              samplePos2->get()[pointOffset + i];
          MPoint &pt = points[i];

          pt.x = vals1.x + (vals2.x - vals1.x) * blend;
          pt.y = vals1.y + (vals2.y - vals1.y) * blend;
          pt.z = vals1.z + (vals2.z - vals1.z) * blend;
        }
      }
      else {
        for (unsigned int i = 0; i < nbCVs; ++i) {
          const Abc::P3fArraySample::value_type &vals =
              samplePos->get()[pointOffset + i];
          MPoint &pt = points[i];
          pt.x = vals.x;
          pt.y = vals.y;
          pt.z = vals.z;
        }
      }
      pointOffset += nbCVs;
    }

    // create a subd either with or without uvs
    MObject mmCurvesData = MFnNurbsCurveData().create();
    if (ldegree == 1 || ldegree == 3)
      mCurves.create(points, knots, ldegree,
                     closed ? MFnNurbsCurve::kClosed : MFnNurbsCurve::kOpen,
                     false, false, mmCurvesData);
    builder.addElement(ii).set(mmCurvesData);
  }
  arrh.set(builder);
  arrh.setAllClean();
  return MStatus::kSuccess;
}
MStatus genRod(
	const MPoint &p0,
	const MPoint &p1,
	const double radius,
	const unsigned int nSegs,
	
	int &nPolys,
	MPointArray &verts,
	MIntArray &polyCounts,
	MIntArray &polyConnects
)
{
	verts.clear();
	polyCounts.clear();
	polyConnects.clear();
	
	unsigned int nCirclePts = nSegs; 
	unsigned int nVerts = 2 * nCirclePts;
	
	// Calculate the local axiis of the rod
	MVector vec( p1 - p0 );
	MVector up( 0.0, 1.0, 0.0 );
	MVector xAxis, yAxis, zAxis;
	
	yAxis = vec.normal();
	if( up.isParallel( yAxis, 0.1 ) )
		up = MVector( 1.0, 0.0, 0.0 );
	xAxis = yAxis ^ up;
	zAxis = (xAxis ^ yAxis).normal();
	xAxis = (yAxis ^ zAxis ).normal(); 
	
	// Calculate the vertex positions
	verts.setLength( nVerts );
	double angleIncr = 2.0 * M_PI / nSegs;
	double angle;
	MPoint p;
	double x, z;
	unsigned int i;
	for( i=0, angle=0; i < nCirclePts; i++, angle += angleIncr )
	{
		// Calculate position in circle
		x = radius * cos( angle );
		z = radius * sin( angle );
		
		p = p0 + x * xAxis + z * zAxis;

		verts[ i ] = p;
		
		p += vec;

		verts[ i + nCirclePts ] = p;
	}
	
	nPolys = nSegs;
	
	// Generate polycounts
	polyCounts.setLength( nPolys );
	for( i=0; i < polyCounts.length(); i++ )
		polyCounts[i] = 4;
	
	// Generate polyconnects
	polyConnects.setLength( nPolys * 4 );
	polyConnects.clear();
	for( i=0; i < nSegs; i++ )
	{
		polyConnects.append( linearIndex( 0, i, 2, nCirclePts ) );
		polyConnects.append( linearIndex( 0, i+1, 2, nCirclePts ) );
		polyConnects.append( linearIndex( 1, i+1, 2, nCirclePts ) );
		polyConnects.append( linearIndex( 1, i, 2, nCirclePts ) );
	}
		
	return MS::kSuccess;
}
void curveColliderLocator::draw(M3dView &view, const MDagPath &path, 
								 M3dView::DisplayStyle style,
								 M3dView::DisplayStatus status)
{ 
	//
	// Get the input curve
	//
	MObject thisNode = thisMObject();
	MPlug radiusPlug(thisNode, colliderRadiusIn);
	MPlug colorPlugR(thisNode, colliderColorR);
	MPlug colorPlugG(thisNode, colliderColorG);
	MPlug colorPlugB(thisNode, colliderColorB);
	MPlug colorPlugT(thisNode, colliderTransparency);
	MPlug radiusElement;
	double radius;
	double radius2;
	double param;
	double param2;
	double paramNorm;
	radiusPlug.getValue(radius);
	MStatus stat;
	MQuaternion rotateQuat;
	double degreesToRadians = ( M_PI/ 180.0 );
	double radiansToDegrees = ( 180.0/M_PI );
	double rotateRadians;
	MVector crvNormalRotated;
	MPointArray radiusPts;
	MPoint radiusPt;
	
	// Alternate method of getting the MFnNurbsCurve:
	MPlug curvePlug(thisNode, colliderCurveIn);
	MPlugArray inputCrvArray;
	curvePlug.connectedTo(inputCrvArray, true, false);
	
	MObject crvColliderObj = inputCrvArray[0].node();
	MFnNurbsCurve cColliderFn(crvColliderObj, &stat);
	if(!stat){
		MGlobal::displayInfo(MString("Error creating MFnNurbsCurve for collider curve"));
		return;
	}
	
	MFnDagNode crvDagNode(crvColliderObj);
	MDagPath crvDagPath;
	crvDagNode.getPath(crvDagPath);
	MMatrix crvXform = crvDagPath.inclusiveMatrix();
	
	int numSpans = cColliderFn.numSpans();
	
	MPoint crvPoint;
	MPoint crvPoint2;
	
	GLUquadricObj* qobj = gluNewQuadric();
	
	view.beginGL(); 
	

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//                  DRAW SMOOTH SHADED 
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
	if ( ( style == M3dView::kFlatShaded ) || ( style == M3dView::kGouraudShaded ) ) {
		glPushAttrib( GL_ALL_ATTRIB_BITS );
		glShadeModel(GL_SMOOTH);
		glEnable(GL_LIGHTING);
		glEnable(GL_BLEND);
		glEnable(GL_LIGHT0);
		glMatrixMode( GL_MODELVIEW );
		
		float3 color; 
		colorPlugR.getValue(color[0]);
		colorPlugG.getValue(color[1]);
		colorPlugB.getValue(color[2]);
		float transparency;
		colorPlugT.getValue(transparency);
		
		float  diffuse[] = {color[0], color[1], color[2], transparency};
		float  specular[] = { 0.7f, 0.7f, 0.7f, transparency};
		float  shine[] = { 100.0f };
		float  ambient[] = { 0.2f, 0.2f, 0.2f, transparency };
		
		glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
		glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shine);
		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
		
		// Draw the beginning and ending sphere caps
		glPushMatrix();
		cColliderFn.getPointAtParam(0, crvPoint, MSpace::kWorld);
		crvPoint = crvPoint*crvXform;
		glTranslatef(crvPoint.x, crvPoint.y, crvPoint.z);
		radiusElement = radiusPlug.elementByPhysicalIndex(0, &stat);
		radiusElement.getValue(radius);
		gluSphere(qobj, radius, 16, 16);
		glPopMatrix();

		glPushMatrix();
		cColliderFn.getPointAtParam(numSpans, crvPoint, MSpace::kWorld);
		crvPoint = crvPoint*crvXform;
		glTranslatef(crvPoint.x, crvPoint.y, crvPoint.z);
		radiusElement = radiusPlug.elementByPhysicalIndex( (radiusPlug.numElements() - 1), &stat);
		radiusElement.getValue(radius);
		gluSphere(qobj, radius, 16, 16);
		glPopMatrix();
	
		int numStacks = numSpans*30;
		int numSlices = 32;
	
		// Initialize our point array with the radius values
		radiusPts.clear();
		radiusPts.setLength(radiusPlug.numElements());
		for(int radiusItr = 0; radiusItr < radiusPlug.numElements(); radiusItr++){
			radiusElement = radiusPlug.elementByPhysicalIndex(radiusItr, &stat);
			if(!stat){MGlobal::displayError(MString("Could not get radius element.")); return;}
			radiusElement.getValue(radius);	
			radiusPt.x = (double)radius; radiusPt.y = 0.0; radiusPt.z = 0.0;
			radiusPts[radiusItr] = radiusPt;
		}
	
		if(numStacks>1){
			for(uint crvItr = 0; crvItr < numStacks - 1; crvItr++){
				
				param = (float(crvItr)/float(numStacks-1))*numSpans;
				param2 = (float(crvItr+1)/float(numStacks-1))*numSpans;
				cColliderFn.getPointAtParam(param, crvPoint, MSpace::kWorld);
				crvPoint = crvPoint*crvXform;
				cColliderFn.getPointAtParam(param2, crvPoint2, MSpace::kWorld);
				crvPoint2 = crvPoint2 * crvXform;
				
				// Determine the radius value 
				int lastRadiusIndex = radiusPlug.numElements() - 1;
				if(lastRadiusIndex == 0){
					radiusElement = radiusPlug.elementByPhysicalIndex(0, &stat);
					if(!stat){MGlobal::displayError(MString("Could not get radius element.")); return;}
					radiusElement.getValue(radius);
					radius2 = radius;
				}else if(lastRadiusIndex > 0){

					paramNorm = param/numSpans;
					radiusPt = getInterpolatedSplinePoint(paramNorm, radiusPts);
					radius = radiusPt.x;
					
					paramNorm = param2/numSpans;
					radiusPt  = getInterpolatedSplinePoint(paramNorm, radiusPts);
					radius2 = radiusPt.x;			
				}
					
				// First, we need to determine our starting position by travelling along the normal 
				MVector crvNormal = cColliderFn.normal(param, MSpace::kWorld);
				crvNormal = crvNormal * crvXform;
				MVector crvTangent = cColliderFn.tangent(param, MSpace::kWorld);
				crvTangent = crvTangent * crvXform;
				crvNormal.normalize();
				crvTangent.normalize();
				
				MVector crvNormal2 = cColliderFn.normal(param2, MSpace::kWorld);
				crvNormal2 = crvNormal2 * crvXform;
				MVector crvTangent2 = cColliderFn.tangent(param2, MSpace::kWorld);
				crvTangent2 = crvTangent2 * crvXform;
				crvNormal2.normalize();
				crvTangent2.normalize();
	//			glTranslatef(crvNormal.x, crvNormal.y, crvNormal.z);

				glBegin(GL_QUADS);
				for(int sliceItr = 0; sliceItr < numSlices; sliceItr++){
					// quad vertex 4
					rotateRadians = ((((float)sliceItr+1)/numSlices)*360)*degreesToRadians;
					rotateQuat.setAxisAngle(crvTangent, rotateRadians);
					crvNormalRotated = crvNormal.rotateBy(rotateQuat);
					glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z );
					glVertex3f((float)crvPoint.x + (crvNormalRotated.x*radius),
							   (float)crvPoint.y + (crvNormalRotated.y*radius),
							   (float)crvPoint.z + (crvNormalRotated.z*radius));		
					// quad vertex 3
					rotateRadians = ((((float)sliceItr+1)/numSlices)*360)*degreesToRadians;
					rotateQuat.setAxisAngle(crvTangent2, rotateRadians);
					crvNormalRotated = crvNormal.rotateBy(rotateQuat);
					glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z );
					glVertex3f((float)crvPoint2.x + (crvNormalRotated.x*radius2),
							   (float)crvPoint2.y + (crvNormalRotated.y*radius2),
							   (float)crvPoint2.z + (crvNormalRotated.z*radius2));
					// quad vertex 2
					rotateRadians = (((float)sliceItr/numSlices)*360)*degreesToRadians;
					rotateQuat.setAxisAngle(crvTangent2, rotateRadians);
					crvNormalRotated = crvNormal.rotateBy(rotateQuat);
					glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z );
					glVertex3f((float)crvPoint2.x + (crvNormalRotated.x*radius2),
							   (float)crvPoint2.y + (crvNormalRotated.y*radius2),
							   (float)crvPoint2.z + (crvNormalRotated.z*radius2));
					// quad vertex 1
					rotateRadians = (((float)sliceItr/numSlices)*360)*degreesToRadians;
					rotateQuat.setAxisAngle(crvTangent, rotateRadians);
					crvNormalRotated = crvNormal.rotateBy(rotateQuat);
					glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z );
					glVertex3f((float)crvPoint.x + (crvNormalRotated.x*radius),
							   (float)crvPoint.y + (crvNormalRotated.y*radius),
							   (float)crvPoint.z + (crvNormalRotated.z*radius));				
				}
				glEnd();
			}
		}
		glPopAttrib();
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//                  END SMOOTH SHADED 
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//                  DRAW WIREFRAME 
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
	if ( style == M3dView::kWireFrame ||  status == M3dView::kActive || status == M3dView::kLead) {
		glPushAttrib( GL_ALL_ATTRIB_BITS );

		// Draw the beginning and ending sphere caps
		// Quadrilateral strips
		glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
		glPushMatrix();
		cColliderFn.getPointAtParam(0, crvPoint, MSpace::kWorld);
		crvPoint = crvPoint*crvXform;
		glTranslatef(crvPoint.x, crvPoint.y, crvPoint.z);
		radiusElement = radiusPlug.elementByPhysicalIndex(0, &stat);
		radiusElement.getValue(radius);
		gluSphere(qobj, radius, 16, 16);
		glPopMatrix();
		
		glPushMatrix();
		cColliderFn.getPointAtParam(numSpans, crvPoint, MSpace::kWorld);
		crvPoint = crvPoint*crvXform;
		glTranslatef(crvPoint.x, crvPoint.y, crvPoint.z);
		radiusElement = radiusPlug.elementByPhysicalIndex( (radiusPlug.numElements() - 1), &stat);
		radiusElement.getValue(radius);
		gluSphere(qobj, radius, 16, 16);
		glPopMatrix();
		
	
		int numStacks = numSpans*10;
		int numSlices = 32;
		
		// Initialize our point array with the radius values
		radiusPts.clear();
		radiusPts.setLength(radiusPlug.numElements());
		for(int radiusItr = 0; radiusItr < radiusPlug.numElements(); radiusItr++){
			radiusElement = radiusPlug.elementByPhysicalIndex(radiusItr, &stat);
			if(!stat){MGlobal::displayError(MString("Could not get radius element.")); return;}
			radiusElement.getValue(radius);	
			radiusPt.x = (double)radius; radiusPt.y = 0.0; radiusPt.z = 0.0;
			radiusPts[radiusItr] = radiusPt;
		}
		
		for(uint crvItr = 0; crvItr < numStacks; crvItr++){
			
			param = (float(crvItr)/float(numStacks))*numSpans;
			param2 = (float(crvItr+1)/float(numStacks))*numSpans;
			cColliderFn.getPointAtParam(param, crvPoint, MSpace::kWorld);
			crvPoint = crvPoint*crvXform;
			cColliderFn.getPointAtParam(param2, crvPoint2, MSpace::kWorld);
			crvPoint2 = crvPoint2 * crvXform;
			
			// Determine the radius value 
			int lastRadiusIndex = radiusPlug.numElements() - 1;
			if(lastRadiusIndex == 0){
				radiusElement = radiusPlug.elementByPhysicalIndex(0, &stat);
				if(!stat){MGlobal::displayError(MString("Could not get radius element.")); return;}
				radiusElement.getValue(radius);
				radius2 = radius;
			}else if(lastRadiusIndex > 0){
				
				paramNorm = param/numSpans;
				radiusPt = getInterpolatedSplinePoint(paramNorm, radiusPts);
				radius = radiusPt.x;
				
				paramNorm = param2/numSpans;
				radiusPt  = getInterpolatedSplinePoint(paramNorm, radiusPts);
				radius2 = radiusPt.x;			
			}
			
			// First, we need to determine our starting position by travelling along the normal 
			MVector crvNormal = cColliderFn.normal(param, MSpace::kWorld);
			crvNormal = crvNormal * crvXform;
			MVector crvTangent = cColliderFn.tangent(param, MSpace::kWorld);
			crvTangent = crvTangent * crvXform;
			crvNormal.normalize();
			crvTangent.normalize();
			
			MVector crvNormal2 = cColliderFn.normal(param2, MSpace::kWorld);
			crvNormal2 = crvNormal2 * crvXform;
			MVector crvTangent2 = cColliderFn.tangent(param2, MSpace::kWorld);
			crvTangent2 = crvTangent2 * crvXform;
			crvNormal2.normalize();
			crvTangent2.normalize();
			//			glTranslatef(crvNormal.x, crvNormal.y, crvNormal.z);
			
			glBegin(GL_LINE_LOOP);
			for(int sliceItr = 0; sliceItr < numSlices; sliceItr++){
				// quad vertex 4
				rotateRadians = ((((float)sliceItr+1)/numSlices)*360)*degreesToRadians;
				rotateQuat.setAxisAngle(crvTangent, rotateRadians);
				crvNormalRotated = crvNormal.rotateBy(rotateQuat);
				glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z );
				glVertex3f((float)crvPoint.x + (crvNormalRotated.x*radius),
						   (float)crvPoint.y + (crvNormalRotated.y*radius),
						   (float)crvPoint.z + (crvNormalRotated.z*radius));		
				// quad vertex 3
				rotateRadians = ((((float)sliceItr+1)/numSlices)*360)*degreesToRadians;
				rotateQuat.setAxisAngle(crvTangent2, rotateRadians);
				crvNormalRotated = crvNormal.rotateBy(rotateQuat);
				glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z );
				glVertex3f((float)crvPoint2.x + (crvNormalRotated.x*radius2),
						   (float)crvPoint2.y + (crvNormalRotated.y*radius2),
						   (float)crvPoint2.z + (crvNormalRotated.z*radius2));
				// quad vertex 2
				rotateRadians = (((float)sliceItr/numSlices)*360)*degreesToRadians;
				rotateQuat.setAxisAngle(crvTangent2, rotateRadians);
				crvNormalRotated = crvNormal.rotateBy(rotateQuat);
				glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z );
				glVertex3f((float)crvPoint2.x + (crvNormalRotated.x*radius2),
						   (float)crvPoint2.y + (crvNormalRotated.y*radius2),
						   (float)crvPoint2.z + (crvNormalRotated.z*radius2));
				// quad vertex 1
				rotateRadians = (((float)sliceItr/numSlices)*360)*degreesToRadians;
				rotateQuat.setAxisAngle(crvTangent, rotateRadians);
				crvNormalRotated = crvNormal.rotateBy(rotateQuat);
				glNormal3f(crvNormalRotated.x, crvNormalRotated.y, crvNormalRotated.z );
				glVertex3f((float)crvPoint.x + (crvNormalRotated.x*radius),
						   (float)crvPoint.y + (crvNormalRotated.y*radius),
						   (float)crvPoint.z + (crvNormalRotated.z*radius));				
			}
			glEnd();
		}
		glPopAttrib();
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//                  END WIREFRAME 
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
//	glEnable(GL_LIGHT0);
	view.endGL();
}
Beispiel #12
0
MStatus fishVizNode::compute( const MPlug& plug, MDataBlock& data )
{    
    MStatus status;
	
	MObject arbitaryMesh = data.inputValue(aInMesh).asMesh();

	MDoubleArray ptc_time_offset;
	MDoubleArray ptc_amplitude;
	MDoubleArray ptc_bend;
	MDoubleArray ptc_scale;
	MDoubleArray masses;
	
	MString cacheName = data.inputValue(acachename, &status).asString();
	MTime currentTime = data.inputValue(atime, &status).asTime();
	cacheName = cacheName+"."+250*int(currentTime.value())+".pdc";
	
	pdcFile* fpdc = new pdcFile();
	if(fpdc->load(cacheName.asChar())==1)
	{
		//MGlobal::displayInfo(MString("FishViz loaded cache file: ")+cacheName);
		fpdc->readPositions(ptc_positions, ptc_velocities, ptc_ups, ptc_views, ptc_time_offset, ptc_amplitude, ptc_bend, ptc_scale, masses);
	}
	else MGlobal::displayWarning(MString("FishViz cannot open cache file: ")+cacheName);
	
	if(currentTime.value()!=int(currentTime.value())) 
	{
		float delta_t = currentTime.value()-int(currentTime.value());
		
		
		for(int i=0; i<fpdc->getParticleCount(); i++)
		{
			ptc_positions[i] += ptc_velocities[i]*delta_t/24.0f;
		}
	}
	
	delete fpdc;
	
	double flapping = zGetDoubleAttr(data, aFlapping);
	double bending= zGetDoubleAttr(data, aBending);
	double oscillate= zGetDoubleAttr(data, aOscillate);
	double length = zGetDoubleAttr(data, aLength);
	m_fish_length = length;
	double frequency = zGetDoubleAttr(data, aFrequency);
	unsigned num_bones = zGetIntAttr(data, aNBone);
	
	unsigned int nptc = ptc_positions.length();
	MPointArray vertices;
	MATRIX44F mat44, mat_bone;
	XYZ vert, front, up, side;
	MDataHandle outputHandle = data.outputValue(outMesh, &status);
	zCheckStatus(status, "ERROR getting polygon data handle\n");
	if(m_num_fish != nptc || m_num_bone != num_bones)
	{
		m_num_bone = num_bones;
		m_num_fish = nptc;
		unsigned int vertex_count;
		unsigned int face_count;
		MIntArray pcounts;
		MIntArray pconnect;
		
		
		
		unsigned  inmeshnv, inmeshnp;
		MPointArray pinmesh;
		MIntArray count_inmesh;
		MIntArray connect_inmesh;
		zWorks::extractMeshParams(arbitaryMesh, inmeshnv, inmeshnp, pinmesh, count_inmesh, connect_inmesh);
		vertex_count = inmeshnv * nptc;
		face_count = inmeshnp * nptc;
		
		for(unsigned int i=0; i<nptc; i++)
		{
			
			// calculate the bone transformations
			poseBones(length, num_bones, ptc_time_offset[i], frequency, ptc_amplitude[i], ptc_bend[i], flapping, bending, oscillate);
			
			front.x = ptc_views[i].x;
			front.y = ptc_views[i].y;
			front.z = ptc_views[i].z;
			up.x = ptc_ups[i].x;
			up.y = ptc_ups[i].y;
			up.z = ptc_ups[i].z;
			
			side = front.cross(up);
			side.normalize();
			
			up = side.cross(front);
			up.normalize();
			
			mat44.setIdentity();
			mat44.setOrientations(side, up, front);
			mat44.scale(ptc_scale[i]);
			mat44.setTranslation(ptc_positions[i].x, ptc_positions[i].y, ptc_positions[i].z);
			
			for(unsigned int j=0; j<inmeshnv; j++)
			{
				vert.x = pinmesh[j].x;
				vert.y = pinmesh[j].y;
				vert.z = pinmesh[j].z;
				
				int bone_id;
				if(vert.z>0) bone_id = 0;
				else if(-vert.z>length)  bone_id = num_bones-1;
				else bone_id = int(-vert.z/length*(num_bones-1));
				
				mat_bone = m_pBone->getBoneById(bone_id);
				vert.z -= -length/(num_bones-1)*bone_id;
				
				mat_bone.transform(vert);
				mat44.transform(vert);
				
				vertices.append(MPoint(vert.x, vert.y, vert.z));
			}
			for(unsigned int j=0; j<inmeshnp; j++)
			{
				pcounts.append(count_inmesh[j]);
			}
		}
		
		int acc=0;
		for(unsigned int i=0; i<nptc; i++)
		{
			for(unsigned int j=0; j<connect_inmesh.length(); j++)
			{
				pconnect.append(connect_inmesh[j]+acc);
			}
			acc += inmeshnv;
		}
		
		
		MObject m_mesh = outputHandle.asMesh();
		
		
		MFnMeshData dataCreator;
		MObject newOutputData = dataCreator.create(&status);
		zCheckStatusNR(status, "ERROR creating outputData");
		
		MFnMesh meshFn;
		m_mesh= meshFn.create(
		  vertex_count,				// number of vertices
		  face_count,		// number of polygons
		  vertices,			// The points
		  pcounts,			// # of vertex for each poly
		  pconnect,			// Vertices index for each poly
		  newOutputData,      // Dependency graph data object
		  &status
		  );
		
		zCheckStatusNR(status, "ERROE creating mesh");
		
		// Update surface 
		//
		outputHandle.set(newOutputData);
		
		
	}
	else
	{
		
		MObject m_mesh = outputHandle.asMesh();
		MFnMesh meshFn(m_mesh);

		unsigned  inmeshnv, inmeshnp;
		MPointArray pinmesh;
		MIntArray count_inmesh;
		MIntArray connect_inmesh;
		zWorks::extractMeshParams(arbitaryMesh, inmeshnv, inmeshnp, pinmesh, count_inmesh, connect_inmesh);
		vertices.setLength(nptc*inmeshnv);
		int acc=0;
		for(unsigned int i=0; i<nptc; i++)
		{
			// calculate the bone transformations
			poseBones(length, num_bones, ptc_time_offset[i], frequency, ptc_amplitude[i], ptc_bend[i], flapping, bending, oscillate);
			
			front.x = ptc_views[i].x;
			front.y = ptc_views[i].y;
			front.z = ptc_views[i].z;
			up.x = ptc_ups[i].x;
			up.y = ptc_ups[i].y;
			up.z = ptc_ups[i].z;
			
			side = front.cross(up);
			side.normalize();
			
			up = side.cross(front);
			up.normalize();
			
			mat44.setIdentity();
			mat44.setOrientations(side, up, front);
			mat44.scale(ptc_scale[i]);
			mat44.setTranslation(ptc_positions[i].x, ptc_positions[i].y, ptc_positions[i].z);
			
			for(unsigned int j=0; j<inmeshnv; j++)
			{
				vert.x = pinmesh[j].x;
				vert.y = pinmesh[j].y;
				vert.z = pinmesh[j].z;
				
				int bone_id;
				if(vert.z>0) bone_id = 0;
				else if(-vert.z>length)  bone_id = num_bones-1;
				else bone_id = int(-vert.z/length*(num_bones-1));
				
				mat_bone = m_pBone->getBoneById(bone_id);
				vert.z -= -length/(num_bones-1)*bone_id;
				
				mat_bone.transform(vert);
				mat44.transform(vert);
				
				vertices[j+acc] = MPoint(vert.x, vert.y, vert.z);
			}
			acc += inmeshnv;
		}
		
		meshFn.setPoints(vertices);
		outputHandle.set(meshFn.object());
		
		
		
	}
	//delete fmat;
	data.setClean( plug );
	
	
	return MS::kSuccess;
}