Bläddra i källkod

Asset updates

Panagiotis Christopoulos Charitos 13 år sedan
förälder
incheckning
a0473be87f

+ 1 - 1
.cproject

@@ -18,7 +18,7 @@
 					<folderInfo id="cdt.managedbuild.config.gnu.exe.debug.1191103617." name="/" resourcePath="">
 					<folderInfo id="cdt.managedbuild.config.gnu.exe.debug.1191103617." name="/" resourcePath="">
 						<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.265738319" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
 						<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.265738319" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
 							<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.1307654940" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/>
 							<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.1307654940" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/>
-							<builder buildPath="${workspace_loc:/anki/build}" id="cdt.managedbuild.target.gnu.builder.exe.debug.887785930" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="4" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
+							<builder buildPath="${workspace_loc:/anki/build}" id="cdt.managedbuild.target.gnu.builder.exe.debug.887785930" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="8" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
 							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1037353125" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
 							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1037353125" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
 							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.733325444" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug">
 							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.733325444" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug">
 								<option id="gnu.cpp.compiler.exe.debug.option.optimization.level.678362421" name="Optimization Level" superClass="gnu.cpp.compiler.exe.debug.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
 								<option id="gnu.cpp.compiler.exe.debug.option.optimization.level.678362421" name="Optimization Level" superClass="gnu.cpp.compiler.exe.debug.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>

+ 1 - 1
.project

@@ -28,7 +28,7 @@
 				</dictionary>
 				</dictionary>
 				<dictionary>
 				<dictionary>
 					<key>org.eclipse.cdt.make.core.buildArguments</key>
 					<key>org.eclipse.cdt.make.core.buildArguments</key>
-					<value>-j4</value>
+					<value>-j8</value>
 				</dictionary>
 				</dictionary>
 				<dictionary>
 				<dictionary>
 					<key>org.eclipse.cdt.make.core.buildCommand</key>
 					<key>org.eclipse.cdt.make.core.buildCommand</key>

+ 1 - 1
include/anki/gl/Texture.h

@@ -270,7 +270,7 @@ public:
 	void genMipmap();
 	void genMipmap();
 
 
 	/// Read the data from the texture. Available only in GL desktop
 	/// Read the data from the texture. Available only in GL desktop
-	void readPixels(void* data, U level = 0);
+	void readPixels(void* data, U level = 0) const;
 
 
 private:
 private:
 	GLuint glId = 0; ///< Identification for OGL
 	GLuint glId = 0; ///< Identification for OGL

+ 2 - 1
include/anki/misc/Xml.h

@@ -75,7 +75,8 @@ public:
 		if(doc.LoadFile(filename))
 		if(doc.LoadFile(filename))
 		{
 		{
 			throw ANKI_EXCEPTION("Cannot parse file. Reason: "
 			throw ANKI_EXCEPTION("Cannot parse file. Reason: "
-				+ doc.GetErrorStr1());
+				+ ((doc.GetErrorStr1() == nullptr)
+				? "unknown" : doc.GetErrorStr1()));
 		}
 		}
 	}
 	}
 
 

+ 1 - 1
include/anki/renderer/Is.h

@@ -32,7 +32,7 @@ class Is: private RenderingPass
 	friend struct UpdateTilesJob;
 	friend struct UpdateTilesJob;
 
 
 public:
 public:
-	static const U MAX_LIGHTS_PER_TILE = 40;
+	static const U MAX_LIGHTS_PER_TILE = 32;
 
 
 	static const U MAX_POINT_LIGHTS = 512;
 	static const U MAX_POINT_LIGHTS = 512;
 	static const U MAX_SPOT_LIGHTS = 8;
 	static const U MAX_SPOT_LIGHTS = 8;

+ 2 - 1
include/anki/renderer/Tiler.h

@@ -79,7 +79,8 @@ private:
 
 
 	void initInternal(Renderer* r);
 	void initInternal(Renderer* r);
 
 
-	void update4Planes(Camera& cam);
+	void update4Planes(Camera& cam, void* jobs);
+	void waitUpdate4Planes();
 	void update2Planes(Camera& cam, const PixelArray& pixels);
 	void update2Planes(Camera& cam, const PixelArray& pixels);
 
 
 	Bool testInternal(const CollisionShape& cs, const Tile& tile, 
 	Bool testInternal(const CollisionShape& cs, const Tile& tile, 

+ 8 - 0
include/anki/scene/ModelNode.h

@@ -107,6 +107,14 @@ public:
 	virtual ~ModelNode();
 	virtual ~ModelNode();
 	/// @}
 	/// @}
 
 
+	/// @name Accessors
+	/// @{
+	const Model& getModel() const
+	{
+		return *model;
+	}
+	/// @}
+
 	/// @name SceneNode virtuals
 	/// @name SceneNode virtuals
 	/// @{
 	/// @{
 
 

+ 1 - 2
include/anki/scene/Sector.h

@@ -2,7 +2,6 @@
 #define ANKI_SCENE_SECTOR_H
 #define ANKI_SCENE_SECTOR_H
 
 
 #include "anki/scene/Octree.h"
 #include "anki/scene/Octree.h"
-#include <array>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -13,7 +12,7 @@ class Sector;
 class Portal
 class Portal
 {
 {
 private:
 private:
-	std::array<Sector*, 2> sectors;
+	Array<Sector*, 2> sectors;
 };
 };
 
 
 /// A sector
 /// A sector

+ 6 - 0
shaders/IsLpGeneric.glsl

@@ -320,4 +320,10 @@ void main()
 		fColor += vec3(0.0, 0.1, 0.0);
 		fColor += vec3(0.0, 0.1, 0.0);
 	}
 	}
 #endif
 #endif
