예제 #1
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;
}
예제 #2
0
bool AlembicPoints::Save(double time, bool bLastFrame)
{
   ESS_PROFILE_FUNC();

    // Note: Particles are always considered to be animated even though
    //       the node does not have the IsAnimated() flag.

    // Extract our particle emitter at the given time
    TimeValue ticks = GetTimeValueFromFrame(time);
    Object *obj = mMaxNode->EvalWorldState(ticks).obj;

	SaveMetaData(mMaxNode, this);

	SimpleParticle* pSimpleParticle = (SimpleParticle*)obj->GetInterface(I_SIMPLEPARTICLEOBJ);
	IPFSystem* ipfSystem = GetPFSystemInterface(obj);
	IParticleObjectExt* particlesExt = GetParticleObjectExtInterface(obj);
	
#ifdef THINKING_PARTICLES
	ParticleMat* pThinkingParticleMat = NULL;
	TP_MasterSystemInterface* pTPMasterSystemInt = NULL;
	if(obj->CanConvertToType(MATTERWAVES_CLASS_ID))
	{
		pThinkingParticleMat = reinterpret_cast<ParticleMat*>(obj->ConvertToType(ticks, MATTERWAVES_CLASS_ID));
		pTPMasterSystemInt = reinterpret_cast<TP_MasterSystemInterface*>(obj->GetInterface(IID_TP_MASTERSYSTEM));     

	}
#endif

	const bool bAutomaticInstancing = GetCurrentJob()->GetOption("automaticInstancing");

	if( 
#ifdef THINKING_PARTICLES
		!pThinkingParticleMat && 
#endif
		!particlesExt && !pSimpleParticle){
		return false;
	}


	//We have to put the particle system into the renders state so that PFOperatorMaterialFrequency::Proceed will set the materialID channel
	//Note: settting the render state to true breaks the shape node instancing export
	bool bRenderStateForced = false;
	if(bAutomaticInstancing && ipfSystem && !ipfSystem->IsRenderState()){
		ipfSystem->SetRenderState(true);
		bRenderStateForced = true;
	}

	int numParticles = 0;
#ifdef THINKING_PARTICLES
	if(pThinkingParticleMat){
		numParticles = pThinkingParticleMat->NumParticles();	
	}
	else 
#endif
	if(particlesExt){
		particlesExt->UpdateParticles(mMaxNode, ticks);
		numParticles = particlesExt->NumParticles();
	}
	else if(pSimpleParticle){
		pSimpleParticle->Update(ticks, mMaxNode);
		numParticles = pSimpleParticle->parts.points.Count();
	}


    // Store positions, velocity, width/size, scale, id, bounding box
    std::vector<Abc::V3f> positionVec;
    std::vector<Abc::V3f> velocityVec;
    std::vector<Abc::V3f> scaleVec;
    std::vector<float> widthVec;
    std::vector<float> ageVec;
    std::vector<float> massVec;
    std::vector<float> shapeTimeVec;
    std::vector<Abc::uint64_t> idVec;
    std::vector<Abc::uint16_t> shapeTypeVec;
    std::vector<Abc::uint16_t> shapeInstanceIDVec;
    std::vector<Abc::Quatf> orientationVec;
    std::vector<Abc::Quatf> angularVelocityVec;
    std::vector<Abc::C4f> colorVec;

    positionVec.reserve(numParticles);
    velocityVec.reserve(numParticles);
    scaleVec.reserve(numParticles);
    widthVec.reserve(numParticles);
    ageVec.reserve(numParticles);
    massVec.reserve(numParticles);
    shapeTimeVec.reserve(numParticles);
    idVec.reserve(numParticles);
    shapeTypeVec.reserve(numParticles);
    shapeInstanceIDVec.reserve(numParticles);
    orientationVec.reserve(numParticles);
    angularVelocityVec.reserve(numParticles);
    colorVec.reserve(numParticles);

    //std::vector<std::string> instanceNamesVec;
    Abc::Box3d bbox;
    bool constantPos = true;
    bool constantVel = true;
    bool constantScale = true;
    bool constantWidth = true;
    bool constantAge = true;
    bool constantOrientation = true;
    bool constantAngularVel = true;
	bool constantColor = true;


	if(bAutomaticInstancing){
		SetMaxSceneTime(ticks);
	}

	//The MAX interfaces return everything in world coordinates,
	//so we need to multiply the inverse the node world transform matrix
    Matrix3 nodeWorldTM = mMaxNode->GetObjTMAfterWSM(ticks);
    // Convert the max transform to alembic
    Matrix3 alembicMatrix;
    ConvertMaxMatrixToAlembicMatrix(nodeWorldTM, alembicMatrix);
    Abc::M44d nodeWorldTrans(	alembicMatrix.GetRow(0).x,  alembicMatrix.GetRow(0).y,  alembicMatrix.GetRow(0).z,  0,
										alembicMatrix.GetRow(1).x,  alembicMatrix.GetRow(1).y,  alembicMatrix.GetRow(1).z,  0,
										alembicMatrix.GetRow(2).x,  alembicMatrix.GetRow(2).y,  alembicMatrix.GetRow(2).z,  0,
										alembicMatrix.GetRow(3).x,  alembicMatrix.GetRow(3).y,  alembicMatrix.GetRow(3).z,  1);
	Abc::M44d nodeWorldTransInv = nodeWorldTrans.inverse();


	//ESS_LOG_WARNING("tick: "<<ticks<<"   numParticles: "<<numParticles<<"\n");

	ExoNullView nullView;
	particleGroupInterface groupInterface(particlesExt, obj, mMaxNode, &nullView);

    {
    ESS_PROFILE_SCOPE("AlembicPoints::SAVE - numParticlesLoop");

	for (int i = 0; i < numParticles; ++i)
	{
		Abc::V3f pos(0.0);
		Abc::V3f vel(0.0);
		Abc::V3f scale(1.0);
		Abc::C4f color(0.5, 0.5, 0.5, 1.0);
		float age = 0;
		Abc::uint64_t id = 0;
	    Abc::Quatd orientation(0.0, 0.0, 1.0, 0.0);
		Abc::Quatd spin(0.0, 0.0, 1.0, 0.0);
		// Particle size is a uniform scale multiplier in XSI.  In Max, I need to learn where to get this 
		// For now, we'll just default to 1
		float width = 1.0f;

		ShapeType shapetype = ShapeType_Point;
		float shapeInstanceTime = (float)time;
		Abc::uint16_t shapeInstanceId = 0;

#ifdef THINKING_PARTICLES
		if(pThinkingParticleMat){
            

			if(pTPMasterSystemInt->IsAlive(i) == FALSE){
				continue;
			}

			//TimeValue ageValue = particlesExt->GetParticleAgeByIndex(i);
			TimeValue ageValue = pTPMasterSystemInt->Age(i);
			if(ageValue == -1){
				continue;
			}

            ESS_PROFILE_SCOPE("AlembicPoints::SAVE - numParticlesLoop - ThinkingParticles");
			age = (float)GetSecondsFromTimeValue(ageValue);

			//pos = ConvertMaxPointToAlembicPoint(*particlesExt->GetParticlePositionByIndex(i));
			pos = ConvertMaxPointToAlembicPoint(pTPMasterSystemInt->Position(i));
			//vel = ConvertMaxVectorToAlembicVector(*particlesExt->GetParticleSpeedByIndex(i) * TIME_TICKSPERSEC);
			vel = ConvertMaxVectorToAlembicVector(pTPMasterSystemInt->Velocity(i) * TIME_TICKSPERSEC);
			scale = ConvertMaxScaleToAlembicScale(pTPMasterSystemInt->Scale(i));
			scale *= pTPMasterSystemInt->Size(i);
			
			//ConvertMaxEulerXYZToAlembicQuat(*particlesExt->GetParticleOrientationByIndex(i), orientation);

			Matrix3 alignmentMatMax = pTPMasterSystemInt->Alignment(i);
			Abc::M44d alignmentMat;
			ConvertMaxMatrixToAlembicMatrix(alignmentMatMax, alignmentMat);
			/*alignmentMat = Abc::M44d( alignmentMatMax.GetRow(0).x,  alignmentMatMax.GetRow(0).y,  alignmentMatMax.GetRow(0).z,  0,
                                 alignmentMatMax.GetRow(1).x,  alignmentMatMax.GetRow(1).y,  alignmentMatMax.GetRow(1).z,  0,
                                 alignmentMatMax.GetRow(2).x,  alignmentMatMax.GetRow(2).y,  alignmentMatMax.GetRow(2).z,  0,
                                 alignmentMatMax.GetRow(3).x,  alignmentMatMax.GetRow(3).y,  alignmentMatMax.GetRow(3).z,  1);*/
			//orientation = ConvertMaxQuatToAlembicQuat(extracctuat(alignmentMat), true);

			alignmentMat = alignmentMat * nodeWorldTransInv;
			orientation = extractQuat(alignmentMat);

			//ConvertMaxAngAxisToAlembicQuat(*particlesExt->GetParticleSpinByIndex(i), spin);
			ConvertMaxAngAxisToAlembicQuat(pTPMasterSystemInt->Spin(i), spin);


			id = particlesExt->GetParticleBornIndex(i);

			//seems to always return 0
			//int nPid = pThinkingParticleMat->ParticleID(i);
					
			int nMatId = -1;
			Matrix3 meshTM;
			meshTM.IdentityMatrix();
			BOOL bNeedDelete = FALSE;
			BOOL bChanged = FALSE;
            Mesh* pMesh = NULL;
            {
            ESS_PROFILE_SCOPE("AlembicPoints::SAVE - numParticlesLoop - ThinkingParticles - GetParticleRenderMesh");
			pMesh = pThinkingParticleMat->GetParticleRenderMesh(ticks, mMaxNode, nullView, bNeedDelete, i, meshTM, bChanged);
            }

			if(pMesh){
                ESS_PROFILE_SCOPE("AlembicPoints::SAVE - numParticlesLoop - ThinkingParticles - CacheShapeMesh");
            meshInfo mi = CacheShapeMesh(pMesh, bNeedDelete, meshTM, nMatId, i, ticks, shapetype, shapeInstanceId, shapeInstanceTime);
            Abc::V3d min = pos + mi.bbox.min;
            Abc::V3d max = pos + mi.bbox.max;
            bbox.extendBy(min);
            bbox.extendBy(max);
			}
			else{
				shapetype = ShapeType_Point;
			}
		}
		else 
#endif
		if(particlesExt && ipfSystem){

			TimeValue ageValue = particlesExt->GetParticleAgeByIndex(i);
			if(ageValue == -1){
				continue;
			}
			age = (float)GetSecondsFromTimeValue(ageValue);

			pos = ConvertMaxPointToAlembicPoint(*particlesExt->GetParticlePositionByIndex(i));
			vel = ConvertMaxVectorToAlembicVector(*particlesExt->GetParticleSpeedByIndex(i) * TIME_TICKSPERSEC);
			scale = ConvertMaxScaleToAlembicScale(*particlesExt->GetParticleScaleXYZByIndex(i));
			ConvertMaxEulerXYZToAlembicQuat(*particlesExt->GetParticleOrientationByIndex(i), orientation);
			ConvertMaxAngAxisToAlembicQuat(*particlesExt->GetParticleSpinByIndex(i), spin);
			//age = (float)GetSecondsFromTimeValue(particlesExt->GetParticleAgeByIndex(i));
			id = particlesExt->GetParticleBornIndex(i);
			if(bAutomaticInstancing){

				int nMatId = -1;
				if(ipfSystem){
					if( groupInterface.setCurrentParticle(ticks, i) ){
						nMatId = groupInterface.getCurrentMtlId();
					}
					else{
						ESS_LOG_WARNING("Error: cound retrieve material ID for particle mesh "<<i);
					}
				}

				Matrix3 meshTM;
				meshTM.IdentityMatrix();
				BOOL bNeedDelete = FALSE;
				BOOL bChanged = FALSE;
				Mesh* pMesh = pMesh = particlesExt->GetParticleShapeByIndex(i);

				if(pMesh){
					meshInfo mi = CacheShapeMesh(pMesh, bNeedDelete, meshTM, nMatId, i, ticks, shapetype, shapeInstanceId, shapeInstanceTime);
               Abc::V3d min = pos + mi.bbox.min;
               Abc::V3d max = pos + mi.bbox.max;
               bbox.extendBy(min);
               bbox.extendBy(max);
				}
				else{
					shapetype = ShapeType_Point;
				}
			}
			else{
				GetShapeType(particlesExt, i, ticks, shapetype, shapeInstanceId, shapeInstanceTime);
			}
			color = GetColor(particlesExt, i, ticks);
		}
		else if(pSimpleParticle){
			if( ! pSimpleParticle->parts.Alive( i ) ) {
				continue;
			}

			pos = ConvertMaxPointToAlembicPoint(pSimpleParticle->ParticlePosition(ticks, i));
			vel = ConvertMaxVectorToAlembicVector(pSimpleParticle->ParticleVelocity(ticks, i));
			//simple particles have no scale?
			//simple particles have no orientation?
			age = (float)GetSecondsFromTimeValue( pSimpleParticle->ParticleAge(ticks, i) );
			//simple particles have born index
			width = pSimpleParticle->ParticleSize(ticks, i);

         Abc::V3d min(pos.x - width/2, pos.y - width/2, pos.z - width/2);
         Abc::V3d max(pos.x + width/2, pos.y + width/2, pos.z + width/2);
         bbox.extendBy(min);
         bbox.extendBy(max);
		}

        {
        ESS_PROFILE_SCOPE("AlembicPoints::SAVE - numParticlesLoop - end loop save");

		//move everything from world space to local space
		pos = pos * nodeWorldTransInv;

		Abc::V4f vel4(vel.x, vel.y, vel.z, 0.0);
		vel4 = vel4 * nodeWorldTransInv;
		vel.setValue(vel4.x, vel4.y, vel4.z);

		//scale = scale * nodeWorldTransInv;
		//orientation = Abc::extractQuat(orientation.toMatrix44() * nodeWorldTransInv);
		//spin = Abc::extractQuat(spin.toMatrix44() * nodeWorldTransInv);

		bbox.extendBy( pos );




		positionVec.push_back( pos );
		velocityVec.push_back( vel );
		scaleVec.push_back( scale );
		widthVec.push_back( width );
		ageVec.push_back( age );
		idVec.push_back( id );
		orientationVec.push_back( orientation );
		angularVelocityVec.push_back( spin );

        shapeTypeVec.push_back( shapetype );
        shapeInstanceIDVec.push_back( shapeInstanceId );
        shapeTimeVec.push_back( shapeInstanceTime );
		colorVec.push_back( color );

		constantPos &= (pos == positionVec[0]);
		constantVel &= (vel == velocityVec[0]);
		constantScale &= (scale == scaleVec[0]);
		constantWidth &= (width == widthVec[0]);
		constantAge &= (age == ageVec[0]);
		constantOrientation &= (orientation == orientationVec[0]);
		constantAngularVel &= (spin == angularVelocityVec[0]);
		constantColor &= (color == colorVec[0]);

		// Set the archive bounding box
		// Positions for particles are already cnsider to be in world space
		if (mJob)
		{
			mJob->GetArchiveBBox().extendBy(pos);
		}

        }
	}

    }

  //  if (numParticles > 1)
  //  {
  //     ESS_PROFILE_SCOPE("AlembicPoints::Save - vectorResize");
  //      if (constantPos)        { positionVec.resize(1); }
  //      if (constantVel)        { velocityVec.resize(1); }
  //      if (constantScale)      { scaleVec.resize(1); }
  //      if (constantWidth)      { widthVec.resize(1); }
  //      if (constantAge)        { ageVec.resize(1); }
  //      if (constantOrientation){ orientationVec.resize(1); }
  //      if (constantAngularVel) { angularVelocityVec.resize(1); }
		//if (constantColor)		{ colorVec.resize(1); }
  //  }

    {
    ESS_PROFILE_SCOPE("AlembicPoints::Save - sample writing");
    // Store the information into our properties and points schema
    Abc::P3fArraySample positionSample( positionVec);
    Abc::P3fArraySample velocitySample(velocityVec);
    Abc::P3fArraySample scaleSample(scaleVec);
    Abc::FloatArraySample widthSample(widthVec);
    Abc::FloatArraySample ageSample(ageVec);
    Abc::FloatArraySample massSample(massVec);
    Abc::FloatArraySample shapeTimeSample(shapeTimeVec);
    Abc::UInt64ArraySample idSample(idVec);
    Abc::UInt16ArraySample shapeTypeSample(shapeTypeVec);
    Abc::UInt16ArraySample shapeInstanceIDSample(shapeInstanceIDVec);
    Abc::QuatfArraySample orientationSample(orientationVec);
    Abc::QuatfArraySample angularVelocitySample(angularVelocityVec);
    Abc::C4fArraySample colorSample(colorVec);  

    mScaleProperty.set(scaleSample);
    mAgeProperty.set(ageSample);
    mMassProperty.set(massSample);
    mShapeTimeProperty.set(shapeTimeSample);
    mShapeTypeProperty.set(shapeTypeSample);
    mShapeInstanceIDProperty.set(shapeInstanceIDSample);
    mOrientationProperty.set(orientationSample);
    mAngularVelocityProperty.set(angularVelocitySample);
    mColorProperty.set(colorSample);

    mPointsSample.setPositions(positionSample);
    mPointsSample.setVelocities(velocitySample);
    mPointsSample.setWidths(AbcG::OFloatGeomParam::Sample(widthSample, AbcG::kVertexScope));
    mPointsSample.setIds(idSample);
    mPointsSample.setSelfBounds(bbox);
	mPointsSchema.getChildBoundsProperty().set( bbox);

    mPointsSchema.set(mPointsSample);
    }

    mNumSamples++;

	//mInstanceNames.pop_back();

	if(bAutomaticInstancing){
		saveCurrentFrameMeshes();
	}

	if(bRenderStateForced){
		ipfSystem->SetRenderState(false);
	}

    if(bLastFrame){
       ESS_PROFILE_SCOPE("AlembicParticles::Save - save instance names property");

       std::vector<std::string> instanceNames(mNumShapeMeshes);

       for(faceVertexHashToShapeMap::iterator it = mShapeMeshCache.begin(); it != mShapeMeshCache.end(); it++){
          std::stringstream pathStream;
          pathStream << "/" << it->second.name<< "/" << it->second.name <<"Shape";
          instanceNames[it->second.nMeshInstanceId] = pathStream.str();
       }

	   //for some reason the .dims property is not written when there is exactly one entry if we don't push an empty string
	   //having an extra unreferenced entry seems to be harmless
	   instanceNames.push_back("");

       mInstanceNamesProperty.set(Abc::StringArraySample(instanceNames));
    }

    return true;
}
예제 #3
0
bool AlembicCamera::Save(double time, bool bLastFrame)
{
    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");
        }
    }
    bForever = false;

    SaveMetaData(mMaxNode, this);

    // Set the xform sample
    Matrix3 wm = mMaxNode->GetObjTMAfterWSM(ticks);
    if (mJob) {
        Point3 worldMaxPoint = wm.GetTrans();
        Abc::V3f alembicWorldPoint = ConvertMaxPointToAlembicPoint(worldMaxPoint);
        mJob->GetArchiveBBox().extendBy(alembicWorldPoint);
    }

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

    // Return a pointer to a Camera given an INode or return false if the node
    // cannot be converted to a Camera

    CameraObject *cam = NULL;

    if (obj->CanConvertToType(Class_ID(SIMPLE_CAM_CLASS_ID, 0))) {
        cam = reinterpret_cast<CameraObject *>(
                  obj->ConvertToType(ticks, Class_ID(SIMPLE_CAM_CLASS_ID, 0)));
    }
    else if (obj->CanConvertToType(Class_ID(LOOKAT_CAM_CLASS_ID, 0))) {
        cam = reinterpret_cast<CameraObject *>(
                  obj->ConvertToType(ticks, Class_ID(LOOKAT_CAM_CLASS_ID, 0)));
    }
    else {
        return false;
    }

    CameraState cs;
    Interval valid = FOREVER;
    cam->EvalCameraState(ticks, valid, &cs);
    float tDist = cam->GetTDist(ticks);
    float ratio = GetCOREInterface()->GetRendImageAspect();
    float aperatureWidth =
        GetCOREInterface()->GetRendApertureWidth();  // this may differ from the
    // imported value
    // unfortunately
    float focalLength =
        (float)((aperatureWidth / 2.0) /
                tan(cs.fov / 2.0));  // alembic wants this one in millimeters
    aperatureWidth /= 10.0f;         // convert to centimeters

    IMultiPassCameraEffect *pCameraEffect = cam->GetIMultiPassCameraEffect();

    Interval interval = FOREVER;

    BOOL bUseTargetDistance = FALSE;
    const int TARGET_DISTANCE = 0;
    pCameraEffect->GetParamBlockByID(0)->GetValue(TARGET_DISTANCE, ticks,
            bUseTargetDistance, interval);
    float fFocalDepth = 0.0f;
    const int FOCAL_DEPTH = 1;
    pCameraEffect->GetParamBlockByID(0)->GetValue(FOCAL_DEPTH, ticks, fFocalDepth,
            interval);

    // store the camera data
    mCameraSample.setNearClippingPlane(cs.hither);
    mCameraSample.setFarClippingPlane(cs.yon);
    // mCameraSample.setLensSqueezeRatio(ratio);

    // should set to 1.0 according the article "Maya to Softimage: Camera
    // Interoperability"
    mCameraSample.setLensSqueezeRatio(1.0);

    mCameraSample.setFocalLength(focalLength);
    mCameraSample.setHorizontalAperture(aperatureWidth);
    mCameraSample.setVerticalAperture(aperatureWidth / ratio);
    if (bUseTargetDistance) {
        mCameraSample.setFocusDistance(tDist);
    }
    else {
        mCameraSample.setFocusDistance(fFocalDepth);
    }

    // save the samples
    mCameraSchema.set(mCameraSample);

    mNumSamples++;

    // Note that the CamObject should only be deleted if the pointer to it is not
    // equal to the object pointer that called ConvertToType()
    if (cam != NULL && obj != cam) {
        delete cam;
        cam = NULL;
        return false;
    }

    return true;
}