XSIPLUGINCALLBACK CStatus Coat3DExport_Init( CRef& in_ctxt )
{
	Context ctxt( in_ctxt );
	Command oCmd;
	oCmd = ctxt.GetSource();
	
	// Specify that the command returns a value
	oCmd.EnableReturnValue(true);
	//Application app;
	app.LogMessage(L"Coat3DExport_Init!");

	// Add arguments to the command
	ArgumentArray oArgs;
	oArgs = oCmd.GetArguments();

	oArgs.Add(L"tempLocation", (CString)siString);
	oArgs.Add(L"coatLocation",(CString)siString);
	oArgs.Add(L"typePaint",(CValue)siUInt);
	//oArgs.Add(L"bCopyTexE",(CValue)siBool);
	oArgs.Add(L"bExpMat",(CValue)siBool);
	oArgs.Add(L"bExpUV",(CValue)siBool);
	oArgs.Add(L"bExpNorm",(CValue)siBool);

	return CStatus::OK;
}
SICALLBACK XSIUnloadPlugin( const PluginRegistrar& in_reg )
{
	CString strPluginName;
	strPluginName = in_reg.GetName();
	app.LogMessage(strPluginName + L" has been unloaded.",siVerboseMsg);
	return CStatus::OK;
}
XSI::CStatus XSIUnloadPlugin( const XSI::PluginRegistrar& in_reg )
{
	Application app;
#ifdef _DEBUG
	app.LogMessage( in_reg.GetName() + L" has been unloaded.");
#endif
	return XSI::CStatus::OK;
}
inline void DebugPrint( const XSI::CString& str, const XSI::MATH::CMatrix3& m3 )
{
	Application app;
	wchar_t wszBuf[256]; 

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

	swprintf( wszBuf, L"%s\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f", (const wchar_t*)str, m0, m1, m2, m3, m4, m5, m6, m7, m8 );
		
	app.LogMessage( (const wchar_t*)wszBuf ); 
}
// Callback for the siOnActivateEvent event.
SICALLBACK siOnActivateEvent_OnEvent( CRef& in_ctxt )
{
	Context ctxt( in_ctxt );
	//Application().LogMessage(L"siOnActivateEvent_OnEvent called",siVerboseMsg);
	//Application().LogMessage(L"State: " + CString(ctxt.GetAttribute(L"State")),siVerboseMsg);

	bool bState = ctxt.GetAttribute(L"State");
	if(bState)
	{
		CustomProperty prop = app.GetActiveSceneRoot().GetProperties().GetItem(L"AppLink_3DCoat");
		if (prop.IsValid())
		{
			if(prop.GetParameter("bEvent").GetValue())
			{
				CString s_CoatLocation = prop.GetParameter(L"coatLocation").GetValue();
				CString exportPath = CUtils::BuildPath(s_CoatLocation, L"export.txt");
				CString objPath;

				std::ifstream fileref(exportPath.GetAsciiString());
				bool bfile = false;
				if(fileref.good())
				{
					std::string row;
					std::getline(fileref, row);
					objPath = row.c_str();
					bfile = true;
				}
				fileref.close();

				if(bfile)
				{				
					UIToolkit uitool = Application().GetUIToolkit();
					LONG out;
					uitool.MsgBox(L"Import file?", siMsgOkCancel|siMsgInformation|MB_APPLMODAL, L"", (LONG) out);
					if(out == siMsgOk)
					{
						app.LogMessage(L"Start Import!");
						CValueArray args(2);
						args[0] = objPath;
						args[1] = prop.GetParameterValue( L"bReplace" );
						CValue noret;
						app.ExecuteCommand( L"Coat3DImport", args, noret ) ;
					}
				}				
			}
		}
	}

// 	Return value is ignored as this event can not be aborted.
	return CStatus::OK;
}
inline void DebugPrint( const XSI::CString& str, const XSI::MATH::CQuaternion& q )
{
			Application app;
			wchar_t wszBuf[256]; 

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

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

			swprintf( wszBuf, L"%s R(%f,%f,%f)]", (const wchar_t*)str, r2d(x),r2d(y),r2d(z) );
			app.LogMessage( (const wchar_t*)wszBuf ); 
}
/** Defines the arguments to the export command */
XSI::CStatus OgreMeshExportCommand_Init( const XSI::CRef& context )
{
	Context ctx(context);
	Command cmd(ctx.GetSource());

	Application app;
	app.LogMessage( L"Defining: " + cmd.GetName() );

	ArgumentArray args = cmd.GetArguments();

    args.Add( L"objectName", L"" );
	args.Add( L"targetMeshFileName", L"c:/default.mesh" );
	args.Add( L"calculateEdgeLists", L"true" );
    args.Add( L"calculateTangents", L"false" );
    args.Add( L"exportSkeleton", L"true" );
	args.Add( L"exportVertexAnimation", L"true" );
    args.Add( L"targetSkeletonFileName", L"c:/default.skeleton" );
    args.Add( L"fps", L"24" );
    args.Add( L"animationList", L"" ); 
	return XSI::CStatus::OK;

}
/** Runs the exporter using arguments obtained from a context object
  (I assume this is to allow general access to this export rather than using
   the property dialog)
*/
XSI::CStatus OgreMeshExportCommand_Execute( XSI::CRef& in_context )
{
	Application app;
	Context ctxt(in_context);
	CValueArray args = ctxt.GetAttribute( L"Arguments" );

#ifdef _DEBUG
	for (long i=0; i<args.GetCount(); i++)
	{
		app.LogMessage( L"Arg" + CValue(i).GetAsText() + L": " + 
			args[i].GetAsText() );			
	}
#endif

	if ( args.GetCount() != 9 ) 
	{
		// Arguments of the command might not be properly registered
		return CStatus::InvalidArgument ;
	}

    // TODO - perform the export!

    return XSI::CStatus::OK;
}
/** Registers the export command, the menu item, and the option dialog */
CStatus XSILoadPlugin( XSI::PluginRegistrar& registrar )
{
	registrar.PutAuthor( L"Steve Streeting" );
	registrar.PutName( L"OGRE Exporter Plugin" );	
    registrar.PutVersion( 1, 0 );
    registrar.PutURL(L"http://www.ogre3d.org");
    

	// register the mesh export command
	registrar.RegisterCommand( L"OgreMeshExportCommand", L"OgreMeshExportCommand" );

    // register the menu under File > Export
	registrar.RegisterMenu(siMenuMainFileExportID, L"OgreMeshExportMenu", false, false);

	// register the export dialog properties factory
	registrar.RegisterProperty( L"OgreMeshExportOptions" );

#ifdef _DEBUG
    Application app;
    app.LogMessage( registrar.GetName() + L" has been loaded.");
#endif

    return XSI::CStatus::OK;	
}
void CAxisInterpOp::ComputeWeights
( 
	XSI::MATH::CQuaternion& qbone2, 
	unsigned long size,			// number of triggers
	double* aweights, 
	double* atriggers, 
	double* atolerances 
)
{
	XSI::MATH::CQuaternion q2;

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

	swprintf( wszBuf, L"ComputeWeights qbone2->[%f V(%f,%f,%f)]",  qbone2.GetW(), qbone2.GetX(), qbone2.GetY(), qbone2.GetZ() );
	app.LogMessage( (const wchar_t*)wszBuf ); 

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

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

	// dim tsec : tsec = timer
	// fntrace "ComputeWeights("&j&") bone2 angle: " & fnstr(q2rot(qbone2))

	double sumw(0), weight(0), dot_product(0), tolerance(0);
	
	for ( unsigned long j=0,i=0; i < size*3; i=i+3,j=j+1 )
	{
		tolerance = d2r(atolerances[j]);
#ifdef _DEBUG_COMPUTEWEIGHTS
		swprintf( wszBuf, L"trigger(%d) ori: (%f,%f,%f)", j, atriggers[i], atriggers[i+1], atriggers[i+2] );
		app.LogMessage( (const wchar_t*)wszBuf ); 

		swprintf( wszBuf, L"trigger(%d) tolerance: %f", j, tolerance );
		app.LogMessage( (const wchar_t*)wszBuf ); 
#endif

		q2.SetFromXYZAnglesValues( d2r(atriggers[i]), d2r(atriggers[i+1]), d2r(atriggers[i+2]) );

		// compute dot product of quaternion
		dot_product = 
			qbone2.GetX() * q2.GetX() + 
			qbone2.GetY() * q2.GetY() + 
			qbone2.GetZ() * q2.GetZ() + 
			qbone2.GetW() * q2.GetW();
#ifdef _DEBUG_COMPUTEWEIGHTS
		swprintf( wszBuf, L"trigger(%d) dot: %f", j, dot_product );
		app.LogMessage( (const wchar_t*)wszBuf ); 
#endif

		if ( tolerance == 0 ) {
			weight = 0;
		} else {
#ifdef _DEBUG_COMPUTEWEIGHTS
//		swprintf( wszBuf, L"ComputeWeights(%d) _acos(%f) = %f", j, fabs(dot_product), _acos(fabs(dot_product)) );
//		app.LogMessage( (const wchar_t*)wszBuf ); 
		swprintf( wszBuf, L"trigger(%d) acos(%f) = %f", j, fabs(dot_product), acos(fabs(dot_product)) );
		app.LogMessage( (const wchar_t*)wszBuf ); 
#endif
			weight = 1.0 - (2.0 * acos(fabs(dot_product)) / tolerance);
#ifdef _DEBUG_COMPUTEWEIGHTS
		swprintf( wszBuf, L"trigger(%d) weight: %f", j, weight );
		app.LogMessage( (const wchar_t*)wszBuf ); 
#endif
			if ( weight < 0 ) {
				weight = 0;
			}
		}
#ifdef _DEBUG_COMPUTEWEIGHTS
		swprintf( wszBuf, L"trigger(%d) computed weight: %f", j, weight );
		app.LogMessage( (const wchar_t*)wszBuf ); 
#endif

		aweights[j] = weight;
		// fntrace "ComputeWeights("&j&") raw: " & aW(j)

		sumw=sumw+aweights[j];
	}

	// make sure sum of weights totals 1
	if ( sumw != 0 ) 
	{
		for ( unsigned long i=0; i < size; i++ )
		{
			if ( aweights[i] != 0 ) {
				aweights[i] = aweights[i] / sumw;
				//fntrace "ComputeWeights("&i&") normalized: " & aW(i)
			}  
#ifdef _DEBUG_COMPUTEWEIGHTS
			swprintf( wszBuf, L"trigger(%d) normalized = %f", i, aweights[i] );
			app.LogMessage( (const wchar_t*)wszBuf ); 
#endif
		}
	}
	//fntrace "AxisInterpOp::ComputeWeights: took " & timer-tsec & " seconds"

}
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;
}
XSIPLUGINCALLBACK CStatus Coat3DExport_Execute( CRef& in_ctxt )
{
	// Unpack the command argument values
	Context ctxt( in_ctxt );
	CValueArray args = ctxt.GetAttribute(L"Arguments");
	CString string;

	// A 3d object with a mesh geometry must be selected
	Selection selection(app.GetSelection());

	bool isPolymesh = true;
	for(int i =0; i< selection.GetCount(); i++)
	{
		X3DObject obj(selection[i]);
		//app.LogMessage(L"obj.IsA(siPolygonMeshID): " + CString(obj.GetType()));
		if(obj.GetType() != L"polymsh" )
		{
			isPolymesh = false;
			break;
		}
	}

	if (selection.GetCount() > 0 && isPolymesh)
	{
		gV = 0; gVn = 0; gVt = 0;
		gVprev = 0; gVnPrev = 0; gVtPrev = 0;
		// prepare the output text file
		CString strOut = Get3DCoatParam( L"tempLocation" ).GetValue();
		
		std::ofstream mfw;
		mfw.open(strOut.GetAsciiString(), std::ios_base::out | std::ios_base::trunc);
		if (mfw.is_open())
		{
			bar.PutMaximum( selection.GetCount() );
			bar.PutStep( 1 );
			bar.PutVisible( true );		

			OutputHeader( mfw);				
			// output the data
			for (int i=0; i < selection.GetCount(); i++)
			{
				gObjCnt = i;
				gVprev = gV;
				gVtPrev = gVt;
				gVnPrev = gVn;
				X3DObject xobj(selection.GetItem(i));

				bar.PutValue(i);
				bar.PutCaption( L"Exporting " + xobj.GetName());

				mfw << "\n";
				mfw << "# Hierarchy (from self to top father)\n";
				string = L"g " + xobj.GetName() + L"\n";
				mfw << string.GetAsciiString();
				mfw << "\n";

				// Get a geometry accessor from the selected object	
				Primitive prim = xobj.GetActivePrimitive();
				PolygonMesh mesh = prim.GetGeometry();
				if (!mesh.IsValid()) return CStatus::False;

				CGeometryAccessor ga = mesh.GetGeometryAccessor();

				OutputVertices( mfw, ga, xobj );
				if (bar.IsCancelPressed()) return CStatus::False;
				OutputPolygonComponents( mfw, ga );
				if (bar.IsCancelPressed()) return CStatus::False;
				//bar.Increment();		
			}
		}
		mfw.close();

		if(Get3DCoatParam(L"bExpMat").GetValue())
		{
			OutputMaterials(selection );
		}
		bar.PutStatusText( L"import.txt" );
		OutputImportTxt();
		bar.PutVisible(false);
                app.LogMessage(L"Export done!");
	}
	else
	{
		app.LogMessage(L"Please, select objects!", siWarningMsg);
		return CStatus::False;
	}

	return CStatus::OK;
}
XSIPLUGINCALLBACK CStatus OutputMaterials( Selection& in_sel )
{
	// prepare the mtl file
	Project prj = app.GetActiveProject();
	Scene scn = prj.GetActiveScene();
	CString tmpLocation = Get3DCoatParam( L"tempLocation" ).GetValue();

	ULONG npos = tmpLocation.ReverseFindString(L".");
	CString substr = tmpLocation.GetSubString(0, npos+1);
	CString strOut = substr + L"mtl";	

	//app.LogMessage(L"strOut:" + strOut);

	std::ofstream matfw;
	matfw.open(strOut.GetAsciiString(), std::ios_base::out | std::ios_base::trunc);
	if (matfw.is_open())
	{
		CRefArray tempMats;

		for(int i=0; i< in_sel.GetCount(); i++)
		{
			X3DObject xobj(in_sel.GetItem(i));

			// Get a geometry accessor from the selected object	
			Primitive prim = xobj.GetActivePrimitive();
			PolygonMesh mesh = prim.GetGeometry();
			if (!mesh.IsValid()) return CStatus::False;

			CGeometryAccessor ga = mesh.GetGeometryAccessor();

			// get the material objects used by the mesh
			CRefArray materials = ga.GetMaterials();

			for (LONG n=0; n < materials.GetCount(); n++)
			{
				bar.PutStatusText( L"materials" );

				Material mat(materials[n]);
				bool inMats = false;
				//app.LogMessage(CString(n) +L" : "+ CString(i)+ L" :" + mat.GetName());

				for(int m = 0; m < tempMats.GetCount(); m++)
				{
					Material tmat(tempMats[m]);
					if(mat.GetName() == tmat.GetName())
					{
						inMats = true;
						break;
					}
				}

				//app.LogMessage(CString(inMats));

				if(!inMats)
				{
					CString string = L"newmtl " + mat.GetName() + L"\n";
					matfw << string.GetAsciiString();

					Parameter surf = mat.GetParameters().GetItem(L"surface");
					Shader lShader(surf.GetSource());
					//app.LogMessage(L"shader: " + lShader.GetFullName());
					//app.LogMessage(L"shader: " + lShader.GetProgID());
					if ( lShader.GetProgID() == L"Softimage.material-phong.1" )
					{
						float r, g, b, a;

						lShader.GetColorParameterValue(L"ambient", r, g, b, a );
						CString ka = L"Ka " + FormatNumber(r) + L" " + FormatNumber(g) + L" " + FormatNumber(b);
						lShader.GetColorParameterValue(L"diffuse", r, g, b, a );
						CString kd = L"Kd " + FormatNumber(r) + L" " + FormatNumber(g) + L" " + FormatNumber(b);
						lShader.GetColorParameterValue(L"specular", r, g, b, a );
						CString ks = L"Ks " + FormatNumber(r) + L" " + FormatNumber(g) + L" " + FormatNumber(b);
						float ns = lShader.GetParameterValue(L"shiny");
						float d = 1.0f;
						CValue illum = 2;

						matfw << ka.GetAsciiString();
						matfw << "\n";
						matfw << kd.GetAsciiString();
						matfw << "\n";
						matfw << ks.GetAsciiString();
						matfw << "\n";
						matfw << "Ns ";
						matfw << FormatNumber(ns).GetAsciiString();
						matfw << "\n";
						matfw << "d ";
						matfw << FormatNumber(d).GetAsciiString();
						matfw << "\n";
						matfw << "illum ";
						matfw << illum.GetAsText().GetAsciiString();
						matfw << "\n";

						Parameter diff = lShader.GetParameters().GetItem(L"diffuse");
						Shader lImageD(diff.GetSource());

						if (lImageD.GetProgID() == L"Softimage.txt2d-image-explicit.1")
						{
							Parameter tex = lImageD.GetParameters().GetItem(L"tex");
							ImageClip2 lTextureD(tex.GetSource());

							//app.LogMessage( L"Found texture shader: " + lTexture.GetFullName() + L", Class: " + lTexture.GetClassIDName() + L", Type: " + lTexture.GetType() );
							app.LogMessage(L"texture GetFileName: " + lTextureD.GetFileName());
							matfw << "map_Kd ";
							matfw << lTextureD.GetFileName().GetAsciiString();
							matfw << "\n";
						}

						Parameter spec = lShader.GetParameters().GetItem(L"specular");
						Shader lImageS(spec.GetSource());

						if (lImageS.GetProgID() == L"Softimage.txt2d-image-explicit.1")
						{
							Parameter tex = lImageD.GetParameters().GetItem(L"tex");
							ImageClip2 lTextureS(tex.GetSource());

							//app.LogMessage( L"Found texture shader: " + lTexture.GetFullName() + L", Class: " + lTexture.GetClassIDName() + L", Type: " + lTexture.GetType() );
							//app.LogMessage(L"texture GetFileName: " + lTexture.GetFileName());
							matfw << "map_Ks ";
							matfw << lTextureS.GetFileName().GetAsciiString();
							matfw << "\n";
						}
					}
					tempMats.Add(mat);
					matfw << "\n";
					matfw << "\n";
				}
			}		
		}
		matfw.close();
	}
	return CStatus::OK;
}
Beispiel #14
0
// Update =============================================================================
CStatus gStretchOp2Multi_Update( CRef& in_ctxt )
{

	OperatorContext ctxt( in_ctxt );

		// User Datas ------------------------------------
		CValue::siPtrType pUserData = ctxt.GetUserData();
		OpUserData* pOpState = (OpUserData*)pUserData;

		if ( pOpState == NULL || pOpState->index >= 2)
		{
			// First time called
			pOpState = new OpUserData();
			ctxt.PutUserData( (CValue::siPtrType)pOpState );

			// Inputs ---------------------------------------
			KinematicState kRoot(ctxt.GetInputValue(0));
			KinematicState kCtrl(ctxt.GetInputValue(1));
			CTransformation tRoot(kRoot.GetTransform());
			CTransformation tCtrl(kCtrl.GetTransform());
			CVector3 vRoot = tRoot.GetTranslation();
			CVector3 vCtrl = tCtrl.GetTranslation();
			CMatrix4 mRoot = tRoot.GetMatrix4();
			CMatrix4 mRootNeg;
			mRootNeg.Invert(mRoot);

			double dRestLength = ctxt.GetParameterValue(L"restlength");
			double dScale      = ctxt.GetParameterValue(L"scale");
			double dSoftness   = ctxt.GetParameterValue(L"soft");
			double dMaxStretch = ctxt.GetParameterValue(L"maxstretch");

			// Distance with MaxStretch ---------------------
			dRestLength = dRestLength * dScale - .00001;
			CVector3 vDistance;
			vDistance.MulByMatrix4(vCtrl, mRootNeg);
			double dDistance = vDistance.GetLength();
			double dDistance2 = dDistance;
			if (dDistance > (dRestLength * dMaxStretch))
			{
				vDistance.NormalizeInPlace();
				vDistance.ScaleInPlace(dRestLength * dMaxStretch);
				dDistance = dRestLength * dMaxStretch;
			}

			Application app;
			app.LogMessage(L"dist : "+CString(dDistance));
			app.LogMessage(L"dist2 : "+CString(dDistance2));

			// Adapt Softness value to chain length --------
			dSoftness = dSoftness * dRestLength *.1;

			// Stretch and softness ------------------------
			/// We use the real distance from root to controler to calculate the softness
			/// This way we have softness working even when there is no stretch
			double dStretch = dDistance/dRestLength;
			if (dStretch < 1)
				dStretch = 1;
			double da = dRestLength - dSoftness;
			if (dSoftness > 0 && dDistance2 > da)
			{
				double newlen = dSoftness*(1.0 - exp(-(dDistance2 -da)/dSoftness)) + da;
				dStretch = dDistance / newlen;
			}

			double dScaleX = dStretch * dScale;
			app.LogMessage(L"scalex : "+CString(dScaleX));

			// Effector Position ----------------------------
			CTransformation t;
			vDistance.MulByMatrix4(vDistance, mRoot);
			t.SetTranslation(vDistance);

			pOpState->index = 0;
			pOpState->t = t;
			pOpState->dLength0 = dScaleX;
		}

	// Outputs -------------------------------------
	CRef outputPortRef=ctxt.GetOutputPort();
	OutputPort OutPort(outputPortRef);

	// Effector Transform
	if (OutPort.GetIndex() == 2)
	{
		KinematicState kOut = ctxt.GetOutputTarget();
		kOut.PutTransform(pOpState->t);
	}
	// Bone 0 Length
	else if (OutPort.GetIndex() == 3)
	{
		OutPort.PutValue(pOpState->dLength0);
	}

	pOpState->index += 1;

	return CStatus::OK;
}
SICALLBACK AppLink_3DCoat_PPGEvent( const CRef& in_ctxt )
{	
	//Application app;
	PPGEventContext ctxt( in_ctxt ) ;
	CustomProperty prop = ctxt.GetSource();
	PPGEventContext::PPGEvent eventID = ctxt.GetEventID() ;

	//CString s_ExeLocation = prop.GetParameter(L"coatExe").GetValue();

	if ( eventID == PPGEventContext::siOnInit )
	{
		CString s_ExportLocation = prop.GetParameter(L"tempLocation").GetValue();
		CString s_CoatLocation = prop.GetParameter(L"coatLocation").GetValue();

		Plugin pl(app.GetPlugins().GetItem(L"AppLink_3DCoat_Plugin"));
		pluginPath = CUtils::BuildPath(app.GetInstallationPath(pl.GetOrigin()), L"AppLink_3DCoat", L"Application", L"Plugins");

		if(prop.GetParameter(L"tempLocation").GetValue() == L"")
		{
			Project prj = app.GetActiveProject();
			Scene scn = prj.GetActiveScene();
			CString tempPath = CUtils::BuildPath(app.GetInstallationPath(siProjectPath), L"3DCoat", scn.GetName(), scn.GetName() + L".obj");
			prop.GetParameter(L"tempLocation").PutValue(tempPath);
			prop.GetParameter(L"tempLocation").PutCapabilityFlag(siReadOnly, true);
		}

		if(prop.GetParameter(L"coatLocation").GetValue() == L"")
		{
			TCHAR Path[MAX_PATH];
			if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, Path))) 
			{
				CString exchPath = CUtils::BuildPath(Path, L"3D-CoatV3", L"Exchange");
				prop.GetParameter(L"coatLocation").PutValue(exchPath);
			}
		}

		//prop.GetParameter(L"bImpNorm").PutCapabilityFlag(siNotInspectable, true);
		//prop.GetParameter(L"bImpNewMat").PutCapabilityFlag(siReadOnly, true);

		ctxt.PutAttribute(L"Refresh",true);

	}
	else if ( eventID == PPGEventContext::siButtonClicked )
	{
		CValue buttonPressed = ctxt.GetAttribute( L"Button" );
		CString tempLocation = prop.GetParameter(L"tempLocation").GetValue();
		CString coatLocation = prop.GetParameter(L"coatLocation").GetValue();
	
		if( buttonPressed.GetAsText() == L"Coat3DExport" )
		{
			CustomProperty in_pset = ctxt.GetSource();

			if(CUtils::EnsureFolderExists(tempLocation, true))
			{
				CValueArray args(6);
				args[0] = tempLocation;
				args[1] = coatLocation;
				args[2] = in_pset.GetParameterValue( L"typePaint" );
				//args[3] = in_pset.GetParameterValue( L"bCopyTexE" );
				args[3] = in_pset.GetParameterValue( L"bExpMat" );
				args[4] = in_pset.GetParameterValue( L"bExpUV" );
				args[5] = in_pset.GetParameterValue( L"bExpNorm" );
				
				CValue retVal;

				app.ExecuteCommand( L"Coat3DExport", args, retVal );
				
				CString exeLocation = prop.GetParameter(L"exeLocation").GetValue();
				bool bStart = prop.GetParameter(L"bStart").GetValue();

				if(exeLocation != L"" && bStart)
				{
					if(!Find3DCoat())
					{
						if((int)::ShellExecute(NULL, TEXT("open"), exeLocation.GetAsciiString(), NULL, NULL, SW_SHOWNORMAL) <= 32)
						{
							app.LogMessage(L"3D-Coat.exe not found!", siWarningMsg);
						}
					}
					else
					{
						app.LogMessage(L"3D-Coat.exe is run!", siWarningMsg);
					}
				}

			}
			else
			{
				app.LogMessage(L"Note temp path exists!", siErrorMsg);
			}
		}
		else if( buttonPressed.GetAsText() == L"Coat3DImport" )
		{
			CustomProperty in_pset = ctxt.GetSource();

			CString exportPath = CUtils::BuildPath(coatLocation, L"export.txt");
			CString objPath;

			std::ifstream mfrExportTxt;
			mfrExportTxt.open (exportPath.GetAsciiString());//c:\Documents and Settings\user\My Documents\3D-CoatV3\Exchange\export.txt
			//app.LogMessage(L"Export.txt is it! :" + strOut);
			if(mfrExportTxt.good())
			{
				std::string row;
				std::getline(mfrExportTxt, row);
				objPath = row.c_str();
				//app.LogMessage(L"first row: " + CString(row.c_str()));
			}
			else
			{
				UIToolkit uitool = app.GetUIToolkit();
				LONG out;
				uitool.MsgBox(L"import file not found!", siMsgOkOnly|siMsgExclamation, L"", (LONG) out);
				if(out == siMsgOk)
				{
					return CStatus::False;
				}
			}
			mfrExportTxt.close();
			app.LogMessage(coatLocation);
			app.LogMessage(exportPath);

			if(objPath != L"")
			{
				CValueArray args(2);
				args[0] = objPath;
				args[1] = in_pset.GetParameterValue( L"bReplace" );

				CValue noret;
				app.ExecuteCommand( L"Coat3DImport", args, noret );
			}
		}
	}
	else if ( eventID == PPGEventContext::siParameterChange )
	{
		Parameter changed = ctxt.GetSource();
		CustomProperty prop = changed.GetParent();		
		CString   paramName = changed.GetScriptName();

		if ( paramName == L"bImpMat" )
		{
			CValue bFlag = prop.GetParameter(L"bImpMat").GetValue();
			//prop.GetParameter(L"swMap").PutCapabilityFlag(siNotInspectable, !bFlag);
			prop.GetParameter(L"swMap").PutCapabilityFlag(siReadOnly, !bFlag);
		}
		ctxt.PutAttribute(L"Refresh",true);
	}

	return CStatus::OK ;
}
/** Callback event when clicking the export menu option. Adds an instance of the
    options dialog as a property, then uses the InspectObj XSI command to pop it up
    in a modal dialog. If it wasn't cancelled, performs an export.
*/
XSI::CStatus OnOgreMeshExportMenu( XSI::CRef& in_ref )
{	
	Ogre::LogManager logMgr;
	logMgr.createLog("OgreXSIExporter.log", true);
	CString msg(L"OGRE Exporter Version ");
	msg += OGRE_XSI_EXPORTER_VERSION;
	LogOgreAndXSI(msg);

	Application app;
	CStatus st(CStatus::OK);
	Property prop = app.GetActiveSceneRoot().GetProperties().GetItem(exportPropertyDialogName);
	if (prop.IsValid())
	{
		// Check version number
		CString currVersion(prop.GetParameterValue(L"version"));
		if (!currVersion.IsEqualNoCase(OGRE_XSI_EXPORTER_VERSION))
		{
			DeleteObj(exportPropertyDialogName);
			prop.ResetObject();
		}
	}
	if (!prop.IsValid())
	{
		prop = app.GetActiveSceneRoot().AddProperty(exportPropertyDialogName);
		prop.PutParameterValue(L"version", CString(OGRE_XSI_EXPORTER_VERSION));
	}
	
	try
	{
		// Popup Returns true if the command was cancelled otherwise it returns false. 
		CStatus ret = Popup(exportPropertyDialogName,CValue(),L"OGRE Mesh / Skeleton Export",((LONG)siModal),true);
		if (ret == CStatus::OK)
		{
			Ogre::XsiMeshExporter meshExporter;
			Ogre::XsiSkeletonExporter skelExporter;

			// retrieve the parameters
			Parameter param = prop.GetParameters().GetItem(L"objectName");
			CString objectName = param.GetValue();
			param = prop.GetParameters().GetItem( L"targetMeshFileName" );
			Ogre::String meshFileName = XSItoOgre(XSI::CString(param.GetValue()));
			if (meshFileName.empty())
			{
				OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, 
					"You must supply a mesh file name", 
					"OGRE Exporter");
			}
			// fix any omission of '.mesh'
			if (!Ogre::StringUtil::endsWith(meshFileName, ".mesh"))
			{
				meshFileName += ".mesh";
			}
			param = prop.GetParameters().GetItem( L"mergeSubmeshes" );
			bool mergeSubmeshes = param.GetValue();
			param = prop.GetParameters().GetItem( L"exportChildren" );
			bool exportChildren = param.GetValue();
			param = prop.GetParameters().GetItem( L"calculateEdgeLists" );
			bool edgeLists = param.GetValue();
			param = prop.GetParameters().GetItem( L"calculateTangents" );
			bool tangents = param.GetValue();
			param = prop.GetParameters().GetItem( L"tangentSemantic" );
			CString tangentSemStr = param.GetValue();
			Ogre::VertexElementSemantic tangentSemantic = (tangentSemStr == L"t")?
				Ogre::VES_TANGENT : Ogre::VES_TEXTURE_COORDINATES;
			param = prop.GetParameters().GetItem( L"tangentsSplitMirrored" );
			bool tangentsSplitMirrored = param.GetValue();
			param = prop.GetParameters().GetItem( L"tangentsSplitRotated" );
			bool tangentsSplitRotated = param.GetValue();
			param = prop.GetParameters().GetItem( L"tangentsUseParity" );
			bool tangentsUseParity = param.GetValue();
			param = prop.GetParameters().GetItem( L"numLodLevels" );
			long numlods = (LONG)param.GetValue();
			Ogre::XsiMeshExporter::LodData* lodData = 0;
			if (numlods > 0)
			{
				param = prop.GetParameters().GetItem( L"lodDistanceIncrement" );
				float distanceInc = param.GetValue();

				param = prop.GetParameters().GetItem(L"lodQuota");
				CString quota = param.GetValue();

				param = prop.GetParameters().GetItem(L"lodReduction");
				float reduction = param.GetValue();

				lodData = new Ogre::XsiMeshExporter::LodData;
				float currentInc = distanceInc;
				for (int l = 0; l < numlods; ++l)
				{
					lodData->distances.push_back(currentInc);
					currentInc += distanceInc;
				}
				lodData->quota = (quota == L"p") ?
					Ogre::ProgressiveMesh::VRQ_PROPORTIONAL : Ogre::ProgressiveMesh::VRQ_CONSTANT;
				if (lodData->quota == Ogre::ProgressiveMesh::VRQ_PROPORTIONAL)
					lodData->reductionValue = reduction * 0.01;
				else
					lodData->reductionValue = reduction;

			}

			param = prop.GetParameters().GetItem( L"exportSkeleton" );
			bool exportSkeleton = param.GetValue();
			param = prop.GetParameters().GetItem( L"exportVertexAnimation" );
			bool exportVertexAnimation = param.GetValue();
			param = prop.GetParameters().GetItem( L"exportMaterials" );
			bool exportMaterials = param.GetValue();
			param = prop.GetParameters().GetItem( L"copyTextures" );
			bool copyTextures = param.GetValue();

			// create singletons
			Ogre::ResourceGroupManager rgm;
			Ogre::MeshManager meshMgr;
			Ogre::SkeletonManager skelMgr;
			Ogre::MaterialManager matMgr;
			Ogre::DefaultHardwareBufferManager hardwareBufMgr;

			
			// determine number of exportsteps
			size_t numSteps = 3 + OGRE_XSI_NUM_MESH_STEPS;
			if (numlods > 0)
				numSteps++;
			if (edgeLists)
				numSteps++;
			if (tangents)
				numSteps++;
			if (exportSkeleton)
				numSteps += 3;

			Ogre::ProgressManager progressMgr(numSteps);
			
			// Any material prefix? We need that for mesh linking too
			param = prop.GetParameters().GetItem( L"materialPrefix" );
			Ogre::String materialPrefix = XSItoOgre(XSI::CString(param.GetValue()));

			param = prop.GetParameters().GetItem( L"fps" );
			float fps = param.GetValue();
			if (fps == 0.0f)
			{
				OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, 
					"You must supply a valid value for 'FPS'", 
					"OGRE Export");
			}

			Ogre::AnimationList selAnimList;
			if (exportSkeleton || exportVertexAnimation)
			{

				param = prop.GetParameters().GetItem( L"animationList" );
				GridData gd(param.GetValue());
				for (int a = 0; a < gd.GetRowCount(); ++a)
				{
					if (gd.GetCell(ANIMATION_LIST_EXPORT_COL, a) == true)
					{
						Ogre::AnimationEntry ae;
						ae.animationName = XSItoOgre(XSI::CString(gd.GetCell(ANIMATION_LIST_NAME_COL, a)));
						ae.ikSampleInterval = gd.GetCell(ANIMATION_LIST_IKFREQ_COL, a);
						ae.startFrame = (LONG)gd.GetCell(ANIMATION_LIST_START_COL, a);
						ae.endFrame = (LONG)gd.GetCell(ANIMATION_LIST_END_COL, a);
						selAnimList.push_back(ae);
					}
				}
			}

			if (exportSkeleton)
			{
				param = prop.GetParameters().GetItem( L"targetSkeletonFileName" );
				Ogre::String skeletonFileName = XSItoOgre(XSI::CString(param.GetValue()));
				if (skeletonFileName.empty())
				{
					OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, 
						"You must supply a skeleton file name", 
						"OGRE Exporter");
				}

				// fix any omission of '.skeleton'
				if (!Ogre::StringUtil::endsWith(skeletonFileName, ".skeleton"))
				{
					skeletonFileName += ".skeleton";
				}

				// Truncate the skeleton filename to just the name (no path)
				Ogre::String skelName = skeletonFileName;
				int pos = skeletonFileName.find_last_of("\\");
				if (pos == Ogre::String::npos)
				{
					pos = skeletonFileName.find_last_of("/");
				}
				if (pos != Ogre::String::npos)
				{
					skelName = skelName.substr(pos+1, skelName.size() - pos - 1);
				}


				// Do the mesh
				Ogre::DeformerMap& deformers = 
					meshExporter.buildMeshForExport(mergeSubmeshes, 
						exportChildren, edgeLists, tangents, tangentSemantic, 
						tangentsSplitMirrored, tangentsSplitRotated, tangentsUseParity,
						exportVertexAnimation, selAnimList, fps, materialPrefix,
						lodData, skelName);
				// do the skeleton
				const Ogre::AxisAlignedBox& skelAABB = 
					skelExporter.exportSkeleton(skeletonFileName, deformers, fps, selAnimList);

				// Do final mesh export
				meshExporter.exportMesh(meshFileName, skelAABB);
			}
			else
			{
				Ogre::AxisAlignedBox nullbb;
				// No skeleton
				meshExporter.buildMeshForExport(mergeSubmeshes, 
					exportChildren, edgeLists, tangents, tangentSemantic, 
					tangentsSplitMirrored, tangentsSplitRotated, tangentsUseParity,
					exportVertexAnimation, selAnimList, fps, materialPrefix, lodData);
				meshExporter.exportMesh(meshFileName, nullbb);
			}

			
			delete lodData;

			// Do we want to export materials too?
			if (exportMaterials)
			{
				param = prop.GetParameters().GetItem( L"targetMaterialFileName" );
				Ogre::String materialFileName = XSItoOgre(XSI::CString(param.GetValue()));
				// fix any omission of '.material'
				if (!Ogre::StringUtil::endsWith(materialFileName, ".material"))
				{
					materialFileName += ".material";
				}
				
				Ogre::XsiMaterialExporter matExporter;
				try 
				{
					matExporter.exportMaterials(meshExporter.getMaterials(), 
						meshExporter.getTextureProjectionMap(), 
						materialFileName, copyTextures);
				}
				catch (Ogre::Exception& e)
				{
					// ignore, non-fatal and will be in log
				}
			}

		}

	}
	catch (Ogre::Exception& e)
	{
		// Will already have been logged to the Ogre log manager
		// Tell XSI
		app.LogMessage(OgretoXSI(e.getDescription()), XSI::siFatalMsg);
		app.LogMessage(OgretoXSI(e.getFullDescription()), XSI::siInfoMsg);
	}

	//DeleteObj( L"OgreMeshExportOptions" );
	return st;	
}