hsBool plMaxNodeBase::CanConvert(bool recalculate)
{
    // Try and find a cached return value
    plMaxNodeData *md = GetMaxNodeData();
    if (md && !recalculate)
        return md->CanConvert();

    if (UserPropExists("IGNORE"))
        return false;

    Object *obj = EvalWorldState(0/*hsConverterUtils::Instance().GetTime(GetInterface())*/).obj;
    if (obj)
    {
        if  (  obj->CanConvertToType(triObjectClassID)      // MeshObjs are accepted here
            || obj->ClassID() == Class_ID(DUMMY_CLASS_ID,0) // Dummy boxes are accepted here
            || obj->SuperClassID() == CAMERA_CLASS_ID       // All Camera types are accepted here
            || obj->ClassID() == Class_ID(UTILITY_CLASS_ID, 0)      // All Camera targets are accepted here
            || (  obj->ClassID() ==  RTOMNI_LIGHT_CLASSID
                || obj->ClassID() == RTSPOT_LIGHT_CLASSID
                || obj->ClassID() == RTDIR_LIGHT_CLASSID 
                || obj->ClassID() == RTPDIR_LIGHT_CLASSID )
            || (  obj->SuperClassID() == LIGHT_CLASS_ID     // All run time lights are accepted here
               && UserPropExists("RunTimeLight"))

            || IsGroupMember()                              // Group objects are accepted here
            )
        return true;
    }
    return false;
}
hsBool plMaxNodeBase::Contains(const Point3& worldPt)
{
    TimeValue currTime = 0;//hsConverterUtils::Instance().GetTime(GetInterface());
    Object *obj = EvalWorldState(currTime).obj;
    if( !obj )
        return false;

    Matrix3 l2w = GetObjectTM(currTime);
    Matrix3 w2l = Inverse(l2w);
    Point3 pt = w2l * worldPt;

    if( obj->ClassID() == Class_ID(DUMMY_CLASS_ID,0) )
    {
        DummyObject* dummy = (DummyObject*)obj;
        Box3 bnd = dummy->GetBox();
        return bnd.Contains(pt);
    }
    if( obj->CanConvertToType(triObjectClassID) )
    {
        TriObject   *meshObj = (TriObject *)obj->ConvertToType(currTime, triObjectClassID);
        if( !meshObj )
            return false;

        Mesh& mesh = meshObj->mesh;
        Box3 bnd = mesh.getBoundingBox();
        if( !bnd.Contains(pt) )
        {
            if( meshObj != obj )
                meshObj->DeleteThis();
            return false;
        }

        hsBool retVal = true;
        int i;
        for( i = 0; i < mesh.getNumFaces(); i++ )
        {
            Face& face = mesh.faces[i];

            Point3 p0 = mesh.verts[face.v[0]];
            Point3 p1 = mesh.verts[face.v[1]];
            Point3 p2 = mesh.verts[face.v[2]];

            Point3 n = CrossProd(p1 - p0, p2 - p0);

            if( DotProd(pt, n) > DotProd(p0, n) )
            {
                retVal = false;
                break;
            }
        }

        if( meshObj != obj )
            meshObj->DeleteThis();

        return retVal;
    }

    // If we can't figure out what it is, the point isn't inside it.
    return false;
}
Example #3
0
// only show these in the dialog
int SelectObjectsInMAX::filter(INode *node)
{
	Object *obj = node->GetObjectRef();
    if (obj->ClassID()!=DELEG_CLASSID) return FALSE;
	return TRUE;

}
Example #4
0
TriObject* MaxExportPlugin::GetTriObjFromNode(INode* node, BOOL &deleteIt)
{
	if (node->IsObjectHidden())
		return 0;
	deleteIt = FALSE;
	Object *obj;
	//obj = node->GetObjectRef();
	obj = node->EvalWorldState(IP->GetTime()).obj;

	if (obj->ClassID() == BONE_OBJ_CLASSID)
		return 0;
	//file << "OBJCLASS: " << std::to_wstring(obj->ClassID().PartA()) << " " << std::to_wstring(obj->ClassID().PartB()) << "\n";

	if (obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0)))
	{
		TriObject *tri = (TriObject *)obj->ConvertToType(IP->GetTime(),
			Class_ID(TRIOBJ_CLASS_ID, 0));

		// Note that the TriObject should only be deleted
		// if the pointer to it is not equal to the object
		// pointer that called ConvertToType()
		if (obj != tri) deleteIt = TRUE;
		return tri;
	}
	else
	{
		return NULL;
	}
}
Example #5
0
bool plAnimComponentBase::IAddLightToAnim(plMaxNode *node, plAGAnim *anim, plErrorMsg *pErrMsg)
{
    if (!node->IsAnimatedLight())
        return false;

    Object *obj = node->GetObjectRef();
    Class_ID cid = obj->ClassID();

    IParamBlock2 *pb = nil;
    if (cid == RTSPOT_LIGHT_CLASSID)
        pb = obj->GetParamBlockByID(plRTLightBase::kBlkSpotLight);
    else if (cid == RTOMNI_LIGHT_CLASSID)
        pb = obj->GetParamBlockByID(plRTLightBase::kBlkOmniLight);
    else if (cid == RTDIR_LIGHT_CLASSID)
        pb = obj->GetParamBlockByID(plRTLightBase::kBlkTSpotLight);
    else if (cid == RTPDIR_LIGHT_CLASSID)
        pb = obj->GetParamBlockByID(plRTLightBase::kBlkMain);

    node->GetRTLightColAnim(pb, anim);

    if (cid == RTSPOT_LIGHT_CLASSID || cid == RTOMNI_LIGHT_CLASSID)
        node->GetRTLightAttenAnim(pb, anim);

    if (cid == RTSPOT_LIGHT_CLASSID)
        node->GetRTConeAnim(pb, anim);

    return true;
}
float plMaxNodeBase::RegionPriority()
{
    TimeValue currTime = 0;//hsConverterUtils::Instance().GetTime(GetInterface());
    Object *obj = EvalWorldState(currTime).obj;
    if( !obj )
        return 0;

    Matrix3 l2w = GetObjectTM(currTime);

    if( obj->ClassID() == Class_ID(DUMMY_CLASS_ID,0) )
    {
        DummyObject* dummy = (DummyObject*)obj;
        Box3 bnd = dummy->GetBox();

        return BoxVolume(bnd, l2w);
    }

    if( obj->CanConvertToType(triObjectClassID) )
    {
        TriObject   *meshObj = (TriObject *)obj->ConvertToType(currTime, triObjectClassID);
        if( !meshObj )
            return 0;

        Mesh& mesh = meshObj->mesh;
        Box3 bnd = mesh.getBoundingBox();
        
        if( meshObj != obj )
            meshObj->DeleteThis();

        return BoxVolume(bnd, l2w);
    }

    // Don't know how to interpret other, it's not contained.
    return 0;
}
Abc::C4f AlembicPoints::GetColor(IParticleObjectExt *pExt, int particleId,
                                 TimeValue ticks)
{
  Abc::C4f color(0.5, 0.5, 0.5, 1.0);

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

  if (!particleGroupObj) {
    return color;
  }

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

  if (!particleActionObj) {
    return color;
  }

  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() == PFOperatorDisplay_Class_ID) {
      pSimpleOperator = static_cast<PFSimpleOperator *>(pActionObj);
      break;
    }
  }

  if (pSimpleOperator) {
    IParamBlock2 *pblock = pSimpleOperator->GetParamBlockByID(0);
    Point3 c = pblock->GetPoint3(kDisplay_color);
    color.r = c.x;
    color.g = c.y;
    color.b = c.z;
    color.a = 1.0;
  }

  return color;
}
Example #8
0
		BOOL Validate(PB2Value &v)
		{
	        INode *node = (INode*) v.r;
			Object *obj = node->GetObjectRef();
            if (obj->ClassID() != DELEG_CLASSID) return FALSE;
	       
			return TRUE;
		};