+
+#if 0
+	vec3 tmpc = vec3((vInstanceId % 4) / 3.0, (vInstanceId % 3) / 2.0, 
+		(vInstanceId % 2));
+	fColor += tmpc / 50.0;
+#endif
 }
 }

+ 0 - 0
shaders/IsMinMax.glsl → shaders/TilerMinMax.glsl


+ 1 - 1
src/gl/Texture.cpp

@@ -366,7 +366,7 @@ void Texture::setFilteringNoBind(TextureFilteringType filterType)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Texture::readPixels(void* pixels, U level)
+void Texture::readPixels(void* pixels, U level) const
 {
 {
 #if ANKI_GL == ANKI_GL_DESKTOP
 #if ANKI_GL == ANKI_GL_DESKTOP
 	TextureUnitsSingleton::get().bindTextureAndActivateUnit(*this);
 	TextureUnitsSingleton::get().bindTextureAndActivateUnit(*this);

+ 6 - 0
src/renderer/MainRenderer.cpp

@@ -118,6 +118,12 @@ void MainRenderer::render(Scene& scene)
 		sProg->findUniformVariable("rasterImage").set(finalFai);
 		sProg->findUniformVariable("rasterImage").set(finalFai);
 		drawQuad();
 		drawQuad();
 	}
 	}
+
+	GLenum glerr = glGetError();
+	if(glerr != GL_NO_ERROR)
+	{
+		throw ANKI_EXCEPTION("GL error");
+	}
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 71 - 13
src/renderer/Tiler.cpp

@@ -4,6 +4,9 @@
 #include "anki/core/ThreadPool.h"
 #include "anki/core/ThreadPool.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/Camera.h"
 
 
+// Default should be 0
+#define ALTERNATIVE_MIN_MAX 0
+
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
@@ -91,6 +94,9 @@ struct UpdateTiles4PlanesPerspectiveCameraJob: ThreadJob
 	}
 	}
 };
 };
 
 
+typedef Array<UpdateTiles4PlanesPerspectiveCameraJob, ThreadPool::MAX_THREADS>
+	Update4JobArray;
+
 //==============================================================================
 //==============================================================================
 /// Job that updates the near and far tile planes and transforms them
 /// Job that updates the near and far tile planes and transforms them
 struct UpdateTiles2PlanesJob: ThreadJob
 struct UpdateTiles2PlanesJob: ThreadJob
@@ -119,10 +125,10 @@ struct UpdateTiles2PlanesJob: ThreadJob
 			// Calculate depth as you do it for the vertex position inside 
 			// Calculate depth as you do it for the vertex position inside 
 			// the shaders
 			// the shaders
 			F32 minZ = planes.y() / (planes.x() + (*pixels)[j][i][0]);
 			F32 minZ = planes.y() / (planes.x() + (*pixels)[j][i][0]);
-			F32 maxZ = -planes.y() / (planes.x() + (*pixels)[j][i][1]);
+			F32 maxZ = planes.y() / (planes.x() + (*pixels)[j][i][1]);
 
 
 			tile.planes[Frustum::FP_NEAR] = Plane(Vec3(0.0, 0.0, -1.0), minZ);
 			tile.planes[Frustum::FP_NEAR] = Plane(Vec3(0.0, 0.0, -1.0), minZ);
-			tile.planes[Frustum::FP_FAR] = Plane(Vec3(0.0, 0.0, 1.0), maxZ);
+			tile.planes[Frustum::FP_FAR] = Plane(Vec3(0.0, 0.0, 1.0), -maxZ);
 
 
 			// Transform planes
 			// Transform planes
 			tile.planesWSpace[Frustum::FP_NEAR] = 
 			tile.planesWSpace[Frustum::FP_NEAR] = 
