bool SplineData::UpdateNode(INode *node)
{
	if (mReset)
	{
		mReset = false;
		return AddNode(node);
	}
	else
	{
		TimeValue t  = GetCOREInterface()->GetTime();
		Interval valid;
		Matrix3 tm = node->GetObjectTM(t,&valid);
		ObjectState nos = node->EvalWorldState(t);
		//make sure it is a shape
		if (nos.obj->IsShapeObject()) 
		{
			ShapeObject *pathOb = (ShapeObject*)nos.obj;
			pathOb->MakePolyShape(t, mShapeCache,32,FALSE);
			mShapeCache.Transform(tm);
			int numberOfCurves = pathOb->NumberOfCurves();
			for (int i = 0; i < numberOfCurves; i++)
			{
				//just rebuild our cache info
				mSplineElementData[i]->ResetBoundingBox();
				mSplineElementData[i]->SetLineCache(&mShapeCache.lines[i]);
				mSplineElementData[i]->ComputePlanarUp(mPlanarMapUp);
				if (pathOb->CurveClosed(t,i))
					mSplineElementData[i]->SetClosed(true);
				else mSplineElementData[i]->SetClosed(false);

				mSplineElementData[i]->Select(FALSE);
			}
			//now rebuild our derived cross sections
			RecomputeCrossSections();
			if (mActiveSpline >= numberOfCurves)
				mActiveSpline = 0;
			mSplineElementData[mActiveSpline]->Select(TRUE);
			return true;
		}
	}
	return false;
}
bool SplineData::AddNode(INode *node)
{
	//see if the node is a shape object
	if (node != NULL) 
	{
		TimeValue t  = GetCOREInterface()->GetTime();
		Interval valid;
		Matrix3 tm = node->GetObjectTM(t,&valid);
		ObjectState nos = node->EvalWorldState(t);
		if (nos.obj->IsShapeObject()) 
		{
			ShapeObject *pathOb = (ShapeObject*)nos.obj;
			int numberOfCurves = pathOb->NumberOfCurves();
			//get number of splines
			if (numberOfCurves != 0) 
			{
				pathOb->MakePolyShape(t, mShapeCache,32,FALSE);
				mShapeCache.Transform(tm);
				mSplineElementData.SetCount(numberOfCurves);
				for (int i = 0; i < numberOfCurves; i++)
					mSplineElementData[i] = NULL;

				for (int i = 0; i < numberOfCurves; i++)
				{

					Box3 bounds;
					bounds.Init();

					//sample the shape object
					int numberOfCurves = pathOb->NumberOfPieces(t, i);
					if (numberOfCurves != 0)
					{

						mSplineElementData[i] = new SplineElementData();
						
						mSplineElementData[i]->ResetBoundingBox();
						mSplineElementData[i]->SetLineCache(&mShapeCache.lines[i]);
						mSplineElementData[i]->ComputePlanarUp(mPlanarMapUp);
						mSplineElementData[i]->SetNumCurves(numberOfCurves);
						mSplineElementData[i]->SetNumberOfCrossSections(numberOfCurves+1);
						if (pathOb->CurveClosed(t,i))
							mSplineElementData[i]->SetClosed(true);
						else mSplineElementData[i]->SetClosed(false);
						float curveLength = pathOb->LengthOfCurve(t,i);

						float runningLength = 0.0f;
						Quat q;
						q.Identity();
						mSplineElementData[i]->SetCrossSection(0,Point3(0.0f,0.0f,0.0f),Point2(20.0f,20.0f),q);
						for (int j = 0; j < numberOfCurves; j++)
						{
							float u = runningLength/curveLength;
							mSplineElementData[i]->SetCrossSection(j,Point3(0.0f,0.0f,u),Point2(20.0f,20.0f),q);
							Point3 lastPoint = pathOb->InterpPiece3D(t,i,j,0.0f,PARAM_NORMALIZED);
							bounds += lastPoint;
							float runningU = 0.0f;
							float inc = 1.0f/(float)(mSampleRate-1);
							for (int k = 1; k < mSampleRate; k++)
							{								
								runningU += inc;
								Point3 p = pathOb->InterpPiece3D(t,i,j,runningU,PARAM_NORMALIZED);
								runningLength += Length(p-lastPoint);
								lastPoint = p;
								bounds += lastPoint;
							}


						}

						mSplineElementData[i]->SetCrossSection(numberOfCurves,Point3(0.0f,0.0f,1.0f),Point2(20.0f,20.0f),q);
						mSplineElementData[i]->Select(FALSE);

					}
				}

				if (mActiveSpline >= numberOfCurves)
					mActiveSpline = 0;
				mSplineElementData[mActiveSpline]->Select(TRUE);

				//build our bounding box
				RecomputeCrossSections();

				return true;
			}
		}
	}

	return false;

}
Example #3
0
bool AlembicCurves::Save(double time, bool bLastFrame)
{
    ESS_PROFILE_FUNC();

    //TimeValue ticks = GET_MAX_INTERFACE()->GetTime();
    TimeValue ticks = GetTimeValueFromFrame(time);
	Object *obj = mMaxNode->EvalWorldState(ticks).obj;
	if(mNumSamples == 0){
		bForever = CheckIfObjIsValidForever(obj, ticks);
	}
	else{
		bool bNewForever = CheckIfObjIsValidForever(obj, ticks);
		if(bForever && bNewForever != bForever){
			ESS_LOG_INFO( "bForever has changed" );
		}
	}

	SaveMetaData(mMaxNode, this);

    // check if the spline is animated
    if(mNumSamples > 0) 
    {
        if(bForever)
        {
            return true;
        }
    }

    AbcG::OCurvesSchema::Sample curvesSample;

	std::vector<AbcA::int32_t> nbVertices;
    std::vector<Point3> vertices;
    std::vector<float> knotVector;
    std::vector<Abc::uint16_t> orders;

    if(obj->ClassID() == EDITABLE_SURF_CLASS_ID){

       NURBSSet nurbsSet;   
       BOOL success = GetNURBSSet(obj, ticks, nurbsSet, TRUE);   

       AbcG::CurvePeriodicity cPeriod = AbcG::kNonPeriodic;
       AbcG::CurveType cType = AbcG::kCubic;
       AbcG::BasisType cBasis = AbcG::kNoBasis;

       int n = nurbsSet.GetNumObjects();
       for(int i=0; i<n; i++){
          NURBSObject* pObject = nurbsSet.GetNURBSObject((int)i);

          //NURBSType type = pObject->GetType();
          if(!pObject){
             continue;
          }

          if( pObject->GetKind() == kNURBSCurve ){
             NURBSCurve* pNurbsCurve = (NURBSCurve*)pObject;

             int degree;
             int numCVs;
             NURBSCVTab cvs;
			 int numKnots;
		     NURBSKnotTab knots;
             pNurbsCurve->GetNURBSData(ticks, degree, numCVs, cvs, numKnots, knots);

             orders.push_back(degree+1);

             const int cvsCount = cvs.Count();
             const int knotCount = knots.Count();

             for(int j=0; j<cvs.Count(); j++){
                NURBSControlVertex cv = cvs[j];
                double x, y, z;
                cv.GetPosition(ticks, x, y, z);
                vertices.push_back( Point3((float)x, (float)y, (float)z) );
             }

             nbVertices.push_back(cvsCount);

             //skip the first and last entry because Maya and XSI use this format
             for(int j=1; j<knots.Count()-1; j++){
                knotVector.push_back((float)knots[j]);
             }

             if(i == 0){
                if(pNurbsCurve->IsClosed()){
                   cPeriod = AbcG::kPeriodic;
                }  
             }
             else{
                if(pNurbsCurve->IsClosed()){
                   if(cPeriod != AbcG::kPeriodic){
                      ESS_LOG_WARNING("Mixed curve wrap types not supported.");
                   }
                }
                else{
                   if(cPeriod != AbcG::kNonPeriodic){
                      ESS_LOG_WARNING("Mixed curve wrap types not supported.");
                   }
                }
             }

          }
          
       }
       

       curvesSample.setType(cType);
       curvesSample.setWrap(cPeriod);
       curvesSample.setBasis(cBasis);
    }
    else
    {
          BezierShape beziershape;
          PolyShape polyShape;
          bool bBezier = false;

          // Get a pointer to the spline shpae
          ShapeObject *pShapeObject = NULL;
          if (obj->IsShapeObject())
          {
              pShapeObject = reinterpret_cast<ShapeObject *>(obj);
          }
          else
          {
              return false;
          }

          // Determine if we are a bezier shape
          if (pShapeObject->CanMakeBezier())
          {
              pShapeObject->MakeBezier(ticks, beziershape);
              bBezier = true;
          }
          else
          {
              pShapeObject->MakePolyShape(ticks, polyShape);
              bBezier = false;
          }

          // Get the control points

          //std::vector<Point3> inTangents;
	      //std::vector<Point3> outTangents;
          if (bBezier)
          {
              int oldVerticesCount = (int)vertices.size();
              for (int i = 0; i < beziershape.SplineCount(); i += 1)
              {
                  Spline3D *pSpline = beziershape.GetSpline(i);
                  int knots = pSpline->KnotCount();
                  for(int ix = 0; ix < knots; ++ix) 
                  {
                      Point3 in = pSpline->GetInVec(ix);
                      Point3 p = pSpline->GetKnotPoint(ix);
                      Point3 out = pSpline->GetOutVec(ix);

                      vertices.push_back( p );
				      //inTangents.push_back( in );
				      //outTangents.push_back( out );
                  }

                  int nNumVerticesAdded = (int)vertices.size() - oldVerticesCount;
                  nbVertices.push_back( nNumVerticesAdded );
                  oldVerticesCount = (int)vertices.size();
              }
          }
          else
          {
              for (int i = 0; i < polyShape.numLines; i += 1)
              {
                  PolyLine &refLine = polyShape.lines[i];
                  nbVertices.push_back(refLine.numPts);
                  for (int j = 0; j < refLine.numPts; j += 1)
                  {
                      Point3 p = refLine.pts[j].p;
                      vertices.push_back(p);
                  }
              }
          }

          // set the type + wrapping
	      curvesSample.setType(bBezier ? AbcG::kCubic : AbcG::kLinear);
          curvesSample.setWrap(pShapeObject->CurveClosed(ticks, 0) ? AbcG::kPeriodic : AbcG::kNonPeriodic);
          curvesSample.setBasis(AbcG::kNoBasis);
    }

    if(nbVertices.size() == 0 || vertices.size() == 0){
       ESS_LOG_WARNING("No curve data to export.");
       return false;
    }
 

    const int vertCount = (int)vertices.size();

    // prepare the bounding box
    Abc::Box3d bbox;

    // allocate the points and normals
    std::vector<Abc::V3f> posVec(vertCount);
    Matrix3 wm = mMaxNode->GetObjTMAfterWSM(ticks);

    for(int i=0;i<vertCount;i++)
    {
        posVec[i] = ConvertMaxPointToAlembicPoint(vertices[i] );
        bbox.extendBy(posVec[i]);

        // Set the archive bounding box
        if (mJob)
        {
            Point3 worldMaxPoint = wm * vertices[i];
            Abc::V3f alembicWorldPoint = ConvertMaxPointToAlembicPoint(worldMaxPoint);
            mJob->GetArchiveBBox().extendBy(alembicWorldPoint);
        }
    }

    if(knotVector.size() > 0 && orders.size() > 0){
       if(!mKnotVectorProperty.valid()){
          mKnotVectorProperty = Abc::OFloatArrayProperty(mCurvesSchema.getArbGeomParams(), ".knot_vector", mCurvesSchema.getMetaData(), mJob->GetAnimatedTs() );
       }
       mKnotVectorProperty.set(Abc::FloatArraySample(knotVector));

       if(!mOrdersProperty.valid()){
          mOrdersProperty = Abc::OUInt16ArrayProperty(mCurvesSchema.getArbGeomParams(), ".orders", mCurvesSchema.getMetaData(), mJob->GetAnimatedTs() );
       }
       mOrdersProperty.set(Abc::UInt16ArraySample(orders));
    }

    // store the bbox
    curvesSample.setSelfBounds(bbox);
	mCurvesSchema.getChildBoundsProperty().set(bbox);

 
    Abc::Int32ArraySample nbVerticesSample(&nbVertices.front(),nbVertices.size());
    curvesSample.setCurvesNumVertices(nbVerticesSample);


 
    // allocate for the points and normals
    Abc::P3fArraySample posSample(&posVec.front(),posVec.size());
	curvesSample.setPositions(posSample);


    mCurvesSchema.set(curvesSample);

   mNumSamples++;

   return true;
}
Example #4
0
//[-------------------------------------------------------]
//[ Private virtual PLSceneNode functions                 ]
//[-------------------------------------------------------]
void PLSceneSpline::WriteToFile(XmlElement &cSceneElement, const String &sApplicationDrive, const String &sApplicationDir)
{
	// Do NOT save it as scene node, it's just a 'resource'

	// Get path filename
	const String sFilename = sApplicationDrive + sApplicationDir + PLTools::GetResourceFilename(PLTools::ResourcePath, GetName() + ".path");

	// Get the IGame spline object of the given IGame node
	IGameObject *pIGameObject = GetIGameNode()->GetIGameObject();
	if (pIGameObject) {
		// Check the type of the IGame object
		if (pIGameObject->GetIGameType() == IGameObject::IGAME_SPLINE && pIGameObject->InitializeData()) {
			IGameSpline &cIGameSpline = *static_cast<IGameSpline*>(pIGameObject);
			if (cIGameSpline.GetNumberOfSplines () > 0) {
				// We only support spline 0
				IGameSpline3D *pIGameSpline3D = cIGameSpline.GetIGameSpline3D(0);
				if (pIGameSpline3D) {
					// Get the local transform matrix
					GMatrix mTransform = cIGameSpline.GetIGameObjectTM();

					// Get the 3ds Max shape object
					ShapeObject *pMaxShapeObject = static_cast<ShapeObject*>(pIGameObject->GetMaxObject()->ConvertToType(TIME_PosInfinity, Class_ID(GENERIC_SHAPE_CLASS_ID, 0)));
					if (pMaxShapeObject != nullptr && pMaxShapeObject->NumberOfCurves() == cIGameSpline.GetNumberOfSplines()) {
						// Create XML document
						XmlDocument cDocument;

						// Add declaration
						XmlDeclaration *pDeclaration = new XmlDeclaration("1.0", "ISO-8859-1", "");
						cDocument.LinkEndChild(*pDeclaration);

						// Add path
						XmlElement *pPathElement = new XmlElement("Path");

						// Setup attributes
						pPathElement->SetAttribute("Version", "1");
						pPathElement->SetAttribute("Closed",  String::Format("%d", pMaxShapeObject->CurveClosed(0, 0)));

						// Add all nodes
						for (int nKnot=0; nKnot<pIGameSpline3D->GetIGameKnotCount(); nKnot++) {
							IGameKnot *pIGameKnot = pIGameSpline3D->GetIGameKnot(nKnot);
							if (pIGameKnot) {
								// Get knot point in object space (although it is not documented it looks like object space...)
								Point3 cPoint = pIGameKnot->GetKnotPoint();

								// We really need to flip the coordinates to OpenGL style, IGame is not doing this automatically...
								cPoint = PLTools::Convert3dsMaxVectorToOpenGLVector(cPoint);

								// Transform to world space
								cPoint = cPoint*mTransform;

								// If there's a parent container, make the position of this scene node relative to it
								PLSceneContainer *pContainer = GetContainer();
								if (pContainer)
									cPoint -= pContainer->GetWorldSpaceCenter();

								// Add node
								XmlElement *pNodeElement = new XmlElement("Node");
								pNodeElement->SetAttribute("Name",     String::Format("%d",       nKnot));
								pNodeElement->SetAttribute("Position", String::Format("%f %f %f", cPoint.x, cPoint.y, cPoint.z));

								// Link general element
								pPathElement->LinkEndChild(*pNodeElement);
							}
						}

						// Link material element
						cDocument.LinkEndChild(*pPathElement);

						// Save settings
						if (cDocument.Save(sFilename))
							g_pLog->LogFLine(PLLog::Hint, "Created '%s'", sFilename.GetASCII());
						else
							g_pLog->LogFLine(PLLog::Error, "Can't create '%s'!", sFilename.GetASCII());
					}
				}
			}
		} else {
			g_pLog->LogFLine(PLLog::Error, "%s: IGame object is no known spline object!", GetIGameNode()->GetName());
		}

		// Release the IGame object
		GetIGameNode()->ReleaseIGameObject();
	} else {
		g_pLog->LogFLine(PLLog::Error, "%s: IGame node has no IGame object!", GetIGameNode()->GetName());
	}
}