Example #9
0
BOOL XsiExp::nodeEnumAnim(INode* node, int & animHit) 
{
	if(exportSelected && node->Selected() == FALSE)
  {
		return TREE_CONTINUE;
  }

	nCurNode++;
	ip->ProgressUpdate( (int)((float)nCurNode/nTotalNodeCount*100.0f) ); 

	// Stop recursing if the user pressed Cancel 
	if (ip->GetCancel())
  {
		return FALSE;
  }
	
	// Only export if exporting everything or it's selected
	if(!exportSelected || node->Selected())
  {
		// The ObjectState is a 'thing' that flows down the pipeline containing
		// all information about the object. By calling EvalWorldState() we tell
		// max to eveluate the object at end of the pipeline.
		ObjectState os = node->EvalWorldState(0); 

		// The obj member of ObjectState is the actual object we will export.
		if (os.obj)
    {
			// We look at the super class ID to determine the type of the object.
			switch(os.obj->SuperClassID())
      {
			case HELPER_CLASS_ID:
        {
      	  Object * obj = node->EvalWorldState(0).obj;
        	if (!obj && obj->ClassID() != Class_ID(BONE_CLASS_ID, 0))
          {
            return FALSE;
          }
        }
        // fall through
			case GEOMOBJECT_CLASS_ID: 
        ExportAnimKeys( node, animHit); 
				break;
			}
		}
	}	
	
	// For each child of this node, we recurse into ourselves 
	// until no more children are found.
	for (int c = 0; c < node->NumberOfChildren(); c++)
  {
		if (!nodeEnumAnim(node->GetChildNode(c), animHit))
    {
			return FALSE;
    }
	}

	return TRUE;
}
Example #10
0
BOOL
Cal3DObjPick::HitTest(IObjParam *ip, HWND hWnd, ViewExp *vpt, IPoint2 m,
                      int flags)
{
    INode *node = ip->PickNode(hWnd, m);
    if (node == NULL)
        return FALSE;
    Object *obj = node->EvalWorldState(0).obj;
    return obj->ClassID() == AudioClipClassID;
}
hsBool plStrongSpringConstraintComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
{
    plStrongSpringConstraintMod* HMod = new plStrongSpringConstraintMod;

    HMod->SetDamp(fCompPB->GetFloat(kStrength));
    HMod->SetRR(fCompPB->GetFloat(kRebound));

    //No MaximumTorque here, might as well use that field for the Pinned state for the Parent...
    HMod->SetParentPin(fCompPB->GetInt(kParentPinnedBool));


        Object *obj = fCompPB->GetINode(kParent)->EvalWorldState(0/*hsConverterUtils::Instance().GetTime(GetInterface())*/).obj;

        plKey ParentKey  = nil;
        if(fCompPB->GetINode(kParent))
            if(((plMaxNode*)fCompPB->GetINode(kParent))->CanConvert() && (obj->ClassID() == Class_ID(DUMMY_CLASS_ID,0) || obj->SuperClassID() == GEOMOBJECT_CLASS_ID ))
            {
                plMaxNode* ParentNode = (plMaxNode*)fCompPB->GetINode(kParent);
                ParentKey = ParentNode->GetKey();
            }
            else
            {
                pErrMsg->Set(true, "Ignored Parent Node", "Parent Node %s was set to be Ignored. Bad! Bad!.", (fCompPB->GetINode(kParent)->GetName()));
                pErrMsg->Set(false);
                return false;
            }           
        else
        {

//          pErrMsg->Set(true, "Bad Parent Node", " Parent Node %s wasn't selected. Strong Spring Constraint failed.", (fCompPB->GetINode(kParent)->GetName()));
//          pErrMsg->Set(false);
//          return false;
        }


    //No motor Angle here, might as well use the field for Length Storage...
    HMod->SetFixedLength(fCompPB->GetFloat(kLength));



    node->AddModifier(HMod, IGetUniqueName(node));
    hsgResMgr::ResMgr()->AddViaNotify( ParentKey, new plGenRefMsg( HMod->GetKey(), plRefMsg::kOnCreate, plHavokConstraintsMod::kParentIdx, 0 ), plRefFlags::kPassiveRef );
    hsgResMgr::ResMgr()->AddViaNotify( node->GetKey(), new plGenRefMsg( HMod->GetKey(), plRefMsg::kOnCreate, plHavokConstraintsMod::kChildIdx, 0 ), plRefFlags::kPassiveRef );









    return true;

}
Example #12
0
BOOL
TriggerPick::HitTest(IObjParam *ip, HWND hWnd, ViewExp *vpt, IPoint2 m,
                     int flags)
{
    INode *node = ip->PickNode(hWnd, m);
    if (node == NULL)
        return FALSE;
    Object *obj = node->EvalWorldState(0).obj;
    if ((obj->SuperClassID() == HELPER_CLASS_ID && obj->ClassID() == Class_ID(Anchor_CLASS_ID1, Anchor_CLASS_ID2)))
        return FALSE;
    return TRUE;
}
Example #13
0
//Get the current position for the purpose of computing the next frame
//This function checks to see whether or not the node is a delegate, in which
//case the GetTM function  is called.
static Matrix3 GetCurrentMatrix(INode *node, TimeValue t)
{
	Object *o = node->GetObjectRef();
    if (o->ClassID() == DELEG_CLASSID) 
	{
        IDelegate *cd = (IDelegate *) o->GetInterface(I_DELEGINTERFACE);
		if (cd->IsComputing())
			return cd->GetTM(node,t);
	}

    return node->GetNodeTM(t);
}
Example #14
0
void XsiExp::ExportMeshObject( INode * node, int indentLevel)
{
	Object * obj = node->EvalWorldState(GetStaticFrame()).obj;
	if (!obj || obj->ClassID() == Class_ID(TARGET_CLASS_ID, 0))
  {
		return;
  }
	TSTR indent = GetIndent(indentLevel);
	
	ExportNodeHeader(node, "Frame", indentLevel);
	
	ExportNodeTM(node, indentLevel);
	
	ExportMesh(node, GetStaticFrame(), indentLevel);
}
Example #15
0
void XsiExp::ExportNodeTM( INode * node, int indentLevel)
{
	// dump the full matrix
	Matrix3 matrix = node->GetNodeTM(GetStaticFrame());
	TSTR indent = GetIndent(indentLevel);
	
	fprintf(pStream,"%s\t%s {\n\n", indent.data(), "FrameTransformMatrix");

	Object * obj = node->EvalWorldState(0).obj;
  BOOL isBone = obj && obj->ClassID() == Class_ID(BONE_CLASS_ID, 0) ? TRUE : FALSE;

  if (node->GetParentNode() && node->GetParentNode()->IsRootNode())
  {
    // bone chains get grafted into the hierarchy tree
    //
	  if (!isBone)
    {
      // root mesh
      oTopMatrix = matrix;
      AffineParts ap;
      decomp_affine( matrix, &ap);
      topMatrix.Set( Point3( ap.k.x,0.0f,0.0f), Point3( 0.0f,ap.k.z,0.0f), Point3(0.0f,0.0f,ap.k.y), Point3(0,0,0));

      // root transform is controlled by the engine
      matrix.IdentityMatrix();
    }
  }
  else
  {
    matrix = matrix * Inverse(node->GetParentTM(GetStaticFrame()));
    if (!isBone)
    {
      matrix.SetRow( 3, topMatrix * matrix.GetRow(3));
    }
  }

  // write the matrix values
  DumpMatrix3( &matrix, indentLevel+2);

  // transform close brace
	fprintf(pStream,"%s\t}\n", indent.data());
}
Example #16
0
BOOL
ProxSensorObjPick::HitTest(IObjParam *ip, HWND hWnd, ViewExp *vpt, IPoint2 m,
                           int flags)
{
    if ( ! vpt || ! vpt->IsAlive() )
		{
			// why are we here?
			DbgAssert(!"Doing HitTest() on invalid view port!");
			return FALSE;
		}
		
		INode *node = ip->PickNode(hWnd, m);
    if (node == NULL)
        return FALSE;
    Object* obj = node->EvalWorldState(0).obj;
    if ((obj->SuperClassID() == HELPER_CLASS_ID &&
         obj->ClassID() == Class_ID(ProxSensor_CLASS_ID1, ProxSensor_CLASS_ID2)))
        return FALSE;
    return TRUE;
}
bool plMaxNodeBase::IsXRef()
{
    // Is this an XRef'd object?
    Object *obj = GetObjectRef();
    if (obj->SuperClassID() == SYSTEM_CLASS_ID && obj->ClassID() == XREFOBJ_CLASS_ID)
        return true;

    //
    // Is this part of an XRef'd scene?
    //
    // Walk up to our root node
    INode *root = GetParentNode();
    while (!root->IsRootNode())
        root = root->GetParentNode();
    // If our root isn't the main root, we're in an XRef'd scene.
    if (root != GetCOREInterface()->GetRootNode())
        return true;

    return false;
}
Example #18
0
void XsiExp::ExportBoneObject( INode * node, int indentLevel)
{
	Object * obj = node->EvalWorldState(GetStaticFrame()).obj;
	if (!obj || obj->ClassID() != Class_ID(BONE_CLASS_ID, 0))
  {
    // reject non-bones
    return;
	}
  if (!node->GetParentNode() || node->GetParentNode()->IsRootNode())
  {
    // bone matrices get passed to children
    // drop root bone
    return;
  }
	TSTR indent = GetIndent(indentLevel);

  ExportNodeHeader(node, "Frame", indentLevel);

  // export parent as this bone
	ExportNodeTM(node->GetParentNode(), indentLevel);
}
Example #19
0
bool XRefObjFinder::Proc(INode * pNode)
{
    TSTR workstring;
	
    // NOTE: We dump all info into one big string
    // Not super realistic, and probably won't work with
    // a scene with lots of XRef objects, but in a real exporter
    // situation, you'd be dumping out to a file pointer anyway
	
    if (!pNode || !m_buffer) return false;
    Object *obj = pNode->GetObjectRef();
    if (obj && obj->SuperClassID()==SYSTEM_CLASS_ID && 
		obj->ClassID()==XREFOBJ_CLASS_ID) {
        IXRefObject *ix = (IXRefObject *)obj;
        // if pNode refs an XRef object, let's pull some info out of it
        workstring.printf(_T("Node <%s> XREF <%s> filename:<%s> proxy:<%s> anim-off:<%s> update-mats:<%s> \x0D\x0A"),
            pNode->GetName(), ix->GetCurObjName(), ix->GetCurFile().GetFileName(), 
            (ix->GetUseProxy()) ? _T("T") : _T("F"),
            (ix->GetIgnoreAnim()) ? _T("T") : _T("F"),
            (ix->GetUpdateMats()) ? _T("T") : _T("F"));
        m_buffer->append(workstring);
    }
    return true;
}
	//------------------------------
	bool MorphControllerCreator::createMorphController( const COLLADAFW::MorphController* morphController, INode* referencingINode )
	{
		Object* sourceObject = getObjectByUniqueId( morphController->getSource() );

		if ( !sourceObject )
		{
			// TODO handle error
			// morph source object not present
			return true;
		}

		mMorphModifier = (MorphR3*) createMaxObject(OSM_CLASS_ID, MORPHER_CLASS_ID);

		if ( !mMorphModifier )
		{
			// TODO handle error
			// morph controller could not be created
			return true;
		}

		if ( (sourceObject->ClassID() == derivObjClassID) || (sourceObject->ClassID() == WSMDerivObjClassID) )
		{
			// Object is a derived object, just attach ourselves to it
			mDerivedObject = (IDerivedObject*) sourceObject;
		}
		else
		{
			// Create the derived object for the target and the modifier
			mDerivedObject = CreateDerivedObject(sourceObject);
		}

		mDerivedObject->AddModifier(mMorphModifier);
		mMorphModifier->cache.MakeCache(sourceObject);

		const COLLADAFW::FloatOrDoubleArray& morphWeights = morphController->getMorphWeights();
		const COLLADAFW::UniqueIdArray& morphTargets = morphController->getMorphTargets();
		// There is a maximum number of channels supported by the 3dsMax morpher:
		// Calculate the number of channels to process
		size_t colladaTargetCount = morphTargets.getCount();
		int channelCount = (int) min(colladaTargetCount, mMorphModifier->chanBank.size());

		const COLLADAFW::UniqueId& morphWeightsAnimationListId = morphWeights.getAnimationList();
		const COLLADAFW::AnimationList* morphWeightsAnimationList = getAnimationListByUniqueId( morphWeightsAnimationListId );

		for (int i = 0; i < channelCount; ++i)
		{
			const COLLADAFW::UniqueId& targetUniqueId = morphTargets[i];
			Object* targetObject = getObjectByUniqueId( targetUniqueId );
			if ( !targetObject )
			{
				// TODO handle error
				// the target has not been created, might be missing in dae file
				return true;
			}
			INodeList targetINodes;
			getObjectINodesByUniqueId( targetUniqueId, targetINodes );
			INode* targetINode = 0;
			if ( !targetINodes.empty() )
			{
				// it does not seem to make a difference which INode we use, as long as it references the correct geometry
				targetINode = targetINodes[0];
			}
		
			morphChannel* channel = &mMorphModifier->chanBank[i];
			if ( targetINode )
			{
				channel->buildFromNode(targetINode);
				channel->mConnection = targetINode;
			}
			else
			{
				// Manually initializes this channel
				initializeChannelGeometry(channel, targetObject);
			}

			if ( !morphWeightsAnimationList )
			{
				float weight = 0;
				if ( morphWeights.getType() == COLLADAFW::FloatOrDoubleArray::DATA_TYPE_FLOAT )
				{
					weight = (*morphWeights.getFloatValues())[i];
				}
				else if ( morphWeights.getType() == COLLADAFW::FloatOrDoubleArray::DATA_TYPE_DOUBLE )
				{
					weight = (float)(*morphWeights.getDoubleValues())[i];
				}
				channel->cblock->SetValue(0, 0, weight * 100);
			}
		}


		if ( morphWeightsAnimationList )
		{
			const COLLADAFW::AnimationList::AnimationBindings& animationBindings = morphWeightsAnimationList->getAnimationBindings();
			for ( size_t i = 0, count = animationBindings.getCount(); i < count; ++i)
			{
				const COLLADAFW::AnimationList::AnimationBinding& animationBinding = animationBindings[i];
				if ( animationBinding.animationClass != COLLADAFW::AnimationList::ARRAY_ELEMENT_1D)
				{
					// this animation does not animate one element of a one dimensional array
					continue;
				}
				const DocumentImporter::MaxControllerList& maxControllerList = getMaxControllerListByAnimationUniqueId( animationBinding.animation );
				assert(maxControllerList.size()==1);
				if ( maxControllerList.size() < 1 )
				{
					// this animation does not animate one element of a one dimensional array
					continue;
				}
				Control* weightController = maxControllerList[0];

				size_t channelNumber = animationBinding.firstIndex;
				if ( (int)channelNumber >= channelCount )
				{
					// invalid channel
					continue;
				}
				morphChannel* channel = &mMorphModifier->chanBank[channelNumber];

				if ( !channel )
				{
					continue;
				}
				Control* scaledWeightController = cloneController( weightController, &ConversionFunctors::toPercent);
				//Control* scaledWeightController = cloneController( weightController);
				//channel->cblock->SetController(0, weightController);
				channel->cblock->SetController(0, scaledWeightController);
			}
		}


		//assign the morph controller to all INodes referencing it
		INodeList referencingINodes;
		getObjectINodesByUniqueId( morphController->getUniqueId(), referencingINodes );

		for ( size_t i = 0, count = referencingINodes.size(); i < count; ++i)
		{
			INode* referencingINode = referencingINodes[i];
			referencingINode->SetObjectRef(mDerivedObject);
		}

		addUniqueIdObjectPair( morphController->getUniqueId(), mDerivedObject );
		return true;
	}
