void AlembicImport_FillInCamera(alembic_fillcamera_options& options)
{
    ESS_CPP_EXCEPTION_REPORTING_START

    ESS_LOG_INFO("AlembicImport_FillInCamera");

    if (options.pCameraObj == NULL ||
            !AbcG::ICamera::matches((*options.pIObj).getMetaData())) {
        return;
    }

    AbcG::ICamera objCamera = AbcG::ICamera(*options.pIObj, Abc::kWrapExisting);
    if (!objCamera.valid()) {
        return;
    }

    double sampleTime = GetSecondsFromTimeValue(options.dTicks);
    SampleInfo sampleInfo =
        getSampleInfo(sampleTime, objCamera.getSchema().getTimeSampling(),
                      objCamera.getSchema().getNumSamples());
    AbcG::CameraSample sample;
    objCamera.getSchema().get(sample, sampleInfo.floorIndex);

    // Extract the camera values from the sample
    // double focalLength = sample.getFocalLength();
    // double fov = sample.getHorizontalAperture();
    // double nearClipping = sample.getNearClippingPlane();
    // double farClipping = sample.getFarClippingPlane();

    // Blend the camera values, if necessary
    // if (sampleInfo.alpha != 0.0)
    //{
    //    objCamera.getSchema().get(sample, sampleInfo.ceilIndex);
    //    focalLength = (1.0 - sampleInfo.alpha) * focalLength + sampleInfo.alpha
    //    * sample.getFocalLength();
    //    fov = (1.0 - sampleInfo.alpha) * fov + sampleInfo.alpha *
    //    sample.getHorizontalAperture();
    //    nearClipping = (1.0 - sampleInfo.alpha) * nearClipping +
    //    sampleInfo.alpha * sample.getNearClippingPlane();
    //    farClipping = (1.0 - sampleInfo.alpha) * farClipping + sampleInfo.alpha
    //    * sample.getFarClippingPlane();
    //}

    // options.pCameraObj->SetTDist(options.dTicks,
    // static_cast<float>(focalLength));
    // options.pCameraObj->SetFOVType(0);  // Width FoV = 0
    // options.pCameraObj->SetFOV(options.dTicks, static_cast<float>(fov));
    // options.pCameraObj->SetClipDist(options.dTicks, CAM_HITHER_CLIP,
    // static_cast<float>(nearClipping));
    // options.pCameraObj->SetClipDist(options.dTicks, CAM_YON_CLIP,
    // static_cast<float>(farClipping));

    options.pCameraObj->SetManualClip(TRUE);

    ESS_CPP_EXCEPTION_REPORTING_END
}
int createAlembicObject(AbcG::IObject &iObj, INode **pMaxNode,
                        alembic_importoptions &options, std::string &file)
{
  AbcA::MetaData mdata = iObj.getMetaData();

  int ret = alembic_success;
  // if(AbcG::IXform::matches(iObj.getMetaData())) //Transform
  //{
  //	ESS_LOG_INFO( "AlembicImport_XForm: " << objects[j].getFullName() );
  //	int ret = AlembicImport_PolyMesh(file, iObj, options, pMaxNode);
  //}
  if (AbcG::IPolyMesh::matches(mdata) ||
      AbcG::ISubD::matches(mdata)) {  // PolyMesh / SubD
    ESS_LOG_INFO("AlembicImport_PolyMesh: " << iObj.getFullName());
    ret = AlembicImport_PolyMesh(file, iObj, options, pMaxNode);
  }
  else if (AbcG::ICamera::matches(mdata)) {  // Camera
    ESS_LOG_INFO("AlembicImport_Camera: " << iObj.getFullName());
    ret = AlembicImport_Camera(file, iObj, options, pMaxNode);
  }
  else if (AbcG::IPoints::matches(mdata)) {  // Points
    ESS_LOG_INFO("AlembicImport_Points: " << iObj.getFullName());
    ret = AlembicImport_Points(file, iObj, options, pMaxNode);
  }
  else if (AbcG::ICurves::matches(mdata)) {  // Curves
    if (options.loadCurvesAsNurbs) {
      ESS_LOG_INFO("AlembicImport_Nurbs: " << iObj.getFullName());
      ret = AlembicImport_NURBS(file, iObj, options, pMaxNode);
    }
    else {
      ESS_LOG_INFO("AlembicImport_Shape: " << iObj.getFullName());
      ret = AlembicImport_Shape(file, iObj, options, pMaxNode);
    }
  }
  else if (AbcG::ILight::matches(mdata)) {  // Light
    ESS_LOG_INFO("AlembicImport_Light: " << iObj.getFullName());
    ret = AlembicImport_Light(file, iObj, options, pMaxNode);
  }
  else if (AbcM::IMaterial::matches(mdata)) {
    ESS_LOG_WARNING(
        "Alembic IMaterial not yet supported: " << iObj.getFullName());
  }
  else {  // NURBS
    if (options.failOnUnsupported) {
      ESS_LOG_ERROR("Alembic data type not supported: " << iObj.getFullName());
      return alembic_failure;
    }
    else {
      ESS_LOG_WARNING(
          "Alembic data type not supported: " << iObj.getFullName());
    }
  }
  return ret;
}
int importAlembicScene(AbcArchiveCache *pArchiveCache,
                       AbcObjectCache *pRootObjectCache,
                       alembic_importoptions &options, std::string &file,
                       progressUpdate &progress,
                       std::map<std::string, bool> &nodeFullPaths)
{
  std::vector<stackElement> sceneStack;
  sceneStack.reserve(200);
  for (size_t j = 0; j < pRootObjectCache->childIdentifiers.size(); j++) {
    sceneStack.push_back(stackElement(
        &(pArchiveCache->find(pRootObjectCache->childIdentifiers[j])->second)));
  }

  while (!sceneStack.empty()) {
    stackElement sElement = sceneStack.back();
    sceneStack.pop_back();
    Abc::IObject &iObj = sElement.pObjectCache->obj;
    INode *pParentMaxNode = sElement.pParentMaxNode;

    if (!iObj.valid()) {
      return alembic_failure;
    }

    const std::string fullname = iObj.getFullName();
    const std::string pname = (pParentMaxNode)
                                  ? EC_MCHAR_to_UTF8(pParentMaxNode->GetName())
                                  : std::string("");
    const std::string name = iObj.getName();

    ESS_LOG_INFO("Importing " << fullname);

    bool bCreateDummyNode = false;
    int mergedGeomNodeIndex = -1;
    AbcObjectCache *pMergedObjectCache = NULL;
    getMergeInfo(pArchiveCache, sElement.pObjectCache, bCreateDummyNode,
                 mergedGeomNodeIndex, &pMergedObjectCache);

    INode *pMaxNode =
        NULL;  // the newly create node, which may be a merged node
    INode *pExistingNode = NULL;
    int keepTM = 1;  // I don't remember why this needed to be set in some
    // cases.

    bool bCreateNode = true;

    if (!nodeFullPaths.empty()) {
      if (mergedGeomNodeIndex != -1) {
        AbcG::IObject mergedGeomChild = pMergedObjectCache->obj;
        bCreateNode = nodeFullPaths.find(mergedGeomChild.getFullName()) !=
                      nodeFullPaths.end();
      }
      else {
        bCreateNode = nodeFullPaths.find(fullname) != nodeFullPaths.end();
      }
    }

    if (bCreateNode) {
      // if we are about to merge a camera with its parent transform, force it
      // to create a dummy node instead if the camera's
      // transform also has children. This is done to prevent the camera
      // correction matrix from being applied to the other children
      if (!bCreateDummyNode && pMergedObjectCache &&
          sElement.pObjectCache->childIdentifiers.size() > 1 &&
          AbcG::ICamera::matches(pMergedObjectCache->obj.getMetaData())) {
        bCreateDummyNode = true;
        mergedGeomNodeIndex = -1;
      }

      if (bCreateDummyNode) {
        std::string importName = removeXfoSuffix(iObj.getName());

        pExistingNode = GetChildNodeFromName(importName, pParentMaxNode);
        if (options.attachToExisting && pExistingNode) {
          pMaxNode = pExistingNode;

          // see if a controller already exists, and then delete it

          int ret = AlembicImport_XForm(pParentMaxNode, pMaxNode, iObj, NULL,
                                        file, options);
          if (ret != 0) {
            return ret;
          }
        }  // only create node if either attachToExisting is false or it is true
        // and the object does not already exist
        else {
          int ret =
              AlembicImport_DummyNode(iObj, options, &pMaxNode, importName);
          if (ret != 0) {
            return ret;
          }

          ret = AlembicImport_XForm(pParentMaxNode, pMaxNode, iObj, NULL, file,
                                    options);
          if (ret != 0) {
            return ret;
          }
        }
      }
      else {
        if (mergedGeomNodeIndex !=
            -1) {  // we are merging, so look at the child geometry node
          AbcG::IObject mergedGeomChild = pMergedObjectCache->obj;
          std::string importName =
              removeXfoSuffix(iObj.getName());  // mergedGeomChild.getName());
          pExistingNode = GetChildNodeFromName(importName, pParentMaxNode);
          if (options.attachToExisting && pExistingNode) {
            pMaxNode = pExistingNode;
          }  // only create node if either attachToExisting is false or it is
          // true and the object does not already exist

          int ret =
              createAlembicObject(mergedGeomChild, &pMaxNode, options, file);
          if (ret != 0) {
            return ret;
          }
          if (pMaxNode != NULL) {
            ret = AlembicImport_XForm(pParentMaxNode, pMaxNode, iObj,
                                      &mergedGeomChild, file, options);
            if (ret != 0) {
              return ret;
            }
          }
        }
        else {  // geometry node(s) under a dummy node (in pParentMaxNode)
          pExistingNode = GetChildNodeFromName(iObj.getName(), pParentMaxNode);
          if (options.attachToExisting && pExistingNode) {
            pMaxNode = pExistingNode;
          }  // only create node if either attachToExisting is false or it is
          // true and the object does not already exist

          int ret = createAlembicObject(iObj, &pMaxNode, options, file);
          if (ret != 0) {
            return ret;
          }

          // since the transform is the identity, should position relative to
          // parent
          keepTM = 0;

          if (AbcG::ICamera::matches(iObj.getMetaData())) {
            // apply camera adjustment matrix to the identity
            Matrix3 rotation(TRUE);
            rotation.RotateX(HALFPI);
            TimeValue zero(0);
            pMaxNode->SetNodeTM(zero, rotation);
          }

          // import identity matrix, since more than goemetry node share the
          // same transform
          // Should we just list MAX put a default position/scale/rotation
          // controller on?

          //	int ret = AlembicImport_XForm(pMaxNode, *piParentObj, file,
          // options);
        }

        if (options.failOnUnsupported) {
          if (!pMaxNode) {
            return alembic_failure;
          }
        }
      }
    }

    if (pMaxNode && pParentMaxNode && !pExistingNode) {
      pParentMaxNode->AttachChild(pMaxNode, keepTM);
    }

    progress.increment();
    progress.update();

    if (pMaxNode) {
      for (size_t j = 0; j < sElement.pObjectCache->childIdentifiers.size();
           j++) {
        AbcObjectCache *pChildObjectCache =
            &(pArchiveCache->find(sElement.pObjectCache->childIdentifiers[j])
                  ->second);
        if (NodeCategory::get(pChildObjectCache->obj) ==
            NodeCategory::UNSUPPORTED) {
          continue;  // skip over unsupported types
        }

        // I assume that geometry nodes are always leaf nodes. Thus, if we
        // merged a geometry node will its parent transform, we don't
        // need to push it to the stack.
        // A geometry node can't be combined with its transform node, the
        // transform node has other tranform nodes as children. These
        // nodes must be pushed.
        if (mergedGeomNodeIndex != j) {
          sceneStack.push_back(stackElement(pChildObjectCache, pMaxNode));
        }
      }
    }
  }

  return alembic_success;
}
Пример #4
0
void AlembicPoints::GetShapeType(IParticleObjectExt *pExt, int particleId, TimeValue ticks, ShapeType &type, Abc::uint16_t &instanceId, float &animationTime)
{
    // Set up initial values
    type = ShapeType_Point;
    instanceId = 0;
    animationTime = 0.0f;

    // Go into the particle's action list
    INode *particleGroupNode = pExt->GetParticleGroup(particleId);
    Object *particleGroupObj = (particleGroupNode != NULL) ? particleGroupNode->EvalWorldState(ticks).obj : NULL;

	if (!particleGroupObj){
        return;
	}

    IParticleGroup *particleGroup = GetParticleGroupInterface(particleGroupObj);
    INode *particleActionListNode = particleGroup->GetActionList();
    Object *particleActionObj = (particleActionListNode != NULL ? particleActionListNode->EvalWorldState(ticks).obj : NULL);

	if (!particleActionObj){
        return;
	}
	
    PFSimpleOperator *pSimpleOperator = NULL;

	//In the case of multiple shape operators in an action list, the one furthest down the list seems to be the one that applies
    IPFActionList *particleActionList = GetPFActionListInterface(particleActionObj);
	
	for (int p = particleActionList->NumActions()-1; p >= 0; p -= 1)
	{
		INode *pActionNode = particleActionList->GetAction(p);
		Object *pActionObj = (pActionNode != NULL ? pActionNode->EvalWorldState(ticks).obj : NULL);

		if (pActionObj == NULL){
			continue;
		}

		if (pActionObj->ClassID() == PFOperatorSimpleShape_Class_ID){
			pSimpleOperator = static_cast<PFSimpleOperator*>(pActionObj);
			break;
		}else if(pActionObj->ClassID() == PFOperatorShapeLib_Class_ID){
			pSimpleOperator = static_cast<PFSimpleOperator*>(pActionObj);
			break;
		}else if(pActionObj->ClassID() == PFOperatorInstanceShape_Class_ID){
			pSimpleOperator = static_cast<PFSimpleOperator*>(pActionObj);
			break;
		}else if(pActionObj->ClassID() == PFOperatorMarkShape_Class_ID){
			pSimpleOperator = static_cast<PFSimpleOperator*>(pActionObj);
			break;
		}else if(pActionObj->ClassID() == PFOperatorFacingShape_Class_ID){
			pSimpleOperator = static_cast<PFSimpleOperator*>(pActionObj);
			break;
		}
	}

	

	for (int p = particleActionList->NumActions()-1; p >= 0; p -= 1)
	{
		INode *pActionNode = particleActionList->GetAction(p);
		Object *pActionObj = (pActionNode != NULL ? pActionNode->EvalWorldState(ticks).obj : NULL);

		if (pActionObj == NULL){
			continue;
		}

		IPFTest* pTestAction = GetPFTestInterface(pActionObj);

		if (pTestAction){
			
			INode* childActionListNode = pTestAction->GetNextActionList(pActionNode, NULL);

			if(childActionListNode){
				AlembicPoints::perActionListShapeMap_it actionListIt = mPerActionListShapeMap.find(childActionListNode);

				//create a cache entry if necessary
				if(actionListIt == mPerActionListShapeMap.end()){
					mPerActionListShapeMap[childActionListNode] = AlembicPoints::shapeInfo();
				}
				AlembicPoints::shapeInfo& sInfo = mPerActionListShapeMap[childActionListNode];
				
				if(!sInfo.pParentActionList){
					sInfo.pParentActionList = particleActionListNode;
				}
			}
		}
	}

	ReadShapeFromOperator(particleGroup, pSimpleOperator, particleId, ticks, type, instanceId, animationTime);

	if(type != ShapeType_NbElements){//write the shape to the cache

		// create cache entry for the current action list node, and then fill in the shape info
		// we will fill in the parent later

		AlembicPoints::perActionListShapeMap_it actionListIt = mPerActionListShapeMap.find(particleActionListNode);

		//create a cache entry if necessary
		if(actionListIt == mPerActionListShapeMap.end()){
			mPerActionListShapeMap[particleActionListNode] = AlembicPoints::shapeInfo();
		}
		AlembicPoints::shapeInfo& sInfo = mPerActionListShapeMap[particleActionListNode];
		
		//if(sInfo.type == ShapeType_NbElements){
		//	sInfo.type = type;
		//	sInfo.animationTime = animationTime;
		//	if(sInfo.type == ShapeType_Instance){
		//		sInfo.instanceName = mInstanceNames[instanceId];
		//	}
		//}
	}
	else{ //read the shape from the cache

		AlembicPoints::shapeInfo sInfo;
		INode* currActionNode = particleActionListNode;
		
		//search for shape along path from this node to the root node
		const int MAX_DEPTH = 10; //just in case there is an infinite loop due a bug
		int i = 0;
		while(currActionNode && sInfo.type == ShapeType_NbElements && i<MAX_DEPTH){

			AlembicPoints::perActionListShapeMap_it actionListIt = mPerActionListShapeMap.find(currActionNode);
			if(actionListIt != mPerActionListShapeMap.end()){
				sInfo = actionListIt->second;
			}

			currActionNode = sInfo.pParentActionList;
			i++;
		}

		if(sInfo.type != ShapeType_NbElements){//We have found shape, so add it to the list if necessary

			// Find if the name is alerady registered, otherwise add it to the list
			//instanceId = FindInstanceName(sInfo.instanceName);
			//if (instanceId == USHRT_MAX)
			//{
			//	mInstanceNames.push_back(sInfo.instanceName);
			//	instanceId = (Abc::uint16_t)mInstanceNames.size()-1;
			//}
			//type = sInfo.type;
		}
		else{
			int nBornIndex = pExt->GetParticleBornIndex(particleId);
			ESS_LOG_INFO("Could not determine shape type for particle with born index: "<<nBornIndex<<". Defaulting to point.");
 			type = ShapeType_Point;
		}
	}
}
Пример #5
0
void AlembicPoints::ReadShapeFromOperator( IParticleGroup *particleGroup, PFSimpleOperator *pSimpleOperator, int particleId, TimeValue ticks, ShapeType &type, Abc::uint16_t &instanceId, float &animationTime)
{
	if(!pSimpleOperator){
		return;
	}

	if (pSimpleOperator->ClassID() == PFOperatorSimpleShape_Class_ID)
    {
        IParamBlock2 *pblock = pSimpleOperator->GetParamBlockByID(0);
        int nShapeId = pblock->GetInt(PFlow_kSimpleShape_shape, ticks);

        switch(nShapeId)
        {
        case PFlow_kSimpleShape_shape_pyramid:
            type = ShapeType_Cone;
            break;
        case PFlow_kSimpleShape_shape_cube:
            type = ShapeType_Box;
            break;
        case PFlow_kSimpleShape_shape_sphere:
            type = ShapeType_Sphere;
            break;
        case PFlow_kSimpleShape_shape_vertex:
            type = ShapeType_Point;
            break;
		default:
			type = ShapeType_Point;
        }
    }
	else if (pSimpleOperator->ClassID() == PFOperatorShapeLib_Class_ID)
	{
        IParamBlock2 *pblock = pSimpleOperator->GetParamBlockByID(0);
		int nDimension = pblock->GetInt(PFlow_kShapeLibary_dimensionType, ticks);
		if(nDimension == PFlow_kShapeLibrary_dimensionType_2D){
			int n2DShapeId = pblock->GetInt(PFlow_kShapeLibary_2DType, ticks);
			if( n2DShapeId == PFlow_kShapeLibrary_dimensionType_2D_square){
				type = ShapeType_Rectangle;
			}
			else{
				ESS_LOG_INFO("Unsupported shape type.");
				type = ShapeType_Point;
			}
		}
		else if(nDimension == PFlow_kShapeLibrary_dimensionType_3D){
			int n3DShapeId = pblock->GetInt(PFlow_kShapeLibary_3DType, ticks);
			if(n3DShapeId == PFlow_kShapeLibary_3DType_cube){
				type = ShapeType_Box;
			}
			else if(n3DShapeId == PFlow_kShapeLibary_3DType_Sphere20sides ||
					n3DShapeId == PFlow_kShapeLibary_3DType_Sphere80sides){
				type = ShapeType_Sphere;
			}
			else{
				ESS_LOG_INFO("Unsupported shape type.");
				type = ShapeType_Point;
			}
		
			//ShapeType_Cylinder unsupported
			//ShapeType_Cone unsupported
			//ShapeType_Disc unsupported
			//ShapeType_NbElements unsupported
		}
		else{
			ESS_LOG_INFO("Unknown dimension.");
			type = ShapeType_Point;
		}
			
		//int nNumParams = pblock->NumParams();

		//for(int i=0; i<nNumParams; i++){
	
		//	ParamID id = pblock->IndextoID(i);
		//	MSTR paramStr = pblock->GetLocalName(id, 0);
		//	int n = 0;
		//
		//}

	}
    else if (pSimpleOperator->ClassID() == PFOperatorInstanceShape_Class_ID)
    {
        // Assign animation time and shape here
        IParamBlock2 *pblock = pSimpleOperator->GetParamBlockByID(0);
        INode *pNode = pblock->GetINode(PFlow_kInstanceShape_objectMaxscript, ticks);
        if (pNode == NULL || pNode->GetName() == NULL)
        {
            return;
        }
        
        type = ShapeType_Instance;

		bool bFlatten = GetCurrentJob()->GetOption("flattenHierarchy");
		std::string nodePath = getNodeAlembicPath( EC_MCHAR_to_UTF8( pNode->GetName() ), bFlatten);

        // Find if the name is alerady registered, otherwise add it to the list
   //     instanceId = FindInstanceName(nodePath);
   //     if (instanceId == USHRT_MAX)
   //     {
			//mInstanceNames.push_back(nodePath);
   //         instanceId = (Abc::uint16_t)mInstanceNames.size()-1;
   //     }

        // Determine if we have an animated shape
        BOOL animatedShape = pblock->GetInt(PFlow_kInstanceShape_animatedShape);
	    BOOL acquireShape = pblock->GetInt(PFlow_kInstanceShape_acquireShape);

        if (!animatedShape && !acquireShape)
        {
            return;
        }

        // Get the necesary particle channels to grab the current time values
        ::IObject *pCont = particleGroup->GetParticleContainer();
        if (!pCont)
        {
            return;
        }

        // Get synch values that we are interested in fromt the param block
        int syncType = pblock->GetInt(PFlow_kInstanceShape_syncType);
        BOOL syncRandom = pblock->GetInt(PFlow_kInstanceShape_syncRandom);

        IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont);
        if (chTime == NULL) 
        {
            return; // can't find particle times in the container
        }

        IChannelContainer* chCont = GetChannelContainerInterface(pCont);
        if (chCont == NULL) 
        {
            return;  // can't get access to ChannelContainer interface
        }

        IParticleChannelPTVR* chBirthTime = NULL;
        IParticleChannelPTVR* chEventStartR = NULL;
        bool initEventStart = false;

        if (syncType == PFlow_kInstanceShape_syncBy_particleAge) 
        {
            chBirthTime = GetParticleChannelBirthTimeRInterface(pCont);
            if (chBirthTime == NULL) 
            {
                return; // can't read particle age
            }
        }
        else if (syncType == PFlow_kInstanceShape_syncBy_eventStart) 
        {
            chEventStartR = GetParticleChannelEventStartRInterface(pCont);
             
            if (chEventStartR == NULL) 
            {
                return; // can't read event start time
            }
        }

        IParticleChannelIntR* chLocalOffR = NULL;
        bool initLocalOff = false;

        // acquire LocalOffset particle channel; if not present then create it.
        if (syncRandom) 
        {
            chLocalOffR =  (IParticleChannelIntR*)chCont->GetPrivateInterface(PARTICLECHANNELLOCALOFFSETR_INTERFACE, pSimpleOperator);
        }

        // get new shape from the source
        PreciseTimeValue time = chTime->GetValue(particleId);
        switch(syncType)
        {
        case PFlow_kInstanceShape_syncBy_absoluteTime:
            break;
        case PFlow_kInstanceShape_syncBy_particleAge:
            time -= chBirthTime->GetValue(particleId);
            break;
        case PFlow_kInstanceShape_syncBy_eventStart:
            time -= chEventStartR->GetValue(particleId);
            break;
        default:
            break;
        }

        if (syncRandom) 
        {
            if (chLocalOffR != NULL)
                time += chLocalOffR->GetValue(particleId);
        }
		
		//timeValueMap::iterator it = mTimeValueMap.find(time);
		//if( it != mTimeValueMap.end() ){
		//	ESS_LOG_WARNING("sampleTime already seen.");
		//}
		//else{
		//	mTimeValueMap[time] = true;
		//	mTimeSamplesCount++;
		//	ESS_LOG_WARNING("sampleTime: "<<(float)time<<" totalSamples: "<<mTimeSamplesCount);
		//}

        TimeValue t = TimeValue(time);
        animationTime = (float)GetSecondsFromTimeValue(t);
    }
	else if (pSimpleOperator->ClassID() == PFOperatorMarkShape_Class_ID)
	{
		ESS_LOG_INFO("Shape Mark operator not supported.");
	}
	else if (pSimpleOperator->ClassID() == PFOperatorFacingShape_Class_ID)
	{
		ESS_LOG_INFO("Shape Facing operator not supported.");
	}

}
Пример #6
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;
}
Пример #7
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;
}