2
0
Эх сурвалжийг харах

Fixed entity scene importing in polyimport, added material file generation and material override options to entity scene import, added proper options to 3d asset import dialog in the IDE, entity files now store rotations in quaternions

Ivan Safrin 11 жил өмнө
parent
commit
42004fd032

+ 1 - 1
Core/Contents/Include/PolySceneEntityInstance.h

@@ -55,7 +55,7 @@ class SceneEntityInstance : public Entity {
 		void clearInstance();
 		void clearInstance();
 
 
 		void parseObjectIntoCurve(ObjectEntry *entry, BezierCurve *curve);
 		void parseObjectIntoCurve(ObjectEntry *entry, BezierCurve *curve);
-		Entity *loadObjectEntryIntoEntity(ObjectEntry *entry, Entity *targetEntity = NULL);
+		Entity *loadObjectEntryIntoEntity(ObjectEntry *entry, Entity *targetEntity = NULL, int entityFileVersion = 1);
 		bool loadFromFile(const String& fileName);
 		bool loadFromFile(const String& fileName);
         void applySceneMesh(ObjectEntry *entry, SceneMesh *sceneMesh);
         void applySceneMesh(ObjectEntry *entry, SceneMesh *sceneMesh);
 		
 		

+ 16 - 4
Core/Contents/Source/PolySceneEntityInstance.cpp

@@ -262,7 +262,7 @@ void SceneEntityInstance::parseObjectIntoCurve(ObjectEntry *entry, BezierCurve *
 	
 	
 }
 }
 
 