Example #21
0
void XsiExp::DumpScaleKeys( INode * node, int indentLevel) 
{
  Control * cont = node->GetTMController()->GetScaleController();
	IKeyControl * ikc = GetKeyControlInterface(cont);
	INode * parent = node->GetParentNode();
	if (!cont || !parent || (parent && parent->IsRootNode()) || !ikc)
  {
    // no controller or root node
		return;
  }
	int numKeys = ikc->GetNumKeys();
	if (numKeys <= 1)
  {  
    return;
  }
	Object * obj = node->EvalWorldState(0).obj;
  BOOL isBone = obj && obj->ClassID() == Class_ID(BONE_CLASS_ID, 0) ? TRUE : FALSE;

  // anim keys header
  TSTR indent = GetIndent(indentLevel);
	fprintf(pStream,"%s\tSI_AnimationKey {\n", indent.data()); 
	fprintf(pStream,"%s\t\t1;\n", indent.data());     // 1 means scale keys
	fprintf(pStream,"%s\t\t%d;\n", indent.data(), numKeys);

	int t, delta = GetTicksPerFrame();
 	Matrix3 matrix;
  AffineParts ap;
	for (int i = 0; i < numKeys; i++)
  {  
    // get the key's time
	  if (cont->ClassID() == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0))
    {
  	  ITCBRotKey key;
			ikc->GetKey(i, &key);
      t = key.time;
    }
    else if (cont->ClassID() == Class_ID(HYBRIDINTERP_SCALE_CLASS_ID, 0))
	  {
		  IBezQuatKey key;
		  ikc->GetKey(i, &key);
      t = key.time;
    }
	  else if (cont->ClassID() == Class_ID(LININTERP_SCALE_CLASS_ID, 0))
    {
  	  ILinRotKey key;
		  ikc->GetKey(i, &key);
      t = key.time;
    }
    // sample the node's matrix
    matrix = node->GetNodeTM(t) * Inverse(node->GetParentTM(t));
    if (!isBone)
    {
      matrix = matrix * topMatrix;
    }
    decomp_affine(matrix, &ap);

		fprintf(pStream, "%s\t\t%d; 3; %.6f, %.6f, %.6f;;%s\n", 
			indent.data(),
			t / delta,
			ap.k.x, ap.k.z, ap.k.y,
      i == numKeys - 1 ? ";\n" : ",");
	}
  // anim keys close
	fprintf(pStream,"%s\t}\n\n", indent.data());
}
Example #22
0
int FormationBhvr::Perform(INode *node, TimeValue t, int numsubsamples, BOOL DisplayHelpers, float BhvrWeight,
			PerformOut &out)
{
	Object *o = node->GetObjectRef();
    if (o->ClassID() != DELEG_CLASSID) return FALSE; // this should never happen
    IDelegate *IDeleg = (IDelegate *) o->GetInterface(I_DELEGINTERFACE);
	Point3 vel= IDeleg->GetCurrentVelocity();

	Point3 pos = IDeleg->GetCurrentPosition();

	INode *leader = GetLeader(t);
	if(leader==NULL)
		return 0;

	
	Matrix3 formationMat;
	//Get the local formation matrix and check

	if(FindFollowerMatrix(t,node,formationMat)==FALSE)
		return 0; //that node doesn't exist in the formation so exit.

	//returned values.
	Point3 frc,goal;
	float speedwt, speedAtGoalwt;

	//Find the Formation Position Target in World Space.

 	Matrix3 currentLeaderMat = GetCurrentMatrix(leader,t);
	currentLeaderMat.NoScale();
	Matrix3 worldSpace = formationMat*currentLeaderMat;
	Point3 target =  worldSpace.GetTrans();

	//set the goal as the target
	goal = target;

	//set the force as the direction to move towards the target
	frc =  goal - pos;

	float length = frc.FLength();

	if(length!=0.0f) //we are not at the goal
	{
		frc  /=length;
		
		//set up the leader Vector
		Point3 leaderVec = leaderVel*leaderSpeed;

	
	
		//If the  target is behind you but moving towards you don't turn around to
		//go toward it.  Instead move in the direction of the leader.
		if(frc%vel<0.0f &&  //if you are behind it
			length/IDeleg->GetAverageSpeed(t)<10 && //AND less than 20 frames
			vel%leaderVel>0.0f) //AND it is going toward you.
		{
			
			//set frc as leader's Velocity.
			frc = leaderVel;

			//move at half the leaderSpeed.  Leader will still catch
			//up to you and you'll have some speed when it does.
			
			//set the speewt
			speedwt = (leaderSpeed*0.5f)/IDeleg->GetAverageSpeed(t);
		}
		else //we should just move towards the target.
		{
			//We need to find the speed to be it.  We do this by
			//finding the time we will intersect our target based
			//upon the leader's velocity and our own velocity.

			vel -= leaderVec;
			
			//find time to intersect..
			float newSpeed = vel.FLength();
			float timeToIntersect = length/newSpeed;

			//from that time.. figure out what it speed should be..
			newSpeed = timeToIntersect * IDeleg->GetMaxAccel(t);
			if(newSpeed>IDeleg->GetAverageSpeed(t))
				newSpeed = IDeleg->GetAverageSpeed(t);


			//check to see if we will move past the goal.. if so
			//move the goal along the leader vec.  This reduces overshooting
			//the goal and decreases wobbling.
			if((newSpeed+leaderSpeed)>length) 	
			{
				goal += leaderVel*(leaderSpeed);  
				frc = goal -pos;
				float newLength = frc.FLength();

				if(newLength!=0.0f) //check for if zero to avoid divide by zero..
				{
					frc /= newLength;
					speedwt = (newSpeed+leaderSpeed)/IDeleg->GetAverageSpeed(t);
										
				}
				else
				{
					speedwt = 0.0f;
				}

			}
			else //far enough away.. leave the ole frc value..
				speedwt = (newSpeed+leaderSpeed)/IDeleg->GetAverageSpeed(t);
			
		}
	}
	else  //we are at the goal
	{
		frc.x = frc.y = frc.z = 0.0f;
	
		//set the speedwt to be the leaderSpeed
		speedwt = leaderSpeed/IDeleg->GetAverageSpeed(t);
	}

	frc *= BhvrWeight *IDeleg->GetAverageSpeed(t); //scale by weight and average speed..

	//set the speedWtAtGoal.. We want it to be the speed of the leader
	speedAtGoalwt = leaderSpeed/IDeleg->GetAverageSpeed(t);

	//Display Any Helpers.
	if (DisplayHelpers && IDeleg->OkToDisplayMyForces())
	{
		if (DisplayTarget(t)) IDeleg->SphereDisplay(goal,pblock->GetFloat(target_scale),GetTargetColor(t));
		if (DisplayForce(t))  IDeleg->LineDisplay(IDeleg->GetCurrentPosition(),IDeleg->GetCurrentPosition()+frc,GetForceColor(t),TRUE);
	}

	//set up the out structure..
	out.frc = frc;
	out.goal = goal;
	out.speedwt = speedwt;
	out.speedAtGoalwt = speedAtGoalwt;

	return BHVR_SETS_FORCE | BHVR_SETS_GOAL | BHVR_SETS_SPEED;
}
Example #23
0
int SceneEnumProc::callback(INode *node)
{
	char line[1024];
	Object *obj = node->EvalWorldState(time).obj;
	
	strcpy(line, node->GetName());
	//if(strstr(line, "Bip") != NULL)
	{
		sprintf(line, "%08X %08X", obj->SuperClassID(), obj->ClassID());
		//		MessageBox(NULL, line, node->GetName(), MB_OK);
	}
	
	if( (obj->SuperClassID() == GEOMOBJECT_CLASS_ID) && 
		(obj->ClassID() == Class_ID(BIP_BONE_CLASS_ID, 0)) )
	{
		Append(node, obj, OBTYPE_BONE);
		return TREE_CONTINUE;
	}
	
	if (obj->CanConvertToType(triObjectClassID))
	{
		Append(node, obj, OBTYPE_MESH);
		return TREE_CONTINUE;
	}
	
	if (node->IsTarget()) 
	{
		INode* ln = node->GetLookatNode();
		if (ln) 
		{
			Object *lobj = ln->EvalWorldState(time).obj;
			switch(lobj->SuperClassID())
			{
			case LIGHT_CLASS_ID:  Append(node, obj, OBTYPE_LTARGET); break;
			case CAMERA_CLASS_ID: Append(node, obj, OBTYPE_CTARGET); break;
			}
		}
		return TREE_CONTINUE;
	}
	switch (obj->SuperClassID()) 
	{ 
	case HELPER_CLASS_ID:
		if ( obj->ClassID()==Class_ID(DUMMY_CLASS_ID,0)) 
			Append(node, obj, OBTYPE_DUMMY);
		if(obj->ClassID() == Class_ID(BONE_CLASS_ID,0))
			Append(node, obj, OBTYPE_BONE);
		break;
	case LIGHT_CLASS_ID:
		if (obj->ClassID()==Class_ID(OMNI_LIGHT_CLASS_ID,0))
			Append(node, obj, OBTYPE_OMNILIGHT);
		else 
			if (obj->ClassID()==Class_ID(SPOT_LIGHT_CLASS_ID,0)) 
				Append(node, obj, OBTYPE_SPOTLIGHT);
			//export DIR_LIGHT and FSPOT_LIGHT????
			break;
	case CAMERA_CLASS_ID:
		if (obj->ClassID()==Class_ID(LOOKAT_CAM_CLASS_ID,0))
			Append(node, obj, OBTYPE_CAMERA);
		break;
	}
	return TREE_CONTINUE;	// Keep on enumeratin'!
}
Example #24
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;
		}
	}
}
Example #25
0
CInstanceGroup*	CExportNel::buildInstanceGroup(const vector<INode*>& vectNode, vector<INode*>& resultInstanceNode, TimeValue tvTime)
{
	// Extract from the node the name, the transformations and the parent

	CInstanceGroup::TInstanceArray aIGArray;
	uint32 i, nNumIG;
	uint32 j,k,m;

	aIGArray.empty ();
	resultInstanceNode.empty ();
	aIGArray.resize (vectNode.size());
	resultInstanceNode.resize (vectNode.size());

	int nNbInstance = 0;
	for (i = 0; i < vectNode.size(); ++i)
	{
		INode *pNode = vectNode[i];

		int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32);

		if ((nAccelType&3) == 0) // If not an accelerator
		if (!RPO::isZone (*pNode, tvTime))
		if (CExportNel::isMesh (*pNode, tvTime) || CExportNel::isDummy(*pNode, tvTime))
		{
			++nNbInstance;
		}
	}

	// Check integrity of the hierarchy and set the parents
	std::vector<INode*>::const_iterator it = vectNode.begin();
	nNumIG = 0;
	for (i = 0; i < (sint)vectNode.size(); ++i, ++it)
	{
		INode *pNode = *it;

		int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32);

		if ((nAccelType&3) == 0) // If not an accelerator
		if (!RPO::isZone( *pNode, tvTime ))
		if (CExportNel::isMesh( *pNode, tvTime ) || CExportNel::isDummy(*pNode, tvTime))
		{
			aIGArray[nNumIG].DontAddToScene = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_DONT_ADD_TO_SCENE, 0)?true:false;
			aIGArray[nNumIG].InstanceName = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_INSTANCE_NAME, "");
			resultInstanceNode[nNumIG] = pNode;
			if (aIGArray[nNumIG].InstanceName == "") // no instance name was set, takes the node name instead
			{
				aIGArray[nNumIG].InstanceName = pNode->GetName();
			}

			// Visible? always true, but if special flag for camera collision
			sint	appDataCameraCol= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_CAMERA_COLLISION_MESH_GENERATION, 0);
			aIGArray[nNumIG].Visible= appDataCameraCol!=3;


			INode *pParent = pNode->GetParentNode();

			// Set the DontCastShadow flag.
			aIGArray[nNumIG].DontCastShadow= pNode->CastShadows()==0;

			// Set the Special DontCastShadow flag.
			aIGArray[nNumIG].DontCastShadowForInterior= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_LIGHT_DONT_CAST_SHADOW_INTERIOR, BST_UNCHECKED)?true:false;
			aIGArray[nNumIG].DontCastShadowForExterior= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_LIGHT_DONT_CAST_SHADOW_EXTERIOR, BST_UNCHECKED)?true:false;

			// Is the pNode has the root node for parent ?
			if( pParent->IsRootNode() == 0 )
			{
				// Look if the parent is in the selection
				int nNumIG2 = 0;
				for (j = 0; j < vectNode.size(); ++j)
				{
					INode *pNode2 = vectNode[j];

					int nAccelType2 = CExportNel::getScriptAppData (pNode2, NEL3D_APPDATA_ACCEL, 32);
					if ((nAccelType2&3) == 0) // If not an accelerator
					if (!RPO::isZone( *pNode2, tvTime ))
					if (CExportNel::isMesh( *pNode2, tvTime ))
					{
						if (pNode2 == pParent)
							break;
						++nNumIG2;
					}
				}
				if (nNumIG2 == nNbInstance)
				{
					// The parent is not selected ! link to root
					aIGArray[nNumIG].nParent = -1;
				}
				else
				{
					aIGArray[nNumIG].nParent = nNumIG2;
				}
			}
			else
			{
				aIGArray[nNumIG].nParent = -1;
			}
			++nNumIG;
		}
	}
	aIGArray.resize( nNumIG );
	resultInstanceNode.resize( nNumIG );

	// Build the array of node
	vGlobalPos = CVector(0,0,0);
	nNumIG = 0;
	it = vectNode.begin();
	for (i = 0; i < (sint)vectNode.size(); ++i, ++it)
	{
		INode *pNode = *it;

		int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32);

		if ((nAccelType&3) == 0) // If not an accelerator
		if (!RPO::isZone (*pNode, tvTime))
		if (CExportNel::isMesh (*pNode, tvTime) || CExportNel::isDummy(*pNode, tvTime))
		{
			CVector vScaleTemp;
			CQuat qRotTemp;
			CVector vPosTemp;

			// Get Nel Name for the object.
			aIGArray[nNumIG].Name= CExportNel::getNelObjectName(*pNode);

			//Get the local transformation matrix
			Matrix3 nodeTM = pNode->GetNodeTM(0);
			INode *pParent = pNode->GetParentNode();
			Matrix3 parentTM = pParent->GetNodeTM(0);
			Matrix3 localTM	= nodeTM*Inverse(parentTM);

			// Extract transformations
			CExportNel::decompMatrix (vScaleTemp, qRotTemp, vPosTemp, localTM);
			aIGArray[nNumIG].Rot   = qRotTemp;
			aIGArray[nNumIG].Pos   = vPosTemp;
			aIGArray[nNumIG].Scale = vScaleTemp;
			vGlobalPos += vPosTemp;
			++nNumIG;
		}
	}
	// todo Make this work (precision):
	/*
	vGlobalPos = vGlobalPos / nNumIG;
	for (i = 0; i < nNumIG; ++i)
		aIGArray[i].Pos -= vGlobalPos;
	*/

	vGlobalPos = CVector(0,0,0); // Temporary !!!

	// Accelerator Portal/Cluster part
	//=================

	// Creation of all the clusters
	vector<CCluster> vClusters;
	it = vectNode.begin();
	for (i = 0; i < (sint)vectNode.size(); ++i, ++it)
	{
		INode *pNode = *it;

		int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, NEL3D_APPDATA_ACCEL_DEFAULT);
		bool bFatherVisible = nAccelType&NEL3D_APPDATA_ACCEL_FATHER_VISIBLE?true:false;
		bool bVisibleFromFather = nAccelType&NEL3D_APPDATA_ACCEL_VISIBLE_FROM_FATHER?true:false;
		bool bAudibleLikeVisible = (nAccelType&NEL3D_APPDATA_ACCEL_AUDIBLE_NOT_LIKE_VISIBLE)?false:true;
		bool bFatherAudible = bAudibleLikeVisible ? bFatherVisible : nAccelType&NEL3D_APPDATA_ACCEL_FATHER_AUDIBLE?true:false;
		bool bAudibleFromFather = bAudibleLikeVisible ? bVisibleFromFather : nAccelType&NEL3D_APPDATA_ACCEL_AUDIBLE_FROM_FATHER?true:false;

		if ((nAccelType&NEL3D_APPDATA_ACCEL_TYPE) == NEL3D_APPDATA_ACCEL_CLUSTER) // If cluster
		if (!RPO::isZone (*pNode, tvTime))
		if (CExportNel::isMesh(*pNode, tvTime))
		{
			CCluster clusterTemp;
			std::string temp;

			temp = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_SOUND_GROUP, "no sound");
			clusterTemp.setSoundGroup(temp != "no sound" ? temp : "");
			temp = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_ENV_FX, "no fx");
			clusterTemp.setEnvironmentFx(temp != "no fx" ? temp : "");

			CMesh::CMeshBuild *pMB;
			CMeshBase::CMeshBaseBuild *pMBB;
			pMB = createMeshBuild (*pNode, tvTime, pMBB);

			convertToWorldCoordinate( pMB, pMBB );

			for (j = 0; j < pMB->Faces.size(); ++j)
			{
				if (!clusterTemp.makeVolume (pMB->Vertices[pMB->Faces[j].Corner[0].Vertex],
											 pMB->Vertices[pMB->Faces[j].Corner[1].Vertex],
											 pMB->Vertices[pMB->Faces[j].Corner[2].Vertex]) )
				{
					// ERROR : The volume is not convex !!!
					char tam[256];
					sprintf(tam,"ERROR: The cluster %s is not convex.",vectNode[i]->GetName());
					//MessageBox(NULL,tam,"Error",MB_OK|MB_ICONERROR);
					nlwarning(tam);
				}
			}

			clusterTemp.FatherVisible = bFatherVisible;
			clusterTemp.VisibleFromFather = bVisibleFromFather;
			clusterTemp.FatherAudible = bFatherAudible;
			clusterTemp.AudibleFromFather = bAudibleFromFather;
			clusterTemp.Name = pNode->GetName();

			vClusters.push_back (clusterTemp);
			delete pMB;
			delete pMBB;
		}
	}

	// Creation of all the portals
	vector<CPortal> vPortals;
	it = vectNode.begin();
	for (i = 0; i < (sint)vectNode.size(); ++i, ++it)
	{
		INode *pNode = *it;

		int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32);

		if ((nAccelType&3) == 1) // If Portal
		if (!RPO::isZone (*pNode, tvTime))
		if (CExportNel::isMesh(*pNode, tvTime))
		{
			CPortal portalTemp;
			std::string temp;

			temp = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_OCC_MODEL, "no occlusion");
			portalTemp.setOcclusionModel(temp != "no occlusion" ? temp : "");
			temp = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_OPEN_OCC_MODEL, "no occlusion");
			portalTemp.setOpenOcclusionModel(temp != "no occlusion" ? temp : "");

			CMesh::CMeshBuild *pMB;
			CMeshBase::CMeshBaseBuild *pMBB;
			pMB = createMeshBuild (*pNode, tvTime, pMBB);

			convertToWorldCoordinate( pMB, pMBB );

			vector<sint32> poly;
			vector<bool> facechecked;
			facechecked.resize (pMB->Faces.size());
			for (j = 0; j < pMB->Faces.size(); ++j)
				facechecked[j] = false;

			poly.push_back(pMB->Faces[0].Corner[0].Vertex);
			poly.push_back(pMB->Faces[0].Corner[1].Vertex);
			poly.push_back(pMB->Faces[0].Corner[2].Vertex);
			facechecked[0] = true;
			for (j = 0; j < pMB->Faces.size(); ++j)
			if (!facechecked[j])
			{
				bool found = false;

				for(k = 0; k < 3; ++k)
				{
					for(m = 0; m < poly.size(); ++m)
					{
						if ((pMB->Faces[j].Corner[k].Vertex == poly[m]) &&
							(pMB->Faces[j].Corner[(k+1)%3].Vertex == poly[(m+1)%poly.size()]))
						{
							found = true;
							break;
						}
						if ((pMB->Faces[j].Corner[(k+1)%3].Vertex == poly[m]) &&
							(pMB->Faces[j].Corner[k].Vertex == poly[(m+1)%poly.size()]))
						{
							found = true;
							break;
						}
					}
					if (found)
						break;
				}
				if (found)
				{
					// insert an empty space in poly between m and m+1
					poly.resize (poly.size()+1);
					for (uint32 a = poly.size()-2; a > m; --a)
						poly[a+1] = poly[a];
					poly[m+1] = pMB->Faces[j].Corner[(k+2)%3].Vertex;
					facechecked[j] = true;
					j = 0;
				}
			}
			vector<CVector> polyv;
			polyv.resize (poly.size());
			for (j = 0; j < poly.size(); ++j)
				polyv[j] = pMB->Vertices[poly[j]];
			
			if (!portalTemp.setPoly (polyv))
			{
				// ERROR : Poly not convex, or set of vertices not plane
				char tam[256];
				sprintf(tam,"ERROR: The portal %s is not convex.",vectNode[i]->GetName());
				//MessageBox(NULL,tam,"Error",MB_OK|MB_ICONERROR);
				nlwarning(tam);
			}

			if (nAccelType&16) // is dynamic portal ?
			{
				string InstanceName = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_INSTANCE_NAME, "");
				if (!InstanceName.empty())
					portalTemp.setName (InstanceName);
				else
					portalTemp.setName (string(pNode->GetName()));
			}

			// Check if portal has 2 cluster
			int nNbCluster = 0;
			for (j = 0; j < vClusters.size(); ++j)
			{
				bool bPortalInCluster = true;
				for (k = 0; k < polyv.size(); ++k)
					if (!vClusters[j].isIn (polyv[k]) )
					{
						bPortalInCluster = false;
						break;
					}
				if (bPortalInCluster)
					++nNbCluster;
			}
			if (nNbCluster != 2)
			{
				// ERROR
				char tam[256];
				sprintf(tam,"ERROR: The portal %s has not 2 clusters but %d",vectNode[i]->GetName(), nNbCluster);
				//MessageBox(NULL,tam,"Error",MB_OK|MB_ICONERROR);
				nlwarning(tam);
			}


			vPortals.push_back (portalTemp);
			delete pMB;
			delete pMBB;
		}
	}

	// Link instance to clusters (an instance has a list of clusters)
	nNumIG = 0;
	it = vectNode.begin();
	for (i = 0; i < (sint)vectNode.size(); ++i, ++it)
	{
		INode *pNode = *it;

		int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32);

		if ((nAccelType&3) == 0) // If not an accelerator
		if (!RPO::isZone (*pNode, tvTime))
		if (CExportNel::isMesh (*pNode, tvTime) || CExportNel::isDummy(*pNode, tvTime))
		{
			if (nAccelType&32) // Is the flag clusterize set ?
			{
				// Test against all clusters

				// The list of vertices used to test against cluster
				std::vector<NLMISC::CVector> *testVertices;
				std::vector<NLMISC::CVector>       FXVertices;  // Used only if the obj is a fx. It contains the corners of the bbox.
				bool  buildMeshBBox = true;

				/** If it is a mesh, we build its bbox and transform in world
				  * If it is a FX, we read its bbox from its shape
				  * If we can't read it, we use the bbox of the fx helper in max
				  */
				Object *obj = pNode->EvalWorldState(tvTime).obj;
				// Check if there is an object
				if (obj)
				{
					Class_ID  clid = obj->ClassID();
					// is the object a particle system ?					
					if (clid.PartA() == NEL_PARTICLE_SYSTEM_CLASS_ID)
					{
						// build the shape from the file name
						std::string objName = CExportNel::getNelObjectName(*pNode); 						
						if (!objName.empty())
						{											
							NL3D::CShapeStream ss;
							NLMISC::CIFile iF;
							if (iF.open(objName.c_str()))
							{
								try
								{								
									iF.serial(ss);
									NL3D::CParticleSystemShape *pss = dynamic_cast<NL3D::CParticleSystemShape *>(ss.getShapePointer());
									if (!pss)
									{
										nlwarning("ERROR: Node %s shape is not a FX", CExportNel::getName(*pNode).c_str());
									}
									else
									{									
										NLMISC::CAABBox bbox;
										pss->getAABBox(bbox);
										// transform in world
										Matrix3 xForm = pNode->GetNodeTM(tvTime);
										NLMISC::CMatrix nelXForm;
										CExportNel::convertMatrix(nelXForm, xForm);									
										bbox = NLMISC::CAABBox::transformAABBox(nelXForm, bbox);
										// store vertices of the bbox in the list
										FXVertices.reserve(8);
										for(uint k = 0; k < 8; ++k)
										{
											FXVertices.push_back(CVector(((k & 1) ? 1 : -1) * bbox.getHalfSize().x + bbox.getCenter().x,
																		 ((k & 2) ? 1 : -1) * bbox.getHalfSize().y + bbox.getCenter().y,
																		 ((k & 4) ? 1 : -1) * bbox.getHalfSize().z + bbox.getCenter().z));
										}
										//
										testVertices = &FXVertices;
										buildMeshBBox = false;
									}
									delete ss.getShapePointer();
								}
								catch (NLMISC::Exception &e)
								{
									nlwarning(e.what());									
								}
							}							
							if (buildMeshBBox)
							{
								nlwarning("ERROR: Can't get bbox of a particle system from its shape, using helper bbox instead");
							}
						}
					}
				}

				CMesh::CMeshBuild *pMB = NULL;
				CMeshBase::CMeshBaseBuild *pMBB = NULL;

				if (buildMeshBBox)
				{				
					pMB = createMeshBuild (*pNode, tvTime, pMBB);
					convertToWorldCoordinate( pMB, pMBB );
					testVertices = &pMB->Vertices;
				}

				for(k = 0; k < vClusters.size(); ++k)
				{
					bool bMeshInCluster = false;

					for(j = 0; j < testVertices->size(); ++j)
					{
						if (vClusters[k].isIn ((*testVertices)[j]))
						{
							bMeshInCluster = true;
							break;
						}
					}

					if (bMeshInCluster)
					{
						aIGArray[nNumIG].Clusters.push_back (k);
					}
				}
				
				// debug purpose : to remove
				if (vClusters.size() > 0)
				if (aIGArray[nNumIG].Clusters.size() == 0)
				{
					char tam[256];
					sprintf(tam,"ERROR: Object %s is not attached to any cluster\nbut his flag clusterize is set", pNode->GetName());
					//MessageBox(NULL, tam, "Warning", MB_OK);
					nlwarning(tam);
				}
				// debug purpose : to remove

				delete pMB;
				delete pMBB;
			}
			
			++nNumIG;
		}
		// debug purpose : to remove
		/*
		if ((nAccelType&3) == 0) // If not an accelerator
		if (!(nAccelType&32))
		{
			char tam[256];
			sprintf(tam,"Object %s is not clusterized", pNode->GetName());
			MessageBox(NULL, tam, "Info", MB_OK);
		}
		*/
		// debug purpose : to remove

	}


	// PointLight part
	//=================
	bool	sunLightEnabled= false;
	sint	nNumPointLight = 0;
	vector<CPointLightNamed>	pointLights;
	pointLights.resize(vectNode.size());
	// For all nodes
	for (i = 0; i < (sint)vectNode.size(); ++i)
	{
		INode *pNode = vectNode[i];

		SLightBuild		sLightBuild;

		// If it is a Max Light.
		if ( sLightBuild.canConvertFromMaxLight(pNode, tvTime) )
		{
			// And if this light is checked to realtime export
			int		nRTExport= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_EXPORT_REALTIME_LIGHT, BST_CHECKED);
			if(nRTExport == BST_CHECKED)
			{
				// get Max Light info.
				sLightBuild.convertFromMaxLight(pNode, tvTime);

				// Skip if LightDir
				if(sLightBuild.Type != SLightBuild::LightDir)
				{
					// Fill PointLight Info.
					NL3D::CPointLightNamed	&plNamed= pointLights[nNumPointLight];

					// Position
					plNamed.setPosition(sLightBuild.Position);
					// Attenuation
					plNamed.setupAttenuation(sLightBuild.rRadiusMin, sLightBuild.rRadiusMax);
					// Colors
					// Ensure A=255 for localAmbient to work.
					NLMISC::CRGBA	ambient= sLightBuild.Ambient;
					ambient.A= 255;
					plNamed.setDefaultAmbient(ambient);
					plNamed.setAmbient(ambient);
					plNamed.setDefaultDiffuse(sLightBuild.Diffuse);
					plNamed.setDiffuse(sLightBuild.Diffuse);
					plNamed.setDefaultSpecular(sLightBuild.Specular);
					plNamed.setSpecular(sLightBuild.Specular);

					// GroupName.
					plNamed.AnimatedLight = sLightBuild.AnimatedLight;
					plNamed.LightGroup = sLightBuild.LightGroup;

					// Which light type??
					if(sLightBuild.bAmbientOnly || sLightBuild.Type== SLightBuild::LightAmbient)
					{
						plNamed.setType(CPointLight::AmbientLight);
						// Special ambient info
						int		nRTAmbAdd= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_REALTIME_AMBIENT_ADD_SUN, BST_UNCHECKED);
						plNamed.setAddAmbientWithSun(nRTAmbAdd==BST_CHECKED);
					}
					else if(sLightBuild.Type== SLightBuild::LightPoint)
					{
						plNamed.setType(CPointLight::PointLight);
					}
					else if(sLightBuild.Type== SLightBuild::LightSpot)
					{
						plNamed.setType(CPointLight::SpotLight);
						// Export Spot infos.
						plNamed.setupSpotDirection(sLightBuild.Direction);
						plNamed.setupSpotAngle(sLightBuild.rHotspot, sLightBuild.rFallof);
					}
					else
					{
						// What???
						nlstop;
					}


					// inc Size
					++nNumPointLight;
				}
			}

			// if this light is a directionnal and checked to export as Sun Light
			int		nExportSun= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_EXPORT_AS_SUN_LIGHT, BST_UNCHECKED);
			if(nExportSun== BST_CHECKED)
			{
				// get Max Light info.
				sLightBuild.convertFromMaxLight(pNode, tvTime);

				// Skip if not dirLight.
				if(sLightBuild.Type == SLightBuild::LightDir)
					sunLightEnabled= true;
			}
		}
	}
	// Good size
	pointLights.resize(nNumPointLight);


	// Build the ig
	//=================

	CInstanceGroup* pIG = new CInstanceGroup;

	// Link portals and clusters and create meta cluster if one
	pIG->build (vGlobalPos,  aIGArray, vClusters, vPortals, pointLights);

	// IG touched by sun ??
	pIG->enableRealTimeSunContribution(sunLightEnabled);

	return pIG;
}
Example #26
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 #27
0
/*
====================
exportNode
====================
*/
void G3DAExport::exportNode( INode* i_node, NODE* parent )
{
	// if it is hidden?
	bool include = false;
	if(!i_node->IsHidden()) include = true;

	// get the result of the pipeline at the current time 	
	Object *obj = i_node->EvalWorldState(mTime).obj;
	if(obj)
	{
		if(obj->ClassID() == Class_ID(TARGET_CLASS_ID, 0)) include = false;
		if(obj->ClassID() == Class_ID(0x74f93b07, 0x1eb34300)) include = false;
		if(obj->ClassID() == Class_ID(BOXOBJ_CLASS_ID, 0)) include = false;
		if(obj->ClassID() == Class_ID(SPHERE_CLASS_ID, 0)) include = false;
		if(obj->ClassID() == Class_ID(CYLINDER_CLASS_ID, 0)) include = false;
		if(obj->ClassID() == Class_ID(CONE_CLASS_ID, 0)) include = false;
		if(obj->SuperClassID() == CAMERA_CLASS_ID) include = false;
		if(obj->SuperClassID() == LIGHT_CLASS_ID) include = false;
		if(obj->SuperClassID() == SHAPE_CLASS_ID) include = false;
	}

	// if this node is renderable?
	if(include)
	{
		if(getModifier(i_node,Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B)) != NULL)
		{
			include = false;
		}

		if(getModifier(i_node,SKIN_CLASSID) != NULL)
		{
			mSkins.push_back(i_node);
			include = false;
		}
	}

	// the new node
	NODE* this_node = new NODE;
	MAX_CHECK(this_node);
	if(parent==NULL)
	{
		mRoot = this_node;		
	}
	else
	{
		parent->children.push_back(this_node);
		this_node->parent = parent;
	}
	this_node->i_node = i_node;
	this_node->include = include;
	this_node->name = i_node->GetName();
	if(this_node->include)
	{
		NODE* parent = this_node->parent;
		while(parent)
		{
			parent->include = true;
			parent = parent->parent;
		}
	}	

	// process the child node
	for(int i = 0; i < i_node->NumberOfChildren(); i++)
	{
		exportNode(i_node->GetChildNode(i),this_node);
	}
}
Example #28
0
// Get hold of the transform controllers for the node... 
void XsiExp::ExportAnimKeys( INode * node, int & animHit) 
{
	// Targets are actually geomobjects, but we will export them
	// from the camera and light objects, so we skip them here.
  //
	Object * obj = node->EvalWorldState(GetStaticFrame()).obj;
	if (!obj || obj->ClassID() == Class_ID( TARGET_CLASS_ID, 0))
  {
		return;
  }
	TSTR indent = GetIndent(1);
	BOOL bPosAnim, bRotAnim, bScaleAnim, bDoKeys = FALSE;
  TCHAR * name = FixupName( node->GetName());

  BOOL isBone = obj->ClassID() == Class_ID(BONE_CLASS_ID, 0) ? TRUE : FALSE;
  if (isBone)
  {
    // bone anims get passed to children
    if (!node->GetParentNode() || node->GetParentNode()->IsRootNode())
    {
      // can't anim top bone
      return;
    }
    node = node->GetParentNode();
  }

	// We can only export keys if all TM controllers are "known" to us.
	// The reason for that is that some controllers control more than what
	// they should. Consider a path position controller, if you turn on
	// follow and banking, this position controller will also control
	// rotation. If a node that had a path position controller also had a
	// TCB rotation controller, the TCB keys would not describe the whole
	// rotation of the node.
	// For that reason we will only export keys if all controllers
	// position, rotation and scale are linear, hybrid (bezier) or tcb.

	if (!GetAlwaysSample())
  {
		Control* pC = node->GetTMController()->GetPositionController();
		Control* rC = node->GetTMController()->GetRotationController();
		Control* sC = node->GetTMController()->GetScaleController();

		if (IsKnownController(pC) && IsKnownController(rC) && IsKnownController(sC))
    {
			bDoKeys = TRUE;
		}
	}
	if (bDoKeys)
  {
		// Only dump the track header if any of the controllers have keys
		if (node->GetTMController()->GetPositionController()->NumKeys()  > 1 ||
  			node->GetTMController()->GetRotationController()->NumKeys()  > 1 ||
	  		node->GetTMController()->GetScaleController()->NumKeys()     > 1)
    {
      if (!animHit)
      {
		    fprintf(pStream,"AnimationSet {\n"); 
        animHit = TRUE;
      }
		  fprintf(pStream,"%sAnimation anim-%s {\n", indent.data(), name ); 

	    indent = GetIndent(2);

		  fprintf(pStream,"%s{frm-%s}\n", indent.data(), name ); 

			DumpRotKeys(   node, 1);
			DumpPosKeys(   node, 1);
			DumpScaleKeys( node, 1);

	    indent = GetIndent(1);

			fprintf(pStream,"%s}\n\n", indent.data());
		}
	}
	else if (CheckForAnimation(node, bPosAnim, bRotAnim, bScaleAnim))
  {
    if (!animHit)
    {
		  fprintf(pStream,"AnimationSet {\n"); 
      animHit = TRUE;
    }

		fprintf(pStream,"%sAnimation anim-%s {\n", indent.data(), name ); 

	  indent = GetIndent(2);

		fprintf(pStream,"%s{frm-%s}\n", indent.data(), name ); 

		DumpRotKeys(   node, 1);
		DumpPosKeys(   node, 1);
		DumpScaleKeys( node, 1);

		fprintf(pStream,"%s}\n", indent.data());
	}
}
Example #29
0
/**
 * This method will export the argument node and traverse
 * into its child nodes to export them.
 */