@@ -167,7 +173,7 @@ void Tiler::initInternal(Renderer* r_)
 		"#define RENDERER_HEIGHT " + std::to_string(r->getHeight()) + "\n";
 		"#define RENDERER_HEIGHT " + std::to_string(r->getHeight()) + "\n";
 
 
 	prog.load(ShaderProgramResource::createSrcCodeToCache(
 	prog.load(ShaderProgramResource::createSrcCodeToCache(
-		"shaders/IsMinMax.glsl", pps.c_str()).c_str());
+		"shaders/TilerMinMax.glsl", pps.c_str()).c_str());
 
 
 	// Create FBO
 	// Create FBO
 	Renderer::createFai(TILES_X_COUNT, TILES_Y_COUNT, GL_RG32UI,
 	Renderer::createFai(TILES_X_COUNT, TILES_Y_COUNT, GL_RG32UI,
@@ -185,18 +191,23 @@ void Tiler::initInternal(Renderer* r_)
 //==============================================================================
 //==============================================================================
 void Tiler::updateTiles(Camera& cam, const Texture& depthMap)
 void Tiler::updateTiles(Camera& cam, const Texture& depthMap)
 {
 {
+	Update4JobArray jobs4;
+
+#if !ALTERNATIVE_MIN_MAX
 	//
 	//
 	// Issue the min/max draw call
 	// Issue the min/max draw call
 	//
 	//
 
 
-	fbo.bind(); // Flush prev FBO on Mali
+	update4Planes(cam, &jobs4);
+
+	fbo.bind(); // Flush prev FBO to force flush on Mali
 	GlStateSingleton::get().setViewport(0, 0, TILES_X_COUNT, TILES_Y_COUNT);
 	GlStateSingleton::get().setViewport(0, 0, TILES_X_COUNT, TILES_Y_COUNT);
 	prog->bind();
 	prog->bind();
 	prog->findUniformVariable("depthMap").set(depthMap);
 	prog->findUniformVariable("depthMap").set(depthMap);
 
 
 	r->drawQuad();
 	r->drawQuad();
 
 
-	update4Planes(cam);
+	waitUpdate4Planes();
 
 
 	//
 	//
 	// Read pixels from the min/max pass
 	// Read pixels from the min/max pass
@@ -212,16 +223,63 @@ void Tiler::updateTiles(Camera& cam, const Texture& depthMap)
 #endif
 #endif
 
 
 	// 
 	// 
-	// Update the 2 planes and transform the planes
+	// Update and transform the 2 planes
 	// 
 	// 
 	update2Planes(cam, pixels);
 	update2Planes(cam, pixels);
 
 
 	prevCam = &cam;
 	prevCam = &cam;
+#else
+	Vector<F32> allpixels;
+
+	update4Planes(cam, &jobs4);
+
+	allpixels.resize(r->getWidth() * r->getHeight());
+	glReadPixels(0, 0, r->getWidth(), r->getHeight(), GL_DEPTH_COMPONENT,
+		GL_FLOAT, &allpixels[0]);
+
+	// Init pixels
+	PixelArray pixels;
+	for(U j = 0; j < TILES_Y_COUNT; j++)
+	{
+		for(U i = 0; i < TILES_X_COUNT; i++)
+		{
+			pixels[j][i][0] = 1.0;
+			pixels[j][i][1] = 0.0;
+		}
+	}
+
+	// Get min max
+	U w = r->getWidth() / TILES_X_COUNT;
+	U h = r->getHeight() / TILES_Y_COUNT;
+	for(U j = 0; j < r->getHeight(); j++)
+	{
+		for(U i = 0; i < r->getWidth(); i++)
+		{
+			U ii = i / w;
+			U jj = j / h;
+
+			F32 depth = allpixels[j * r->getWidth() + i];
+
+			pixels[jj][ii][0] = std::min(pixels[jj][ii][0], depth);
+			pixels[jj][ii][1] = std::max(pixels[jj][ii][1], depth);
+		}
+	}
+
+	waitUpdate4Planes();
+
+	// Update and transform the 2 planes
+	update2Planes(cam, pixels);
+
+	prevCam = &cam;
+
+#endif
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Tiler::update4Planes(Camera& cam)
+void Tiler::update4Planes(Camera& cam, void* jobs_)
 {
 {
+	Update4JobArray& jobs = *(Update4JobArray*)jobs_;
+
 	U32 camTimestamp = cam.getFrustumable()->getFrustumableTimestamp();
 	U32 camTimestamp = cam.getFrustumable()->getFrustumableTimestamp();
 
 
 	// Transform only the planes when:
 	// Transform only the planes when:
@@ -230,14 +288,10 @@ void Tiler::update4Planes(Camera& cam)
 	Bool onlyTransformPlanes = 
 	Bool onlyTransformPlanes = 
 		camTimestamp < planes4UpdateTimestamp && prevCam == &cam;
 		camTimestamp < planes4UpdateTimestamp && prevCam == &cam;
 
 
-
 	// Update the planes in parallel
 	// Update the planes in parallel
 	// 
 	// 
 	ThreadPool& threadPool = ThreadPoolSingleton::get();
 	ThreadPool& threadPool = ThreadPoolSingleton::get();
 
 
-	// Dont even think of defining that in the switch
-	Array<UpdateTiles4PlanesPerspectiveCameraJob, ThreadPool::MAX_THREADS> jobs;
-
 	switch(cam.getCameraType())
 	switch(cam.getCameraType())
 	{
 	{
 	case Camera::CT_PERSPECTIVE:
 	case Camera::CT_PERSPECTIVE:
@@ -254,14 +308,18 @@ void Tiler::update4Planes(Camera& cam)
 		break;
 		break;
 	}
 	}
 
 
-	threadPool.waitForAllJobsToFinish();
-
 	if(!onlyTransformPlanes)
 	if(!onlyTransformPlanes)
 	{
 	{
 		planes4UpdateTimestamp = Timestamp::getTimestamp();
 		planes4UpdateTimestamp = Timestamp::getTimestamp();
 	}
 	}
 }
 }
 
 
+//==============================================================================
+void Tiler::waitUpdate4Planes()
+{
+	ThreadPoolSingleton::get().waitForAllJobsToFinish();
+}
+
 //==============================================================================
 //==============================================================================
 void Tiler::update2Planes(Camera& cam, const PixelArray& pixels)
 void Tiler::update2Planes(Camera& cam, const PixelArray& pixels)
 {
 {

+ 0 - 6
src/scene/Scene.cpp

@@ -40,12 +40,6 @@ void Scene::update(float prevUpdateTime, float crntTime, Renderer& r)
 		{
 		{
 			m->update();
 			m->update();
 		}
 		}
-
-		Spatial* sp = n->getSpatial();
-		if(sp)
-		{
-			sp->disableFlag(Spatial::SF_VISIBLE);
-		}
 	}
 	}
 
 
 	// Then the rest
 	// Then the rest

+ 4 - 2
src/scene/VisibilityTester.cpp

@@ -35,15 +35,17 @@ void VisibilityTester::test(Frustumable& ref, Scene& scene, Renderer& r)
 			continue;
 			continue;
 		}
 		}
 
 
+		sp->disableFlag(Spatial::SF_VISIBLE);
+
 		if(!ref.insideFrustum(*sp))
 		if(!ref.insideFrustum(*sp))
 		{
 		{
 			continue;
 			continue;
 		}
 		}
 
 
-		if(!r.doVisibilityTests(sp->getAabb()))
+		/*if(!r.doVisibilityTests(sp->getAabb()))
 		{
 		{
 			continue;
 			continue;
-		}
+		}*/
 
 
 		sp->enableFlag(Spatial::SF_VISIBLE);
 		sp->enableFlag(Spatial::SF_VISIBLE);
 
 

+ 20 - 10
testapp/Main.cpp

@@ -63,7 +63,7 @@ void init()
 	cam->setAll(
 	cam->setAll(
 		MainRendererSingleton::get().getAspectRatio() * toRad(ang),
 		MainRendererSingleton::get().getAspectRatio() * toRad(ang),
 		toRad(ang), 0.5, 500.0);
 		toRad(ang), 0.5, 500.0);
-	cam->setLocalTransform(Transform(Vec3(100.0, 5.0, 8.0),
+	cam->setLocalTransform(Transform(Vec3(90.0, 5.0, 8.0),
 		Mat3(Euler(toRad(-10.0), toRad(90.0), toRad(0.0))),
 		Mat3(Euler(toRad(-10.0), toRad(90.0), toRad(0.0))),
 		1.0));
 		1.0));
 	scene.setActiveCamera(cam);
 	scene.setActiveCamera(cam);
@@ -79,7 +79,8 @@ void init()
 		1.0));
 		1.0));
 
 
 	// lights
 	// lights
