INode* PatchDeformPW::GetNodeFromModContext(LocalPatchData *smd)
	{

	int	i;

    PatchEnumProc dep;              
	DoEnumDependents(&dep);
	for ( i = 0; i < dep.Nodes.Count(); i++)
		{
		INode *node = dep.Nodes[i];
		BOOL found = FALSE;

		if (node)
			{
			Object* obj = node->GetObjectRef();
	
			if ( RecursePipeAndMatch(smd,obj) )
				{
				return node;
				}
// look at the SkinWrapMesh.cpp code here....
			}
		}
	return NULL;
	}
Example #2
0
static INode *FindObjectsNode(ReferenceTarget *ths, Object *obj) 
{
	if (NULL == ths) {
		return NULL;
	}
	DependentIterator di(ths);
	ReferenceMaker* maker = NULL;
	while ((maker = di.Next()) != NULL) {
		if (maker->SuperClassID()==BASENODE_CLASS_ID) {
			// Verify that we are this node's object
			INode  *node   = (INode*)maker;
			Object *nobj   = node->GetObjectRef();
			if (nobj) nobj = nobj->FindBaseObject();
			if (nobj==obj)
				return (INode*)maker;
			}

		if (maker->IsRefTarget()) {
			INode *node = FindObjectsNode((ReferenceTarget*)maker, obj);
			if (node) return node;
			}
	}

	return NULL;
}
static void DoNotifyNodeUnHide(void *param, NotifyInfo *info)
{
	int code = info->intcode;
	INode *node = (INode*)info->callParam;
	if (Object* obj = node->GetObjectRef())
	{
		// Look for messages in network\Max.log
		// MAXScript_interface->Log()->LogEntry(SYSLOG_DEBUG, NO_DIALOG, "NifTools Max Plugin", 
		// 	"Entered DoNotifyNodeUnHide; node is -%s- and class ID is %ld\n", node->GetName(), obj->ClassID().PartA());

	   if (obj->ClassID() == BHKLISTOBJECT_CLASS_ID)
	   {
		   const int PB_MESHLIST = 1;
		   IParamBlock2* pblock2 = obj->GetParamBlockByID(0);
		   int nBlocks = pblock2->Count(PB_MESHLIST);
		   for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++)
		   {
			   INode *tnode = nullptr;
			   pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i);	
			   if (tnode != nullptr)
			   {
				   tnode->Hide(FALSE);
			   }
		   }
	   }
	}
}
Example #4
0
void PolyOpExtrudeAlongSpline::GetValues (IParamBlock2 *pblock, TimeValue t, Interval & ivalid)
{
	PolyOperation::GetValues (pblock, t, ivalid);

	// Special case for the spline & transform.
	if (!mSplineValidity.InInterval (t))
	{
		mSplineValidity.SetInfinite ();
		INode *pSplineNode;
		pblock->GetValue (kEPExtrudeSpline, t, pSplineNode, mSplineValidity);
		if (pSplineNode == NULL) mpSpline = NULL;
		else
		{
			bool del = FALSE;
			SplineShape *pSplineShape = NULL;
			ObjectState os = pSplineNode->GetObjectRef()->Eval(t);
			if (os.obj->IsSubClassOf(splineShapeClassID)) pSplineShape = (SplineShape *) os.obj;
			else {
				if (!os.obj->CanConvertToType(splineShapeClassID)) return;
				pSplineShape = (SplineShape*)os.obj->ConvertToType (t, splineShapeClassID);
				if (pSplineShape!=os.obj) del = TRUE;
			}
			BezierShape & bezShape = pSplineShape->GetShape();

			Matrix3 mSplineXfm = pSplineNode->GetObjectTM (t, &mSplineValidity);
			if (mpSpline != NULL) delete mpSpline;
			mpSpline = new Spline3D(*bezShape.GetSpline(0));

			if (del) delete pSplineShape;
		}
	}

	ivalid &= mSplineValidity;
}
Example #5
0
void CreateMorphMode::Begin(INode *n,IObjParam *i) 
   {
   ReplaceReference(0,n);
   svNode = node;
   assert(node);
   ip = i;
   proc.Init(ip);

   theHold.Begin();
   theHold.Put(new CreateMorphRestore);

   obj = new MorphObject;
   
   theHold.Put(new CreateMorphNotify(obj,1));

   TSTR name = TSTR(_T("M_")) + node->GetName();
   SetMorphTargetPacket pckt(node->GetObjectRef(),name);
   obj->morphCont->SetValue(0,&pckt);
   
   node->SetObjectRef(obj);
   
   theHold.Put(new CreateMorphNotify(obj,0));

   theHold.Accept(IDS_DS_CREATE);

   obj->BeginEditParams(i,BEGIN_EDIT_CREATE,NULL);
   }
Example #6
0
		BOOL Validate(PB2Value &v)
		{
	        INode *node = (INode*) v.r;
			Object *obj = node->GetObjectRef();
            if (obj->ClassID() != DELEG_CLASSID) return FALSE;
	       
			return TRUE;
		};
void AlembicImport_TimeControl( alembic_importoptions &options ) {

   if(!options.loadTimeControl){
      return;
   }

	// check if an Alembic Time Control already exists in the scene.

	BOOL alreadyExists = ExecuteMAXScriptScript( _T( "select $Alembic_Time_Control" ), TRUE );
	if( alreadyExists != 0 ) {
		if( GetCOREInterface()->GetSelNodeCount() > 0 ) {
			INode *pSelectedNode = GetCOREInterface()->GetSelNode( 0 );
			HelperObject *pSelectedHelper = static_cast<HelperObject*>( pSelectedNode->GetObjectRef() );
			options.pTimeControl = pSelectedHelper;
			return;
		}
	}

	// Create the xform modifier
	HelperObject *pHelper = static_cast<HelperObject*>
		(GetCOREInterface()->CreateInstance(HELPER_CLASS_ID, ALEMBIC_TIME_CONTROL_HELPER_CLASSID));

	TimeValue zero( 0 );

	// Set the alembic id
	pHelper->GetParamBlockByID( 0 )->SetValue( GetParamIdByName( pHelper, 0, "current" ), zero, 0.0f );
	pHelper->GetParamBlockByID( 0 )->SetValue( GetParamIdByName( pHelper, 0, "offset" ), zero, 0.0f );
	pHelper->GetParamBlockByID( 0 )->SetValue( GetParamIdByName( pHelper, 0, "factor" ), zero, 1.0f );

	// Create the object node
	INode *node = GET_MAX_INTERFACE()->CreateObjectNode(pHelper, pHelper->GetObjectName() );

	// Add the new inode to our current scene list
	SceneEntry *pEntry = options.sceneEnumProc.Append(node, pHelper, OBTYPE_CURVES, &std::string( EC_MCHAR_to_UTF8( node->GetName() ) ) ); 
	options.currentSceneList.Append(pEntry);

	//GET_MAX_INTERFACE()->SelectNode( node );

	//std::string nodeName = EC_MCHAR_to_UTF8( node->GetName() );
	//char szBuffer[10000];	
	//sprintf_s( szBuffer, 10000,
	//	"$'%s'.current.controller = float_expression()\n"
	//	"$'%s'.current.controller.setExpression \"S\"\n"
	//	"$'%s'.offset.controller = bezier_float()\n"
	//	"$'%s'.factor.controller = bezier_float()\n"
	//	, nodeName.c_str(), nodeName.c_str(), nodeName.c_str(), nodeName.c_str() );
	//ExecuteMAXScriptScript( EC_UTF8_to_TCHAR( szBuffer ) );

	options.pTimeControl = pHelper;
}
Example #8
0
BOOL PickTarget::HitTest(
      IObjParam *ip,HWND hWnd,ViewExp *vpt,IPoint2 m,int flags)
   {
   INode *node = ip->PickNode(hWnd,m,this);
   
   if (node) {
      if (mo->morphCont->ValidTarget(
            mo->ip->GetTime(),
            node->GetObjectRef())) {         
         return TRUE;
         }
      }

   return FALSE;
   }
void PatchDeformPW::SetResampleModContext(BOOL resample)
{
    PatchEnumProc dep;              
	DoEnumDependents(&dep);
	for ( int i = 0; i < dep.Nodes.Count(); i++)
		{
		INode *node = dep.Nodes[i];
		BOOL found = FALSE;

		if (node)
			{
			Object* obj = node->GetObjectRef();
	
			 RecursePipeAndMatch2(this,obj,resample) ;
			}
		}
}
Example #10
0
BOOL SWrapPickOperand::HitTest(
		IObjParam *ip,HWND hWnd,ViewExp *vpt,IPoint2 m,int flags)
	{	
	INode *node = ip->PickNode(hWnd,m,this);
	
	if (node) 
	{	ObjectState os = node->GetObjectRef()->Eval(ip->GetTime());
	  if (!IsGEOM(os.obj)) 
		{	node = NULL;
			return FALSE;
			}
	node->BeginDependencyTest();
	po->NotifyDependents(FOREVER,0,REFMSG_TEST_DEPENDENCY);
	if (node->EndDependencyTest()) return FALSE;
	}
	return node ? TRUE : FALSE;
	}
Example #11
0
BOOL PickTarget::Pick(IObjParam *ip,ViewExp *vpt)
   {
   if ( ! vpt || ! vpt->IsAlive() )
	{
		// why are we here
		DbgAssert(!_T("Invalid viewport!"));
		return FALSE;
	}
	 
	 INode *node = vpt->GetClosestHit();
   assert(node);
   if (mo->morphCont->
         ValidTarget(
            mo->ip->GetTime(),
            node->GetObjectRef())) {
      mo->AddNewTarget(node,mo->ip->GetTime(),mo->AddTargMethod());
      mo->SetupTargetList();
      ip->RedrawViews(ip->GetTime());
      }
   return FALSE;
   }
