//----------------------------------------------------------------------------
SceneBuilder::SceneBuilder (const TCHAR *filename, BOOL exportSelected, 
							ExportSettings *settings, ExpInterface *ept,
							Interface *max, INode *exportNode)
{
	float time = (float)PX2::Time::GetTimeInSeconds();

	const size_t size = _tcslen(filename)+1;
	mFileName = new1<TCHAR>((int)size);
	_tcscpy_s(mFileName, size, filename);

	mExportSelected = exportSelected;
	mSettings = settings;
	mExport = ept;
	mMax = max;
	mExportMaxNode = exportNode;
	mTicksPerFrame = GetTicksPerFrame();

	if (mSettings->IncludeCurrentFrame)
	{
		mTimeStart = mMax->GetAnimRange().Start();
		mTimeEnd = mTimeStart;
	}
	else
	{
		mTimeStart = mSettings->StartFrame * GetTicksPerFrame();
		mTimeEnd = mSettings->EndFrame * GetTicksPerFrame();

		if (mSettings->UseLocalTime)
		{
			mTimeOffset = mTimeStart;
		}
		else
		{
			mTimeOffset = 0;
		}
	}

	// 遍历场景3次。第1次处理materials,第2次遍历节点继承关系,第3次应用 modifiers

	mScene = new0 PX2::Node();
	mScene->SetName("RootNode");

	// 1
	CollectMaterials(mExportMaxNode);
	ConvertMaterials();

	// 2
	if (!mExportSelected)
	{
		// entire scene

		if (mSettings->IncludeLights)
		{
			BuildAmbientLight();
		}

		int numChildren = mExportMaxNode->NumberOfChildren();
		for (int i=0; i<numChildren; i++)
		{
			Traverse(mExportMaxNode->GetChildNode(i), mScene);
		}
	}
	else
	{
		// selection only

		Traverse(mExportMaxNode, mScene);
	}
	
	mScene->Update(0.0f);

	// 3
	if (mSettings->IncludeModifiers)
	{
		ApplyModifiers();
	}

	PX2::OutStream stream;

	if (mExportSelected)
	{
		stream.Insert(mScene->GetChild(0));
	}
	else
	{
		stream.Insert(mScene);
	}

	stream.Save(filename);

	mScene = 0;
}
BOOL CMeshConverter::Convert(CGraphicsObject** ppcGraphicsObject, CMeshObject** ppcMeshObject, CMesh* pcMesh, CArrayIntAndPointer* pcConnectionAndIndex)
{
	//This assumes mpcMesh is already touched

	mpcMesh = pcMesh;
	mpcConnectionsAndIndices = pcConnectionAndIndex;
	mpcGraphicsObject = NULL;
	mpcMeshObject = NULL;

	if (mpcSceneConverter->GetMapper()->GetMesh(pcMesh->GetOI(), ppcGraphicsObject, ppcMeshObject))
	{
		return TRUE;
	}

	//Get the Position array, also make sure it has one.
	if (pcMesh->TestNumPositions() == 0)
	{
		CChars	sz;

		sz.Init("The Mesh [");
		sz.Append(pcMesh->GetName());
		sz.Append("] has no vertex position channel");
		gcUserError.Set(sz.Text());
		sz.Kill();
		return FALSE;
	}

	maiMatrixIndices.Init(256);

	//Create the graphics object for the conversion destination.
	mpcGraphicsObject = mpcSceneConverter->GetWorld()->CreateGraphicsObject(FALSE);
	mpcMeshObject = mpcSceneConverter->GetWorld()->CreateMeshObject();

	FillUniqueMatricies();

	if (!ConvertMaterials())
	{
		return FALSE;
	}

	if (!ConvertMesh())
	{
		return FALSE;
	}

	if (!CreateLinkNodes())
	{
		return FALSE;
	}

	if (!SetObjectMatricies())
	{
		return FALSE;
	}

	maiMatrixIndices.Kill();

	//Optimise the vertex and index buffers in the graphics object according to current hardware.
	OptimiseGraphicsObject();

	mpcSceneConverter->GetMapper()->AddGraphicsObject(pcMesh->GetOI(), mpcGraphicsObject, mpcMeshObject);

	SafeAssign(ppcGraphicsObject, mpcGraphicsObject);
	SafeAssign(ppcMeshObject, mpcMeshObject);
	return TRUE;
}