-	Vec3 lpos(-100.0, 0.0, -50.0);
+#if 1
+	Vec3 lpos(-90.0, 1.2, -32.0);
 	for(int i = 0; i < 50; i++)
 	for(int i = 0; i < 50; i++)
 	{
 	{
 		for(int j = 0; j < 10; j++)
 		for(int j = 0; j < 10; j++)
@@ -95,12 +96,13 @@ void init()
 				randFloat(6.0) - 3.0, randFloat(6.0) - 3.0, 0.0));
 				randFloat(6.0) - 3.0, randFloat(6.0) - 3.0, 0.0));
 			point->setLocalTranslation(lpos);
 			point->setLocalTranslation(lpos);
 
 
-			lpos.z() += 10.0;
+			lpos.z() += 7.0;
 		}
 		}
 
 
-		lpos.x() += 4.0;
-		lpos.z() = -50;
+		lpos.x() += 3.5;
+		lpos.z() = -32;
 	}
 	}
+#endif
 
 
 #if 1
 #if 1
 	SpotLight* spot = new SpotLight("spot0", &scene, Movable::MF_NONE, nullptr);
 	SpotLight* spot = new SpotLight("spot0", &scene, Movable::MF_NONE, nullptr);
@@ -141,22 +143,30 @@ void init()
 	point1->setLocalTranslation(Vec3(-3.0, 2.0, 0.0));*/
 	point1->setLocalTranslation(Vec3(-3.0, 2.0, 0.0));*/
 
 
 	// horse
 	// horse
-	horse = new ModelNode("meshes/horse/horse.mdl", "horse", &scene,
+	horse = new ModelNode("data/models/horse/horse.mdl", "horse", &scene,
 		Movable::MF_NONE, nullptr);
 		Movable::MF_NONE, nullptr);
 	horse->setLocalTransform(Transform(Vec3(-2, 0, 0), Mat3::getIdentity(),
 	horse->setLocalTransform(Transform(Vec3(-2, 0, 0), Mat3::getIdentity(),
 		1.0));
 		1.0));
 
 
-#if 1
+#if 0
 	// Sponza
 	// Sponza
 	ModelNode* sponzaModel = new ModelNode(
 	ModelNode* sponzaModel = new ModelNode(
 		"maps/sponza-crytek/sponza_crytek.mdl",
 		"maps/sponza-crytek/sponza_crytek.mdl",
 		"sponza", &scene, Movable::MF_NONE, nullptr);
 		"sponza", &scene, Movable::MF_NONE, nullptr);
 
 
 	sponzaModel->setLocalScale(0.1);
 	sponzaModel->setLocalScale(0.1);
