void SMDNodeList::AddNodeS ( char* in_szString , int in_iParentID, XSI::X3DObject in_pModel, XSI::Kinematics	l_pHierarchyCompensation, XSI::Kinematics l_pHierarchyCompensation2)
{
	
	for (int n=0;n<m_pNodeList.GetUsed();n++)
	{
		if ( !strcmp ( m_pNodeList[n]->GetName(), in_szString ) )
		{
			return;
		}
	}

	// zero out compensation if the user is exporting with Zero Root Transforms option

	if ( (ExportSelectedOnly)&&(ZeroRootTransforms) && (in_iParentID==-1))
	{
		char l_szMessage[1024];
		sprintf(l_szMessage,"Zeroing out the parent transforms of root node %s", in_szString);
		XSILogMessage(l_szMessage, XSI::siWarningMsg );

		g_ResetTranforms.Extend(1);
		g_ResetTranforms[g_ResetTranforms.GetUsed()-1].m_kine = l_pHierarchyCompensation;
		g_ResetTranforms[g_ResetTranforms.GetUsed()-1].m_xfo = l_pHierarchyCompensation.GetLocal().GetTransform();

		g_ResetTranforms.Extend(1);
		g_ResetTranforms[g_ResetTranforms.GetUsed()-1].m_kine = l_pHierarchyCompensation2;
		g_ResetTranforms[g_ResetTranforms.GetUsed()-1].m_xfo = l_pHierarchyCompensation2.GetLocal().GetTransform();

		XSI::MATH::CTransformation zeroxfo;
		zeroxfo.SetScalingFromValues(1.0,1.0,1.0);

		l_pHierarchyCompensation.GetLocal().PutTransform(zeroxfo);
		l_pHierarchyCompensation2.GetLocal().PutTransform(zeroxfo);
	}

	SMDNode	*l_pNewNode = new SMDNode;

	l_pNewNode->SetName ( in_szString );
	l_pNewNode->SetParentID ( in_iParentID );
	l_pNewNode->SetModel ( in_pModel );
	l_pNewNode->SetHierarchicalCompensation ( l_pHierarchyCompensation );
	l_pNewNode->SetHierarchicalCompensation2 ( l_pHierarchyCompensation2 );
	

	m_pNodeList.Extend(1);
	m_pNodeList[m_pNodeList.GetUsed()-1] = l_pNewNode;

	l_pNewNode->SetID ( m_pNodeList.GetUsed()-1 );

}
void SMDImporter::RecurseCreateNull ( XSI::X3DObject in_pParent, SMDNode* in_pNode )
{
	
	LPWSTR l_wszModelName;
	DSA2W(&l_wszModelName,FixName ( in_pNode->m_szName ) );
				
	XSI::Null myNull = DoesObjectExist ( in_pParent, XSI::CString(l_wszModelName) );

	if ( !myNull.IsValid() )
	{
		in_pParent.AddNull ( l_wszModelName, myNull );
	}

	in_pNode->m_x3d = myNull;

	XSI::KinematicState l_lLocal = myNull.GetKinematics().GetLocal();

	XSI::MATH::CTransformation xfo;

	if ( in_pNode->m_pKeys.GetUsed() )
	{

		SMDKey* l_pKey = in_pNode->GetKey (0);
		
		xfo = l_lLocal.GetTransform();
		xfo.SetRotationFromXYZAnglesValues ( l_pKey->m_vRotation.GetX(), l_pKey->m_vRotation.GetY(), l_pKey->m_vRotation.GetZ() );
		xfo.SetTranslationFromValues ( l_pKey->m_vPosition.GetX(), l_pKey->m_vPosition.GetY(), l_pKey->m_vPosition.GetZ() );
	}

	if ( in_pNode->m_pParent ==NULL )
	{
		XSI::MATH::CTransformation xfo2;
		xfo2.SetRotationFromXYZAnglesValues ( -1.570796, 0.0, 0.0 );
		xfo.MulInPlace(xfo2);
	}

	l_lLocal.PutTransform ( xfo );

	for (int c=0;c<in_pNode->m_pChildren.GetUsed();c++)
	{
		RecurseCreateNull ( myNull, in_pNode->GetChild(c));
	}

}
	//-----------------------------------------------------------------------------
	void XsiSkeletonExporter::sampleAllBones(DeformerMap& deformers, 
		std::vector<NodeAnimationTrack*> deformerTracks, double frame, 
		Real time, float fps, AxisAlignedBox& AABBPadding)
	{
		CValueArray args;
		CValue dummy;
		args.Resize(2);
		// set the playcontrol 
		args[0] = L"PlayControl.Key";
		args[1] = frame;
		mXsiApp.ExecuteCommand(L"SetValue", args, dummy);
		args[0] = L"PlayControl.Current";
		mXsiApp.ExecuteCommand(L"SetValue", args, dummy);

		// Refresh
		mXsiApp.ExecuteCommand(L"Refresh", CValueArray(), dummy);
		// Sample all bones
		for (DeformerMap::iterator di = deformers.begin(); di != deformers.end(); ++di)
		{
			DeformerEntry* deformer = di->second;
			NodeAnimationTrack* track = deformerTracks[deformer->boneID];

			double initposx, initposy, initposz;
			deformer->initialXform.GetTranslationValues(initposx, initposy, initposz);
			double initrotx, initroty, initrotz;
			deformer->initialXform.GetRotation().GetXYZAngles(initrotx, initroty, initrotz);
			double initsclx, initscly, initsclz;
			deformer->initialXform.GetScalingValues(initsclx, initscly, initsclz);
			XSI::MATH::CMatrix4 invTrans = deformer->initialXform.GetMatrix4();
			invTrans.InvertInPlace();

			XSI::MATH::CTransformation transformation;
			if (deformer->pBone->getParent() == 0)
			{
				// Based on global
				transformation = 
					deformer->obj.GetKinematics().GetGlobal().GetTransform();
			}
			else
			{
				// Based on local
				transformation = 
					deformer->obj.GetKinematics().GetLocal().GetTransform();
			}

			double posx, posy, posz;
			transformation.GetTranslationValues(posx, posy, posz);
			double sclx, scly, sclz;
			transformation.GetScalingValues(sclx, scly, sclz);

			// Make relative to initial
			XSI::MATH::CMatrix4 transformationMatrix = transformation.GetMatrix4();
			transformationMatrix.MulInPlace(invTrans);
			transformation.SetMatrix4(transformationMatrix);

			// create keyframe
			TransformKeyFrame* kf = track->createNodeKeyFrame(time);
			// not sure why inverted transform doesn't work for position, but it doesn't
			// I thought XSI used same transform order as OGRE
			kf->setTranslate(Vector3(posx - initposx, posy - initposy, posz - initposz));
			kf->setRotation(XSItoOgre(transformation.GetRotationQuaternion()));
			kf->setScale(Vector3(sclx / initsclx, scly / initscly, sclz / initsclz));

			// Derive AABB of bone positions, for padding animated mesh AABB
			XSI::MATH::CVector3 bonePos = 
				deformer->obj.GetKinematics().GetGlobal().GetTransform().GetTranslation();
			AABBPadding.merge(XSItoOgre(bonePos));



		}

	}