BOOL OSGExp::nodeEnum(osg::Group* rootTransform, INode* node, osg::Group* parent)
{
	osg::ref_ptr<osg::Group> child = NULL;

	_nCurNode++;
	_ip->ProgressUpdate((int)((float)_nCurNode/_nTotalNodeCount*100.0f)); 

	// Stop traversing if the user pressed Cancel.
	if (_ip->GetCancel())
		return TRUE;


	// If node is hidden and we are not exporting hidden nodes then return.
	if(node->IsNodeHidden() && !_options->getExportHiddenNodes()){
		return TRUE;
   }

   // Capture a special group helper if one is returned.
   // Nodes such as LODs and Switches will have to apply
   // special flags to their immediate children and thus
   // cannot be traversed in the normal recursive flow.
//   osg::Group* specialGroup = NULL;


	// Only export if hole scene is to be exported or
	// this node is choosen to be exported.
	if(!_onlyExportSelected || node->Selected())
   {
		// The ObjectState is a 'thing' that flows down the pipeline containing
		// all information about the object. By calling EvalWorldState() we tell
		// max to evaluate the object at the end of the pipeline.
		// An object may start out as an sphere, but could be modified by an modifier
		// object, the EvalWorldState will apply all modifiers to the original object
		// and return the final geometry for the object.
		ObjectState os = node->EvalWorldState(_ip->GetTime());

      // Use temporary variables for cleaner code.
      Object* obj = os.obj;
      TimeValue timeValue = _ip->GetTime();


		// If this a group node then make a OSG group node and add it to
		// the parent node and traverse into the children.
		if(node->IsGroupHead() || obj->ClassID() == Class_ID(DUMMY_CLASS_ID,0))
      {
			// Do not export referenced groups.
			if(Util::isReferencedByHelperObjects(node, _helperIDs))
				return TRUE;
			osg::MatrixTransform* groupNode = new osg::MatrixTransform();
			// Set name of group node.
			groupNode->setName(std::string(node->GetName()));
			// Set static datavariance for better performance
			groupNode->setDataVariance(osg::Object::STATIC);

			// Are we exporting animations.
			if(_options->getExportAnimations()){
				addAnimation(node, timeValue, groupNode);
			}
			
			// Set NodeMask
			if(_options->getUseDefaultNodeMaskValue())
				groupNode->setNodeMask(_options->getDefaultNodeMaskValue());
			groupNode->setMatrix(getNodeTransform(node, timeValue));
			parent->addChild(groupNode);
			parent = groupNode;
			applyNodeMaskValue(node, timeValue, groupNode);
		}

		// If this is not a group node it could be a geomtry object,
		// a camera, a light, or some other class. Switch the class ID
		// to carry out a specific export.
		// Note, it is the obj member of ObjectState which
		// is the actual object we are exporting.
		else if(obj != NULL)
      {
         Class_ID cid = obj->ClassID();

			// We look at the super class ID to determine the type of the object.
			switch(obj->SuperClassID())
         {
				case GEOMOBJECT_CLASS_ID:
					if(!Util::isReferencedByHelperObjects(node, _helperIDs))
               {
						child = createGeomObject(rootTransform, node, obj, timeValue).get();
						parent->addChild(child.get());
					}
					break;
				case CAMERA_CLASS_ID:
					if(_options->getExportCameras())
               {
						child = createCameraObject(rootTransform, node, obj, timeValue).get();
						parent->addChild(child.get());
					}
					break;
				case LIGHT_CLASS_ID:
					if(_options->getExportLights())
               {
						child = createLightObject(rootTransform, node, obj, timeValue).get();
						parent->addChild(child.get());
					}
					break;
				case SHAPE_CLASS_ID:
					if(_options->getExportShapes() && !Util::isReferencedByHelperObject(node, OCCLUDER_CLASS_ID))
               {
						child = createShapeObject(rootTransform, node, obj, timeValue).get();
						parent->addChild(child.get());
					}
					break;
				case HELPER_CLASS_ID:
               {
                  bool notRefByHelpers = Util::isReferencedByHelperObjects(node, _helperIDs) == NULL;
                  bool exportHelpers = _options->getExportHelpers() == TRUE;

                  if(_options->getExportPointHelpers() && cid == Class_ID(POINTHELP_CLASS_ID,0)) 
                  {
                     child = createPointFromHelperObject(rootTransform, node, obj, timeValue).get();
                     parent->addChild(child.get());
                  }
                  if(exportHelpers && notRefByHelpers)
                  {
                     if(cid == OSGGROUP_CLASS_ID)
                     {
                        child = createGroupFromHelper(parent, node, obj, timeValue).get();
                     }
                     else if(cid == LOD_CLASS_ID)
                     {
                        child = createLODFromHelperObject(parent, node, obj, timeValue).get();
                     }
                     else if(cid == SWITCH_CLASS_ID)
                     {
                        child = createSwitchFromHelperObject(parent, node, obj, timeValue).get();
                     }
                     else if(cid == DOFTRANSFORM_CLASS_ID) 
                     {
                        child = createDOFFromHelper(parent, node, obj, timeValue).get();                  
                     }
		               else
                     {
			               rootTransform->addChild(createHelperObject(rootTransform, node, obj, timeValue).get());
		               }
                  }
               }
					break;
            default:
               break;
			}
		}
	}

   for(int c = 0; c < node->NumberOfChildren(); c++)
   {
	   if(_ip->GetCancel() || ! nodeEnum(rootTransform, node->GetChildNode(c),child.valid()?child.get():parent))
      {
		   // If user cancels export we return false.
		   return FALSE;
	   }
   }

	return TRUE;
}
bool PFOperatorForceSpaceWarp::Proceed(IObject* pCont, 
									 PreciseTimeValue timeStart, 
									 PreciseTimeValue& timeEnd,
									 Object* pSystem,
									 INode* pNode,
									 INode* actionNode,
									 IPFIntegrator* integrator)
{
	// acquire all necessary channels, create additional if needed

	IChannelContainer* chCont;
	chCont = GetChannelContainerInterface(pCont);
	if (chCont == NULL) return false;

	IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont);
	if(chAmount == NULL) return false;
	int iQuant = chAmount->Count();
	if (iQuant < 1) return true; // no particles to proceed

	IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont);
	if (chNew == NULL) return false; 

	IParticleChannelIDR* chID = GetParticleChannelIDRInterface(pCont);
	if (chID == NULL) return false;

	IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont);
	if(chTime == NULL) return false;

	IParticleChannelPTVR* chAge = GetParticleChannelBirthTimeRInterface(pCont);
	if(chAge == NULL) return false;