-#endif
 
 
 	// Sectors
 	// Sectors
-	scene.sectors.push_back(new Sector(Aabb(Vec3(-10.0), Vec3(10.0))));
+	Aabb sectorAabb;
+	sponzaModel->getModel().getVisibilityShape().toAabb(sectorAabb);
+	scene.sectors.push_back(new Sector(sectorAabb));
+#endif
+
+	ModelNode* sponzaModel = new ModelNode(
+		"data/maps/sponza/sponza.mdl",
+		"sponza", &scene, Movable::MF_NONE, nullptr);
+
+	(void)sponzaModel;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -362,7 +372,7 @@ void initSubsystems(int argc, char* argv[])
 	// Main renderer
 	// Main renderer
 	RendererInitializer initializer;
 	RendererInitializer initializer;
 	initializer.ms.ez.enabled = true;
 	initializer.ms.ez.enabled = true;
-	initializer.dbg.enabled = true;
+	initializer.dbg.enabled = false;
 	initializer.is.sm.bilinearEnabled = true;
 	initializer.is.sm.bilinearEnabled = true;
 	initializer.is.sm.enabled = true;
 	initializer.is.sm.enabled = true;
 	initializer.is.sm.pcfEnabled = false;
 	initializer.is.sm.pcfEnabled = false;

+ 65 - 24
tools/dae2anki/dae2anki.py

@@ -3,6 +3,7 @@
 import optparse
 import optparse
 import xml.etree.cElementTree as xml
 import xml.etree.cElementTree as xml
 from struct import pack
 from struct import pack
+import os
 
 
 class Vector:
 class Vector:
 	""" 3D vector """
 	""" 3D vector """
@@ -50,7 +51,8 @@ class Mesh:
 		self.id = "" # The mesh:id needed for skinning
 		self.id = "" # The mesh:id needed for skinning
 		# The mesh/source/float_array that includes the vertex positions. 
 		# The mesh/source/float_array that includes the vertex positions. 
 		# Needed for skinning
 		# Needed for skinning
-		self.vert_positions = None 
+		self.vert_positions = None
+		self.material_name = "unnamed.mtl"
 
 
 def compare_arr(a, b):
 def compare_arr(a, b):
 	""" Compare 2 arrays """
 	""" Compare 2 arrays """
@@ -71,6 +73,13 @@ def search_in_array(arr, el):
 			return i
 			return i
 	return -1
 	return -1
 
 
+def to_collada_tag(name):
+	""" Transform a name of the tag to something that COLLADA format 
+	    understands """
+	collada_str = "{http://www.collada.org/2005/11/COLLADASchema}"
+	s = name.replace("/", "/" + collada_str)
+	return collada_str + s
+
 def parse_commandline():
 def parse_commandline():
 	""" Parse the command line arguments """
 	""" Parse the command line arguments """
 	parser = optparse.OptionParser("usage: %prog [options]")
 	parser = optparse.OptionParser("usage: %prog [options]")
@@ -91,7 +100,7 @@ def parse_commandline():
 def parse_library_geometries(el):
 def parse_library_geometries(el):
 	geometries = []
 	geometries = []
 
 
-	geometry_el_arr = el.findall("geometry")
+	geometry_el_arr = el.findall(to_collada_tag("geometry"))
 	for geometry_el in geometry_el_arr:
 	for geometry_el in geometry_el_arr:
 		geometries.append(parse_geometry(geometry_el))
 		geometries.append(parse_geometry(geometry_el))
 
 
@@ -116,24 +125,24 @@ def get_positions_and_uvs(mesh_el):
 	uvs_float_array = None
 	uvs_float_array = None
 
 
 	# First get all
 	# First get all
-	source_elarr = mesh_el.findall("source")
+	source_elarr = mesh_el.findall(to_collada_tag("source"))
 	all_float_array = {}
 	all_float_array = {}
 	for source_el in source_elarr:
 	for source_el in source_elarr:
 		source_id = source_el.get("id")
 		source_id = source_el.get("id")
 	
 	
-		float_array_el = source_el.find("float_array")
+		float_array_el = source_el.find(to_collada_tag("float_array"))
 		all_float_array[source_id] = parse_float_array(float_array_el)
 		all_float_array[source_id] = parse_float_array(float_array_el)
 
 
 	# Create a link between vertices:id and vertices/input:source
 	# Create a link between vertices:id and vertices/input:source
 	vertices_id_to_source = {}
 	vertices_id_to_source = {}
-	vertices_el = mesh_el.find("vertices")
+	vertices_el = mesh_el.find(to_collada_tag("vertices"))
 	vertices_id = vertices_el.get("id")
 	vertices_id = vertices_el.get("id")
-	input_el = vertices_el.find("input")
+	input_el = vertices_el.find(to_collada_tag("input"))
 	vertices_input_source = input_el.get("source")
 	vertices_input_source = input_el.get("source")
 	vertices_id_to_source[vertices_id] = vertices_input_source[1:]
 	vertices_id_to_source[vertices_id] = vertices_input_source[1:]
 
 
 	# Now find what it is what
 	# Now find what it is what