Example #12
0
Point3 Jiggle::GetDynamicsForces(TimeValue t, Point3 pos, Point3 vel)
{
	INode *aforce;
	Point3 f(0.0f,0.0f,0.0f);

	for( int i=0;i<force_pb->Count(jig_force_node);i++)
	{
		Interval for_ever = FOREVER;
		force_pb->GetValue(jig_force_node, 0, aforce, for_ever, i);
		
		if (aforce)
		{
			Object* obref = aforce->GetObjectRef();

			ForceField* ff = NULL;
			if (obref != NULL)
			{
				WSMObject* wsmObj = static_cast<WSMObject*>(obref->GetInterface(I_WSMOBJECT));
				if (NULL == wsmObj && WSM_OBJECT_CLASS_ID == obref->SuperClassID()) {
					wsmObj = static_cast<WSMObject*>(obref);
				}

				if (wsmObj != NULL) 
				{
					ff = wsmObj->GetForceField(aforce);
				}
			}

		
			if (ff)
			{
				f += ff->Force(t, pos, vel, 0);
				ff->DeleteThis();
			}
		}
	}
	return f;
}
Example #13
0
void ResetXForm::ResetNodes(const INodeTab& nodesToReset)
{
	Interface *ip = GetCOREInterface();
	for (int i = 0; i < nodesToReset.Count(); i++) {
		INode *node = nodesToReset[i];
		if (!node || node->IsGroupMember() || node->IsGroupHead()) 
			continue;
		if (SelectedAncestor(node)) 
			continue;

		Matrix3 ntm, ptm, rtm(1), piv(1), tm;
		
		// Get Parent and Node TMs
		ntm = node->GetNodeTM(ip->GetTime());
		ptm = node->GetParentTM(ip->GetTime());
		
		// Compute the relative TM
		ntm = ntm * Inverse(ptm);
		
		// The reset TM only inherits position
		rtm.SetTrans(ntm.GetTrans());
		
		// Set the node TM to the reset TM		
		tm = rtm*ptm;
		node->SetNodeTM(ip->GetTime(), tm);

		// Compute the pivot TM
		piv.SetTrans(node->GetObjOffsetPos());
		PreRotateMatrix(piv,node->GetObjOffsetRot());
		ApplyScaling(piv,node->GetObjOffsetScale());
		
		// Reset the offset to 0
		node->SetObjOffsetPos(Point3(0,0,0));
		node->SetObjOffsetRot(IdentQuat());
		node->SetObjOffsetScale(ScaleValue(Point3(1,1,1)));

		// Take the position out of the matrix since we don't reset position
		ntm.NoTrans();

		// Apply the offset to the TM
		ntm = piv * ntm;

		// Apply a derived object to the node's object
		Object *obj = node->GetObjectRef();
		IDerivedObject *dobj = CreateDerivedObject(obj);
		
		// Create an XForm mod
		SimpleMod *mod = (SimpleMod*)ip->CreateInstance(
			OSM_CLASS_ID,
			Class_ID(CLUSTOSM_CLASS_ID,0));

		// Apply the transformation to the mod.
		SetXFormPacket pckt(ntm);
		mod->tmControl->SetValue(ip->GetTime(),&pckt);

		// Add the modifier to the derived object.
		dobj->SetAFlag(A_LOCK_TARGET); // RB 3/11/99: When the macro recorder is on the derived object will get deleted unless it is locked.
		dobj->AddModifier(mod);
		dobj->ClearAFlag(A_LOCK_TARGET);

		// Replace the node's object
		node->SetObjectRef(dobj);
	}
	
//	Why on earth were we clearing the undo stack?
//	GetSystemSetting(SYSSET_CLEAR_UNDO);
	ip->RedrawViews(ip->GetTime());
	SetSaveRequiredFlag(TRUE);
}
	//---------------------------------------------------------------
	void LightExporter::exportLight( ExportNode* exportNode )
	{
		if ( !exportNode->getIsInVisualScene() )
			return;
		
		String lightId = getLightId(*exportNode);

		INode * iNode = exportNode->getINode();

		LightObject* lightObject = (LightObject*) (iNode->GetObjectRef());

		if ( !lightObject )
			return;

		if (  mDocumentExporter->isExportedObject(ObjectIdentifier(lightObject)) )
			return;

		mDocumentExporter->insertExportedObject(ObjectIdentifier(lightObject), exportNode);

		// Retrieve the target node, if we are not baking matrices.
		// Baked matrices must always sample the transform!
		ULONG ClassId = lightObject->ClassID().PartA();
		bool isTargeted = !mDocumentExporter->getOptions().getBakeMatrices() && (ClassId == SPOT_LIGHT_CLASS_ID || ClassId == TDIR_LIGHT_CLASS_ID);
		
		INode* targetNode = isTargeted ? iNode->GetTarget() : 0;

		// some lights are not supported at all
		switch (ClassId)
		{
		case FSPOT_LIGHT_CLASS_ID:
		case SPOT_LIGHT_CLASS_ID:
		case DIR_LIGHT_CLASS_ID: 
		case TDIR_LIGHT_CLASS_ID:
		case SKY_LIGHT_CLASS_ID_PART_A:
		case OMNI_LIGHT_CLASS_ID:
			break;
		default:
			return;
		}


		// Determine the light's type
		bool isSpot = false;
		bool isDirectional = false;
		bool isPoint = false;
		bool isSky = false;

		COLLADASW::Light::LightType lightType;

		switch (ClassId)
		{
		case FSPOT_LIGHT_CLASS_ID:
		case SPOT_LIGHT_CLASS_ID: 
			lightType = COLLADASW::Light::SPOT; 
			isSpot = true; 
			break;
		case DIR_LIGHT_CLASS_ID: 
		case TDIR_LIGHT_CLASS_ID: 
			lightType = COLLADASW::Light::DIRECTIONAL; 
			isDirectional = true; 
			break;
		case SKY_LIGHT_CLASS_ID_PART_A:
			lightType = COLLADASW::Light::POINT; 
			isSky = true;
			break;
		case OMNI_LIGHT_CLASS_ID:
			lightType = COLLADASW::Light::POINT; 
			isPoint = true;
			break;
		}

		COLLADASW::Light * colladaLight = 0;

		switch ( lightType )
		{
		case COLLADASW::Light::DIRECTIONAL:
			colladaLight = new COLLADASW::DirectionalLight(COLLADASW::LibraryLights::mSW, lightId, COLLADASW::Utils::checkNCName(NativeString(exportNode->getINode()->GetName())));
			break;
		case COLLADASW::Light::POINT:
			colladaLight = new COLLADASW::PointLight(COLLADASW::LibraryLights::mSW, lightId, COLLADASW::Utils::checkNCName(NativeString(exportNode->getINode()->GetName())));
			break;
		case COLLADASW::Light::SPOT:
			colladaLight = new COLLADASW::SpotLight(COLLADASW::LibraryLights::mSW, lightId, COLLADASW::Utils::checkNCName(NativeString(exportNode->getINode()->GetName())));
			break;
		}

		// Retrieve the parameter block
		IParamBlock* parameters = 0;
		IParamBlock2* parametersSky = 0;

		if (isSky)
			parametersSky = (IParamBlock2*) lightObject->GetReference(MaxLight::PBLOCK_REF_SKY);
		else
			parameters = (IParamBlock*) lightObject->GetReference(MaxLight::PBLOCK_REF);

		if (!parameters && !parametersSky)
		{
			delete colladaLight;
			return;
		}


		if (parameters)
		{
			bool hasAnimatedColor = mAnimationExporter->addAnimatedParameter(parameters, MaxLight::PB_COLOR, lightId, colladaLight->getColorDefaultSid(), 0 );
			colladaLight->setColor(EffectExporter::maxColor2Color(parameters->GetColor(MaxLight::PB_COLOR)), hasAnimatedColor);
		}
		else if (parametersSky )
		{
			bool hasAnimatedColor = mAnimationExporter->addAnimatedParameter(parametersSky, MaxLight::PB_SKY_COLOR, lightId, colladaLight->getColorDefaultSid(), 0 );
			colladaLight->setColor(EffectExporter::maxColor2Color(parametersSky->GetColor(MaxLight::PB_SKY_COLOR)), hasAnimatedColor);
		}


		if (isSpot || isPoint)
		{
			int decayFunction = parameters->GetInt(isPoint ? MaxLight::PB_DECAY : MaxLight::PB_OMNIDECAY, mDocumentExporter->getOptions().getAnimationStart());
			switch (decayFunction)
			{
			case 1:
				colladaLight->setConstantAttenuation(0.0f);
				colladaLight->setLinearAttenuation(1.0f);
				break;
			case 2:
				colladaLight->setConstantAttenuation(0.0f);
				colladaLight->setQuadraticAttenuation(1.0f);
				break;
			case 0:
			default:
				colladaLight->setConstantAttenuation(1.0f);
				break;
			}
		}
		else if (isSky)
		{
			colladaLight->setConstantAttenuation(1.0f);
		}

		setExtraTechnique(colladaLight);


		if ( parameters )
			addParamBlockAnimatedExtraParameters(LIGHT_ELEMENT, LIGHT_PARAMETERS, LIGHT_PARAMETER_COUNT, parameters, lightId);
		else
			addParamBlockAnimatedExtraParameters(SKYLIGHT_ELEMENT, SKYLIGHT_PARAMETERS, SKYLIGHT_PARAMETER_COUNT, parametersSky, lightId);

		// add all the information to extra tag, that are not contained in IParamBlock
		if (isSpot || isDirectional || isPoint)
		{
			GenLight* light = (GenLight*)(lightObject);

			if (!light)
			{
				delete colladaLight;
				return;
			}


			// Export the overshoot flag for directional lights
			if (isDirectional || isSpot)
			{
				addExtraChildParameter(LIGHT_ELEMENT, OVERSHOOT_PARAMETER, light->GetOvershoot() != false);
			}

			addExtraChildParameter(LIGHT_ELEMENT, DECAY_TYPE_PARAMETER, (int)light->GetDecayType());
			addExtraChildParameter(LIGHT_ELEMENT, USE_NEAR_ATTENUATION_PARAMETER, (light->GetUseAttenNear() != false));
			addExtraChildParameter(LIGHT_ELEMENT, USE_FAR_ATTENUATION_PARAMETER, (light->GetUseAtten() != false));

			exportShadowParameters(light);

			if (light->GetProjector())
			{
				Texmap* projectorMap = light->GetProjMap();
				if (projectorMap)
				{
					String imageId = exportTexMap(projectorMap);
					if ( !imageId.empty() )
					{
						addExtraChildParameter(LIGHT_ELEMENT, LIGHT_MAP_ELEMENT, "#" + imageId);
					}
				}
			}


		}
		else // isSky
		{
			Texmap *colorMap = parametersSky->GetTexmap(MaxLight::PB_SKY_COLOR_MAP, mDocumentExporter->getOptions().getAnimationStart());
			
			String imageId = exportTexMap(colorMap);
			if ( !imageId.empty())
			{
				addExtraChildParameter(SKYLIGHT_ELEMENT, SKYLIGHT_COLORMAP_ELEMENT, "#" + imageId);
			}
		}

		addLight(*colladaLight);

		delete colladaLight;

	}