XSI::CStatus CAxisInterpOp::Update
(
	UpdateContext&	ctx,
	OutputPort&	output
)
{
	Operator op(ctx.GetOperator());

	///////////////////////////////////////////////////////////////
	// get operator parameters
	///////////////////////////////////////////////////////////////

	XSI::CString triggers(op.GetParameterValue(L"Triggers"));

	// triggers changed
	if ( m_csTriggers != triggers )
	{
		m_csTriggers = triggers;

		Init( ctx, 0 );
	}

	double boneperc = op.GetParameterValue(L"BoneDist");

	///////////////////////////////////////////////////////////////
	// get objects connected to input & output ports
	///////////////////////////////////////////////////////////////
 
	InputPort rootboneport(op.GetPort(L"globalkineport",L"RootBoneGroup",0));
	InputPort parentboneport(op.GetPort(L"globalkineport",L"ParentBoneGroup",0));
	InputPort parentbonelenport(op.GetPort(L"bonelengthport",L"ParentBoneGroup",0));
	InputPort childboneport(op.GetPort(L"globalkineport",L"ChildBoneGroup",0));

	KinematicState gkRoot(rootboneport.GetValue());
	KinematicState gkParent(parentboneport.GetValue());
	double parentbonelen(parentbonelenport.GetValue());
	KinematicState gkChild(childboneport.GetValue());
	KinematicState gkHelper(output.GetValue());

	// GET TRANSFORMATIONS OF ROOT, PARENT & CHILD
	CTransformation tGRoot = gkRoot.GetTransform();
	CTransformation tGBone1 = gkParent.GetTransform();
	CTransformation tGBone2 = gkChild.GetTransform();

#ifdef _DEBUG_UPDATE
	{
		Application app;
		wchar_t wszBuf[256]; 

		XSI::MATH::CQuaternion q = tGBone1.GetRotationQuaternion();

		double x, y, z;
		
		q.GetXYZAnglesValues(x,y,z);

		swprintf( wszBuf, L"parent R(%f,%f,%f)]",  r2d(x),r2d(y),r2d(z) );
		app.LogMessage( (const wchar_t*)wszBuf ); 
	}
#endif
#ifdef _DEBUG_UPDATE
	{
		Application app;
		wchar_t wszBuf[256]; 

		XSI::MATH::CQuaternion q = tGBone2.GetRotationQuaternion();

		double x, y, z;
		
		q.GetXYZAnglesValues(x,y,z);

		swprintf( wszBuf, L"child R(%f,%f,%f)]",  r2d(x),r2d(y),r2d(z) );
		app.LogMessage( (const wchar_t*)wszBuf ); 
	}
#endif

	///////////////////////////////////////////////////////////////
	// perform update function
	///////////////////////////////////////////////////////////////
 
	// GET LOCAL TRANSFORM OF CHILD RELATIVE TO PARENT
	XSI::MATH::CMatrix3 mBone1( tGBone1.GetRotationMatrix3() );
	XSI::MATH::CMatrix3 mBone2( tGBone2.GetRotationMatrix3() );

#ifdef _DEBUG_UPDATE
	{
		Application app;
		wchar_t wszBuf[256]; 

		double m0, m1, m2, m3, m4, m5, m6, m7, m8;
		
		mBone1.Get(m0, m1, m2, m3, m4, m5, m6, m7, m8);

		swprintf( wszBuf, L"mBone1->\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f", m0, m1, m2, m3, m4, m5, m6, m7, m8 );
			
		app.LogMessage( (const wchar_t*)wszBuf ); 
	}
#endif
#ifdef _DEBUG_UPDATE
	{
		Application app;
		wchar_t wszBuf[256]; 

		double m0, m1, m2, m3, m4, m5, m6, m7, m8;
		
		mBone2.Get(m0, m1, m2, m3, m4, m5, m6, m7, m8);

		swprintf( wszBuf, L"mBone2->\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f", m0, m1, m2, m3, m4, m5, m6, m7, m8 );
			
		app.LogMessage( (const wchar_t*)wszBuf ); 
	}
#endif
	mBone1.TransposeInPlace();
#ifdef _DEBUG_UPDATE
	{
		Application app;
		wchar_t wszBuf[256]; 

		double m0, m1, m2, m3, m4, m5, m6, m7, m8;
		
		mBone1.Get(m0, m1, m2, m3, m4, m5, m6, m7, m8);

		swprintf( wszBuf, L"mBone1.TransposeInPlace->\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f", m0, m1, m2, m3, m4, m5, m6, m7, m8 );
			
		app.LogMessage( (const wchar_t*)wszBuf ); 
	}
#endif

	XSI::MATH::CMatrix3  tmpMat3;

	for(int nR=0; nR<3; nR++)
		for(int nC=0; nC<3; nC++)
		{
			tmpMat3.SetValue(nR,nC , 
				mBone2.GetValue(nR,0) * mBone1.GetValue(0,nC) +
				mBone2.GetValue(nR,1) * mBone1.GetValue(1,nC) +
				mBone2.GetValue(nR,2) * mBone1.GetValue(2,nC) );
		}
	
	mBone2 = tmpMat3;

	// bug #90494
	// mBone2.MulInPlace( mBone1 );
#ifdef _DEBUG_UPDATE
	{
		Application app;
		wchar_t wszBuf[256]; 

		double m0, m1, m2, m3, m4, m5, m6, m7, m8;
		
		mBone2.Get(m0, m1, m2, m3, m4, m5, m6, m7, m8);

		swprintf( wszBuf, L"mBone2.MulInPlace( mBone1 )->\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f", m0, m1, m2, m3, m4, m5, m6, m7, m8 );
			
		app.LogMessage( (const wchar_t*)wszBuf ); 
	}
#endif

	// GET ORIENTATION OF BONE2 RELATIVE TO BONE1 AS A QUATERNION
	XSI::MATH::CQuaternion qBone2 = mBone2.GetQuaternion();

	// MATCH QUATERNIONS
	XSI::MATH::CVector3 vBasePos(
		op.GetParameterValue(L"BasePoseX"), 
		op.GetParameterValue(L"BasePoseY"), 
		op.GetParameterValue(L"BasePoseZ") );
	
#ifdef _DEBUG_UPDATE
	{
		Application app;
		wchar_t wszBuf[256]; 

		double x, y, z;
		
		qBone2.GetXYZAnglesValues(x,y,z);

		swprintf( wszBuf, L"child2parent R(%f,%f,%f)]",  r2d(x),r2d(y),r2d(z) );
		app.LogMessage( (const wchar_t*)wszBuf ); 
	}
#endif

	ComputeBaseOffset(vBasePos, boneperc, parentbonelen );

	ComputeWeights( qBone2, m_cTriggers, m_aWeights, m_aTriggerOri, m_aTriggerTol );

	// SUM TARGET ORIENTATIONS & POSITIONS
	XSI::MATH::CQuaternion qNewOri;

	SumTargets( qNewOri, vBasePos, m_cTriggers, m_aWeights, m_aTargetOri, m_aTargetPos );	

#ifdef _DEBUG_UPDATE
	Application app;
	wchar_t wszBuf[256]; 

	double x, y, z;
	
	qNewOri.GetXYZAnglesValues(x,y,z);

	swprintf( wszBuf, L"qNewOri->R(%f,%f,%f)]",  r2d(x),r2d(y),r2d(z) );
	app.LogMessage( (const wchar_t*)wszBuf ); 
#endif

	// UPDATE TRANSFORMATION
	XSI::MATH::CTransformation tNewPose;

	tNewPose.SetRotationFromQuaternion( qNewOri );
	tNewPose.SetTranslation( vBasePos );
	tNewPose.MulInPlace( tGRoot );

	///////////////////////////////////////////////////////////////
	// update output port
	///////////////////////////////////////////////////////////////

	gkHelper.PutTransform( tNewPose );

	return CStatus::OK;
}
CStatus CHelperBoneOp::Update
(
	UpdateContext&	ctx,
	OutputPort&	output
)
{
	///////////////////////////////////////////////////////////////
	// get operator
	///////////////////////////////////////////////////////////////
	Operator op(ctx.GetOperator());

	///////////////////////////////////////////////////////////////
	// get output port
	///////////////////////////////////////////////////////////////
 
	KinematicState gkHelper(output.GetValue());

	///////////////////////////////////////////////////////////////
	// get helper bone data
	///////////////////////////////////////////////////////////////

	InputPort bonedataport(op.GetPort(L"bonedataport",L"HelperBoneGroup",0));
	Property  HelperBoneData(bonedataport.GetValue());

	bool enabled = HelperBoneData.GetParameterValue(L"Enabled");

	// not enabled: do nothing
	if (!enabled) 
		return CStatus::OK;

	///////////////////////////////////////////////////////////////
	// evaluate new transformation for helperbone
	///////////////////////////////////////////////////////////////
	XSI::MATH::CTransformation tNewPose;

	bool bComputeInWorldSpace = (0!=(long)HelperBoneData.GetParameterValue(L"ComputationSpace"));

	///////////////////////////////////////////////////////////////
	// get objects connected to input & output ports
	///////////////////////////////////////////////////////////////

	InputPort rootboneport(op.GetPort(L"globalkineport",L"RootBoneGroup",0));
	InputPort parentboneport(op.GetPort(L"globalkineport",L"ParentBoneGroup",0));
	InputPort childboneport(op.GetPort(L"globalkineport",L"ChildBoneGroup",0));

	KinematicState gkRoot(rootboneport.GetValue());
	KinematicState gkParent(parentboneport.GetValue());
	KinematicState gkChild(childboneport.GetValue());

	// get helperbonedata values
	XSI::MATH::CVector3 vBasePos(
		HelperBoneData.GetParameterValue(L"BoneOffsetX"), 
		HelperBoneData.GetParameterValue(L"BoneOffsetY"), 
		HelperBoneData.GetParameterValue(L"BoneOffsetZ") );

	double perc_along_root = (double)HelperBoneData.GetParameterValue(L"BoneDistance") / 100.0;
	double root_bone_length = (double)HelperBoneData.GetParameterValue(L"RootBoneLength");

	XSI::GridData griddata(HelperBoneData.GetParameterValue(L"Triggers"));

	// read triggers
	ReadTriggerData(griddata);

	// GET TRANSFORMATIONS OF ROOT, PARENT & CHILD
	CTransformation tGRoot = gkRoot.GetTransform();
	CTransformation tGParent = gkParent.GetTransform();
	CTransformation tGChild = gkChild.GetTransform();

	///////////////////////////////////////////////////////////////
	// compute new orientation and position based on triggers
	///////////////////////////////////////////////////////////////
	DebugPrint( L"parent", tGParent.GetRotationQuaternion() );
	DebugPrint( L"child", tGChild.GetRotationQuaternion() );

	// GET LOCAL TRANSFORM OF CHILD RELATIVE TO PARENT
	XSI::MATH::CMatrix3 m3Parent( tGParent.GetRotationMatrix3() );
	DebugPrint(L"m3Parent->", m3Parent);

	XSI::MATH::CMatrix3 m3Child( tGChild.GetRotationMatrix3() );
	DebugPrint(L"m3Parent->", m3Child);

	m3Parent.TransposeInPlace();
	DebugPrint(L"m3Parent.TransposeInPlace->", m3Parent);

	// bug #90494
	// m3Child.MulInPlace( m3Parent );
	MulInPlace( m3Child, m3Parent );
	DebugPrint(L"m3Child.MulInPlace->", m3Child);

	// GET ORIENTATION OF BONE2 RELATIVE TO BONE1 AS A QUATERNION
	XSI::MATH::CQuaternion qBone2 = m3Child.GetQuaternion();
	DebugPrint( L"child2parent", qBone2 );

	// MATCH QUATERNIONS
	ComputeWeights( qBone2, m_cTriggers, m_aEnabled, m_aWeights, m_aTriggerOri, m_aTriggerTol );

	// SUM TARGET ORIENTATIONS & POSITIONS
	XSI::MATH::CQuaternion qNewOri;
	XSI::MATH::CVector3 vNewPos;

	SumTargets( qNewOri, vNewPos, m_cTriggers, m_aWeights, m_aTargetOri, m_aTargetPos );	
	DebugPrint( L"qNewPos->", qNewPos );
	DebugPrint( L"vNewOri->", qNewOri );

	// UPDATE TRANSFORMATION
	if (bComputeInWorldSpace)
	{
		// not implemented
	}
	else // Root object space
	{
		// compute initial helperbone position
		vBasePos.PutX( vBasePos.GetX() + (root_bone_length * perc_along_root) );
		vNewPos.AddInPlace(vBasePos);

		// apply changes from triggers
		tNewPose.SetRotationFromQuaternion( qNewOri );
		tNewPose.SetTranslation( vNewPos );

		// map root object space to worldspace
		tNewPose.MulInPlace( tGRoot );
	}

	///////////////////////////////////////////////////////////////
	// update output port
	///////////////////////////////////////////////////////////////

	gkHelper.PutTransform( tNewPose );


	return CStatus::OK;
}
void	SMDImporter::CreateGeometry()
{

	if ( !m_pTriangles.GetUsed() )
		return;

	long t;

	XSI::MATH::CTransformation xfo;
	xfo.SetRotationFromXYZAnglesValues ( -1.570796, 0.0, 0.0 );

	for (t=0;t<m_pTriangles.GetUsed();t++)
	{
		for (int v=0;v<3;v++)
		{
			XSI::MATH::CVector3 vec = XSI::MATH::MapObjectPositionToWorldSpace ( xfo, m_pTriangles[t]->m_pVertex[v].m_vPosition );
			
			long outindex;
			compress.AddVertex ( vec.GetX(), 
									vec.GetY(), 
									vec.GetZ(), 
									m_pTriangles[t]->m_pVertex[v].m_vUV.GetX(), 
									m_pTriangles[t]->m_pVertex[v].m_vUV.GetY(),
									&m_pTriangles[t]->m_pVertex[v],
									&outindex);

			m_lVertexMap.Extend(1);
			m_lVertexMap[m_lVertexMap.GetUsed()-1] = outindex;
		}
	}

	XSI::MATH::CVector3Array verts(compress.GetCount());
	long vindex = 0;
	long cnt  = compress.GetCount ();
	for (t=0;t<compress.GetCount ();t++)
	{
		uvvec vec;
		compress.GetVertex (t, &vec);
		verts[t] = XSI::MATH::CVector3 ( vec.x, vec.y, vec.z );
	}
	
	
	XSI::CLongArray indices((m_pTriangles.GetUsed() * 3) + m_pTriangles.GetUsed());

	long iindex = 0;
	

	char *l_szGlobalTexture = m_pTriangles[0]->m_szTexture;
	CSIBCArray<TriCluster>	ClusterList;
	
	for (t=0;t<m_pTriangles.GetUsed();t++)
	{
		
		XSI::MATH::CVector3 vec1 = XSI::MATH::MapObjectPositionToWorldSpace ( xfo, m_pTriangles[t]->m_pVertex[0].m_vPosition );
		XSI::MATH::CVector3 vec2 = XSI::MATH::MapObjectPositionToWorldSpace ( xfo, m_pTriangles[t]->m_pVertex[1].m_vPosition );
		XSI::MATH::CVector3 vec3 = XSI::MATH::MapObjectPositionToWorldSpace ( xfo, m_pTriangles[t]->m_pVertex[2].m_vPosition );

		long i1 = compress.GetIndex ( vec1.GetX(), vec1.GetY(), vec1.GetZ(), m_pTriangles[t]->m_pVertex[0].m_vUV.GetX(), m_pTriangles[t]->m_pVertex[0].m_vUV.GetY());
		long i2 = compress.GetIndex ( vec2.GetX(), vec2.GetY(), vec2.GetZ(), m_pTriangles[t]->m_pVertex[1].m_vUV.GetX(), m_pTriangles[t]->m_pVertex[1].m_vUV.GetY());
		long i3 = compress.GetIndex ( vec3.GetX(), vec3.GetY(), vec3.GetZ(), m_pTriangles[t]->m_pVertex[2].m_vUV.GetX(), m_pTriangles[t]->m_pVertex[2].m_vUV.GetY());

		indices[iindex] = 3;
		indices[iindex+1] = i1;
		indices[iindex+2] = i2;
		indices[iindex+3] = i3;
		iindex += 4;

		if ( strcmp ( l_szGlobalTexture, m_pTriangles[t]->m_szTexture ))
		{
			//
			// found a local material
			//

			TriCluster* cls = NULL;

			for (int c=0;c<ClusterList.GetUsed();c++)
			{
				if ( !strcmp ( ClusterList[c].m_szName, m_pTriangles[t]->m_szTexture))
				{
					cls = &ClusterList[c];
					break;
				}

			}

			if ( cls == NULL )
			{
				ClusterList.Extend(1);
				strcpy ( ClusterList[ClusterList.GetUsed()-1].m_szName, m_pTriangles[t]->m_szTexture );
				cls = &ClusterList[ClusterList.GetUsed()-1];
			}

			cls->m_indices.Add ( t );

		}

	}

	char mname[1024];
	sprintf (mname, "mesh" );
	if ( m_pMeshNode )
	{
		sprintf (mname, FixName(m_pMeshNode->m_szName));
	}

	LPWSTR l_wszModelName;
	DSA2W(&l_wszModelName,mname);

	m_pModel.AddPolygonMesh ( verts, indices, l_wszModelName, m_pMesh );


	XSI::Application	app;
	XSI::CValueArray	args(4);
	XSI::CValue			outArg;
	XSI::CStatus		st;

	args[0] = XSI::CValue( XSI::CString(L"") );
	args[1] = XSI::CValue(false);
	args[0] = XSI::CValue(m_pMesh.GetRef());
	args[1] = XSI::CValue((long)XSI::siTxtUV);
	args[2] = XSI::CValue((long)XSI::siTxtDefaultSpherical);
	args[3] = XSI::CValue(XSI::CString(L"Texture_Support"));

	app.ExecuteCommand( L"CreateTextureSupport", args, outArg );

	XSI::CValueArray	moreargs(1);
	XSI::CValueArray	moreoutargs(3);
	moreargs[0] = m_pMesh.GetRef();
	app.ExecuteCommand(L"FreezeObj",moreargs, outArg);

	XSI::Material		l_matMaterial;
	st = m_pMesh.AddMaterial(L"Phong", true, L"CubeMat", l_matMaterial);
		
	XSI::OGLTexture		l_oglTexture(l_matMaterial.GetOGLTexture());

	XSI::CString		l_szFullNameDefaultOut	= l_oglTexture.GetFullName();
	int			l_nHeightDefaultOut		= l_oglTexture.GetHeight();
	int			l_nWidthDefaultOut		= l_oglTexture.GetWidth();

	

	// Now actually add a texture, so we can test it.
	args[0] = XSI::CValue( XSI::CString(L"Image") );
	args[1] = XSI::CValue(m_pMesh.GetRef());
	args[2] = XSI::CValue((short)1);
	args[3] = XSI::CValue(false);
	st = app.ExecuteCommand( L"BlendInPresets", args, outArg );

	
	//
	// create the texture and connect
	//
	
	XSI::CValueArray	clipargs(3);
	XSI::ImageClip2 l_pClip;
	
	char l_szTextureFullname[1024];
	sprintf ( l_szTextureFullname, "%s%s", m_szDirectory, m_pTriangles[0]->m_szTexture);
	char clipname[1024];
	_splitpath ( m_pTriangles[0]->m_szTexture, NULL, NULL, clipname, NULL );

	LPWSTR l_wszClipName;
	DSA2W(&l_wszClipName,l_szTextureFullname);

	LPWSTR l_wszClipName2;
	DSA2W(&l_wszClipName2,clipname);

	
	
	clipargs[0] = XSI::CValue( XSI::CString(l_wszClipName) );
	clipargs[1] = XSI::CValue( XSI::CString(l_wszClipName2) );
	clipargs[2] = XSI::CValue(l_pClip.GetRef());
	app.ExecuteCommand( L"SICreateImageClip", clipargs, outArg );
	
	XSI::CString		l_szMaterialName	= l_matMaterial.GetFullName(); 
	XSI::CString		l_szImageNode = l_szMaterialName + L".CubeMat.ambient_blend.Image.tex";
	XSI::CString		l_szFullclipname = L"Clips." +  XSI::CString(l_wszClipName2);
	
	XSI::CValueArray	clipargs2(2);
	clipargs2[0] = XSI::CValue( XSI::CString(l_szFullclipname) );
	clipargs2[1] = XSI::CValue( XSI::CString(l_szImageNode) );
	
	app.ExecuteCommand( L"SIConnectShaderToCnxPoint", clipargs2, outArg );

	//
	// Create all clusters
	//

	XSI::Geometry geom( m_pMesh.GetActivePrimitive().GetGeometry() );
	
	for (int b=0;b<ClusterList.GetUsed();b++)
	{
		TriCluster* cls = &ClusterList[b];
		
		
		sprintf ( l_szTextureFullname, "%s%s", m_szDirectory, cls->m_szName);
		_splitpath ( cls->m_szName, NULL, NULL, clipname, NULL );
		
		DSA2W(&l_wszClipName,l_szTextureFullname);
		DSA2W(&l_wszClipName2,clipname);
		
		XSI::CLongArray array;
		XSI::Cluster polyCluster ;
		geom.AddCluster( XSI::siPolygonCluster, l_wszClipName2, cls->m_indices, polyCluster ) ;
		
		st = polyCluster.AddMaterial(L"Phong", true, L"CubeMat", l_matMaterial);
		
		XSI::OGLTexture		l_oglTexture(l_matMaterial.GetOGLTexture());
	
		// Now actually add a texture, so we can test it.
		args[0] = XSI::CValue( XSI::CString(L"Image") );
		args[1] = XSI::CValue(polyCluster.GetRef());
		args[2] = XSI::CValue((short)1);
		args[3] = XSI::CValue(false);
		st = app.ExecuteCommand( L"BlendInPresets", args, outArg );
			

		
		
		
		clipargs[0] = XSI::CValue( XSI::CString(l_wszClipName) );
		clipargs[1] = XSI::CValue( XSI::CString(l_wszClipName2) );
		clipargs[2] = XSI::CValue(l_pClip.GetRef());
		app.ExecuteCommand( L"SICreateImageClip", clipargs, outArg );
		
		l_szMaterialName	= l_matMaterial.GetFullName(); 
		l_szImageNode = l_szMaterialName + L".CubeMat.ambient_blend.Image.tex";
		l_szFullclipname = L"Clips." +  XSI::CString(l_wszClipName2);
		
		clipargs2[0] = XSI::CValue( XSI::CString(l_szFullclipname) );
		clipargs2[1] = XSI::CValue( XSI::CString(l_szImageNode) );
		
		app.ExecuteCommand( L"SIConnectShaderToCnxPoint", clipargs2, outArg );
		
	}

	
	if ( m_pMesh.IsValid () )
	{
		XSI::Geometry geom( m_pMesh.GetActivePrimitive().GetGeometry() );
		XSI::PolygonMesh mesh(m_pMesh.GetActivePrimitive().GetGeometry());

		XSI::CPointRefArray Geompoints = geom.GetPoints();
		
				
		XSI::CTriangleRefArray triangles(geom.GetTriangles());
		XSI::ClusterProperty UVWProp(m_pMesh.GetMaterial().GetCurrentUV());
		
		if ( UVWProp.IsValid() )
		{

		XSI::CClusterPropertyElementArray clusterPropertyElements = UVWProp.GetElements();
		XSI::CDoubleArray elementArray = clusterPropertyElements.GetArray();
		
		long totalUvCount = elementArray.GetCount ();
		int cc=0;
		int uvc = 0;
		for (int c=0;c<m_pTriangles.GetUsed();c++)
		{
			long l_iNumVertex = indices[cc];
			
			cc++;
			for (int i=0;i<l_iNumVertex;i++)
			{
				long l_iID = indices[cc];
				cc++;
				
				uvvec vec;
				compress.GetVertex (l_iID, &vec);

				elementArray[ uvc * 3 ] = vec.u;
				
				elementArray[ (uvc * 3) + 1] = vec.v;
				elementArray[ (uvc * 3) + 2] = 0.0f;
				
				uvc++;
			}
			
			
			
		}


			clusterPropertyElements.PutArray(elementArray);
		}
	}

}
void	SMDImporter::WeightGeometry()
{
	if ( !m_pTriangles.GetUsed() )
		return;

	XSI::CRefArray l_bones;
	CSIBCArray<XSI::CDoubleArray>	weightList;
	weightList.Extend ( m_pNodes.GetUsed() );

	for (int e=0;e<m_pNodes.GetUsed();e++)
	{
		weightList[e].Resize ( compress.GetCount() );
	}


	XSI::MATH::CTransformation xfo;
	xfo.SetRotationFromXYZAnglesValues ( -1.570796, 0.0, 0.0 );

	for (int n=0;n<m_pTriangles.GetUsed();n++)
	{
		SMDTriangle* tri = m_pTriangles[n];
		for (int v=0;v<3;v++)
		{
			//
			// get the index of this vertex
			//
			XSI::MATH::CVector3 vec1 = XSI::MATH::MapObjectPositionToWorldSpace ( xfo, tri->m_pVertex[v].m_vPosition );

			long index = compress.GetIndex (vec1.GetX(), 
											vec1.GetY(), 
											vec1.GetZ(),
											tri->m_pVertex[v].m_vUV.GetX(),
											tri->m_pVertex[v].m_vUV.GetY() );

			for (int w=0;w<tri->m_pVertex[v].m_vWeights.GetUsed();w++)
			{
				Weight* weight = &tri->m_pVertex[v].m_vWeights[w];

				XSI::X3DObject bone = GetNodeByID(weight->m_iBoneID);

				bool found = false;
				int ib = 0;
				for (int b=0;b<l_bones.GetCount();b++)
				{
					if ( l_bones[b] == bone )
					{
						found =true;
						break;
					}
					ib++;
				}

				if ( !found )
				{
					l_bones.Add ( bone );
				}

				weightList[ib];
				weightList[ib][index] = weight->m_fWeight * 100.0f;

			}
		}

	}

	//
	// apply envelope
	//

	XSI::Envelope myEnvelope;
	m_pMesh.ApplyEnvelope(	l_bones, XSI::siUnspecified, XSI::siUnspecified, myEnvelope);


	//
	// zero all weights
	//

	for (int z=0;z<l_bones.GetCount();z++)
	{

		XSI::X3DObject	X3d = l_bones[z];

		XSI::CDoubleArray refWeights = myEnvelope.GetDeformerWeights( X3d, 0.0 );

		for (int wc=0;wc<refWeights.GetCount();wc++)
		{
			refWeights[wc] = 0.0;
		}
	
		//
		// first set to zero
		myEnvelope.SetDeformerWeights( X3d, refWeights );


	}

	for (int f=0;f<l_bones.GetCount();f++)
	{

		XSI::X3DObject	X3d = l_bones[f];

		myEnvelope.SetDeformerWeights( X3d, weightList[f] );
	}

}
Exemple #8
0
bool bulletSimulation::SetFrame(int in_Frame)
{
   // see if we have to reset the world
   if(in_Frame <= 0)
   {
      ResetWorld();
      return true;
   }

   // now let's skip if we already have that frame or the interval>5 - we don't want bullet to compute the whole sequence if you move to the last frame.
   if(mLastFrame >= in_Frame || (in_Frame-mLastFrame)>5)
   {
      return false;
   }

   mChangingFrame = true;

   // if this is not the first frame, let's update all rbd!
   for(btRigidBodyIt it = mRigidBodies.begin();it!=mRigidBodies.end();it++)
   {
      // skip corrupt bodies
      if(it->second->body==NULL)
         continue;
      if(it->first.secondary != -1)
         continue;

      btCollisionShape * shape = (btBoxShape*)it->second->body->getCollisionShape();
      if(shape != NULL)
      {
         // refresh the kine ptr
         it->second->kine.Set(it->second->kine.GetAsText());

         XSI::MATH::CTransformation xf = XSI::KinematicState(it->second->kine).GetTransform();//(float)in_Frame);
         shape->setLocalScaling(btVector3(xf.GetSclX(),xf.GetSclY(),xf.GetSclZ()));

         // skip non valid ops
         if(!it->second->op.IsValid())
            continue;

         // update the mass an inertia
         it->second->mass = XSI::CustomOperator(it->second->op).GetParameterValue(L"mass");
         btVector3 inertia(0,0,0);
         if(it->second->mass > 0.0f)
            shape->calculateLocalInertia(it->second->mass,inertia);
         it->second->body->setMassProps(it->second->mass,inertia);

         // if we are passive rigid body, let's update the transform
         if(it->second->mass == 0.0f)
         {
            btDefaultMotionState * motionState = (btDefaultMotionState*)it->second->body->getMotionState();
            if(motionState != NULL)
            {
               btTransform transform;
               transform.setOrigin(btVector3(xf.GetPosX(),xf.GetPosY(),xf.GetPosZ()));

               XSI::MATH::CQuaternion q = xf.GetRotationQuaternion();
               transform.setRotation(btQuaternion(q.GetX(),q.GetY(),q.GetZ(),q.GetW()));
               it->second->body->proceedToTransform( transform );
            }
         }
      }
   }

   // step to the given frame
   if(in_Frame > 0)
   {
      while(in_Frame > mLastFrame)
      {
         float dt=(1.0f/mFps)/(float)mSubSteps;
         //Step every subframe
         for (int i=0;i<mSubSteps;i++)
             mDynamicsWorld->stepSimulation(dt,0,1.0f/mFps);

         mLastFrame++;
      }
   }
   mLastFrame = in_Frame;

   mChangingFrame = false;
   return true;
}