-	input_elarr = mesh_el.findall("polylist/input")
+	input_elarr = mesh_el.findall(to_collada_tag("polylist/input"))
 	for input_el in input_elarr:
 	for input_el in input_elarr:
 		semantic = input_el.get("semantic")
 		semantic = input_el.get("semantic")
 		source = input_el.get("source")
 		source = input_el.get("source")
@@ -173,19 +182,22 @@ def parse_geometry(geometry_el):
 	geom_id = geometry_el.get("id")
 	geom_id = geometry_el.get("id")
 	print("---- Parsing geometry: %s" % geom_name)
 	print("---- Parsing geometry: %s" % geom_name)
 
 
-	mesh_el = geometry_el.find("mesh")
+	mesh_el = geometry_el.find(to_collada_tag("mesh"))
 
 
 	# Get positions and UVs
 	# Get positions and UVs
 	(positions_vec_array, positions_offset, uvs_float_array, uvs_offset) = \
 	(positions_vec_array, positions_offset, uvs_float_array, uvs_offset) = \
 		get_positions_and_uvs(mesh_el)
 		get_positions_and_uvs(mesh_el)
 
 
-	# get polylist
-	polylist_el = mesh_el.find("polylist")
-	inputs_count = len(polylist_el.findall("input"))
+	# Get polylist
+	polylist_el = mesh_el.find(to_collada_tag("polylist"))
+	inputs_count = len(polylist_el.findall(to_collada_tag("input")))
+
+	# Get material
+	mtl = polylist_el.get("material")
 
 
 	# Make sure that we are dealing with triangles
 	# Make sure that we are dealing with triangles
 	tokens = [x.strip() for x in 
 	tokens = [x.strip() for x in 
-		polylist_el.find("vcount").text.split(" ")]
+		polylist_el.find(to_collada_tag("vcount")).text.split(" ")]
 
 
 	for token in tokens:
 	for token in tokens:
 		if token:
 		if token:
@@ -193,13 +205,13 @@ def parse_geometry(geometry_el):
 				raise Exception("Only triangles are alowed")	
 				raise Exception("Only triangles are alowed")	
 
 
 	# Get face number
 	# Get face number
-	face_count = int(mesh_el.find("polylist").get("count"))
+	face_count = int(mesh_el.find(to_collada_tag("polylist")).get("count"))
 
 
 	# Get p. p is a 3D array where the 1st dim is the face, 2nd is the vertex
 	# Get p. p is a 3D array where the 1st dim is the face, 2nd is the vertex
 	# and the 3rd is 0 for position, 1 for normal and 2 for text coord
 	# and the 3rd is 0 for position, 1 for normal and 2 for text coord
 	p = []
 	p = []
 	tokens = [x.strip() for x in 
 	tokens = [x.strip() for x in 
-		polylist_el.find("p").text.split(" ")]
+		polylist_el.find(to_collada_tag("p")).text.split(" ")]
 
 
 	for token in tokens:
 	for token in tokens:
 		if token:
 		if token:
@@ -241,6 +253,8 @@ def parse_geometry(geometry_el):
 	geom.name = geom_name
 	geom.name = geom_name
 	geom.id = geom_id
 	geom.id = geom_id
 	geom.vert_positions = positions_vec_array
 	geom.vert_positions = positions_vec_array
+	if mtl:
+		geom.material_name = mtl
 
 
 	print("------ Number of verts: %d" % len(geom.vertices))
 	print("------ Number of verts: %d" % len(geom.vertices))
 	print("------ Number of faces: %d" % (len(geom.indices) / 3))
 	print("------ Number of faces: %d" % (len(geom.indices) / 3))
@@ -252,12 +266,12 @@ def update_mesh_with_vertex_weights(mesh, skin_el):
 
 
 	# Get all <source>
 	# Get all <source>
 	source_data = {}
 	source_data = {}
-	source_elarr = skin_el.findall("source")
+	source_elarr = skin_el.findall(to_collada_tag("source"))
 	for source_el in source_elarr:
 	for source_el in source_elarr:
 		source_id = source_el.get("id")
 		source_id = source_el.get("id")
 	
 	
-		float_array_el = source_el.find("float_array")
-		name_array_el = source_el.find("Name_array")
+		float_array_el = source_el.find(to_collada_tag("float_array"))
+		name_array_el = source_el.find(to_collada_tag("Name_array"))
 
 
 		if float_array_el != None:
 		if float_array_el != None:
 			source_data[source_id] = parse_float_array(float_array_el)
 			source_data[source_id] = parse_float_array(float_array_el)
@@ -277,8 +291,8 @@ def update_mesh_with_vertex_weights(mesh, skin_el):
 	weight_arr = None
 	weight_arr = None
 	weight_arr_offset = -1
 	weight_arr_offset = -1
 
 
-	vertex_weights_el = skin_el.find("vertex_weights")
-	input_elarr = vertex_weights_el.findall("input")
+	vertex_weights_el = skin_el.find(to_collada_tag("vertex_weights"))
+	input_elarr = vertex_weights_el.findall(to_collada_tag("input"))
 	for input_el in input_elarr:
 	for input_el in input_elarr:
 		semantic = input_el.get("semantic")
 		semantic = input_el.get("semantic")
 		source = input_el.get("source")
 		source = input_el.get("source")
