Beispiel #1
0
/**
*  @brief
*    Returns the position, rotation and scale of the scene node at a given time
*/
void PLSceneNode::GetPosRotScale(Point3 &vPos, Quat &qRot, Point3 &vScale, TimeValue nTime)
{
	if (m_pIGameNode) {
		// Get the position, rotation and scale - relative to the parent node
		GMatrix mParentMatrix;
		IGameNode *pIGameNodeParent = m_pIGameNode->GetNodeParent();
		if (pIGameNodeParent)
			mParentMatrix = pIGameNodeParent->GetWorldTM(nTime);
		PLTools::GetPosRotScale(m_pIGameNode->GetWorldTM(nTime)*PLTools::Inverse(mParentMatrix), vPos, qRot, vScale, IsRotationFlipped());

		// Get the scale (NOT done for special nodes!)
		if (m_nType != TypeContainer && m_nType != TypeScene && m_nType != TypeCell &&
			m_nType != TypeCamera && m_nType != TypeLight) {
			// [TODO] Do we still need this hint?
			// Check for none uniform scale
//			if (m_vScale.x != m_vScale.y || m_vScale.x != m_vScale.z || m_vScale.y != m_vScale.z) {
				// We have to use '%e' because else we may get output like '(1 1 1) is no uniform scale'
				// g_pLog->LogFLine(PLLog::Hint, "Node '%s' has a none uniform scale. (%e %e %e) This 'may' cause problems in special situations...", m_sName.c_str(), m_vScale.x, m_vScale.y, m_vScale.z);
//			}
		} else {
			// Set scale to 1
			vScale.Set(1.0f, 1.0f, 1.0f);
		}
	}
}
void CModelExporter::Export(const char* pszFileName)
{
    m_serializer.Reset();
    size_t uTotalRootNodeCnt = m_pIGameScene->GetTopLevelNodeCount();
    std::vector<IGameNode*> meshNodeVector;
    for(size_t x = 0; x < uTotalRootNodeCnt; x++)
    {
        IGameNode* pNode = m_pIGameScene->GetTopLevelNode(x);
        IGameObject* pObject = pNode->GetIGameObject();

        IGameObject::ObjectTypes gameType = pObject->GetIGameType();

        if(gameType == IGameObject::IGAME_MESH)
        {
            meshNodeVector.push_back(pNode);
        }
    }

    int uMeshNodeCount = meshNodeVector.size();
    m_serializer << uMeshNodeCount;

    for(auto pNode : meshNodeVector)
    {
        ExportMesh(pNode);
    }

    m_serializer.Deserialize(pszFileName);
}
void Unreal3DExport::WriteTracking()
{
    Tab<Point3> Loc;
    Tab<Quat> Quat;
    Tab<Point3> Euler;

    Loc.SetCount(FrameCount);
    Quat.SetCount(FrameCount);
    Euler.SetCount(FrameCount);

    for( int n=0; n<TrackedNodes.Count(); ++n )
    {
        IGameNode* node = TrackedNodes[n];

        for( int t=0; t<FrameCount; ++t )
        {            
            // Progress
            CheckCancel();
            
            // Set frame
            int curframe = FrameStart + t;
            pScene->SetStaticFrame(curframe);

            // Write tracking
            GMatrix objTM = node->GetWorldTM();
            Loc[t] = objTM.Translation();
            Quat[t] = objTM.Rotation();

            float eu[3];
            QuatToEuler(Quat[t],eu);
            Euler[t]=Point3(eu[0],eu[1],eu[2]);
            Euler[t] *= 180.0f/pi;

            eu[1] *= -1;
            EulerToQuat(eu,Quat[t],EULERTYPE_YXZ);
        }
        
        for( int t=0; t<FrameCount; ++t )
        {    
            _ftprintf( fLog, _T("%sLoc[%d]=(X=%f,Y=%f,Z=%f)\n"), node->GetName(), t, Loc[t].x, Loc[t].y, Loc[t].z );
        }
        
        for( int t=0; t<FrameCount; ++t )
        {    
            _ftprintf( fLog, _T("%sQuat[%d]=(W=%f,X=%f,Y=%f,Z=%f)\n"), node->GetName(), t, Quat[t].w, Quat[t].x, Quat[t].y, Quat[t].z ); 
        }
        
        for( int t=0; t<FrameCount; ++t )
        {    
            _ftprintf( fLog, _T("%sEuler[%d]=(X=%f,Y=%f,Z=%f)\n"), node->GetName(), t, Euler[t].x, Euler[t].y, Euler[t].z ); 
        }
    }
}
Beispiel #4
0
ExporterF3D::EExportError ExporterF3D::CreateModel()
{
    m_scene = new CSceneData();

    s32 nodeCount = m_iGameScene->GetTopLevelNodeCount();
    LOG_INFO("In Game Scene found [%d] Nodes", nodeCount);

    if (nodeCount == 0)
    {
        return eSceneEmptyError;
    }

    s32 id = 0;
    m_scene->setId(id);
    m_scene->setName("");
    LOG_INFO("Game Scene Name %s, id %d", TCHARToString(m_iGameScene->GetSceneFileName()).c_str(), id);

    for (u32 objectIndex = 0; objectIndex < nodeCount; ++objectIndex)
    {
        IGameNode* gameNode = m_iGameScene->GetTopLevelNode(objectIndex);
        LOG_INFO("Processing Parent object [%d/%d:%s] ", objectIndex + 1, nodeCount, TCHARToString(gameNode->GetName()).c_str());

        EExportError error = ExportNode(gameNode, objectIndex);
        if (error != eNoError)
        {
            return error;
        }
    }

    return eNoError;
}
Beispiel #5
0
void MeshExporter::ExtractSkeleton(IGameNode * node)
{
	if(!node->IsGroupOwner())
		_dumpJoint(node);

	for(int i=0;i<node->GetChildCount();i++)
	{
		IGameNode * child = node->GetNodeChild(i);
		// we deal with targets in the light/camera section
		if(child->IsTarget())
			continue;

		ExtractSkeleton(child);
	}

	node->ReleaseIGameObject();
}
Beispiel #6
0
int TrianExporter::DoExport( const TCHAR * name, ExpInterface *ei, Interface *i, BOOL suppressPrompts, DWORD options )
{
	//Open the file to export to.
	m_of.open( name );

	//Create an Error procedure.
	MyErrorProc pErrorProc;
	SetErrorCallBack( &pErrorProc );

	//Get the game interface
	m_pIGame = GetIGameInterface();

	//Start the progress bar.
	i->ProgressStart( _T( "Exporting to .trian file..." ), TRUE, fn, NULL );

	//Set up the conversion manager.
	IGameConversionManager * cm = GetConversionManager();
	
	//Set up the whacky coordinate system that 3DS Max uses.
	UserCoord whacky = 
	{
		1, //Right-Handed.
		1, //X Axis goes right.
		4, //Y Axis goes in.
		3, //Z Axis goes down.
		0, //U Tex Axis is left.
		1  //V Tex Axis is down.
	};
	cm->SetUserCoordSystem( whacky );

	//Set the coordinate system.
	cm->SetCoordSystem( IGameConversionManager::IGAME_MAX );
	
	//Initialize the game scene.
	m_pIGame->InitialiseIGame( options & SCENE_EXPORT_SELECTED );

	//Go through all the nodes of the scene and export only the Game Meshes.
	for( int l = 0; l < m_pIGame->GetTopLevelNodeCount(); l++ )
	{
		//Get the current Game node.
		IGameNode * node = m_pIGame->GetTopLevelNode( l );

		//Check for selected state.
		if( node->IsTarget() )
			continue;

		ExportNodeInfo( node );
	}

	//End the progress bar.
	i->ProgressEnd();

	//Release the scene.
	m_pIGame->ReleaseIGame();
	m_pIGame = 0;

	//Close the output stream.
	m_of.close();

	return TRUE;
}
	bool MeshXMLExporter::Export(OutputMap& output) 
	{

		try {

			// write XML to a strstream
			std::stringstream of;

			while (!m_submeshNames.empty())
				m_submeshNames.pop();

			if (m_pGame) {
				m_pGame->ReleaseIGame();
				m_pGame = 0;
			}

			m_ei->theScene->EnumTree(this);

			m_pGame = GetIGameInterface();
			IGameConversionManager* cm = GetConversionManager();
			cm->SetCoordSystem(IGameConversionManager::IGAME_OGL);
			m_pGame->InitialiseIGame(m_nodeTab, false);
			m_pGame->SetStaticFrame(0);
			int nodeCount = m_pGame->GetTopLevelNodeCount();

			if (nodeCount == 0) {
				MessageBox(GetActiveWindow(), "No nodes available to export, aborting...", "Nothing To Export", MB_ICONINFORMATION);
				m_pGame->ReleaseIGame();
				return false;
			}

			// if we are writing everything to one file, use the name provided when the user first started the export;
			// otherwise, create filenames on the basis of the node (submesh) names
			std::string fileName;
			IGameNode* node = m_pGame->GetTopLevelNode(0);
			if (!m_config.getExportMultipleFiles())
				fileName = m_config.getExportFilename();
			else {
				fileName = m_config.getExportPath() + "\\";
				fileName += node->GetName();
				fileName += ".mesh.xml";
			}

			// write start of XML data
			streamFileHeader(of);

			int nodeIdx = 0;
			std::map<std::string, std::string> materialScripts;

			while (nodeIdx < nodeCount) {

				std::string mtlName;
				IGameNode* node = m_pGame->GetTopLevelNode(nodeIdx);
				IGameObject* obj = node->GetIGameObject();

				// InitializeData() is important -- it performs all of the WSM/time eval for us; no data without it
				obj->InitializeData();
				
				IGameMaterial* mtl = node->GetNodeMaterial();
				if (mtl == NULL)
					mtlName = m_config.getDefaultMaterialName();
				else
					mtlName = mtl->GetMaterialName();

				// clean out any spaces the user left in their material name
				std::string::size_type pos;
				while ((pos = mtlName.find_first_of(' ')) != std::string::npos)
					mtlName.replace(pos, 1, _T("_"));

				if (materialScripts.find(mtlName) == materialScripts.end()) {

					// export new material script
					MaterialExporter mexp(m_config, m_materialMap);
					std::string script;

					mexp.buildMaterial(mtl, mtlName, script);
					materialScripts[mtlName] = script;
				}

				//if (streamSubmesh(of, node, mtlName))
				if (streamSubmesh(of, obj, mtlName))
					m_submeshNames.push(std::string(node->GetName()));

				node->ReleaseIGameObject();
				nodeIdx++;

				if (m_config.getExportMultipleFiles() || nodeIdx == nodeCount) {

					// write end of this file's XML
					streamFileFooter(of);

					// insert new filename --> stream pair into output map
					output[fileName] = std::string(of.str());
					of.str("");

					if (nodeIdx != nodeCount) {
						fileName = m_config.getExportPath() + "\\";
						node = m_pGame->GetTopLevelNode(nodeIdx);
						fileName += node->GetName();
						fileName += ".mesh.xml";

						// start over again with new data
						streamFileHeader(of);
					}
				}
			}

			m_pGame->ReleaseIGame();

			// export materials if we are writing those
			if (m_config.getExportMaterial()) {

				std::ofstream materialFile;
				materialFile.open((m_config.getExportPath() + "\\" + m_config.getMaterialFilename()).c_str(), std::ios::out);

				if (materialFile.is_open()) {
					for (std::map<std::string, std::string>::iterator it = materialScripts.begin();
						it != materialScripts.end(); ++it)
					{
						materialFile << it->second;
					}

					materialFile.close();
				}
			}

			return true;
		}
		catch (...) {
			MessageBox(GetActiveWindow(), "An unexpected error has occurred while trying to export, aborting", "Error", MB_ICONEXCLAMATION);

			if (m_pGame)
				m_pGame->ReleaseIGame();

			return false;
		}
	}