-Entity *SceneEntityInstance::loadObjectEntryIntoEntity(ObjectEntry *entry, Entity *targetEntity) {
+Entity *SceneEntityInstance::loadObjectEntryIntoEntity(ObjectEntry *entry, Entity *targetEntity, int entityFileVersion) {
 
 
 	Entity *entity = NULL;
 	Entity *entity = NULL;
 
 
@@ -456,7 +456,12 @@ Entity *SceneEntityInstance::loadObjectEntryIntoEntity(ObjectEntry *entry, Entit
 
 
         entity->setScale((*entry)["sX"]->NumberVal, (*entry)["sY"]->NumberVal, (*entry)["sZ"]->NumberVal);
         entity->setScale((*entry)["sX"]->NumberVal, (*entry)["sY"]->NumberVal, (*entry)["sZ"]->NumberVal);
         entity->setPosition((*entry)["pX"]->NumberVal, (*entry)["pY"]->NumberVal, (*entry)["pZ"]->NumberVal);
         entity->setPosition((*entry)["pX"]->NumberVal, (*entry)["pY"]->NumberVal, (*entry)["pZ"]->NumberVal);
-        entity->setRotationEuler(Vector3((*entry)["rX"]->NumberVal, (*entry)["rY"]->NumberVal, (*entry)["rZ"]->NumberVal));
+        
+        if(entityFileVersion > 1) {
+            entity->setRotationQuat((*entry)["rW"]->NumberVal, (*entry)["rX"]->NumberVal, (*entry)["rY"]->NumberVal, (*entry)["rZ"]->NumberVal);
+        } else {
+            entity->setRotationEuler(Vector3((*entry)["rX"]->NumberVal, (*entry)["rY"]->NumberVal, (*entry)["rZ"]->NumberVal));
+        }
 	}
 	}
 	
 	
 	if((*entry)["id"]->stringVal != "") {
 	if((*entry)["id"]->stringVal != "") {
@@ -487,7 +492,7 @@ Entity *SceneEntityInstance::loadObjectEntryIntoEntity(ObjectEntry *entry, Entit
 	if(children) {
 	if(children) {
 		for(int i=0; i < children->length; i++) {
 		for(int i=0; i < children->length; i++) {
 			ObjectEntry *childEntry = ((*children))[i];
 			ObjectEntry *childEntry = ((*children))[i];
-			ScreenEntity *childEntity = loadObjectEntryIntoEntity(childEntry);
+			ScreenEntity *childEntity = loadObjectEntryIntoEntity(childEntry, NULL, entityFileVersion);
 			entity->addChild(childEntity);				
 			entity->addChild(childEntity);				
 		}
 		}
 	}
 	}
@@ -529,6 +534,13 @@ bool SceneEntityInstance::loadFromFile(const String& fileName) {
         }
         }
 	}
 	}
     
     
+    int entityFileVersion = 1;
+    
+    ObjectEntry *versionObject = loadObject.root["version"];
+    if(versionObject) {
+        entityFileVersion = versionObject->intVal;
+    }
+    
 	ObjectEntry *settings = loadObject.root["settings"];
 	ObjectEntry *settings = loadObject.root["settings"];
     if(settings) {
     if(settings) {
         ObjectEntry *matFiles = (*settings)["matFiles"];
         ObjectEntry *matFiles = (*settings)["matFiles"];
@@ -552,7 +564,7 @@ bool SceneEntityInstance::loadFromFile(const String& fileName) {
     
     
 	ObjectEntry *root = loadObject.root["root"];
 	ObjectEntry *root = loadObject.root["root"];
 	if(root) {
 	if(root) {
-		loadObjectEntryIntoEntity(root, this);
+		loadObjectEntryIntoEntity(root, this, entityFileVersion);
 	}
 	}
 	
 	
 	return true;
 	return true;

+ 1 - 1
IDE/Contents/Include/PolycodeToolLauncher.h

@@ -53,7 +53,7 @@ class PolycodeToolLauncher {
 		static void openExternalEditor(String app, String file, String inFolder);
 		static void openExternalEditor(String app, String file, String inFolder);
 		static String generateTempPath(PolycodeProject *project);
 		static String generateTempPath(PolycodeProject *project);
 		static void buildProject(PolycodeProject *project, String destinationPath, bool compileScripts);
 		static void buildProject(PolycodeProject *project, String destinationPath, bool compileScripts);
-		static String importAssets(String sourceFile, String inFolder, bool addMeshes, String prefix, bool swapZY, bool generateNormals, bool generateTangents, bool listOnly,bool writeNormals, bool writeTangents, bool writeColors, bool writeBoneWeights, bool writeUVs, bool writeSecondaryUVs, bool exportScene);
+		static String importAssets(String sourceFile, String inFolder, bool addMeshes, String prefix, bool swapZY, bool generateNormals, bool generateTangents, bool listOnly,bool writeNormals, bool writeTangents, bool writeColors, bool writeBoneWeights, bool writeUVs, bool writeSecondaryUVs, bool exportScene, bool generateMaterialFile, bool overrideMaterials, String materialOverrideName, bool specifyBaseAssetPath, String baseAssetPath);
 
 
 		static void runPolyapp(String polyappPath);
 		static void runPolyapp(String polyappPath);
 };
 };

+ 7 - 2
IDE/Contents/Include/ToolWindows.h

@@ -93,7 +93,7 @@ class AssetImporterWindow : public UIWindow {
 		void addFile(String fileName);
 		void addFile(String fileName);
 		void setFilesToImport(String files);
 		void setFilesToImport(String files);
 		
 		
-		void setSourceFileAndTargetFolder(String file, String folder);
+		void setSourceFileAndTargetFolder(String file, String folder, String projectRelativeFolder);
 		void refreshPreview();
 		void refreshPreview();
 			
 			
 		void handleEvent(Event *event);	
 		void handleEvent(Event *event);	
@@ -102,7 +102,8 @@ class AssetImporterWindow : public UIWindow {
 
 
 		String file;
 		String file;
 		String folder;
 		String folder;
-
+		String projectRelativeFolder;
+    
 		UIButton *cancelButton;
 		UIButton *cancelButton;
 		UIButton *okButton;
 		UIButton *okButton;
 		std::vector<UILabel*> fileLabels;
 		std::vector<UILabel*> fileLabels;
@@ -122,6 +123,10 @@ class AssetImporterWindow : public UIWindow {
         UICheckBox *exportSecondaryUVs;
         UICheckBox *exportSecondaryUVs;
         UICheckBox *exportScene;
         UICheckBox *exportScene;
     
     
+        UICheckBox *generateMatFile;
+        UICheckBox *overrideMaterial;
+        UITextInput *overrideMaterialInput;
+    
 		Entity *filesAnchor;
 		Entity *filesAnchor;
 		UIScrollContainer *filesScroller;
 		UIScrollContainer *filesScroller;
 
 

+ 6 - 3
IDE/Contents/Source/PolycodeEntityEditor.cpp

@@ -1859,9 +1859,10 @@ void PolycodeEntityEditor::saveEntityToObjectEntry(Entity *entity, ObjectEntry *
     entry->addChild("sY", entity->getScale().y);
     entry->addChild("sY", entity->getScale().y);
     entry->addChild("sZ", entity->getScale().z);
     entry->addChild("sZ", entity->getScale().z);
         
         
-    entry->addChild("rX", entity->getPitch());
-    entry->addChild("rY", entity->getYaw());
-    entry->addChild("rZ", entity->getRoll());
+    entry->addChild("rX", entity->getRotationQuat().x);
+    entry->addChild("rY", entity->getRotationQuat().y);
+    entry->addChild("rZ", entity->getRotationQuat().z);
+    entry->addChild("rW", entity->getRotationQuat().w);
     
     
     entry->addChild("pX", entity->getPosition().x);
     entry->addChild("pX", entity->getPosition().x);
     entry->addChild("pY", entity->getPosition().y);
     entry->addChild("pY", entity->getPosition().y);
@@ -1980,6 +1981,8 @@ void PolycodeEntityEditor::saveFile() {
     }    
     }    
     
     
     saveObject.root.name = "entity";
     saveObject.root.name = "entity";
+    saveObject.root.addChild("version", 2);
+    
     ObjectEntry *children = saveObject.root.addChild("root");
     ObjectEntry *children = saveObject.root.addChild("root");
     saveEntityToObjectEntry(mainView->getObjectRoot(), children);
     saveEntityToObjectEntry(mainView->getObjectRoot(), children);
     
     

+ 1 - 1
IDE/Contents/Source/PolycodeIDEApp.cpp

@@ -570,7 +570,7 @@ void PolycodeIDEApp::importAssets() {
 			
 			
 	std::vector<String> files = core->openFilePicker(extensions, false);	
 	std::vector<String> files = core->openFilePicker(extensions, false);	
 	if(files.size()) {		
 	if(files.size()) {		
-		frame->assetImporterWindow->setSourceFileAndTargetFolder(files[0], projectManager->activeFolder);
+		frame->assetImporterWindow->setSourceFileAndTargetFolder(files[0], projectManager->activeFolder, projectManager->activeFolder.replace(projectManager->getActiveProject()->getRootFolder(), ""));
 		frame->showModal(frame->assetImporterWindow);
 		frame->showModal(frame->assetImporterWindow);
 		frame->assetImporterWindow->addEventListener(this, UIEvent::OK_EVENT);
 		frame->assetImporterWindow->addEventListener(this, UIEvent::OK_EVENT);
 	}
 	}

+ 11 - 2
IDE/Contents/Source/PolycodeToolLauncher.cpp

@@ -113,7 +113,7 @@ void PolycodeToolLauncher::buildProject(PolycodeProject *project, String destina
 
 
 }
 }
 
 
-String PolycodeToolLauncher::importAssets(String sourceFile, String inFolder, bool addMeshes, String prefix, bool swapZY, bool generateNormals, bool generateTangents, bool listOnly, bool writeNormals, bool writeTangents, bool writeColors, bool writeBoneWeights, bool writeUVs, bool writeSecondaryUVs, bool exportScene) {
+String PolycodeToolLauncher::importAssets(String sourceFile, String inFolder, bool addMeshes, String prefix, bool swapZY, bool generateNormals, bool generateTangents, bool listOnly, bool writeNormals, bool writeTangents, bool writeColors, bool writeBoneWeights, bool writeUVs, bool writeSecondaryUVs, bool exportScene, bool generateMaterialFile, bool overrideMaterials, String materialOverrideName, bool specifyBaseAssetPath, String baseAssetPath) {
 
 
 	String ret;
 	String ret;
 	String polycodeBasePath = CoreServices::getInstance()->getCore()->getDefaultWorkingDirectory();
 	String polycodeBasePath = CoreServices::getInstance()->getCore()->getDefaultWorkingDirectory();
@@ -154,9 +154,18 @@ String PolycodeToolLauncher::importAssets(String sourceFile, String inFolder, bo
     }
     }
     if(exportScene) {
     if(exportScene) {
 		args = "-e "+args;
 		args = "-e "+args;
+    }
+    if(generateMaterialFile) {
+		args = "-f "+args;
+    }
+    if(overrideMaterials) {
+		args = "-o \""+materialOverrideName+"\" "+args;
+    }
+    if(specifyBaseAssetPath) {
+		args = "-x \""+baseAssetPath+"\" "+args;        
     }
     }
 	if(prefix != "") {
 	if(prefix != "") {
-		args = "-p "+prefix+" "+args;
+		args = "-p \""+prefix+"\" "+args;
 	}
 	}
     
     
 
 

+ 21 - 7
IDE/Contents/Source/ToolWindows.cpp

@@ -197,7 +197,7 @@ YesNoCancelPopup::~YesNoCancelPopup() {
 	
 	
 }
 }
 
 
-AssetImporterWindow::AssetImporterWindow() : UIWindow("3D Asset Importer", 650, 280) {
+AssetImporterWindow::AssetImporterWindow() : UIWindow("3D Asset Importer", 650, 330) {
 	filesToImportLabel = new UILabel("Files that will be imported:", 12);
 	filesToImportLabel = new UILabel("Files that will be imported:", 12);
 	addChild(filesToImportLabel);
 	addChild(filesToImportLabel);
 	filesToImportLabel->setPosition(padding, 35);
 	filesToImportLabel->setPosition(padding, 35);
@@ -211,12 +211,12 @@ AssetImporterWindow::AssetImporterWindow() : UIWindow("3D Asset Importer", 650,
 	cancelButton = new UIButton(L"Cancel", 100);
 	cancelButton = new UIButton(L"Cancel", 100);
 	cancelButton->addEventListener(this, UIEvent::CLICK_EVENT);
 	cancelButton->addEventListener(this, UIEvent::CLICK_EVENT);
 	addChild(cancelButton);
 	addChild(cancelButton);
-	cancelButton->setPosition(padding+650-100-100-10-10, 265);
+	cancelButton->setPosition(padding+650-100-100-10-10, 315);
 	
 	
 	okButton = new UIButton(L"OK", 100);
 	okButton = new UIButton(L"OK", 100);
 	okButton->addEventListener(this, UIEvent::CLICK_EVENT);
 	okButton->addEventListener(this, UIEvent::CLICK_EVENT);
 	addChild(okButton);
 	addChild(okButton);
-	okButton->setPosition(padding+650-100-10, 265);
+	okButton->setPosition(padding+650-100-10, 315);
 	
 	
 	closeOnEscape = true;
 	closeOnEscape = true;
 
 
@@ -272,8 +272,21 @@ AssetImporterWindow::AssetImporterWindow() : UIWindow("3D Asset Importer", 650,
 	addChild(exportSecondaryUVs);
 	addChild(exportSecondaryUVs);
 
 
     exportScene = new UICheckBox("Export Entity file", false);
     exportScene = new UICheckBox("Export Entity file", false);
-	exportScene->setPosition(520, 210);
+	exportScene->setPosition(290, 240);
 	addChild(exportScene);
 	addChild(exportScene);
+
+    generateMatFile = new UICheckBox("Generate material file", false);
+	generateMatFile->setPosition(450, 240);
+	addChild(generateMatFile);
+
+    overrideMaterial = new UICheckBox("Override materials:", false);
+	overrideMaterial->setPosition(290, 270);
+	addChild(overrideMaterial);
+
+    overrideMaterialInput = new UITextInput(false, 200, 16);
+	overrideMaterialInput->setPosition(450, 265);
+	addChild(overrideMaterialInput);
+    overrideMaterialInput->setText("Default");
     
     
 }
 }
 
 
@@ -287,7 +300,7 @@ void AssetImporterWindow::handleEvent(Event *event) {
 		if(usePrefixCheckbox->isChecked() && prefixInput->getText() != "") {
 		if(usePrefixCheckbox->isChecked() && prefixInput->getText() != "") {
 			prefixString = prefixInput->getText().replace(" ", "_");
 			prefixString = prefixInput->getText().replace(" ", "_");
 		}
 		}
-		PolycodeToolLauncher::importAssets(file, folder, addMeshesCheckbox->isChecked(), prefixString, swapZYAxisCheckbox->isChecked(), generateNormalsCheckbox->isChecked(), generateTangensCheckbox->isChecked(), false, exportNormals->isChecked(), exportTangents->isChecked(), exportColors->isChecked(), exportBoneWeights->isChecked(), exportUVs->isChecked(), exportSecondaryUVs->isChecked(), exportScene->isChecked());
+		PolycodeToolLauncher::importAssets(file, folder, addMeshesCheckbox->isChecked(), prefixString, swapZYAxisCheckbox->isChecked(), generateNormalsCheckbox->isChecked(), generateTangensCheckbox->isChecked(), false, exportNormals->isChecked(), exportTangents->isChecked(), exportColors->isChecked(), exportBoneWeights->isChecked(), exportUVs->isChecked(), exportSecondaryUVs->isChecked(), exportScene->isChecked(), generateMatFile->isChecked(), overrideMaterial->isChecked(), overrideMaterialInput->getText(), true, projectRelativeFolder);
 	
 	
 		dispatchEvent(new UIEvent(), UIEvent::OK_EVENT);
 		dispatchEvent(new UIEvent(), UIEvent::OK_EVENT);
 		dispatchEvent(new UIEvent(), UIEvent::CLOSE_EVENT);	
 		dispatchEvent(new UIEvent(), UIEvent::CLOSE_EVENT);	
@@ -322,9 +335,10 @@ void AssetImporterWindow::addFile(String fileName) {
 	fileLabels.push_back(fileLabel);
 	fileLabels.push_back(fileLabel);
 }
 }
 
 
-void AssetImporterWindow::setSourceFileAndTargetFolder(String file, String folder) {
+void AssetImporterWindow::setSourceFileAndTargetFolder(String file, String folder, String projectRelativeFolder) {
 	this->file = file;
 	this->file = file;
 	this->folder = folder;
 	this->folder = folder;
+    this->projectRelativeFolder = projectRelativeFolder;
 	refreshPreview();
 	refreshPreview();
 }
 }
 
 
@@ -333,7 +347,7 @@ void AssetImporterWindow::refreshPreview() {
 	if(usePrefixCheckbox->isChecked() && prefixInput->getText() != "") {
 	if(usePrefixCheckbox->isChecked() && prefixInput->getText() != "") {
 		prefixString = prefixInput->getText().replace(" ", "_");
 		prefixString = prefixInput->getText().replace(" ", "_");
 	}
 	}
-	String fileList = PolycodeToolLauncher::importAssets(file, folder, addMeshesCheckbox->isChecked(), prefixString, swapZYAxisCheckbox->isChecked(), generateNormalsCheckbox->isChecked(), generateTangensCheckbox->isChecked(), true, false, false, false, false, false, false, false);
+	String fileList = PolycodeToolLauncher::importAssets(file, folder, addMeshesCheckbox->isChecked(), prefixString, swapZYAxisCheckbox->isChecked(), generateNormalsCheckbox->isChecked(), generateTangensCheckbox->isChecked(), true, false, false, false, false, false, false, false, false, false, "", false, "");
 	setFilesToImport(fileList);		
 	setFilesToImport(fileList);		
 }
 }
 
 

+ 135 - 32
Tools/Contents/polyimport/Source/polyimport.cpp

@@ -18,6 +18,8 @@ bool hasWeights = false;
 vector<aiBone*> bones;
 vector<aiBone*> bones;
 unsigned int numBones = 0;
 unsigned int numBones = 0;
 
 
+std::vector<String> materialsInFile;
+
 
 
 bool writeNormals = false;
 bool writeNormals = false;
 bool writeTangents = false;
 bool writeTangents = false;
@@ -26,6 +28,14 @@ bool writeBoneWeights = false;
 bool writeUVs = false;
 bool writeUVs = false;
 bool writeSecondaryUVs = false;
 bool writeSecondaryUVs = false;
 
 
+bool hasMaterial(String materialName) {
+    for(int i=0; i < materialsInFile.size(); i++) {
+        if(materialsInFile[i] == materialName) {
+            return true;
+        }
+    }
+    return false;
+}
 
 
 unsigned int addBone(aiBone *bone) {
 unsigned int addBone(aiBone *bone) {
 	for(int i=0; i < bones.size(); i++) {
 	for(int i=0; i < bones.size(); i++) {
@@ -36,7 +46,7 @@ unsigned int addBone(aiBone *bone) {
 	return bones.size()-1;
 	return bones.size()-1;
 }
 }
 
 
-void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, const struct aiNode* nd, bool swapZY, bool addSubmeshes, bool listOnly, ObjectEntry *parentSceneObject) {
+void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, const struct aiNode* nd, bool swapZY, bool addSubmeshes, bool listOnly, ObjectEntry *parentSceneObject, String overrideMaterial, ObjectEntry *materialsParent, String assetPrefixPath) {
 	int i, nIgnoredPolygons = 0;
 	int i, nIgnoredPolygons = 0;
 	unsigned int n = 0, t;
 	unsigned int n = 0, t;
 	// draw all meshes assigned to this node
 	// draw all meshes assigned to this node
@@ -112,13 +122,13 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
             }
             }
             
             
             if(fabs(vertex->x) > bBox.x) {
             if(fabs(vertex->x) > bBox.x) {
-                bBox.x = vertex->x;
+                bBox.x = fabs(vertex->x);
             }
             }
             if(fabs(vertex->y) > bBox.y) {
             if(fabs(vertex->y) > bBox.y) {
-                bBox.y = vertex->y;
+                bBox.y = fabs(vertex->y);
             }
             }
             if(fabs(vertex->z) > bBox.z) {
             if(fabs(vertex->z) > bBox.z) {
-                bBox.z = vertex->z;
+                bBox.z = fabs(vertex->z);
             }
             }
             
             
             tmesh->addVertex(vertex);
             tmesh->addVertex(vertex);
@@ -161,24 +171,54 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
             nd->mTransformation.Decompose(s, r, p);
             nd->mTransformation.Decompose(s, r, p);
             
             
             meshEntry->addChild("sX", s.x);
             meshEntry->addChild("sX", s.x);
-            meshEntry->addChild("sY", s.y);
-            meshEntry->addChild("sZ", s.z);
-
+            
+            if(swapZY) {
+                meshEntry->addChild("sY", s.z);
+                meshEntry->addChild("sZ", s.y);
+            } else {
+                meshEntry->addChild("sY", s.y);
+                meshEntry->addChild("sZ", s.z);
+            }
+            
             meshEntry->addChild("rX", r.x);
             meshEntry->addChild("rX", r.x);
-            meshEntry->addChild("rY", r.y);
-            meshEntry->addChild("rZ", r.z);
+            
+            if(swapZY) {
+                meshEntry->addChild("rY", r.z);
+                meshEntry->addChild("rZ", -r.y);
+            } else {
+                meshEntry->addChild("rY", r.y);
+                meshEntry->addChild("rZ", r.z);
+            }
             meshEntry->addChild("rW", r.w);
             meshEntry->addChild("rW", r.w);
             
             
             meshEntry->addChild("pX", p.x);
             meshEntry->addChild("pX", p.x);
-            meshEntry->addChild("pY", p.y);
-            meshEntry->addChild("pZ", p.z);
+            
+            if(swapZY) {
+                meshEntry->addChild("pY", p.z);
+                meshEntry->addChild("pZ", -p.y);
+            } else{
+                meshEntry->addChild("pY", p.y);
+                meshEntry->addChild("pZ", p.z);
+            }
+            
+            bBox = bBox * 2.0;
+            
+            if(bBox.x == 0.0) {
+                bBox.x = 0.001;
+            }
+            if(bBox.y == 0.0) {
+                bBox.y = 0.001;
+            }
+            if(bBox.z == 0.0) {
+                bBox.z = 0.001;
+            }
             
             
             meshEntry->addChild("bbX", bBox.x);
             meshEntry->addChild("bbX", bBox.x);
             meshEntry->addChild("bbY", bBox.y);
             meshEntry->addChild("bbY", bBox.y);
             meshEntry->addChild("bbZ", bBox.z);
             meshEntry->addChild("bbZ", bBox.z);
             
             
             ObjectEntry *sceneMeshEntry = meshEntry->addChild("SceneMesh");
             ObjectEntry *sceneMeshEntry = meshEntry->addChild("SceneMesh");
-            sceneMeshEntry->addChild("file", fileNameMesh);
+            sceneMeshEntry->addChild("file", assetPrefixPath+fileNameMesh);
             
             
             String materialName = "Default";
             String materialName = "Default";
             int materialIndex = mesh->mMaterialIndex;
             int materialIndex = mesh->mMaterialIndex;
@@ -189,7 +229,26 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
                     materialName = String(name.data);
                     materialName = String(name.data);
                 }
                 }
             }
             }
-            sceneMeshEntry->addChild("material", materialName);
+            
+            if(materialsParent && materialName != "Default") {
+                if(!hasMaterial(materialName)) {
+                    ObjectEntry *materialEntry = materialsParent->addChild("material");
+                    materialEntry->addChild("name", materialName);
+                    materialEntry->addChild("blendingMode", 0);
+                    materialEntry->addChild("blendingMode", 0);
+                    ObjectEntry *shaderEntry = materialEntry->addChild("shader");
+                    shaderEntry->addChild("name", "DefaultShaderNoTexture");
+                    materialsInFile.push_back(materialName);
+                }
+            }
+            
+            if(overrideMaterial != "") {
+                sceneMeshEntry->addChild("material", overrideMaterial);
+            } else {
+                sceneMeshEntry->addChild("material", materialName);
+            }
+            
+            
 		}
 		}
 		if (nIgnoredPolygons) {
 		if (nIgnoredPolygons) {
 			printf("Ignored %d non-triangular polygons\n", nIgnoredPolygons);
 			printf("Ignored %d non-triangular polygons\n", nIgnoredPolygons);
@@ -198,7 +257,7 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
 	   
 	   
 	// draw all children
 	// draw all children
 	for (n = 0; n < nd->mNumChildren; ++n) {
 	for (n = 0; n < nd->mNumChildren; ++n) {
-		addToMesh(prefix, tmesh, sc, nd->mChildren[n], swapZY, addSubmeshes, listOnly, parentSceneObject);
+		addToMesh(prefix, tmesh, sc, nd->mChildren[n], swapZY, addSubmeshes, listOnly, parentSceneObject, overrideMaterial, materialsParent, assetPrefixPath);
 	}
 	}
 }
 }
 
 
@@ -229,10 +288,19 @@ void addToISkeleton(ISkeleton *skel, IBone *parent, const struct aiScene *sc, co
 	skel->addIBone(bone, getBoneID(bone->name));
 	skel->addIBone(bone, getBoneID(bone->name));
 }
 }
 
 
-int exportToFile(String prefix, bool swapZY, bool addSubmeshes, bool listOnly, bool exportEntity) {
+int exportToFile(String prefix, bool swapZY, bool addSubmeshes, bool listOnly, bool exportEntity, bool generateMaterialFile, String overrideMaterial, String assetPrefixPath, String baseFileName) {
 
 
+    Object materialObject;
+    ObjectEntry *materialsParent = NULL;;
+    
+    if(generateMaterialFile) {
+        materialObject.root.name = "polycode";
+        materialsParent = materialObject.root.addChild("materials");
+    }
+    
     Object sceneObject;
     Object sceneObject;
     sceneObject.root.name = "entity";
     sceneObject.root.name = "entity";
+    sceneObject.root.addChild("version", 2);
     ObjectEntry *parentEntry = sceneObject.root.addChild("root");
     ObjectEntry *parentEntry = sceneObject.root.addChild("root");
     
     
     parentEntry->addChild("id", "");
     parentEntry->addChild("id", "");
@@ -265,7 +333,7 @@ int exportToFile(String prefix, bool swapZY, bool addSubmeshes, bool listOnly, b
 		
 		
 	Polycode::Mesh *mesh = new Polycode::Mesh(Mesh::TRI_MESH);
 	Polycode::Mesh *mesh = new Polycode::Mesh(Mesh::TRI_MESH);
     mesh->indexedMesh = true;
     mesh->indexedMesh = true;
-	addToMesh(prefix, mesh, scene, scene->mRootNode, swapZY, addSubmeshes, listOnly, children);
+	addToMesh(prefix, mesh, scene, scene->mRootNode, swapZY, addSubmeshes, listOnly, children, overrideMaterial, materialsParent, assetPrefixPath);
     
     
 	
 	
 	if(addSubmeshes) {
 	if(addSubmeshes) {
@@ -349,13 +417,23 @@ int exportToFile(String prefix, bool swapZY, bool addSubmeshes, bool listOnly, b
 		}
 		}
 	}
 	}
     
     
+    String matFileName = baseFileName+".mat";
+    if(!listOnly && materialsParent) {
+        materialObject.saveToXML(matFileName);
+    }
+    
     if(!listOnly && exportEntity) {
     if(!listOnly && exportEntity) {
-		String entityFileName;
-		if(prefix != "") {
-			entityFileName = prefix+".entity";
-		} else {
-			entityFileName = "out.entity";
-		}        sceneObject.saveToXML(entityFileName);
+        
+        if(materialsParent) {
+            ObjectEntry *settings = sceneObject.root.addChild("settings");
+            ObjectEntry *matFiles = settings->addChild("matFiles");
+            ObjectEntry *matFile = matFiles->addChild("matFile");
+            matFile->addChild("path", assetPrefixPath+matFileName);
+            
+        }
+        
+		String entityFileName = baseFileName+".entity";
+        sceneObject.saveToXML(entityFileName);
     }
     }
 
 
 	if(mesh) {
 	if(mesh) {
@@ -377,11 +455,14 @@ int main(int argc, char **argv) {
 	bool showAssimpDebug = false;
 	bool showAssimpDebug = false;
     bool generateNormals = false;
     bool generateNormals = false;
     bool exportEntity = false;
     bool exportEntity = false;
-	   
+	bool generateMaterialFile = false;
+    String overrideMaterial;
+    
 	String prefix;
 	String prefix;
+    String assetPrefixPath;
 	
 	
 	int opt;
 	int opt;
-	while ((opt = getopt(argc, argv, "engcwuvadlhp:stm")) != -1) {
+	while ((opt = getopt(argc, argv, "engcwuvadlhp:stmfo:x:")) != -1) {
 		switch ((char)opt) {
 		switch ((char)opt) {
             case 'e':
             case 'e':
                 exportEntity = true;
                 exportEntity = true;
@@ -427,7 +508,16 @@ int main(int argc, char **argv) {
 			break;
 			break;
 			case 'h':
 			case 'h':
 				showHelp = true;
 				showHelp = true;
-			break;			
+			break;
+            case 'f':
+                generateMaterialFile = true;
+            break;
+			case 'o':
+				overrideMaterial = String(optarg);
+            break;
+			case 'x':
+				assetPrefixPath = String(optarg)+"/";
+            break;
 			default:
 			default:
 				argsValid = false;
 				argsValid = false;
 			break;
 			break;
@@ -448,25 +538,29 @@ int main(int argc, char **argv) {
 	}
 	}
 	
 	
 	if(showHelp || argc < 2) {
 	if(showHelp || argc < 2) {
-		printf("usage: polyimport [-adhlstngcwuvme] [-p output_prefix] source_file\n\n");
+		printf("usage: polyimport [-adhlstngcwuvmef] [-o override_material] [-p output_prefix] [-x asset_path] source_file\n\n");
 		printf("Misc options:\n");
 		printf("Misc options:\n");
 		printf("d: Show Assimp debug info.\n");
 		printf("d: Show Assimp debug info.\n");
 		printf("h: Show this help.\n");
 		printf("h: Show this help.\n");
 		printf("l: List output files, but do not convert.\n");
 		printf("l: List output files, but do not convert.\n");
-		printf("p: Specify a file prefix for exported files.\n\n");
-		printf("Mesh import options:\n");
+		printf("p: Specify a file prefix for exported files.\n");
+		printf("\nMesh import options:\n");
 		printf("a: Add all meshes to a single mesh.\n");
 		printf("a: Add all meshes to a single mesh.\n");
 		printf("s: Swap Z/Y axis (e.g. import from Blender)\n");
 		printf("s: Swap Z/Y axis (e.g. import from Blender)\n");
 		printf("m: Generate normals.\n");
 		printf("m: Generate normals.\n");
-		printf("t: Generate tangents.\n\n");
-		printf("Mesh export options:\n");
+		printf("t: Generate tangents.\n");
+		printf("\nMesh export options:\n");
 		printf("n: Export normals\n");
 		printf("n: Export normals\n");
 		printf("g: Export tangents\n");
 		printf("g: Export tangents\n");
 		printf("c: Export colors\n");
 		printf("c: Export colors\n");
 		printf("w: Export bone weights\n");
 		printf("w: Export bone weights\n");
 		printf("u: Export UV coordinates\n");
 		printf("u: Export UV coordinates\n");
 		printf("v: Export secondary UV coordinates\n");
 		printf("v: Export secondary UV coordinates\n");
+		printf("\nEntity export options:\n");
 		printf("e: Export entity scene\n");
 		printf("e: Export entity scene\n");
+		printf("f: Generate material file\n");
+		printf("o: Specify override material.\n");
+		printf("x: Specify asset prefix path.\n");
 		printf("\n");
 		printf("\n");
 		return 0;
 		return 0;
 	}
 	}
@@ -484,7 +578,16 @@ int main(int argc, char **argv) {
 	if(!listOnly) {
 	if(!listOnly) {
 		printf("Loading %s...\n", argv[inputArg]);
 		printf("Loading %s...\n", argv[inputArg]);
 	}
 	}
-	
+    
+    String baseFileName = String(argv[inputArg]);
+
+	std::vector<String> parts = baseFileName.split("/");	
+	if(parts.size() > 1) {
+        baseFileName = parts[parts.size()-1];
+	}
+    
+    baseFileName = baseFileName.substr(0, baseFileName.find_last_of("."));
+    
 	scene = aiImportFile(argv[inputArg], aiProcess_JoinIdenticalVertices|
 	scene = aiImportFile(argv[inputArg], aiProcess_JoinIdenticalVertices|
                          aiProcess_Triangulate);
                          aiProcess_Triangulate);
     
     
@@ -498,7 +601,7 @@ int main(int argc, char **argv) {
             aiApplyPostProcessing(scene, aiProcess_GenSmoothNormals);
             aiApplyPostProcessing(scene, aiProcess_GenSmoothNormals);
         }
         }
         
         
-		exportToFile(prefix, swapZYAxis, addSubmeshes, listOnly, exportEntity);
+		exportToFile(prefix, swapZYAxis, addSubmeshes, listOnly, exportEntity, generateMaterialFile, overrideMaterial, assetPrefixPath, baseFileName);
 	} else {
 	} else {
 		printf("Error opening scene (%s)\n", aiGetErrorString());
 		printf("Error opening scene (%s)\n", aiGetErrorString());
 	}
 	}