@@ -301,7 +315,7 @@ def update_mesh_with_vertex_weights(mesh, skin_el):
 	# Get <vcount>
 	# Get <vcount>
 	vcount = []
 	vcount = []
 	tokens = [x.strip() for x in 
 	tokens = [x.strip() for x in 
-		vertex_weights_el.find("vcount").text.split(" ")]
+		vertex_weights_el.find(to_collada_tag("vcount")).text.split(" ")]
 
 
 	for token in tokens:
 	for token in tokens:
 		if token:
 		if token:
@@ -310,7 +324,7 @@ def update_mesh_with_vertex_weights(mesh, skin_el):
 	# Get <v>
 	# Get <v>
 	v = []
 	v = []
 	tokens = [x.strip() for x in 
 	tokens = [x.strip() for x in 
-		vertex_weights_el.find("v").text.split(" ")]
+		vertex_weights_el.find(to_collada_tag("v")).text.split(" ")]
 
 
 	for token in tokens:
 	for token in tokens:
 		if token:
 		if token:
@@ -398,7 +412,7 @@ def write_mesh(mesh, directory, flip):
 		buff += pack("ff", vert.uv.x, vert.uv.y)
 		buff += pack("ff", vert.uv.x, vert.uv.y)
 
 
 	# Vert weight
 	# Vert weight
-	if mesh.vertices[0].bones_count != -1:
+	if mesh.vertices[0].bones_count > 0:
 		buff += pack("I", len(mesh.vertices))
 		buff += pack("I", len(mesh.vertices))
 
 
 		for vert in mesh.vertices:
 		for vert in mesh.vertices:
@@ -414,6 +428,28 @@ def write_mesh(mesh, directory, flip):
 def write_mesh_v2(mesh, directory, flip):
 def write_mesh_v2(mesh, directory, flip):
 	noop
 	noop
 
 
+def write_model(meshes, directory, mdl_name):
+	""" Write the .model XML file """
+	filename = directory + "/" + mdl_name + ".mdl"
+	print("---- Writing file: %s" % filename)
+	f = open(filename, "w")
+
+	f.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n")
+	f.write("<model>\n")
+	f.write("\t<modelPatches>\n")
+
+	for mesh in meshes:
+		f.write("\t\t<modelPatch>\n")
+		f.write("\t\t\t<mesh>%s</mesh>\n" 
+			% os.path.abspath(directory + "/" + mesh.name + ".mesh"))
+		f.write("\t\t\t<material>%s</material>\n" % "unnamed.mtl")
+		f.write("\t\t</modelPatch>\n")
+
+	f.write("\t</modelPatches>\n")
+	f.write("</model>\n")
+
+	f.close()
+
 def main():
 def main():
 	(infile, outdir, flip) = parse_commandline()
 	(infile, outdir, flip) = parse_commandline()
 
 
@@ -422,12 +458,13 @@ def main():
 	tree = xml.parse(infile)
 	tree = xml.parse(infile)
 
 
 	# Get meshes
 	# Get meshes
-	el_arr = tree.findall("library_geometries")
+	el_arr = tree.findall(to_collada_tag("library_geometries"))
 	for el in el_arr:
 	for el in el_arr:
 		meshes = parse_library_geometries(el)
 		meshes = parse_library_geometries(el)
 
 
 	# Update with skin info
 	# Update with skin info
-	skin_elarr = tree.findall("library_controllers/controller/skin")
+	skin_elarr = tree.findall(to_collada_tag(
+		"library_controllers/controller/skin"))
 	for skin_el in skin_elarr:
 	for skin_el in skin_elarr:
 		source = skin_el.get("source")
 		source = skin_el.get("source")
 		source = source[1:]
 		source = source[1:]
@@ -440,6 +477,10 @@ def main():
 	for mesh in meshes:
 	for mesh in meshes:
 		write_mesh(mesh, outdir, flip)
 		write_mesh(mesh, outdir, flip)
 
 
+	# Write the model
+	mdl_name = os.path.splitext(os.path.basename(infile))[0]
+	write_model(meshes, outdir, mdl_name)
+
 	print("-- Bye!")
 	print("-- Bye!")
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":

+ 42 - 0
tools/material/create_material.py

@@ -0,0 +1,42 @@
+#!/usr/bin/python3
+
+import optparse
+
+def main():
+	# Command line args
+	parser = optparse.OptionParser("usage: %prog [options]")
+
+	parser.add_option("-t", "--template", dest="template",
+		type="string", help="specify material template")
+	parser.add_option("-o", "--output", dest="out",
+		type="string", help="specify the output filename")
+	parser.add_option("-v", "--vars", dest="vars",
+		type="string", help="specify the variables to replace. "
+		"Format var:val,var1:val1")
+
+	(options, args) = parser.parse_args()
+
+	if not options.template or not options.out:
+		parser.error("argument is missing")
+
+	# Open template
+	ftempl = open(options.template, "r")
+	templ = ftempl.read()
+	ftempl.close()
+	
+	# Parse vars
+	if options.vars:
+		varvals = options.vars.split(",")
+		for varval in varvals:
+			(var, val) = varval.split(":")
+			print("-- Replacing %%%s%% with %s" % (var, val))
+
+			templ = templ.replace("%" + var + "%", val)
+
+	# Write out file
+	fout = open(options.out, "w")
+	fout.write(templ)
+	fout.close()
+
+if __name__ == "__main__":
+	main()