bool NifImporter::ImportSkin(ImpNode *node, NiTriBasedGeomRef triGeom, int v_start/*=0*/)
{
   bool ok = true;
   NiSkinInstanceRef nifSkin = triGeom->GetSkinInstance();
   if (!nifSkin) 
      return false;

   INode *tnode = node->GetINode();

   NiSkinDataRef data = nifSkin->GetSkinData();
   NiSkinPartitionRef part = nifSkin->GetSkinPartition();

   vector<NiNodeRef> nifBones = nifSkin->GetBones();

   //create a skin modifier and add it
   Modifier *skinMod = GetOrCreateSkin(tnode);
   TriObject *triObject = GetTriObject(tnode->GetObjectRef());
   Mesh& m = triObject->GetMesh();

   //get the skin interface
   if (ISkin *skin = (ISkin *) skinMod->GetInterface(I_SKIN)){
      ISkinImportData* iskinImport = (ISkinImportData*) skinMod->GetInterface(I_SKINIMPORTDATA);

      // Set the num weights to 4.  Yes its in the nif but Shon doesn't like to expose those values 
      //   and the value always seems to be 4 anyway.  I'd also this be more dynamic than hard coded numbers
      //   but I cant figure out the correct values to pass the scripting engine from here so I'm giving up.
      int numWeightsPerVertex = 4;
#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+
      IParamBlock2 *params = skinMod->GetParamBlockByID(2/*advanced*/);
      params->SetValue(0x7/*bone_Limit*/, 0, numWeightsPerVertex);
#endif

      // Can get some truly bizarre animations without this in MAX with Civ4 Leaderheads
#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 6+
      BOOL ignore = TRUE;
      params->SetValue(0xE/*ignoreBoneScale*/, 0, ignore);
#endif

      //RefTargetHandle advanced = skinMod->GetReference(3);
      //setMAXScriptValue(advanced, "bone_Limit", 0, numWeightsPerVertex);

      Matrix3 geom = TOMATRIX3(triGeom->GetLocalTransform());
      Matrix3 m3 = TOMATRIX3(data->GetOverallTransform());
      Matrix3 im3 = Inverse(m3);
      Matrix3 nm3 = im3 * geom;
      iskinImport->SetSkinTm(tnode, nm3, nm3); // ???
      // Create Bone List
      Tab<INode*> bones;
      for (size_t i=0; i<nifBones.size(); ++i){
         NiNodeRef bone = nifBones[i];
         if (INode *boneRef = FindNode(bone)) {
            bones.Append(1, &boneRef);
            iskinImport->AddBoneEx(boneRef, TRUE);

            //// Set Bone Transform
            Matrix3 b3 = TOMATRIX3(data->GetBoneTransform(i));
            Matrix3 ib3 = Inverse(b3);
            ib3 *= geom;
            iskinImport->SetBoneTm(boneRef, ib3, ib3);
         }
      }
      if (bones.Count() != data->GetBoneCount())
         return false;

      ObjectState os = tnode->EvalWorldState(0);

      // Need to get a list of bones and weights for each vertex.
      vector<VertexHolder> vertexHolders;
      vertexHolders.resize(m.numVerts);
      for (int i=0, n=data->GetBoneCount();i<n; ++i){
         if (INode *boneRef = bones[i]){
            vector<SkinWeight> weights = data->GetBoneWeights(i);
            for (vector<SkinWeight>::iterator itr=weights.begin(), end=weights.end(); itr != end; ++itr){
               VertexHolder& h = vertexHolders[itr->index];
               h.vertIndex = itr->index;
               ++h.count;
               h.weights.Append(1, &itr->weight);
               h.boneNodeList.Append(1, &boneRef);
            }
         }
      }

      tnode->EvalWorldState(0);
      skinMod->DisableModInViews();
      skinMod->EnableModInViews();
#if VERSION_3DSMAX < ((5000<<16)+(15<<8)+0) // Version 4
      gi->SetCommandPanelTaskMode(TASK_MODE_MODIFY);
      gi->SelectNode(tnode);
#endif
      // Assign the weights 
      for (vector<VertexHolder>::iterator itr=vertexHolders.begin(), end=vertexHolders.end(); itr != end; ++itr){
         VertexHolder& h = (*itr);
         if (h.count){
            float sum = 0.0f;
			for (int i = 0; i < h.count; ++i)
				sum += h.weights[i];
            ASSERT(fabs(sum-1.0f) < 0.001f);
            BOOL add = iskinImport->AddWeights(tnode, h.vertIndex, h.boneNodeList, h.weights);
            add = add;		//	What was the purpose of this?
         }
      }
      //	This is a kludge to get skin transforms to update and avoid jumping around after modifying the transforms.
      //	Initially they show up incorrectly but magically fix up if you go to the modifier roll up.
      //	There is still an outstanding issue with skeleton and GetObjectTMBeforeWSM.
      skinMod->DisableModInViews();
      skinMod->EnableModInViews();


      // If BSDismembermentSkinInstance, ...
      if ( BSDismemberSkinInstanceRef bsdsi = DynamicCast<BSDismemberSkinInstance>(nifSkin) )
      {
         Modifier *dismemberSkinMod = GetOrCreateBSDismemberSkin(tnode);
         if (IBSDismemberSkinModifier *disSkin = (IBSDismemberSkinModifier *) dismemberSkinMod->GetInterface(I_BSDISMEMBERSKINMODIFIER)){
            //	Evaluate node ensure the modifier data is created
            //	ObjectState os = tnode->EvalWorldState(0);

            FaceMap faceMap;
            int nfaces = m.getNumFaces();
            for ( int i=0; i<nfaces; ++i ){
               Face f = m.faces[i];
               faceMap[ rotate(f) ] = i;
            }

            Tab<IBSDismemberSkinModifierData*> modData = disSkin->GetModifierData();
            for (int i=0; i<modData.Count(); ++i) {
               IBSDismemberSkinModifierData* bsdsmd = modData[i];

               Tab<BSDSPartitionData> &flags = bsdsmd->GetPartitionFlags();
               vector<BodyPartList> partitions = bsdsi->GetPartitions();
               if (partitions.empty())
                  continue;

               //bsdsmd->SetActivePartition( partitions.size() - 1 );				// Old Code

			   for (unsigned int j = 0; j < (partitions.size() - 1); ++j){
				   bsdsmd->AddPartition();
			   }

               for (unsigned int j=0; j < partitions.size(); ++j ) {
				   flags[j].bodyPart = (DismemberBodyPartType)partitions[j].bodyPart;
				   flags[j].partFlag = partitions[j].partFlag;
               }

               for (int j=0; j < part->GetNumPartitions(); ++j) {
                  bsdsmd->SetActivePartition( j );
                  dismemberSkinMod->SelectAll(3); // ensures bitarrays are properly synced to mesh
                  dismemberSkinMod->ClearSelection(3);
                  vector<Triangle> triangles = part->GetTriangles(j);
                  vector<unsigned short> map = part->GetVertexMap(j);
                  GenericNamedSelSetList& fselSet = bsdsmd->GetFaceSelList();
                  if ( BitArray* fsel = fselSet.GetSetByIndex(j) )
                  {
                     for (vector<Triangle>::iterator itrtri = triangles.begin(); itrtri != triangles.end(); ++itrtri) {
                        Face f;
						f.setVerts( map[(*itrtri).v1], map[(*itrtri).v2], map[(*itrtri).v3] );
                        FaceMap::iterator fitr = faceMap.find( rotate(f) );
                        if (fitr != faceMap.end())
                           fsel->Set((*fitr).second);
                     }
                  }
               }
               bsdsmd->SetActivePartition( 0 );
               disSkin->LocalDataChanged();
            }
         }
      }
   }
   return ok;
}
void MaxAWDExporter::ProcessGeoBlocks()
{
    AWDTriGeom *geoBlock;
    AWDBlockIterator *it;
    int proccessed=0;
    it = new AWDBlockIterator(awd->get_mesh_data_blocks());
    UpdateProgressBar(MAXAWD_PHASE_PROCESS_GEOMETRY, (double)proccessed/(double)awd->get_mesh_data_blocks()->get_num_blocks());
    INodeTab lNodes;
    while ((geoBlock = (AWDTriGeom * ) it->next()) != NULL){
        INode * node = (INode *)INodeToGeoBlockCache->Get(geoBlock);
        if (node==NULL){
            AWDMessageBlock * newWarning = new AWDMessageBlock(geoBlock->get_name(), "ERROR: Could not find the INode for this AWDGeometry.");
            awd->get_message_blocks()->append(newWarning);
            return;
        }
        lNodes.AppendNode( node );
    }

    IGameScene* _pIgame = NULL;
    _pIgame = GetIGameInterface();
    _pIgame->InitialiseIGame( lNodes );
    it->reset();
    while ((geoBlock = (AWDTriGeom * ) it->next()) != NULL){
        INode * node = (INode *)INodeToGeoBlockCache->Get(geoBlock);
        if (node==NULL){
            AWDMessageBlock * newWarning = new AWDMessageBlock(geoBlock->get_name(), "ERROR: Could not find the INode for this AWDGeometry.");
            awd->get_message_blocks()->append(newWarning);
        }
        else{
            int exportThis=false;
            IGameObject * gobj = NULL;
            IGameMesh * igame_mesh = NULL;
            gobj = GetIGameInterface()->GetIGameNode(node)->GetIGameObject();
            if(gobj->GetIGameType()==IGameObject::IGAME_MESH){
                igame_mesh = (IGameMesh*)gobj;
                if (igame_mesh!=NULL){
                    igame_mesh->InitializeData();
                    if(igame_mesh->GetNumberOfFaces()>0){
                        exportThis=true;
                    }
                }
            }
            if (exportThis){
                Object *obj;
                obj = node->GetObjectRef();
                int skinIdx;
                ObjectState os;
                IDerivedObject *derivedObject = NULL;
                skinIdx = IndexOfSkinMod(node->GetObjectRef(), &derivedObject);
                if (skinIdx >= 0) {
                    // Flatten all modifiers up to but not including
                    // the skin modifier.
                    // to do: get the correct time for the neutral-pose
                    os = derivedObject->Eval(0, skinIdx + 1);
                }
                else {
                    // Flatten entire modifier stack
                    // to do: get the correct time for the neutral-pose
                    os = node->EvalWorldState(maxInterface->GetTime());
                }
                obj = os.obj;
                ISkin *skin = NULL;
                if (derivedObject != NULL && skinIdx >= 0) {
                    Modifier *mod = derivedObject->GetModifier(skinIdx);
                    skin = (ISkin *)mod->GetInterface(I_SKIN);
                }
                ExportTriGeom(geoBlock,obj,node,skin, igame_mesh);
                RETURN_IF_ERROR;
            }
        }
        proccessed++;
        UpdateProgressBar(MAXAWD_PHASE_PROCESS_GEOMETRY, (double)proccessed/(double)awd->get_mesh_data_blocks()->get_num_blocks());
    }
    delete it;
    _pIgame->ReleaseIGame();
}
Example #17
0
void Import::ApplyModifiers (dScene& scene, const MaxNodeChache& maxNodeCache)
{
    dScene::Iterator iter (scene);
    for (iter.Begin(); iter; iter ++) {
        dScene::dTreeNode* meshNode = iter.GetNode();
        dNodeInfo* info = scene.GetInfoFromNode(meshNode);
        if (info->IsType(dGeometryNodeInfo::GetRttiType())) {
            dScene::dTreeNode* skinModifierNode = NULL;
            for (void* ptr = scene.GetFirstChild(meshNode); ptr; ptr = scene.GetNextChild(meshNode, ptr)) {
                dScene::dTreeNode* node = scene.GetNodeFromLink(ptr);
                dNodeInfo* info = scene.GetInfoFromNode(node);
                if (info->GetTypeId() == dGeometryNodeSkinModifierInfo::GetRttiType()) {
                    skinModifierNode = node;
                    break;
                }
            }

            if (skinModifierNode) {
                //create a skin modifier and add it
                Modifier* skinMod = (Modifier*) CreateInstance(OSM_CLASS_ID, SKIN_CLASSID);
                ISkinImportData* iskinImport = (ISkinImportData*) skinMod->GetInterface(I_SKINIMPORTDATA);
                INode* maxNode = maxNodeCache.Find(meshNode)->GetInfo();
                _ASSERTE (maxNode);

                IDerivedObject *derob = NULL;
                Object* obj = maxNode->GetObjectRef();
                if(obj->SuperClassID() != GEN_DERIVOB_CLASS_ID)
                {
                    derob = CreateDerivedObject(obj);
                    maxNode->SetObjectRef(derob);
                } else {
                    derob = (IDerivedObject*) obj;
                }
                derob->AddModifier(skinMod);

                dGeometryNodeSkinModifierInfo* skinModifier = (dGeometryNodeSkinModifierInfo*) scene.GetInfoFromNode(skinModifierNode);

                dMatrix matrix (skinModifier->m_shapeBindMatrix);
                Matrix3 bindPoseMatrix;
                bindPoseMatrix.SetRow (0, *((Point3*) &matrix[0]));
                bindPoseMatrix.SetRow (1, *((Point3*) &matrix[1]));
                bindPoseMatrix.SetRow (2, *((Point3*) &matrix[2]));
                bindPoseMatrix.SetRow (3, *((Point3*) &matrix[3]));
                iskinImport->SetSkinTm(maxNode, bindPoseMatrix, bindPoseMatrix);

                int maxNodeCount = 0;
                INode* maxNodes[1024];

                for (void* ptr = scene.GetFirstChild(skinModifierNode); ptr; ptr = scene.GetNextChild(skinModifierNode, ptr)) {
                    dScene::dTreeNode* boneNode = scene.GetNodeFromLink(ptr);
                    INode* skelBone = maxNodeCache.Find(boneNode)->GetInfo();
                    maxNodes[maxNodeCount] = skelBone;
                    maxNodeCount ++;
                    skelBone->SetBoneNodeOnOff(TRUE, 0);
                    skelBone->BoneAsLine(TRUE);
                    skelBone->ShowBone(1);
                    if (iskinImport->AddBoneEx(skelBone, TRUE)) {
                        dSceneNodeInfo* sceneNode = (dSceneNodeInfo*) scene.GetInfoFromNode(boneNode);
                        dMatrix matrix (sceneNode->GetTransform());
                        Matrix3 bindPoseMatrix;
                        bindPoseMatrix.SetRow (0, *((Point3*) &matrix[0]));
                        bindPoseMatrix.SetRow (1, *((Point3*) &matrix[1]));
                        bindPoseMatrix.SetRow (2, *((Point3*) &matrix[2]));
                        bindPoseMatrix.SetRow (3, *((Point3*) &matrix[3]));
                        iskinImport->SetBoneTm(skelBone, bindPoseMatrix, bindPoseMatrix);
                    }
                }

                // must evaluate the node after adding bones
                maxNode->EvalWorldState(0);

                for (int i = 0; i < skinModifier->m_vertexCount; i ++) {
                    Tab<float> weightList;
                    Tab<INode*> boneNodeList;
                    for (int j = 0; j < 4; j ++) {
                        if (skinModifier->m_vertexWeights[i][j] > 1.0e-5f) {
                            int boneIndex = skinModifier->m_boneWeightIndex[i].m_index[j];
                            INode *skelBone = maxNodes[boneIndex];
                            _ASSERTE (skelBone);
                            boneNodeList.Append (1, &skelBone);
                            weightList.Append (1, &skinModifier->m_vertexWeights[i][j]);
                        }
                    }
                    iskinImport->AddWeights(maxNode, i, boneNodeList, weightList);
                }
            }
        }
    }
}
Example #18
0
/**
*  @brief
*    Constructor
*/
PLSceneNode::PLSceneNode(PLSceneContainer *pContainer, IGameNode *pIGameNode, const String &sName, EType nType, const String &sClassName) :
	m_pContainer(pContainer),
	m_pIGameNode(pIGameNode),
	m_sName(sName),
	m_nType(nType),
	m_sClassName(sClassName),
	m_sFlags(""),
	m_vPos(0.0f, 0.0f, 0.0f),
	m_vRot(0.0f, 0.0f, 0.0f),
	m_vScale(1.0f, 1.0f, 1.0f),
	m_nIsRotationFlipped(-1)
{
	// Check some universal flags
	INode *pMaxNode = GetMaxNode();
	if (pMaxNode) { // If this is not a container...
		TSTR sString;

		// Check whether the default PixelLight class is changed
		if (pMaxNode->GetUserPropString(_T("Class"), sString)) {
			m_sClassName = sString;

			// Erase all '"'
			int i = m_sClassName.IndexOf("\"");
			while (i >= 0) {
				m_sClassName.Delete(i, 1);
				i = m_sClassName.IndexOf("\"");
			}
		}

		// Is this 3ds Max node frozen?
		if (pMaxNode->IsFrozen())
			AddFlag("Frozen");

		// Is this 3ds Max node invisible?
		if (pMaxNode->IsHidden() || !pMaxNode->Renderable())
			AddFlag("Invisible");

		// Is this 3ds Max node excluded from lighting?
		INodeGIProperties *pINodeGIProperties = static_cast<INodeGIProperties*>(pMaxNode->GetInterface(NODEGIPROPERTIES_INTERFACE));
		if (pINodeGIProperties && pINodeGIProperties->GIGetIsExcluded())
			AddFlag("NoLighting");

		{ // Get the world space bounding box of the scene node. Because this is not 'trival' we're using
		  // the sample code from "3dsMaxSDK.chm" (3ds Max SDK) -> "The Pipeline and the INode TM Methods"
		  // to get it working correctly.
			::Object *pMaxObject = pMaxNode->GetObjectRef();
			if (pMaxObject) {
				TimeValue t = 0;
				Matrix3 mat;	// The Object TM

				// Determine if the object is in world space or object space
				// so we can get the correct TM. We can check this by getting
				// the Object TM after the world space modifiers have been
				// applied. It the matrix returned is the identity matrix the
				// points of the object have been transformed into world space.
				if (pMaxNode->GetObjTMAfterWSM(t).IsIdentity()) {
					// It's in world space, so put it back into object
					// space. We can do this by computing the inverse
					// of the matrix returned before any world space
					// modifiers were applied.
					mat = Inverse(pMaxNode->GetObjTMBeforeWSM(t));
				} else { 
					// It's in object space, get the Object TM
					mat = pMaxNode->GetObjectTM(t);
				}

				// Get the bound box, and affect it by just the scaling portion
				pMaxObject->GetDeformBBox(t, m_cBoundingBox, &mat);
			}
		}

		// We really need to flip the coordinates to OpenGL style
		m_cBoundingBox.pmin = PLTools::Convert3dsMaxVectorToOpenGLVector(m_cBoundingBox.pmin);
		m_cBoundingBox.pmax = PLTools::Convert3dsMaxVectorToOpenGLVector(m_cBoundingBox.pmax);

		// Validate minimum/maximum - I already had situations with incorrect values causing problems!
		PLTools::ValidateMinimumMaximum(m_cBoundingBox);
	}

	// Get the position, rotation and scale
	GetPosRotScale(m_vPos, m_vRot, m_vScale);
}
void ParticleMesherObject::BuildMesh(TimeValue t)
   {
//check if render time
//get node
//mkae ivalid interesect with the 
   int isRendering = 0;
   ivalid = FOREVER;

   TimeValue offset;
   float foffset;
   Interval iv;
   pblock2->GetValue(particlemesher_time, 0, foffset, iv);
   foffset = -foffset;
   pblock2->GetValue(particlemesher_radius, 0, radius, iv);
   foffset *= GetTicksPerFrame();
   offset = (TimeValue) foffset;

// pblock2->GetValue(particlemesher_time, 0, foffset, iv);
   if ((lastTime == t)  )
      {
      ivalid.Set(t,t);
      return;
      }


   pblock2->GetValue(particlemesher_rendertimeonly, 0, isRendering, ivalid);
   isRendering = !isRendering;
    if ((isRendering) || (TestAFlag(A_RENDER)))
      {
      INode *node=NULL;
      pblock2->GetValue(particlemesher_pick, 0, node, ivalid);

      
      BOOL reevalGroup = FALSE;
      if ((node != NULL) && (node->IsGroupHead()) )
         {  
         for (int ch=0;ch<node->NumberOfChildren();ch++)
            {  
            INode *cnode= node->GetChildNode(ch);
            Interval iv;
            Matrix3 tm=cnode->GetObjectTM(t,&iv);
      

            if (cnode->IsGroupMember())
               {
               reevalGroup = TRUE;
               for (int groupCount = 0; groupCount < pblock2->Count(particlemesher_extranodes); groupCount++)
                  {
                  INode *extraNode = pblock2->GetINode(particlemesher_extranodes,t,ch);
                  if (cnode == extraNode)
                     {
                     reevalGroup = FALSE;
                     groupCount = pblock2->Count(particlemesher_extranodes);
                     }
                  }
               if (reevalGroup)
                  ch=node->NumberOfChildren();

               }
            }

         if (reevalGroup)
            {
            tmList.ZeroCount();
   
            pblock2->ZeroCount(particlemesher_extranodes);
            for (int ch=0;ch<node->NumberOfChildren();ch++)
               {  
               INode *cnode= node->GetChildNode(ch);
               Interval iv;
               Matrix3 tm=cnode->GetObjectTM(t,&iv);
      

               if (cnode->IsGroupMember())
                  {
                  pblock2->Append(particlemesher_extranodes,1,&cnode);
                  tmList.Append(1,&tm);
                  }
               }

            }
         }

      if (node) 
         {

         if ( (node->IsGroupHead()) && (pblock2->Count(particlemesher_extranodes)!=0))
            {

            int ct = 0;
            Matrix3 ident(1), inverseTm(1);
            mesh.setNumVerts(0);
            mesh.setNumFaces(0);
            for (int ch=0;ch<pblock2->Count(particlemesher_extranodes);ch++)
               {  
               INode *cnode = pblock2->GetINode(particlemesher_extranodes,t,ch);
               if (cnode)
                  {
                  Object *pobj = cnode->EvalWorldState(t+offset).obj;
               
                  if ( (pobj->SuperClassID() == GEOMOBJECT_CLASS_ID) ||
                      (pobj->SuperClassID() == SHAPE_CLASS_ID) )                    
                     {  


                     BOOL needDel;
                     NullView nullView;
                     Mesh *msh = ((GeomObject*)pobj)->GetRenderMesh(t+offset,cnode,nullView,needDel);

                     Mesh tmsh = *msh;

                     ivalid &= pobj->ObjectValidity(t+offset);

                     Matrix3 tm(1);
                     if (ch < tmList.Count())
                        tm = tmList[ch];
                     for (int v = 0; v < msh->numVerts; v++)
                        {
                        tmsh.verts[v] = tmsh.verts[v] * tm;
                        }
                     if (tmsh.numVerts != 0)
                        {
                        if (ct ==0)
                           {
                           mesh = tmsh;
                           }
                        else 
                           mesh = mesh + tmsh;
                  
                        ct++;
                        }

                     if (needDel) delete msh;
                     }

                     
               
                  }
                  
               }
            mesh.InvalidateTopologyCache();

            }
         else
            {
//          Object *tobj =  node->GetObjectRef();
//          macroRecorder->FunctionCall(_T("time"), 1, 0, mr_int, t);
//          macroRecorder->EmitScript();
            ObjectState os = node->EvalWorldState(t+offset);

            IParticleObjectExt* epobj;
            epobj = (IParticleObjectExt*) os.obj->GetInterface(PARTICLEOBJECTEXT_INTERFACE);
            
            if (os.obj->IsParticleSystem() && epobj)
               {
      
               if (epobj) 
                  {
                  BOOL useAllPFEvents;
                  pblock2->GetValue(particlemesher_useallpf,0,useAllPFEvents,FOREVER);
                  
                  pfNodes.ZeroCount();
                  
                  INode *basenode=NULL;
                  pblock2->GetValue(particlemesher_pick, 0, basenode, ivalid);                  

                  tmList.ZeroCount();

                  if (useAllPFEvents)
                     {
                     MyEnumProc dep;              
                     os.obj->DoEnumDependents(&dep);
                     
                     for (int i = 0; i < dep.Nodes.Count(); i++)
                        {
                        Interval valid;
                        INode *node = dep.Nodes[i];

                        Object *obj = node->GetObjectRef();

                        
                        if (ParticleGroupInterface(obj) != nullptr)
                           {
                           pfNodes.Append(1,&node);
                           Matrix3 tm = node->GetNodeTM(t+offset);
                           tmList.Append(1,&tm);
                           }
                        }                 
                     }
                  else
                     {
                     int ct = pblock2->Count(particlemesher_pfeventlist);
                     for (int i = 0; i < ct; i++)
                        {
                        INode *node;
                        pblock2->GetValue(particlemesher_pfeventlist,t,node,FOREVER,i);
                        if (node)
                           {

                           Object *obj = node->GetObjectRef();
                           if (ParticleGroupInterface(obj) != nullptr)
                              {
                              pfNodes.Append(1,&node);
                              Matrix3 tm(1);// = basenode->GetNodeTM(t+offset);
                              Matrix3 ntm = node->GetObjectTM(t+offset);
                              tm = ntm;
                              tmList.Append(1,&ntm);
                              
                              }                          
                           }
                        }
                     }
                     
                  mesh.setNumVerts(0);
                  mesh.setNumFaces(0);
                  int ct = 0;
                  for (int ch=0;ch< pfNodes.Count();ch++)
                     {  
                     INode *cnode = pfNodes[ch];
                     if (cnode)
                        {
                        Object *pobj = cnode->EvalWorldState(t+offset).obj;
                     
                        if ( (pobj->SuperClassID() == GEOMOBJECT_CLASS_ID) ||
                           (pobj->SuperClassID() == SHAPE_CLASS_ID) )                     
                           {  


                           BOOL needDel;
                           NullView nullView;
                           Mesh *msh = ((GeomObject*)pobj)->GetRenderMesh(t+offset,cnode,nullView,needDel);

                           Mesh tmsh = *msh;

                           ivalid &= pobj->ObjectValidity(t+offset);

                           Matrix3 tm(1);
                           if (ch < tmList.Count())
                              tm = tmList[ch];
                           for (int v = 0; v < msh->numVerts; v++)
                              {
                              tmsh.verts[v] = tmsh.verts[v] * tm;
                              }
                           if (tmsh.numVerts != 0)
                              {
                              if (ct ==0)
                                 {
                                 mesh = tmsh;
                                 }
                              else 
                                 {
                                 Mesh tempMesh = mesh;
                                 CombineMeshes(mesh, tempMesh, tmsh);
                                 }
                        
                              ct++;
                              }

                           if (needDel) delete msh;
                           }

                           
                     
                        }
                        
                     }
                  mesh.InvalidateTopologyCache();
                     
                     
                                       
                  }
               }
            else if ( (os.obj->SuperClassID() == GEOMOBJECT_CLASS_ID) ||
             (os.obj->SuperClassID() == SHAPE_CLASS_ID) )
               {

               BOOL needDel;
               NullView nullView;
               Mesh *msh = ((GeomObject*)os.obj)->GetRenderMesh(t+offset,node,nullView,needDel);
               ivalid &= os.obj->ObjectValidity(t);

               if (msh)
                  {
                  mesh = *msh;
                  mesh.InvalidateTopologyCache();
         
                  if (needDel) delete msh;
                  }
               }
            }
         lastTime = t;
         }
      else
         {
//build proxy mesh
         if (node == NULL)
            {
            mesh.setNumVerts(5);
            mesh.setNumFaces(8);

            mesh.setNumMaps(2);
            mesh.setNumMapVerts(0, 0);
            mesh.setNumMapVerts(1, 0);
            mesh.setNumMapFaces(0, 0);
            mesh.setNumMapFaces(1, 0);

            mesh.setVert(0, Point3(-radius,-radius, 0.0f));
            mesh.setVert(1, Point3( radius,-radius, 0.0f));
            mesh.setVert(2, Point3( radius, radius, 0.0f));
            mesh.setVert(3, Point3(-radius, radius, 0.0f));

//          mesh.setVert(4, Point3(0.0f, 0.0f, 0.0f));
            mesh.setVert(4, Point3(0.0f, 0.0f, radius));
   
            mesh.faces[0].setEdgeVisFlags(1,0,1);
            mesh.faces[0].setSmGroup(1);
            mesh.faces[0].setVerts(0,1,3);

            mesh.faces[1].setEdgeVisFlags(1,1,0);
            mesh.faces[1].setSmGroup(1);
            mesh.faces[1].setVerts(1,2,3);   

            mesh.faces[2].setEdgeVisFlags(1,1,1);
            mesh.faces[2].setSmGroup(1);
            mesh.faces[2].setVerts(0,4,1);   

            mesh.faces[3].setEdgeVisFlags(1,1,1);
            mesh.faces[3].setSmGroup(1);
            mesh.faces[3].setVerts(1,4,0);   

            mesh.faces[4].setEdgeVisFlags(1,1,1);
            mesh.faces[4].setSmGroup(1);
            mesh.faces[4].setVerts(2,4,3);   

            mesh.faces[5].setEdgeVisFlags(1,1,1);
            mesh.faces[5].setSmGroup(1);
            mesh.faces[5].setVerts(3,4,2);   

            mesh.faces[6].setEdgeVisFlags(1,0,1);
            mesh.faces[6].setSmGroup(1);
            mesh.faces[6].setVerts(3,1,0);

            mesh.faces[7].setEdgeVisFlags(1,1,0);
            mesh.faces[7].setSmGroup(1);
            mesh.faces[7].setVerts(3,2,1);   


            }

         }
      }  
   else
      {
//build proxy mesh
//build proxy mesh
      INode *node=NULL;
      pblock2->GetValue(particlemesher_pick, 0, node, ivalid);
   // if (node == NULL)
         {
            mesh.setNumVerts(5);
            mesh.setNumFaces(8);

            mesh.setNumMaps(2);
            mesh.setNumMapVerts(0, 0);
            mesh.setNumMapVerts(1, 0);
            mesh.setNumMapFaces(0, 0);
            mesh.setNumMapFaces(1, 0);

            mesh.setVert(0, Point3(-radius,-radius, 0.0f));
            mesh.setVert(1, Point3( radius,-radius, 0.0f));
            mesh.setVert(2, Point3( radius, radius, 0.0f));
            mesh.setVert(3, Point3(-radius, radius, 0.0f));

//          mesh.setVert(4, Point3(0.0f, 0.0f, 0.0f));
            mesh.setVert(4, Point3(0.0f, 0.0f, radius));
   
            mesh.faces[0].setEdgeVisFlags(1,0,1);
            mesh.faces[0].setSmGroup(1);
            mesh.faces[0].setVerts(0,1,3);

            mesh.faces[1].setEdgeVisFlags(1,1,0);
            mesh.faces[1].setSmGroup(1);
            mesh.faces[1].setVerts(1,2,3);   

            mesh.faces[2].setEdgeVisFlags(1,1,1);
            mesh.faces[2].setSmGroup(1);
            mesh.faces[2].setVerts(0,4,1);   

            mesh.faces[3].setEdgeVisFlags(1,1,1);
            mesh.faces[3].setSmGroup(1);
            mesh.faces[3].setVerts(1,4,0);   

            mesh.faces[4].setEdgeVisFlags(1,1,1);
            mesh.faces[4].setSmGroup(1);
            mesh.faces[4].setVerts(2,4,3);   

            mesh.faces[5].setEdgeVisFlags(1,1,1);
            mesh.faces[5].setSmGroup(1);
            mesh.faces[5].setVerts(3,4,2);   

            mesh.faces[6].setEdgeVisFlags(1,0,1);
            mesh.faces[6].setSmGroup(1);
            mesh.faces[6].setVerts(3,1,0);

            mesh.faces[7].setEdgeVisFlags(1,1,0);
            mesh.faces[7].setSmGroup(1);
            mesh.faces[7].setVerts(3,2,1);   

         }
      }

   mesh.InvalidateTopologyCache();
}
void
ParticleMesherObject::PickPFEvents(HWND hWnd)
{
   Tab<INode *> pfEvents;
   int numberOfNodes = 1;;

   TimeValue t = GetCOREInterface()->GetTime();


   pfNodes.ZeroCount();
   addPFNodes.ZeroCount();
   

   for (int i = 0; i < numberOfNodes; i++)
      {
      INode *node;
      pblock2->GetValue(particlemesher_pick,t,node,ivalid,i);

      if (node)
         {
         ObjectState tos =  node->EvalWorldState(t,TRUE);

         if (tos.obj->IsParticleSystem())
            {
            IParticleObjectExt* epobj;
            epobj = (IParticleObjectExt*) tos.obj->GetInterface(PARTICLEOBJECTEXT_INTERFACE);
   
            if (epobj) 
               {
               MyEnumProc dep;              
               tos.obj->DoEnumDependents(&dep);
               for (int i = 0; i < dep.Nodes.Count(); i++)
                  {
                  Interval valid;
                  INode *node = dep.Nodes[i];

                  Object *obj = node->GetObjectRef();
				  IParticleGroup* iPGroup = ParticleGroupInterface(obj);
				  if (iPGroup != nullptr)
					  {
						 // we need to filter out the global action list events since
						 // they do not carry any actual particle shape geometry
						 if (iPGroup->GetParticleSystem() != iPGroup->GetActionList())
						 {
							 pfNodes.Append(1, &node);
						 }
					  }
			      }
               }

            }

         }
      }
   if (pfNodes.Count() > 0)
      {
      int iret = DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_ADD_DIALOG),
            hWnd,AddDlgProc,(LPARAM)this);
      if ((iret) && (addPFNodes.Count() > 0))
         {
         theHold.Begin();
         for (int i = 0; i < addPFNodes.Count(); i++)
            {
            int index = addPFNodes[i];
            INode *node = pfNodes[index];
            pblock2->Append(particlemesher_pfeventlist,1,&node);
            }
         theHold.Accept(GetString(IDS_ADDEVENTS));

         }
      }  

}
Example #21
0
void
	BlobMesh::PickPFEvents(HWND hWnd)
{
	Tab<INode *> pfEvents;
	int numberOfNodes = pblock2->Count(pb_nodelist);

	TimeValue t = GetCOREInterface()->GetTime();


	pfNodes.ZeroCount();
	addPFNodes.ZeroCount();


	for (int i = 0; i < numberOfNodes; i++)
	{
		INode *node;
		pblock2->GetValue(pb_nodelist,t,node,ivalid,i);

		if (node)
		{
			ObjectState tos =  node->EvalWorldState(t,TRUE);

			if (tos.obj->IsParticleSystem())
			{
				IParticleObjectExt* epobj;
				epobj = (IParticleObjectExt*) tos.obj->GetInterface(PARTICLEOBJECTEXT_INTERFACE);

				if (epobj) 
				{
					MyEnumProc dep(false);              
					tos.obj->DoEnumDependents(&dep);
					for (int i = 0; i < dep.Nodes.Count(); i++)
					{
						Interval valid;
						INode *node = dep.Nodes[i];

						Object *obj = node->GetObjectRef();


						if ((obj) && (obj->GetInterface(PARTICLEGROUP_INTERFACE)) )
						{
							pfNodes.Append(1,&node);
						}
					}

				}

			}

		}
	}
	if (pfNodes.Count() > 0)
	{
		int iret = DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_ADD_DIALOG),
			hWnd,AddDlgProc,(LPARAM)this);
		if ((iret) && (addPFNodes.Count() > 0))
		{
			theHold.Begin();
			for (int i = 0; i < addPFNodes.Count(); i++)
			{
				int index = addPFNodes[i];
				INode *node = pfNodes[index];
				pblock2->Append(pb_pfeventlist,1,&node);
			}
			theHold.Accept(GetString(IDS_ADDEVENTS));

		}
	}  

}
Example #22
0
/**
*  @brief
*    Adds a 3ds Max node to the scene
*/
bool PLSceneContainer::AddIGameNode(IGameNode &cIGameNode)
{
	// Unknown node type by default
	EType nType = TypeUnknown;

	// Is there a '.' within the node name? If yes, replace it by '-'.
	String sName = cIGameNode.GetName();
	int nIndex = sName.IndexOf(".");
	if (nIndex >= 0) {
		g_pLog->LogFLine(PLLog::Warning, "Node name '%s' has '.' within it, '.' is replaced by '-' automatically", cIGameNode.GetName());
		char *pszName = const_cast<char*>(sName.GetASCII()) + nIndex;
		while (*pszName != '\0') {
			if (*pszName == '.')
				*pszName = '-';
			pszName++;
		}
	}
	const char *pszName = sName.GetASCII();

	// Look for 'cell_' (cell_<cell name>_<node name> or cell_<cell name>_<mesh name>_<instance name>)
	String sSceneCellName, sTargetSceneCellName, sSceneNodeName, sMeshName;
	if (!_strnicmp(pszName, "cell_", 5)) {
		// Get the name of the cell
		const char *pszNameT = pszName += 5;

		// Check for '\0'
		if (*pszNameT == '\0') {
			g_pLog->LogFLine(PLLog::Error, "Node name '%s' does not follow the name convention cell_<cell name>_<node name> or cell_<cell name>_<mesh name>_<instance name>. <cell name> is missing!", cIGameNode.GetName());
			sSceneCellName = "?";
			sMeshName	   = "?";
			sSceneNodeName = "?";
		} else {
			// Read the cell name
			while (*pszNameT != '_' && *pszNameT != '\0')
				pszNameT++;
			sSceneCellName.Insert(pszName, 0, pszNameT-pszName);

			// Check for '_'
			if (*pszNameT != '_') {
				g_pLog->LogFLine(PLLog::Error, "Node name '%s' does not follow the name convention cell_<cell name>_<node name> or cell_<cell name>_<mesh name>_<instance name>. <mesh name>/<instance name> is missing!", cIGameNode.GetName());
				sMeshName	   = "?";
				sSceneNodeName = "?";
			} else {
				// Skip '_'
				pszNameT++; 

				// Get the name of the node/mesh
				pszName = pszNameT;
				while (*pszNameT != '_' && *pszNameT != '\0')
					pszNameT++;
				sMeshName.Insert(pszName, 0, pszNameT-pszName);

				// Check for '_'
				if (*pszNameT != '_') {
					// Check for spaces within the mesh name
					CheckAndCorrectName(sMeshName, cIGameNode.GetName(), "mesh");

					// cell_<cell name>_<node name> is used so node name = mesh name
					sSceneNodeName = sMeshName;

					// Construct a 'save' mesh name later if the final scene node name is known...
					sMeshName = "";
				} else {
					// Skip '_'
					pszNameT++; 

					// Get the name of the scene node
					sSceneNodeName = sMeshName+"_";
					pszName = pszNameT;
					while (*pszNameT != '_' && *pszNameT != '\0')
						pszNameT++;
					sSceneNodeName.Insert(pszName, sSceneNodeName.GetLength(), pszNameT-pszName);

					// Is there an instance name? - No log hint because people find this behavior annoying...
				//	if (!(pszNameT-pszName))
				//		g_pLog->LogFLine(PLLog::Hint, "Node name '%s' does not follow the name convention cell_<cell name>_<mesh name>_<instance name>. <instance name> is missing!", cIGameNode.GetName());

					// Check for spaces and tabs within the mesh and node names
					CheckAndCorrectName(sMeshName,      cIGameNode.GetName(), "mesh");
					CheckAndCorrectName(sSceneNodeName, cIGameNode.GetName(), "node");
				}
			}
		}

		// Check for spaces/tabs within the cell name
		CheckAndCorrectName(sSceneCellName, cIGameNode.GetName(), "cell");

	// Look for 'portal_' (portal_<from cell>_<to cell>)
	} else if (!_strnicmp(pszName, "portal_", 7)) {
		// Get the name of the cell, the cell-portal is a scene node of this cell :)
		const char *pszNameT = pszName += 7;

		// Check for '\0'
		if (*pszNameT == '\0') {
			g_pLog->LogFLine(PLLog::Error, "Node name '%s' does not follow the name convention portal_<from cell>_<to cell>. <from cell> is missing!", cIGameNode.GetName());
			sSceneCellName       = "?";
			sTargetSceneCellName = "?";
		} else {
			// Read the cell name
			while (*pszNameT != '_' && *pszNameT != '\0')
				pszNameT++;
			sSceneCellName.Insert(pszName, 0, pszNameT-pszName);

			// Check for '_'
			if (*pszNameT != '_') {
				g_pLog->LogFLine(PLLog::Error, "Node name '%s' does not follow the name convention portal_<from cell>_<to cell>. <to cell> is missing!", cIGameNode.GetName());
				sTargetSceneCellName = "?";
			} else {
				// Skip '_'
				pszNameT++; 

				// Get the name of the target cell
				pszName = pszNameT;
				while (*pszNameT != '_' && *pszNameT != '\0')
					pszNameT++;
				sTargetSceneCellName.Insert(pszName, 0, pszNameT-pszName);
			}
		}

		// Check for spaces/tabs within the names
		CheckAndCorrectName(sSceneCellName,       cIGameNode.GetName(), "cell");
		CheckAndCorrectName(sTargetSceneCellName, cIGameNode.GetName(), "target cell");

		// Get the name of the scene node
		sSceneNodeName = "CellPortalTo_";
		sSceneNodeName += sTargetSceneCellName;

		// Get the 'real' target cell name - in our case, this cell MUST be within the parent container...
		sTargetSceneCellName = "Parent." + sTargetSceneCellName;

		// Set the correct scene node type
		nType = TypeCellPortal;

	// Look for 'antiportal_' (antiportal_<name>)
	} else if (!_strnicmp(pszName, "antiportal_", 11)) {
		// Get the name of the anti-portal)
		sSceneNodeName = String("AntiPortal_") + (pszName += 11);

		// Set the correct scene node type
		nType = TypeAntiPortal;

	// ...
	} else {
		// No log hint because people find this behavior annoying...
	//	g_pLog->LogFLine(PLLog::Hint, "Node name '%s' does not follow the name convention cell_<cell name>_<node name> or cell_<cell name>_<mesh name>_<instance name>. Node is added to the scene root.", cIGameNode.GetName());

		// Set scene node name
		sSceneNodeName = pszName;
	}

	// Check whether the scene cell and node names are valid
	if (sSceneCellName.CompareNoCase("This")) {
		sSceneCellName += '-';
		g_pLog->LogFLine(PLLog::Warning, "'This' is NOT allowed as node name. (3ds Max node '%s') Name is changed into '%s' ", cIGameNode.GetName(), sSceneCellName.GetASCII());
	}
	if (sSceneCellName.CompareNoCase("Root")) {
		sSceneCellName += '-';
		g_pLog->LogFLine(PLLog::Warning, "'Root' is NOT allowed as node name. (3ds Max node '%s') Name is changed into '%s' ", cIGameNode.GetName(), sSceneCellName.GetASCII());
	}
	if (sSceneCellName.CompareNoCase("Parent")) {
		sSceneCellName += '-';
		g_pLog->LogFLine(PLLog::Warning, "'Parent' is NOT allowed as node name. (3ds Max node '%s') Name is changed into '%s' ", cIGameNode.GetName(), sSceneCellName.GetASCII());
	}
	if (sSceneNodeName.CompareNoCase("This")) {
		sSceneNodeName += '-';
		g_pLog->LogFLine(PLLog::Warning, "'This' is NOT allowed as node name. (3ds Max node '%s') Name is changed into '%s' ", cIGameNode.GetName(), sSceneNodeName.GetASCII());
	}
	if (sSceneNodeName.CompareNoCase("Root")) {
		sSceneNodeName += '-';
		g_pLog->LogFLine(PLLog::Warning, "'Root' is NOT allowed as node name. (3ds Max node '%s') Name is changed into '%s' ", cIGameNode.GetName(), sSceneNodeName.GetASCII());
	}
	if (sSceneNodeName.CompareNoCase("Parent")) {
		sSceneNodeName += '-';
		g_pLog->LogFLine(PLLog::Warning, "'Root' is NOT allowed as node name. (3ds Max node '%s') Name is changed into '%s' ", cIGameNode.GetName(), sSceneNodeName.GetASCII());
	}

	// Get cell, this scene node is in
	PLSceneCell *pCell = GetCell(sSceneCellName, cIGameNode);

	// The exporter isn't case sensitive, but compare the 'real' cell names just for sure :)
	if (pCell && pCell->GetName() != sSceneCellName)
		g_pLog->LogFLine(PLLog::Warning, "Node '%s' is within the cell '%s', but '%s' was written -> It's recommended to take care of lower/upper case!", cIGameNode.GetName(), pCell->GetName().GetASCII(), sSceneCellName.GetASCII());

	// Get the container the new scene node is created in. If no cell was found, create the scene node
	// within THIS container.
	PLSceneContainer *pContainer = pCell ? pCell : this;

	// Check whether there's already an scene node with this name, if so, rename it and write a warning
	// into the log
	String sSceneNodeNameLower = sSceneNodeName;
	sSceneNodeNameLower.ToLower(); // Do ONLY use lower case, else the hashing will NOT return the same values!
	std::map<String, PLSceneNode*>::iterator pIterator = pContainer->m_mapNodes.find(sSceneNodeNameLower);
	if (pIterator != pContainer->m_mapNodes.end()) {
		String sNewName;
		int nConflictIndex = 1;

		// Find an unused scene node name
		do {
			sNewName = sSceneNodeName;
			sNewName += "_Conflict_";
			sNewName += PLTools::ToString(nConflictIndex);
			nConflictIndex++;
			sSceneNodeNameLower = sNewName;
			sSceneNodeNameLower.ToLower(); // Do ONLY use lower case, else the hashing will NOT return the same values!
			pIterator = pContainer->m_mapNodes.find(sSceneNodeNameLower);
		} while (pIterator != pContainer->m_mapNodes.end());

		// Write a log message
		g_pLog->LogFLine(PLLog::Warning, "'%s': There's already a scene node with the name '%s' within the container '%s' -> Changed name into '%s'",
			cIGameNode.GetName(), sSceneNodeName.GetASCII(), sSceneCellName.GetASCII(), sNewName.GetASCII());

		// Set the new name
		sSceneNodeName = sNewName;
	}

	// Construct a 'save' mesh name...
	if (!sMeshName.GetLength())
		sMeshName = sSceneCellName.GetLength() ? sSceneCellName + '_' + sSceneNodeName : sSceneNodeName;

	// Are there any children? If yes, we need to create a container for this node containing THIS node AND the children...
	if (cIGameNode.GetChildCount()) {
		PLSceneContainer *pNewContainer = new PLSceneContainer(pContainer, sSceneNodeName);

		// Register the new scene node
		pContainer->m_lstSceneNodes.push_back(pNewContainer);
		sSceneNodeNameLower = sSceneNodeName;
		sSceneNodeNameLower.ToLower(); // Do ONLY use lower case, else the hashing will NOT return the same values!
		pContainer->m_mapNodes.insert(std::make_pair(sSceneNodeNameLower, pNewContainer));

		// The new container becomes the current container
		pContainer = pNewContainer;

		// [TODO] Update the statistics
		// pContainer->m_sStatistics.nNumOfUnknown++;
		// GetScene().m_sSceneStatistics.nNumOfUnknown++;
	}

	// Create the scene node...
	PLSceneNode *pSceneNode = nullptr;
	INode *pMaxNode = cIGameNode.GetMaxNode();
	if (pMaxNode) {
		Object *pMaxObject = pMaxNode->GetObjectRef();
		if (pMaxObject) {
			// Get 'real' 3ds Max object (we really need to do this)
			while (pMaxObject->SuperClassID() == GEN_DERIVOB_CLASS_ID)
				pMaxObject = static_cast<IDerivedObject*>(pMaxObject)->GetObjRef();

			// Check the type of the object
			switch (pMaxObject->SuperClassID()) {
				case LIGHT_CLASS_ID:
					// Create the scene node
					pSceneNode = new PLSceneLight(*pContainer, cIGameNode, sSceneNodeName);

					// Update the statistics
					pContainer->m_sStatistics.nNumOfLights++;
					GetScene().m_sSceneStatistics.nNumOfLights++;
					break;

				case GEOMOBJECT_CLASS_ID:
					// Is this a cell-portal?
					if (nType == TypeCellPortal) {
						// Create the scene node
						pSceneNode = new PLSceneCellPortal(*pContainer, cIGameNode, sSceneNodeName, sTargetSceneCellName);

						// Update the number of outgoing cell-portals
						if (pContainer->GetType() == TypeCell) {
							static_cast<PLSceneCell*>(pContainer)->m_lstOutgoingCellPortals.push_back(static_cast<PLSceneCellPortal*>(pSceneNode));

						// ?? There's something totally wrong! ??
						} else {
							g_pLog->LogFLine(PLLog::Warning, "'%s': This cell-portal is within the container '%s', but cell-portals should only be within cells!",
											 cIGameNode.GetName(), sTargetSceneCellName.GetASCII());
						}

						// Update the statistics
						pContainer->m_sStatistics.nNumOfCellPortals++;
						GetScene().m_sSceneStatistics.nNumOfCellPortals++;

					// Is this a anti-portal?
					} else if (nType == TypeAntiPortal) {
						// Create the scene node
						pSceneNode = new PLSceneAntiPortal(*pContainer, cIGameNode, sSceneNodeName);

						// Update the statistics
						pContainer->m_sStatistics.nNumOfAntiPortals++;
						GetScene().m_sSceneStatistics.nNumOfAntiPortals++;

					} else {
						// [TODO] Add rename to mesh node...
						// Create the scene node
						pSceneNode = new PLSceneObject(*pContainer, cIGameNode, sSceneNodeName, GetScene().AddMesh(cIGameNode, sMeshName));

						// Update the statistics
						pContainer->m_sStatistics.nNumOfObjects++;
						GetScene().m_sSceneStatistics.nNumOfObjects++;
					}
					break;

				case SHAPE_CLASS_ID:
					// Create the scene node
					pSceneNode = new PLSceneSpline(*pContainer, cIGameNode, sSceneNodeName);

					// We do not need to update the statistics...
					break;

				case CAMERA_CLASS_ID:
					// Create the scene node
					pSceneNode = new PLSceneCamera(*pContainer, cIGameNode, sSceneNodeName);

					// Update the statistics
					pContainer->m_sStatistics.nNumOfCameras++;
					GetScene().m_sSceneStatistics.nNumOfCameras++;
					break;

				case HELPER_CLASS_ID:
					// Create the scene node
					pSceneNode = new PLSceneHelper(*pContainer, cIGameNode, sSceneNodeName);

					// Update the statistics
					pContainer->m_sStatistics.nNumOfHelpers++;
					GetScene().m_sSceneStatistics.nNumOfHelpers++;
					break;

				default:
					// Create the scene node
					pSceneNode = new PLSceneUnknown(*pContainer, cIGameNode, sSceneNodeName);

					// Update the statistics
					pContainer->m_sStatistics.nNumOfUnknown++;
					GetScene().m_sSceneStatistics.nNumOfUnknown++;
					break;
			}
		}
	}

	// Valid scene node?
	if (pSceneNode) {
		// Are there any children? If yes, we need to create a container for this node containing THIS node AND the children...
		if (cIGameNode.GetChildCount()) {
			// Setup the scene container
			pContainer->m_bFixedCenter = true;
			pContainer->m_vCenter.Set(0.0f, 0.0f, 0.0f);
			pContainer->m_vPos = pSceneNode->m_vPos;
			pContainer->m_vRot = pSceneNode->m_vRot;

			// Setup the scene node 'creating' the scene container
			pSceneNode->m_vPos.Set(0.0f, 0.0f, 0.0f);
			pSceneNode->m_vRot.Set(0.0f, 0.0f, 0.0f);
		}

		// Register the new scene node
		pContainer->m_lstSceneNodes.push_back(pSceneNode);
		sSceneNodeNameLower = sSceneNodeName;
		sSceneNodeNameLower.ToLower(); // Do ONLY use lower case, else the hashing will NOT return the same values!
		pContainer->m_mapNodes.insert(std::make_pair(sSceneNodeNameLower, pSceneNode));

		{ // Add to 3ds Max node to PL node map
			String sKey = String::Format("%19p", cIGameNode.GetMaxNode());
			GetScene().m_mapMaxToPLNodes.insert(std::make_pair(sKey, pSceneNode));
		}

		// Loop through all child nodes
		for (int nNode=0; nNode<cIGameNode.GetChildCount(); nNode++) {
			IGameNode *pIGameNode = cIGameNode.GetNodeChild(nNode);
			if (pIGameNode) {
				g_pLog->LogFLine(PLLog::Scene, "Found 3ds Max child node: %s", pIGameNode->GetName());
				pContainer->AddIGameNode(*pIGameNode);
			}
		}

		// Done
		return true;
	}

	// Error!
	return false;
}
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;
}
	//---------------------------------------------------------------
	void CameraExporter::exportCamera( ExportNode* exportNode )
	{
		if ( !exportNode->getIsInVisualScene() )
			return;
		
		String cameraId = getCameraId(*exportNode);

		INode* iNode = exportNode->getINode();

		CameraObject* camera = (CameraObject*)iNode->GetObjectRef();

		INode* targetNode =  ( camera->ClassID().PartA() == LOOKAT_CAM_CLASS_ID) ? iNode->GetTarget() : 0;

		if ( camera )
		{
			if (  mDocumentExporter->isExportedObject(ObjectIdentifier(camera)) )
				return;

			mDocumentExporter->insertExportedObject(ObjectIdentifier(camera), exportNode);


			// Retrieve the camera parameters block
			IParamBlock* parameters = (IParamBlock*) camera->GetReference(MaxCamera::PBLOCK_REF);

			COLLADASW::BaseOptic * optics = 0; 
			if ( camera->IsOrtho() )
			{
				optics = new COLLADASW::OrthographicOptic(COLLADASW::LibraryCameras::mSW);

				// Calculate the target distance for FOV calculations
				float targetDistance;
				if ( targetNode )
				{
					Point3 targetTrans = targetNode->GetNodeTM(mDocumentExporter->getOptions().getAnimationStart()).GetTrans();
					Point3 cameraTrans = iNode->GetNodeTM(mDocumentExporter->getOptions().getAnimationStart()).GetTrans();
					targetDistance = (targetTrans - cameraTrans).Length();
				}
				else
				{
					targetDistance = camera->GetTDist(mDocumentExporter->getOptions().getAnimationStart());
				}
				ConversionInverseOrthoFOVFunctor conversionInverseOrthoFOVFunctor(targetDistance);

				if ( AnimationExporter::isAnimated(parameters, MaxCamera::FOV) )
				{
					optics->setXMag(conversionInverseOrthoFOVFunctor(parameters->GetFloat(MaxCamera::FOV)), XMAG_SID);
					mAnimationExporter->addAnimatedParameter(parameters, MaxCamera::FOV, cameraId, XMAG_SID, 0, true, &conversionInverseOrthoFOVFunctor);
				}
				else
				{
					optics->setXMag(conversionInverseOrthoFOVFunctor(parameters->GetFloat(MaxCamera::FOV)));	
				}
			}
			else
			{
				optics = new COLLADASW::PerspectiveOptic(COLLADASW::LibraryCameras::mSW);
				if ( AnimationExporter::isAnimated(parameters, MaxCamera::FOV) )
				{
					optics->setXFov(COLLADASW::MathUtils::radToDegF(parameters->GetFloat(MaxCamera::FOV)), XFOV_SID);
					mAnimationExporter->addAnimatedParameter(parameters, MaxCamera::FOV, cameraId, XFOV_SID, 0, true, &ConversionFunctors::radToDeg);
				}
				else
				{
					optics->setXFov(COLLADASW::MathUtils::radToDegF(parameters->GetFloat(MaxCamera::FOV)));	
				}
			}

			bool hasAnimatedZNear = mAnimationExporter->addAnimatedParameter(parameters, MaxCamera::NEAR_CLIP, cameraId, optics->getZNearDefaultSid(), 0);
			optics->setZNear(parameters->GetFloat(MaxCamera::NEAR_CLIP), hasAnimatedZNear);

			bool hasAnimatedZFar = mAnimationExporter->addAnimatedParameter(parameters, MaxCamera::FAR_CLIP, cameraId, optics->getZFarDefaultSid(), 0);
			optics->setZFar(parameters->GetFloat(MaxCamera::FAR_CLIP), hasAnimatedZFar);


#ifdef UNICODE
			String exportNodeName = COLLADABU::StringUtils::wideString2utf8String(exportNode->getINode()->GetName());
			COLLADASW::Camera colladaCamera(COLLADASW::LibraryCameras::mSW, optics, cameraId, COLLADASW::Utils::checkNCName(exportNodeName));
#else
			COLLADASW::Camera colladaCamera(COLLADASW::LibraryCameras::mSW, optics, cameraId, COLLADASW::Utils::checkNCName(exportNode->getINode()->GetName()));
#endif
			setExtraTechnique(&colladaCamera);


			// Retrieve the camera target
			if ( targetNode )
			{
				ExportNode* targetExportNode = mExportSceneGraph->getExportNode(targetNode);
				addExtraParameter(EXTRA_PARAMETER_TARGET, "#" + targetExportNode->getId());
			}

			if (camera->GetMultiPassEffectEnabled(0, FOREVER))
			{
				IMultiPassCameraEffect *multiPassCameraEffect = camera->GetIMultiPassCameraEffect();
				if (multiPassCameraEffect)
				{
					Class_ID id = multiPassCameraEffect->ClassID();

					// the camera could have both effects, but not in Max
					if (id == FMULTI_PASS_MOTION_BLUR_CLASS_ID)
					{
						IParamBlock2 *parameters = multiPassCameraEffect->GetParamBlock(0);
						if (parameters )
						{
							addParamBlockAnimatedExtraParameters(MOTION_BLUR_ELEMENT, MOTION_BLUR_PARAMETERS, MOTION_BLUR_PARAMETER_COUNT, parameters, cameraId);
						}
					}
					else if (id == FMULTI_PASS_DOF_CLASS_ID)
					{
						IParamBlock2 *parameters = multiPassCameraEffect->GetParamBlock(0);
						if (parameters )
						{
							addParamBlockAnimatedExtraParameters(DEPTH_OF_FIELD_ELEMENT, DEPTH_OF_FIELD_PARAMETERS, DEPTH_OF_FIELD_PARAMETER_COUNT, parameters, cameraId);
							addExtraParameter(TARGETDISTANCE_PARAMETER, camera->GetTDist(0));
						}
					}
				}
			}
			addCamera(colladaCamera);
		
			delete optics;
		}

	}