Przeglądaj źródła

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 lat temu
rodzic
commit
42004fd032

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

@@ -55,7 +55,7 @@ class SceneEntityInstance : public Entity {
 		void clearInstance();
 
 		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);
         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;
 
@@ -456,7 +456,12 @@ Entity *SceneEntityInstance::loadObjectEntryIntoEntity(ObjectEntry *entry, Entit
 
         entity->setScale((*entry)["sX"]->NumberVal, (*entry)["sY"]->NumberVal, (*entry)["sZ"]->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 != "") {
@@ -487,7 +492,7 @@ Entity *SceneEntityInstance::loadObjectEntryIntoEntity(ObjectEntry *entry, Entit
 	if(children) {
 		for(int i=0; i < children->length; i++) {
 			ObjectEntry *childEntry = ((*children))[i];
-			ScreenEntity *childEntity = loadObjectEntryIntoEntity(childEntry);
+			ScreenEntity *childEntity = loadObjectEntryIntoEntity(childEntry, NULL, entityFileVersion);
 			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"];
     if(settings) {
         ObjectEntry *matFiles = (*settings)["matFiles"];
@@ -552,7 +564,7 @@ bool SceneEntityInstance::loadFromFile(const String& fileName) {
     
 	ObjectEntry *root = loadObject.root["root"];
 	if(root) {
-		loadObjectEntryIntoEntity(root, this);
+		loadObjectEntryIntoEntity(root, this, entityFileVersion);
 	}
 	
 	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 String generateTempPath(PolycodeProject *project);
 		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);
 };

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

@@ -93,7 +93,7 @@ class AssetImporterWindow : public UIWindow {
 		void addFile(String fileName);
 		void setFilesToImport(String files);
 		
-		void setSourceFileAndTargetFolder(String file, String folder);
+		void setSourceFileAndTargetFolder(String file, String folder, String projectRelativeFolder);
 		void refreshPreview();
 			
 		void handleEvent(Event *event);	
@@ -102,7 +102,8 @@ class AssetImporterWindow : public UIWindow {
 
 		String file;
 		String folder;
-
+		String projectRelativeFolder;
+    
 		UIButton *cancelButton;
 		UIButton *okButton;
 		std::vector<UILabel*> fileLabels;
@@ -122,6 +123,10 @@ class AssetImporterWindow : public UIWindow {
         UICheckBox *exportSecondaryUVs;
         UICheckBox *exportScene;
     
+        UICheckBox *generateMatFile;
+        UICheckBox *overrideMaterial;
+        UITextInput *overrideMaterialInput;
+    
 		Entity *filesAnchor;
 		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("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("pY", entity->getPosition().y);
@@ -1980,6 +1981,8 @@ void PolycodeEntityEditor::saveFile() {
     }    
     
     saveObject.root.name = "entity";
+    saveObject.root.addChild("version", 2);
+    
     ObjectEntry *children = saveObject.root.addChild("root");
     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);	
 	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->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 polycodeBasePath = CoreServices::getInstance()->getCore()->getDefaultWorkingDirectory();
@@ -154,9 +154,18 @@ String PolycodeToolLauncher::importAssets(String sourceFile, String inFolder, bo
     }
     if(exportScene) {
 		args = "-e "+args;
+    }
+    if(generateMaterialFile) {
+		args = "-f "+args;
+    }
+    if(overrideMaterials) {
+		args = "-o \""+materialOverrideName+"\" "+args;
+    }
+    if(specifyBaseAssetPath) {
+		args = "-x \""+baseAssetPath+"\" "+args;        
     }
 	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);
 	addChild(filesToImportLabel);
 	filesToImportLabel->setPosition(padding, 35);
@@ -211,12 +211,12 @@ AssetImporterWindow::AssetImporterWindow() : UIWindow("3D Asset Importer", 650,
 	cancelButton = new UIButton(L"Cancel", 100);
 	cancelButton->addEventListener(this, UIEvent::CLICK_EVENT);
 	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->addEventListener(this, UIEvent::CLICK_EVENT);
 	addChild(okButton);
-	okButton->setPosition(padding+650-100-10, 265);
+	okButton->setPosition(padding+650-100-10, 315);
 	
 	closeOnEscape = true;
 
@@ -272,8 +272,21 @@ AssetImporterWindow::AssetImporterWindow() : UIWindow("3D Asset Importer", 650,
 	addChild(exportSecondaryUVs);
 
     exportScene = new UICheckBox("Export Entity file", false);
-	exportScene->setPosition(520, 210);
+	exportScene->setPosition(290, 240);
 	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() != "") {
 			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::CLOSE_EVENT);	
@@ -322,9 +335,10 @@ void AssetImporterWindow::addFile(String fileName) {
 	fileLabels.push_back(fileLabel);
 }
 
-void AssetImporterWindow::setSourceFileAndTargetFolder(String file, String folder) {
+void AssetImporterWindow::setSourceFileAndTargetFolder(String file, String folder, String projectRelativeFolder) {
 	this->file = file;
 	this->folder = folder;
+    this->projectRelativeFolder = projectRelativeFolder;
 	refreshPreview();
 }
 
@@ -333,7 +347,7 @@ void AssetImporterWindow::refreshPreview() {
 	if(usePrefixCheckbox->isChecked() && prefixInput->getText() != "") {
 		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);		
 }
 

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

@@ -18,6 +18,8 @@ bool hasWeights = false;
 vector<aiBone*> bones;
 unsigned int numBones = 0;
 
+std::vector<String> materialsInFile;
+
 
 bool writeNormals = false;
 bool writeTangents = false;
@@ -26,6 +28,14 @@ bool writeBoneWeights = false;
 bool writeUVs = 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) {
 	for(int i=0; i < bones.size(); i++) {
@@ -36,7 +46,7 @@ unsigned int addBone(aiBone *bone) {
 	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;
 	unsigned int n = 0, t;
 	// 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) {
-                bBox.x = vertex->x;
+                bBox.x = fabs(vertex->x);
             }
             if(fabs(vertex->y) > bBox.y) {
-                bBox.y = vertex->y;
+                bBox.y = fabs(vertex->y);
             }
             if(fabs(vertex->z) > bBox.z) {
-                bBox.z = vertex->z;
+                bBox.z = fabs(vertex->z);
             }
             
             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);
             
             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("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("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("bbY", bBox.y);
             meshEntry->addChild("bbZ", bBox.z);
             
             ObjectEntry *sceneMeshEntry = meshEntry->addChild("SceneMesh");
-            sceneMeshEntry->addChild("file", fileNameMesh);
+            sceneMeshEntry->addChild("file", assetPrefixPath+fileNameMesh);
             
             String materialName = "Default";
             int materialIndex = mesh->mMaterialIndex;
@@ -189,7 +229,26 @@ void addToMesh(String prefix, Polycode::Mesh *tmesh, const struct aiScene *sc, c
                     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) {
 			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
 	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));
 }
 
-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;
     sceneObject.root.name = "entity";
+    sceneObject.root.addChild("version", 2);
     ObjectEntry *parentEntry = sceneObject.root.addChild("root");
     
     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);
     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) {
@@ -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) {
-		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) {
@@ -377,11 +455,14 @@ int main(int argc, char **argv) {
 	bool showAssimpDebug = false;
     bool generateNormals = false;
     bool exportEntity = false;
-	   
+	bool generateMaterialFile = false;
+    String overrideMaterial;
+    
 	String prefix;
+    String assetPrefixPath;
 	
 	int opt;
-	while ((opt = getopt(argc, argv, "engcwuvadlhp:stm")) != -1) {
+	while ((opt = getopt(argc, argv, "engcwuvadlhp:stmfo:x:")) != -1) {
 		switch ((char)opt) {
             case 'e':
                 exportEntity = true;
@@ -427,7 +508,16 @@ int main(int argc, char **argv) {
 			break;
 			case 'h':
 				showHelp = true;
-			break;			
+			break;
+            case 'f':
+                generateMaterialFile = true;
+            break;
+			case 'o':
+				overrideMaterial = String(optarg);
+            break;
+			case 'x':
+				assetPrefixPath = String(optarg)+"/";
+            break;
 			default:
 				argsValid = false;
 			break;
@@ -448,25 +538,29 @@ int main(int argc, char **argv) {
 	}
 	
 	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("d: Show Assimp debug info.\n");
 		printf("h: Show this help.\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("s: Swap Z/Y axis (e.g. import from Blender)\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("g: Export tangents\n");
 		printf("c: Export colors\n");
 		printf("w: Export bone weights\n");
 		printf("u: Export UV coordinates\n");
 		printf("v: Export secondary UV coordinates\n");
+		printf("\nEntity export options:\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");
 		return 0;
 	}
@@ -484,7 +578,16 @@ int main(int argc, char **argv) {
 	if(!listOnly) {
 		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|
                          aiProcess_Triangulate);
     
@@ -498,7 +601,7 @@ int main(int argc, char **argv) {
             aiApplyPostProcessing(scene, aiProcess_GenSmoothNormals);
         }
         
-		exportToFile(prefix, swapZYAxis, addSubmeshes, listOnly, exportEntity);
+		exportToFile(prefix, swapZYAxis, addSubmeshes, listOnly, exportEntity, generateMaterialFile, overrideMaterial, assetPrefixPath, baseFileName);
 	} else {
 		printf("Error opening scene (%s)\n", aiGetErrorString());
 	}