+ 83 - 0
tools/material/diff.template.mtl

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<material>
+	<renderingStage>0</renderingStage>
+	
+	<passes>COLOR DEPTH</passes>
+
+	<shaderProgram>
+		<shader>
+			<type>vertex</type>
+			<includes>
+				<include>shaders/MaterialVertex.glsl</include>
+			</includes>
+		
+			<inputs>
+				<input><type>mat4</type><name>modelViewProjectionMat</name><value></value></input>
+				<input><type>mat3</type><name>normalMat</name><value></value></input>
+				<input><type>vec2</type><name>specular</name><value>1.0 90.0</value></input>
+			</inputs>
+
+			<operations>
+				<operation>
+					<id>0</id>
+					<returnType>void</returnType>
+					<function>prepackSpecular</function>
+					<arguments><argument>specular</argument></arguments>
+				</operation>
+
+				<operation>
+					<id>1</id>
+					<returnType>void</returnType>
+					<function>setVaryings2</function>
+					<arguments><argument>modelViewProjectionMat</argument><argument>normalMat</argument></arguments>
+				</operation>
+			</operations>
+		</shader>
+
+		<shader>
+			<type>fragment</type>
+
+			<includes>
+				<include>shaders/MaterialFragmentVariables.glsl</include>
+				<include>shaders/MaterialFragmentFunctions.glsl</include>
+			</includes>
+			
+			<inputs>
+				<input><type>sampler2D</type><name>diffuseMap</name><value>%diffuseMap%</value></input>
+			</inputs>
+			
+			<operations>
+				<operation>
+					<id>0</id>
+					<returnType>vec3</returnType>
+					<function>readRgbFromTexture</function>
+					<arguments>
+						<argument>diffuseMap</argument>
+						<argument>vTexCoords</argument>
+					</arguments>
+				</operation>
+				<operation>
+					<id>1</id>
+					<returnType>vec3</returnType>
+					<function>getNormalSimple</function>
+					<arguments>
+						<argument>vNormal</argument>
+					</arguments>
+				</operation>
+				<operation>
+					<id>2</id>
+					<returnType>void</returnType>
+					<function>writeFais</function>
+					<arguments>
+						<argument>operationOut0</argument>
+						<argument>operationOut1</argument>
+						<argument>vSpecularComponent</argument>
+						<argument>0.0</argument>
+					</arguments>
+				</operation>
+			</operations>
+		</shader>
+	</shaderProgram>
+</material>
+

+ 88 - 0
tools/material/diff_norm.template.mtl

@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<material>
+	<renderingStage>0</renderingStage>
+	
+	<passes>COLOR DEPTH</passes>
+
+	<shaderProgram>
+		<shader>
+			<type>vertex</type>
+			<includes>
+				<include>shaders/MaterialVertex.glsl</include>
+			</includes>
+		
+			<inputs>
+				<input><type>mat4</type><name>modelViewProjectionMat</name><value></value></input>
+				<input><type>mat3</type><name>normalMat</name><value></value></input>
+				<input><type>vec2</type><name>specular</name><value>1.0 90.0</value></input>
+			</inputs>
+
+			<operations>
+				<operation>
+					<id>0</id>
+					<returnType>void</returnType>
+					<function>prepackSpecular</function>
+					<arguments><argument>specular</argument></arguments>
+				</operation>
+
+				<operation>
+					<id>1</id>
+					<returnType>void</returnType>
+					<function>setVaryings2</function>
+					<arguments><argument>modelViewProjectionMat</argument><argument>normalMat</argument></arguments>
+				</operation>
+			</operations>
+		</shader>
+
+		<shader>
+			<type>fragment</type>
+
+			<includes>
+				<include>shaders/MaterialFragmentVariables.glsl</include>
+				<include>shaders/MaterialFragmentFunctions.glsl</include>
+			</includes>
+			
+			<inputs>
+				<input><type>sampler2D</type><name>diffuseMap</name><value>%diffuseMap%</value></input>
+				<input><type>sampler2D</type><name>normalMap</name><value>%normalMap%</value></input>
+			</inputs>
+			
+			<operations>
+				<operation>
+					<id>0</id>
+					<returnType>vec3</returnType>
+					<function>readRgbFromTexture</function>
+					<arguments>
+						<argument>diffuseMap</argument>
+						<argument>vTexCoords</argument>
+					</arguments>
+				</operation>
+				<operation>
+					<id>1</id>
+					<returnType>vec3</returnType>
+					<function>getNormalFromTexture</function>
+					<arguments>
+						<argument>vNormal</argument>
+						<argument>vTangent</argument>
+						<argument>vTangentW</argument>
+						<argument>normalMap</argument>
+						<argument>vTexCoords</argument>
+					</arguments>
+				</operation>
+				<operation>
+					<id>2</id>
+					<returnType>void</returnType>
+					<function>writeFais</function>
+					<arguments>
+						<argument>operationOut0</argument>
+						<argument>operationOut1</argument>
+						<argument>vSpecularComponent</argument>
+						<argument>0.0</argument>
+					</arguments>
+				</operation>
+			</operations>
+		</shader>
+	</shaderProgram>
+</material>
+