// the channel of interest speed
	bool initSpeed = false;
//channel does not exist so make it and note that we have to fill it out
	IParticleChannelPoint3W* chSpeedW = (IParticleChannelPoint3W*)chCont->EnsureInterface(PARTICLECHANNELSPEEDW_INTERFACE,
																			ParticleChannelPoint3_Class_ID,
																			true, PARTICLECHANNELSPEEDR_INTERFACE,
																			PARTICLECHANNELSPEEDW_INTERFACE, true,
																			actionNode, NULL, &initSpeed);
	IParticleChannelPoint3R* chSpeed = GetParticleChannelSpeedRInterface(pCont);
	if ((chSpeedW == NULL) || (chSpeed == NULL)) return false;

	bool initPosition = false;
	IParticleChannelPoint3W* chPosW = (IParticleChannelPoint3W*)chCont->EnsureInterface(PARTICLECHANNELPOSITIONW_INTERFACE,
																			ParticleChannelPoint3_Class_ID,
																			true, PARTICLECHANNELPOSITIONR_INTERFACE,
																			PARTICLECHANNELPOSITIONW_INTERFACE, true,
																			actionNode, NULL, &initPosition);
	IParticleChannelPoint3R* chPos = GetParticleChannelPositionRInterface(pCont);
	if ((chPosW == NULL) || (chPos == NULL)) return false;

	bool useScript = ((scriptPBlock()->GetInt(kForceSpaceWarp_useScriptWiring, 0) != 0)
						&& (scriptPBlock()->GetInt(kForceSpaceWarp_useFloat, 0) == kForceSpaceWarp_useFloat_influence));
	IParticleChannelFloatR* chFloat = NULL;
	if (useScript) {
		chFloat = GetParticleChannelMXSFloatRInterface(pCont);
		if (chFloat == NULL) return false;
	}

	int timeType = kAbsoluteTime;
	_pblock()->GetValue(kForceSpaceWarp_Sync,0, timeType, FOREVER);

	IParticleChannelPTVR* chEventStart = NULL;
	IParticleChannelPTVW* chEventStartW = NULL;
	bool initEventStart = false;
	if (timeType == kEventDuration)
	{
		chEventStartW = (IParticleChannelPTVW*) chCont->EnsureInterface(PARTICLECHANNELEVENTSTARTW_INTERFACE,
								  ParticleChannelPTV_Class_ID,
								  true, PARTICLECHANNELEVENTSTARTR_INTERFACE,
								  PARTICLECHANNELEVENTSTARTW_INTERFACE, false,
								  actionNode, NULL, &initEventStart);

		chEventStart = GetParticleChannelEventStartRInterface(pCont);
		if ((chEventStart == NULL) || (chEventStartW == NULL)) return false;
	}

	int overlapping = pblock()->GetInt(kForceSpaceWarp_Overlapping, 0);
	// collecting force fields
	Tab<ForceField*> ff;
	ForceField* curFF;
	int i, j;
	for(i=0; i<pblock()->Count(kForceSpaceWarp_ForceNodeList); i++) {
		INode* node = pblock()->GetINode(kForceSpaceWarp_ForceNodeList, 0, i);
		if (node == NULL) continue;
		Object* ob = GetPFObject(node->GetObjectRef());
		if (ob == NULL) continue;
		if (ob->SuperClassID() == WSM_OBJECT_CLASS_ID) {
			WSMObject* obref = (WSMObject*)ob;
			curFF = obref->GetForceField(node);
			if (curFF != NULL) {
				if (ob->ClassID() == CS_VFIELDOBJECT_CLASS_ID) {
					// CS VectorField SW doesn't init properly partobj on GetForceField
					// this is a quick fix for that (bayboro 3/6/2003)
					CS_VectorField* vf = (CS_VectorField*)curFF;
					vf->partobj = GetParticleInterface(pSystem);
				}
				ff.Append(1, &curFF);
			}
		}
	}
	if (ff.Count() == 0) return true; // no force fields

	// some calls for a reference node TM may initiate REFMSG_CHANGE notification
	// we have to ignore that while processing the particles
	bool wasIgnoring = IsIgnoringRefNodeChange();
	if (!wasIgnoring) SetIgnoreRefNodeChange();

	float influence = 0.0f;
	for(i = 0; i < iQuant; i++) 
	{
		TimeValue t = 0;
		if (timeType == kAbsoluteTime)
			t = chTime->GetValue(i).TimeValue();
		else if (timeType == kParticleAge)
			t = chTime->GetValue(i).TimeValue() - chAge->GetValue(i).TimeValue();
		else 
		{
			if (initEventStart && chNew->IsNew(i))
				chEventStartW->SetValue(i, chTime->GetValue(i));
			t = chTime->GetValue(i).TimeValue() - chEventStart->GetValue(i).TimeValue();
		}

		if (useScript) {
			influence = chFloat->GetValue(i);
		} else {
			influence = GetPFFloat(pblock(), kForceSpaceWarp_Influence, t);
		}

		Point3 v(0.0f,0.0f,0.0f);
		if (!initSpeed || !chNew->IsNew(i)) //if we created a speed channel the channel incoming is bogus so just use 0,0,0 ad default
			v = chSpeed->GetValue(i);

		Point3 p(0.0f,0.0f,0.0f);
		if (!initPosition || !chNew->IsNew(i)) //if we created a pos channel the channel incoming is bogus so just use 0,0,0 ad default
			p = chPos->GetValue(i);

		Point3 force = Point3::Origin;
		for(j=0; j<ff.Count(); j++) {
			// buffer vectors to guard true position and speed from malicious force
			Point3 pp = p;
			Point3 vv = v;
			Point3 nextForce = ff[j]->Force(t,pp,vv,chID->GetParticleBorn(i)) * influence;
			float lenSq = LengthSquared(nextForce);
			if (lenSq <= 0.0f) continue; // not a valid force
			if (overlapping == kForceSpaceWarp_Overlapping_additive) {
				force += nextForce;
			} else {
				if (lenSq > LengthSquared(force))
					force = nextForce;
			}
//			p = pp;
//			v = vv;
		}

		v += force * float(timeEnd - chTime->GetValue(i));
		chPosW->SetValue(i, p);
		chSpeedW->SetValue(i, v);
	}

	for(i=0; i<ff.Count(); i++)
		if (ff[i] != NULL) ff[i]->DeleteThis();

	if (!wasIgnoring) ClearIgnoreRefNodeChange();
	return true;
}