/**
*  @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;
}
void Unreal3DExport::GetTris()
{
    
    // Export triangle data
    FJSMeshTri nulltri = FJSMeshTri();
    for( int n=0; n<Nodes.Count(); ++n )
    {
        CheckCancel();
        
        IGameNode* node = Nodes[n];
        IGameMesh* mesh = static_cast<IGameMesh*>(node->GetIGameObject());
        if( mesh->InitializeData() )
        {
            int vertcount = mesh->GetNumberOfVerts();
            int tricount = mesh->GetNumberOfFaces();
            if( vertcount > 0 && tricount > 0 )
            {
                // Progress
                ProgressMsg.printf(GetString(IDS_INFO_MESH),n+1,Nodes.Count(),TSTR(node->GetName()));
                pInt->ProgressUpdate(Progress+(static_cast<float>(n)/Nodes.Count()*U3D_PROGRESS_MESH), FALSE, ProgressMsg.data());

                // Alloc triangles space
                Tris.Resize(Tris.Count()+tricount);

                // Append triangles
                for( int i=0; i!=tricount; ++i )
                {
                    FaceEx* f = mesh->GetFace(i);
                    if( f )
                    {
                        FJSMeshTri tri(nulltri);

                        // TODO: add material id listing
                        RegisterMaterial( node, mesh, f, &tri );

                        tri.iVertex[0] = VertsPerFrame + f->vert[0];
                        tri.iVertex[1] = VertsPerFrame + f->vert[1];
                        tri.iVertex[2] = VertsPerFrame + f->vert[2];

                        Point2 p;
                        if( mesh->GetTexVertex(f->texCoord[0],p) ){
                            tri.Tex[0] = FMeshUV(p);
                        }
                        if( mesh->GetTexVertex(f->texCoord[1],p) ){
                            tri.Tex[1] = FMeshUV(p);
                        }
                        if( mesh->GetTexVertex(f->texCoord[2],p) ){
                            tri.Tex[2] = FMeshUV(p);
                        }
                        
                        Tris.Append(1,&tri);                       
                    }
                }

                VertsPerFrame += vertcount;
            }
            else
            {
                // remove invalid node
                Nodes.Delete(n--,1);
            }
        }
        node->ReleaseIGameObject();
    }
    Progress += U3D_PROGRESS_MESH;
}
Beispiel #10
0
void MeshExporter::ExtractMesh(IGameNode * node)
{
	IGameObject* obj = node->GetIGameObject();

	// export option
	bool expColor = ExportConfig::Instance()->IsExportColor();
	bool expNormal = ExportConfig::Instance()->IsExportNormal();
	bool expTexcoord = ExportConfig::Instance()->IsExportTexcoord();
	bool expLightmapUV = ExportConfig::Instance()->IsExportLightmapUV();

	obj->InitializeData();

	const char * nodeName = node->GetName();

	IGameNode * parent = node->GetNodeParent();
	IGameMesh::ObjectTypes type = obj->GetIGameType();

	if (type == IGameMesh::IGAME_MESH)
	{
		IGameMesh* mesh = (IGameMesh*) obj;
		Tab<int> texMaps = mesh->GetActiveMapChannelNum();

		mMeshData.VertexElems |= MeshSerializer::VE_POSITION;

		// position
		for (int i = 0; i < mesh->GetNumberOfVerts(); ++i)
			mMeshData.P.PushBack(Utility::ToFloat3(mesh->GetVertex(i)));

		// vertex color
		for (int i = 0; expColor && i < mesh->GetNumberOfColorVerts(); ++i)
		{
			Point3 c = mesh->GetColorVertex(i);
			float a = mesh->GetAlphaVertex(i);

			mMeshData.C.PushBack(Float4(c.x, c.y, c.z, a));
			mMeshData.VertexElems |= MeshSerializer::VE_COLOR;
		}

		// normal
		for (int i = 0; expNormal && i < mesh->GetNumberOfNormals(); ++i)
		{
			mMeshData.N.PushBack(Utility::ToFloat3(mesh->GetNormal(i)));
			mMeshData.VertexElems |= MeshSerializer::VE_NORMAL;
		}

		// uv
		for (int i = 0;  expTexcoord && texMaps.Count() > 1 && i < mesh->GetNumberOfMapVerts(texMaps[1]); ++i)
		{
			Point3 tv = mesh->GetMapVertex(texMaps[1], i);

			mMeshData.UV.PushBack(Float2(tv.x, 1 - tv.y));
			mMeshData.VertexElems |= MeshSerializer::VE_TEXCOORD;
		}

		// light map uv
		for (int i = 0;  expLightmapUV && texMaps.Count() > 2 && i < mesh->GetNumberOfMapVerts(texMaps[2]); ++i)
		{
			Point3 tv = mesh->GetMapVertex(texMaps[2], i);

			mMeshData.LUV.PushBack(Float2(tv.x, 1 - tv.y));
			mMeshData.VertexElems |= MeshSerializer::VE_LIGHTMAPUV;
		}

		IGameSkin * skin = obj->GetIGameSkin();
		if (skin != NULL)
			_dumpSkinInfo(skin);
		else if (parent != NULL && parent->GetIGameObject()->GetIGameType() == IGameMesh::IGAME_BONE)
			_genSkinInfo(parent);

		_dumpMeshBuffer(mesh);

		mMeshData.Clear();
	}

	for(int i=0;i<node->GetChildCount();i++)
	{
		IGameNode * child = node->GetNodeChild(i);
		// we deal with targets in the light/camera section
		if(child->IsTarget())
			continue;

		ExtractMesh(child);
	}

	node->ReleaseIGameObject();
}
Beispiel #11
0
void MeshExporter::Export()
{
	mRoot = new Root;
	mResourceManager = new ResourceManager;
	mRenderSystem = new NullRenderSystem;
	mWorld = new World;

	try 
	{
		IGameConversionManager* cm = GetConversionManager();
		cm->SetCoordSystem(IGameConversionManager::IGAME_D3D);
		mGameScene->InitialiseIGame(ExportConfig::Instance()->IsExportSelected());
		mGameScene->SetStaticFrame(0);

		int nodeCount = mGameScene->GetTopLevelNodeCount();
		if (nodeCount == 0)
		{
			MessageBox(GetActiveWindow(), "No nodes available!", "Error", MB_OK);
			goto __end;
		}

		mMeshSource = MeshManager::Instance()->NewMesh("MaxExporter");

		// extract skeleton
		for (int i = 0; i < nodeCount; ++i)
		{
			IGameNode* node = mGameScene->GetTopLevelNode(i);

			if (node->IsNodeHidden())
				continue ;

			ExtractSkeleton(node);
		}

		// extract mesh
		mMeshData.Clear();

		for (int i = 0; i < nodeCount; ++i)
		{
			IGameNode* node = mGameScene->GetTopLevelNode(i);

			if (node->IsNodeHidden())
				continue ;

			ExtractMesh(node);
		}

		if (mMMPairs.Size() == 0)
		{
			MessageBox(GetActiveWindow(), "No Objects!", "Error", MB_OK);
			goto __end;
		}

		BuildMesh();

		// save mesh
		MeshSerializer::Save(mMeshSource.c_ptr(), ExportConfig::Instance()->GetExportFilename());

		MessageBox(GetActiveWindow(), "Export OK!", "Info", MB_ICONINFORMATION);
	}
	catch (...) 
	{
		MessageBox(GetActiveWindow(), "Error!", "Error", MB_ICONEXCLAMATION);
	}

__end:
	mMeshSource = NULL;

	delete mWorld;
	delete mRenderSystem;
	delete mResourceManager;
	delete mRoot;
}
int	MaxExporter::DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options)
{

	/*if(!suppressPrompts)
		DialogBoxParam(hInstance, 
				MAKEINTRESOURCE(IDD_PANEL), 
				GetActiveWindow(), 
				MaxExporterOptionsDlgProc, (LPARAM)this);*/

	#pragma message(TODO("return TRUE If the file is exported properly"))

	Node::s_nextID = 1;
	ofstream myFile;
	myFile.open("DebugExporter.txt");
	wstring wFileName( name );
	string fileName( wFileName.begin(), wFileName.end() );
	//f= fopen( fileName.c_str(),"wb");
	BinaryFile = loadSave( fileName.c_str() );
	//BinaryFile.saveInt( 5 );
	//BinaryFile.close();
	myFile << "Start Export\n";

	IGameScene* gameScene = GetIGameInterface();
	gameScene->InitialiseIGame();
	int nodeCount = gameScene->GetTopLevelNodeCount();
	myFile << "Number of top level nodes: " << nodeCount << "\n";
	//get all of the materials
	for( int nodeNumber = 0; nodeNumber < nodeCount; ++nodeNumber)
	{
		IGameNode* gameNode = gameScene->GetTopLevelNode( nodeNumber );
		
		Node* myNode = new Node( gameNode );
		m_NodeList.push_back( myNode );
		findFaces( myNode, myFile );
		
	}

	myFile << "Number of materials\n";
	myFile << m_materialSet.size() << "\n";
	

	int totalBatches = 0;
	//myFile<< "Number of triangleBatchMaps: " << m_triangleBatchesPerNode.size() << "\n";
	for( auto nodeIter = m_NodeList.begin(); nodeIter != m_NodeList.end(); ++nodeIter )
	{
		std::map< IGameMaterial*, TriangleBatch* > triangleBatches = (*nodeIter)->m_triangleBatchesPerMaterial;
		myFile << "Invidiual triangleBatch size: " << triangleBatches.size() << "\n";

		for( auto materialIter = m_materialSet.begin(); materialIter != m_materialSet.end(); ++materialIter )
		{
			auto found = triangleBatches.find( * materialIter );
			if( found != triangleBatches.end() )
			{
				++totalBatches;
			}
		}
	}

	BinaryFile.saveInt( m_NodeList.size() );
	myFile << "Number of Nodes: " << m_NodeList.size() << "\n";
	
	for( auto nodeIter = m_NodeList.begin(); nodeIter != m_NodeList.end(); ++nodeIter )
	{
		std::map< IGameMaterial*, TriangleBatch* > triangleBatches = (*nodeIter)->m_triangleBatchesPerMaterial;
		std::map<IGameMaterial*, std::vector< NodeFace > > facesPerMaterial = (*nodeIter)->m_facesPerMaterial;
		IGameNode* currentNode = (*nodeIter)->m_gameNode;
		IGameNode* parentNode;
		GMatrix parentWTM;
		GMatrix toParentMatrix;
		GMatrix worldTM;
		GMatrix localTM;
		int time = gameScene->GetSceneStartTime();
		for( ; time < gameScene->GetSceneEndTime(); time += 4800/30 )
		{
			if( (*nodeIter)->m_parentID != 0 )
			{
				myFile << "Trying to find parent... \n";
				parentNode = (*nodeIter)->m_parent->m_gameNode;
				if( parentNode != nullptr )
				{
					myFile << "Parent found \n";
					parentWTM = parentNode->GetWorldTM( time );
					toParentMatrix = parentWTM.Inverse();

					worldTM = currentNode->GetWorldTM(  time ) * toParentMatrix;

				}

			}
			else
			{
				worldTM = currentNode->GetWorldTM( time );
				
			}
			(*nodeIter)->m_toParentMatrix.push_back( Matrix4x4( worldTM[0], worldTM[1], worldTM[2], worldTM[3] ) );
		}


		localTM = currentNode->GetWorldTM().Inverse();
		(*nodeIter)->m_worldToLocal = Matrix4x4(  localTM[0], localTM[1], localTM[2], localTM[3] );
		

		//Save the node
		BinaryFile.saveNode( *nodeIter, myFile );
		BinaryFile.saveInt( (*nodeIter)->m_triangleBatchesPerMaterial.size() );
	
		for( auto materialIter = m_materialSet.begin(); materialIter != m_materialSet.end(); ++materialIter )
		{
			//Set the current material's VBO and IBO
			//
			IGameMaterial* currentMaterial = *materialIter;
			TriangleBatch* currentBatch = triangleBatches[ currentMaterial ];
			
			GMatrix localTMNoTrans = localTM;
			localTMNoTrans.SetRow( 3, Point4( 0,0,0,1) );
			if( currentBatch != nullptr )
			{
				
				MaxMaterial* currentMaxMaterial = currentBatch->m_material;
				VBO* currentVBO = currentBatch->m_vbo;
				IBO* currentIBO = currentBatch->m_ibo;
				vector< NodeFace >& faceVector = facesPerMaterial.find( currentMaterial )->second;

				//Get texture materials and export them
				//
				if( currentMaterial != nullptr )
				{
					int numOfTexMaps = currentMaterial->GetNumberOfTextureMaps();
					myFile << "Number of texture maps: " << numOfTexMaps << "\n";
					for( int i = 0; i < numOfTexMaps; ++i )
					{
						IGameTextureMap* gameTextureMap = currentMaterial->GetIGameTextureMap( i );
						
						if( gameTextureMap != nullptr && gameTextureMap->IsEntitySupported() )
						{
							int stdMapSlot = gameTextureMap->GetStdMapSlot();
							if( stdMapSlot == ID_DI )
							{
								wstring wBitmapFileName;
								wBitmapFileName = gameTextureMap->GetBitmapFileName();
								if( wBitmapFileName.size() > 0 )
								{
									BitmapInfo bi( gameTextureMap->GetBitmapFileName() );
									BMMGetFullFilename( &bi );
									wBitmapFileName = bi.Name();
									std::string fullBitmapFileName( wBitmapFileName.begin(), wBitmapFileName.end() );
									if( fullBitmapFileName.size() > 0 )
									{
										int lastSlash = fullBitmapFileName.find_last_of('\\') + 1;
										if( lastSlash != string::npos )
										{
											const std::string bitmapFileName = fullBitmapFileName.substr( lastSlash );
											wstring nameAsWString( name );
											std::string nameAsString( nameAsWString.begin(), nameAsWString.end() );
											const std::string extension = nameAsString.substr( 0, nameAsString.find_last_of('\\') + 1 );
											std::string newFileName = extension;
											newFileName.append( bitmapFileName );
											wstring wNewFileName(newFileName.begin(), newFileName.end());
											if( CopyFile( wBitmapFileName.c_str(), wNewFileName.c_str(), false ) )
											{
												if( stdMapSlot == ID_DI )
												{
													currentMaxMaterial->m_diffuseTexture = bitmapFileName;
													currentMaxMaterial->bHasDiffuseTexture = true;
												}
											//BinaryFile.saveString( bitmapFileName );
											}
											else
											{
												myFile << GetLastError() << "\n";
												myFile << "copying the file FAILED.\n";
											}
										}
									}	
								}
							}
						}
					}
				}
				
				myFile<< "Number of faces for this material: " << faceVector.size() << "\n";
				for( int face = 0; face < faceVector.size(); ++face )
				{
					FaceEx* meshFace = faceVector[face].m_face;
					IGameMesh* gameMesh = faceVector[face].m_mesh;
					IGameSkin* gameSkin = gameMesh->GetIGameSkin();
					int position, normal, color, texCoordinate, maxPosition;
					for( int i = 0; i < 3; ++i)
					{
						
						maxPosition = (int)meshFace->vert[i];
						
						Point3 tempPos = gameMesh->GetVertex( maxPosition );
						tempPos = tempPos * localTM;
						Vector3D positionVec3( tempPos.x, tempPos.y, tempPos.z );
						position = currentVBO->insertPosition(positionVec3);

						normal = (int)meshFace->norm[i];
						Point3 tempNormal = gameMesh->GetNormal( normal );
						tempNormal = tempNormal * localTMNoTrans;
						tempNormal = tempNormal.Normalize();
						
						Vector3D normalVec3( tempNormal.x, tempNormal.y, tempNormal.z );
						normal = currentVBO->insertNormal(normalVec3);

						//IBO
						texCoordinate = (int)meshFace->texCoord[i];
						Point2 tempTexCoord = gameMesh->GetTexVertex( texCoordinate );
						Vector2 texCoordVec2( tempTexCoord.x, tempTexCoord.y );
						texCoordinate = currentVBO->insertTexCoord(texCoordVec2);
						VertexIndex VI( position, normal, texCoordinate );
						if( gameSkin != nullptr )
						{
							int numberOfBones = gameSkin->GetNumberOfBones( maxPosition );
							for( int boneIndex = 0; boneIndex < numberOfBones; ++boneIndex )
							{
								float boneWeight = gameSkin->GetWeight( maxPosition, boneIndex );
								IGameNode* bone = gameSkin->GetIGameBone( maxPosition, boneIndex );
								myFile << "Bone node ID: " << bone->GetNodeID() << "\n";
								int nodeIDForBone = m_boneIDToNodeID[ bone->GetNodeID() ];
								myFile << "Node ID: " << nodeIDForBone << "\n";
								VI.addBoneWeight( nodeIDForBone, boneWeight );

								/*for( auto boneIter = m_NodeList.begin(); boneIter != m_NodeList.end(); ++boneIter )
								{
									if( (*boneIter)->m_gameNode == bone )
									{
										myFile << "Found the bone!\n"; 
										
									}
								}*/
								
							}
							VI.topBoneWeights();
						}

						int vertIndex = currentVBO->insertVertex( VI );
						currentIBO->addIndex( vertIndex );

					}

				}
				
				BinaryFile.saveTriangleMesh( currentBatch, myFile );
			}
		}

	}
	myFile.close();

	for( int nodeNumber = 0; nodeNumber < nodeCount; ++nodeNumber)
	{
		IGameNode* gameNode = gameScene->GetTopLevelNode( nodeNumber );
		if( gameNode != nullptr )
		{
			tearDown( gameNode );
		}
		
	}

	BinaryFile.close();
	return TRUE;

	//return FALSE;
}