Browse Source

Adding python converter from dae to anki mesh format, Adding new XML library

Panagiotis Christopoulos Charitos 13 years ago
parent
commit
a11a16a32a

+ 6 - 0
.project

@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.python.pydev.PyDevBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
 			<triggers>clean,full,incremental,</triggers>
@@ -79,5 +84,6 @@
 		<nature>org.eclipse.cdt.core.ccnature</nature>
 		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
 		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+		<nature>org.python.pydev.pythonNature</nature>
 	</natures>
 </projectDescription>

+ 1 - 1
CMakeLists.txt

@@ -122,7 +122,7 @@ ANKI_ADD_LIB(${BULLET_INCLUDE_DIR}/bullet ${BULLET_LIBRARY_DIR}
 #
 ADD_SUBDIRECTORY(extern)
 
-INCLUDE_DIRECTORIES(extern/GLEW/include)
+INCLUDE_DIRECTORIES(extern/GLEW/include extern/tinyxml2/include)
 INCLUDE_DIRECTORIES(extern/include)
 LINK_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/extern/lib64")
 

+ 93 - 0
include/anki/misc/Xml.h

@@ -0,0 +1,93 @@
+#ifndef ANKI_XML_H
+#define ANKI_XML_H
+
+#include "anki/util/Exception.h"
+#include <tinyxml2.h>
+#if !ANKI_TINYXML2
+#	error "Wrong tinyxml2 included"
+#endif
+
+namespace anki {
+
+/// XXX
+struct XmlElement
+{
+	friend class XmlDocument;
+public:
+	XmlElement()
+	{}
+	XmlElement(const XmlElement& b)
+		: el(b.el)
+	{}
+
+	const char* getText() const
+	{
+		return el->GetText();
+	}
+
+	XmlElement getChildElementOptional(const char* name)
+	{
+		XmlElement out;
+		out.el = el->FirstChildElement(name);
+		return out;
+	}
+
+	XmlElement getChildElement(const char* name)
+	{
+		XmlElement out = getChildElementOptional(name);
+		if(!out)
+		{
+			throw ANKI_EXCEPTION("Cannot find <" + name + ">");
+		}
+		return out;
+	}
+
+	XmlElement getNextSiblingElement(const char* name)
+	{
+		XmlElement out;
+		out.el = el->NextSiblingElement(name);
+		return out;
+	}
+
+	/// If element has something return true
+	operator bool() const
+	{
+		return el != nullptr;
+	}
+
+	XmlElement& operator=(const XmlElement& b)
+	{
+		el = b.el;
+		return *this;
+	}
+
+private:
+	tinyxml2::XMLElement* el = nullptr;
+};
+
+/// XXX
+class XmlDocument
+{
+public:
+	void loadFile(const char* filename)
+	{
+		if(doc.LoadFile(filename))
+		{
+			throw ANKI_EXCEPTION("Cannot parse file");
+		}
+	}
+
+	XmlElement getChildElement(const char* name)
+	{
+		XmlElement el;
+		el.el = doc.FirstChildElement(name);
+		return el;
+	}
+
+private:
+	tinyxml2::XMLDocument doc;
+};
+
+} // end namespace anki
+
+#endif

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

@@ -36,6 +36,7 @@ public:
 
 private:
 	Smo smo;
+	Sm sm;
 	Texture fai;
 	Fbo fbo;
 	BufferObject ubo;

+ 7 - 1
include/anki/scene/Frustumable.h

@@ -57,12 +57,18 @@ public:
 	/// Called when a frustum parameter changes
 	virtual void frustumUpdate() = 0;
 
-	/// Is a spatial inside the frustum
+	/// Is a spatial inside the frustum?
 	bool insideFrustum(const Spatial& sp) const
 	{
 		return frustum->insideFrustum(sp.getSpatialCollisionShape());
 	}
 
+	/// Is a collision shape inside the frustum?
+	bool insideFrustum(const CollisionShape& cs) const
+	{
+		return frustum->insideFrustum(cs);
+	}
+
 protected:
 	Frustum* frustum = nullptr;
 };

+ 1 - 1
include/anki/scene/Light.h

@@ -281,6 +281,6 @@ private:
 	ANKI_SLOT(updateFov, const float&)
 };
 
-} // end namespace
+} // end namespace anki
 
 #endif

+ 5 - 0
include/anki/scene/VisibilityTester.h

@@ -2,6 +2,7 @@
 #define ANKI_SCENE_VISIBILITY_TESTER_H
 
 #include <vector>
+#include <cstdint>
 
 namespace anki {
 
@@ -29,6 +30,10 @@ public:
 	{
 		return renderables.end();
 	}
+	uint32_t getRenderablesCount() const
+	{
+		return renderables.size();
+	}
 
 	Lights::iterator getLightsBegin()
 	{

+ 1 - 1
shaders/IsLpGeneric.glsl

@@ -16,7 +16,7 @@
 /// @{
 
 /// Watch the placement
-layout(std140) uniform uniforms
+layout(std140, row_major) uniform uniforms
 {
 	/// For the calculation of frag pos in view space. Only the .xy is used
 	uniform vec4 planes_;

+ 2 - 6
src/CMakeLists.txt

@@ -1,5 +1,4 @@
-SET(ANKI_SUB_DIRS script renderer scene ui event 
-	input physics resource core misc gl collision math util)
+SET(ANKI_SUB_DIRS script renderer scene ui event input physics resource core misc gl collision math util)
 
 SET(ANKI_LIBS "")
 
@@ -10,10 +9,7 @@ ENDFOREACH()
 
 ADD_LIBRARY(anki)
 
-TARGET_LINK_LIBRARIES(anki ${ANKI_LIBS} BulletSoftBody BulletDynamics 
-	BulletCollision LinearMath ankiglew GLU GL jpeg SDL png python${PYTHON_VER}
-	boost_system boost_python boost_filesystem boost_thread boost_regex 
-	freetype)
+TARGET_LINK_LIBRARIES(anki ${ANKI_LIBS} BulletSoftBody BulletDynamics BulletCollision LinearMath ankiglew ankitinyxml2 GLU GL jpeg SDL png python${PYTHON_VER} boost_system boost_python boost_thread freetype)
 
 SET_TARGET_PROPERTIES(anki PROPERTIES LINKER_LANGUAGE CXX)
 

+ 4 - 2
src/gl/BufferObject.cpp

@@ -58,10 +58,13 @@ void BufferObject::write(void* buff)
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(usage != GL_STATIC_DRAW);
 	bind();
+#if 0
 	void* mapped = glMapBuffer(target, GL_WRITE_ONLY);
 	memcpy(mapped, buff, sizeInBytes);
 	glUnmapBuffer(target);
-	unbind();
+#else
+	glBufferData(target, sizeInBytes, buff, usage);
+#endif
 }
 
 //==============================================================================
@@ -75,7 +78,6 @@ void BufferObject::write(void* buff, size_t offset, size_t size)
 	ANKI_ASSERT(mapped != nullptr);
 	memcpy(mapped, buff, size);
 	glUnmapBuffer(target);
-	unbind();
 }
 
 } // end namespace

+ 85 - 1
src/renderer/Is.cpp

@@ -24,7 +24,7 @@ struct UniformBlockData
 
 //==============================================================================
 Is::Is(Renderer* r_)
-	: RenderingPass(r_), smo(r_)
+	: RenderingPass(r_), smo(r_), sm(r_)
 {}
 
 //==============================================================================
@@ -39,6 +39,7 @@ void Is::init(const RendererInitializer& initializer)
 		// Init the passes
 		//
 		smo.init(initializer);
+		sm.init(initializer);
 
 		// Load the programs
 		//
@@ -120,6 +121,8 @@ void Is::pointLightPass(PointLight& light)
 {
 	const Camera& cam = r->getScene().getActiveCamera();
 
+	/// XXX write the UBO async before calling SMO
+
 	// SMO
 	smo.run(light);
 	GlStateSingleton::get().disable(GL_DEPTH_TEST);
@@ -149,6 +152,86 @@ void Is::pointLightPass(PointLight& light)
 	r->drawQuad();
 }
 
+//==============================================================================
+void Is::spotLightPass(SpotLight& light)
+{
+	const Camera& cam = r->getScene().getActiveCamera();
+	const ShaderProgram* shdr;
+	//bool withShadow = light.getShadowEnabled() && sm.getEnabled();
+	bool withShadow = false;
+
+	// shadow mapping
+	if(withShadow)
+	{
+		/*Vec3 zAxis = light.getWorldTransform().getRotation().getColumn(2);
+			LineSegment seg(light.getWorldTransform().getOrigin(),
+		-zAxis * light.getCamera().getZFar());
+
+		const Plane& plane = cam.getWSpaceFrustumPlane(Camera::FP_NEAR);
+
+		float dist = seg.testPlane(plane);
+
+		sm.run(light, dist);
+
+		// restore the IS FBO
+		fbo.bind();
+
+		// and restore blending and depth test
+		GlStateMachineSingleton::get().enable(GL_BLEND, BLEND_ENABLE);
+		glBlendFunc(GL_ONE, GL_ONE);
+		GlStateMachineSingleton::get().enable(GL_DEPTH_TEST, false);
+		GlStateMachineSingleton::get().setViewport(0, 0,
+		r.getWidth(), r.getHeight());*/
+		shdr = spotLightShadowSProg.get();
+	}
+	else
+	{
+		shdr = spotLightNoShadowSProg.get();
+	}
+
+	// stencil optimization
+	smo.run(light);
+	GlStateSingleton::get().enable(GL_DEPTH_TEST, false);
+
+	shdr->bind();
+
+	// the block
+	UniformBlockData data;
+	data.planes = Vec4(r->getPlanes(), 0.0, 0.0);
+	data.limitsOfNearPlane = Vec4(r->getLimitsOfNearPlane(),
+		r->getLimitsOfNearPlane2());
+	data.zNearLightRadius = Vec4(cam.getNear(), light.getDistance(), 0.0, 0.0);
+	Vec3 lightPosEyeSpace = light.getWorldTransform().getOrigin().
+		getTransformed(cam.getViewMatrix());
+	data.lightPos = Vec4(lightPosEyeSpace, 0.0);
+	data.lightDiffuseCol = light.getDiffuseColor();
+	data.lightSpecularCol = light.getSpecularColor();
+
+	// set texture matrix for texture & shadowmap projection
+	// Bias * P_light * V_light * inv(V_cam)
+	static const Mat4 biasMat4(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0,
+		0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0);
+	data.texProjectionMat = biasMat4 * light.getProjectionMatrix() *
+		Mat4::combineTransformations(light.getViewMatrix(),
+		Mat4(cam.getWorldTransform()));
+
+	ubo.write(&data, 0, sizeof(UniformBlockData));
+
+	// bind the FAIs
+	shdr->findUniformVariable("msFai0").set(r->getMs().getFai0());
+	shdr->findUniformVariable("msDepthFai").set(r->getMs().getDepthFai());
+	shdr->findUniformVariable("lightTex").set(light.getTexture());
+
+	// the shadowmap
+	if(withShadow)
+	{
+		shdr->findUniformVariable("shadowMap").set(sm.getShadowMap());
+	}
+
+	// render quad
+	r->drawQuad();
+}
+
 //==============================================================================
 void Is::run()
 {
@@ -179,6 +262,7 @@ void Is::run()
 		switch(light.getLightType())
 		{
 		case Light::LT_SPOT:
+			spotLightPass(static_cast<SpotLight&>(light));
 			break;
 		case Light::LT_POINT:
 			pointLightPass(static_cast<PointLight&>(light));

+ 39 - 1
src/renderer/Smo.cpp

@@ -117,11 +117,49 @@ void Smo::run(const PointLight& light)
 	sphereGeom.vao.bind();
 	glDrawElements(GL_TRIANGLES, sphereGeom.mesh->getIndicesNumber(0),
 		GL_UNSIGNED_SHORT, 0);
-	sphereGeom.vao.unbind();
 
 	// restore GL
 	restoreGl(inside);
 
 }
 
+//==============================================================================
+void Smo::run(const SpotLight& light)
+{
+	const Camera& cam = r->getScene().getActiveCamera();
+	const Vec3& origin = cam.getWorldTransform().getOrigin();
+	float radius = cam.getNear() + THRESHOLD;
+	bool inside =  light.insideFrustum(Sphere(origin, radius));
+
+	// set GL state
+	setupGl(inside);
+
+	// Calc the camera shape scale matrix
+	Mat4 localMat(Mat4::getIdentity());
+
+	// Scale in x
+	localMat(0, 0) = tan(light.getFovX() / 2.0) * light.getFar();
+	// Scale in y
+	localMat(1, 1) = tan(light.getFovY() / 2.0) * light.getFar();
+	localMat(2, 2) = light.getFar(); // Scale in z
+
+	const Geom& cg = camGeom[0];
+
+	// Setup the sprog
+	sProg->bind();
+	Mat4 modelMat = Mat4(light.getWorldTransform());
+
+	Mat4 trf = cam.getViewProjectionMatrix() * modelMat * localMat;
+	sProg->findUniformVariable("modelViewProjectionMat").set(trf);
+
+	// Render
+	//
+	cg.vao.bind();
+	glDrawElements(GL_TRIANGLES, cg.mesh->getIndicesNumber(0),
+		GL_UNSIGNED_SHORT, 0);
+
+	// restore GL state
+	restoreGl(inside);
+}
+
 } // end namespace anki

+ 1 - 1
src/resource/Material.cpp

@@ -99,7 +99,7 @@ void Material::load(const char* filename)
 	{
 		using namespace boost::property_tree;
 		ptree pt;
-		read_xml(filename, pt);
+		read_xml(filename, pt, xml_parser::no_comments);
 		parseMaterialTag(pt.get_child("material"));
 	}
 	catch(std::exception& e)

+ 3 - 13
testapp/Main.cpp

@@ -38,6 +38,7 @@
 #include "anki/resource/ShaderProgramPrePreprocessor.h"
 #include "anki/resource/Material.h"
 #include "anki/core/ParallelManager.h"
+#include "anki/misc/Xml.h"
 
 using namespace anki;
 
@@ -67,13 +68,6 @@ void init()
 		1.0));
 	scene.setActiveCamera(cam);
 
-	// XXX
-	PerspectiveCamera* ccam = new PerspectiveCamera("ccam",
-		&scene, Movable::MF_NONE, nullptr);
-	ccam->setAll(
-		MainRendererSingleton::get().getAspectRatio() * Math::toRad(ang),
-		Math::toRad(ang), 0.5, 20.0);
-
 	// lights
 
 	SpotLight* spot = new SpotLight("spot0", &scene, Movable::MF_NONE, nullptr);
@@ -95,8 +89,8 @@ void init()
 	PointLight* point1 = new PointLight("point1", &scene, Movable::MF_NONE,
 		nullptr);
 	point1->setRadius(3.0);
-	point1->setDiffuseColor(Vec4(10.0, 10.0, 10.0, 0.0));
-	point1->setSpecularColor(Vec4(0.0, 0.0, 1.0, 0.0));
+	point1->setDiffuseColor(Vec4(2.0, 2.0, 2.0, 0.0));
+	point1->setSpecularColor(Vec4(3.0, 3.0, 0.0, 0.0));
 	point1->getLocalTransform().setOrigin(Vec3(-3.0, 2.0, 0.0));
 
 	// horse
@@ -125,10 +119,6 @@ void mainLoopExtra()
 	{
 		mover = &SceneSingleton::get().getActiveCamera();
 	}
-	if(in.getKey(SDL_SCANCODE_2))
-	{
-		mover = SceneSingleton::get().findSceneNode("ccam")->getMovable();
-	}
 	if(in.getKey(SDL_SCANCODE_3))
 	{
 		mover = SceneSingleton::get().findSceneNode("spot0")->getMovable();

+ 249 - 0
tools/dae2anki/dae2anki.py

@@ -0,0 +1,249 @@
+#!/usr/bin/python3
+
+import optparse
+import xml.etree.cElementTree as xml
+from struct import pack
+
+class Vector:
+	""" 3D vector """
+	def __init__(self, x, y, z):
+		self.x = x
+		self.y = y
+		self.z = z
+
+	def __eq__(self, b):
+		return self.x == b.x and self.y == b.y and self.z == b.z
+
+	def __ne__(self, b):
+		return not self.__eq__(b)
+
+	def __str__(self):
+		return "x: %f, y: %f, z: %f" %(self.x, self.y, self.z)
+
+class Vertex:
+	""" Vertex """
+	def __init__(self):
+		self.position = Vector(0.0, 0.0, 0.0)
+		self.uv = Vector(0.0, 0.0, 0.0)
+
+	def __eq__(self, b):
+		return self.position == b.position and self.uv == b.uv
+
+	def __ne__(self, b):
+		return not self.__eq__(b)
+
+	def __srt__(self):
+		return "pos: %s, uv: %s" % (self.position.__str__(), self.uv.__str__())
+
+class Mesh:
+	def __init__(self):
+		self.name = ""
+		self.vertices = []
+		self.indices = []
+
+def parse_commandline():
+	""" Parse the command line arguments """
+	parser = optparse.OptionParser("usage: %prog [options]")
+	parser.add_option("-i", "--input", dest="inp",
+		type="string", help="specify the .DAE file to parse")
+	parser.add_option("-o", "--output", dest="out",
+		type="string", help="specify the directory to save the files")
+	(options, args) = parser.parse_args()
+
+	if not options.inp or not options.out:
+		parser.error("argument is missing")
+
+	return (options.inp, options.out)
+
+def parse_library_geometries(el):
+	geometries = []
+
+	geometry_el_arr = el.findall("geometry")
+	for geometry_el in geometry_el_arr:
+		geometries.append(parse_geometry(geometry_el))
+
+	return geometries
+
+def parse_float_array(float_array_el):
+	""" XXX """
+	floats = []
+
+	tokens = [x.strip() for x in float_array_el.text.split(' ')]
+
+	for token in tokens:
+		if token:
+			floats.append(float(token))
+
+	return floats
+
+def get_positions_and_uvs(mesh_el):
+	""" Given a <mesh> get the positions and the UVs float_array. Also return
+		the offset of the mesh/polylist/input:offset for those two arrays """
+	positions_float_array = None
+	uvs_float_array = None
+
+	# First get all
+	source_elarr = mesh_el.findall("source")
+	all_float_array = {}
+	for source_el in source_elarr:
+		source_id = source_el.get("id")
+	
+		float_array_el = source_el.find("float_array")
+		all_float_array[source_id] = parse_float_array(float_array_el)
+
+	# Create a link between vertices:id and vertices/input:source
+	vertices_id_to_source = {}
+	vertices_el = mesh_el.find("vertices")
+	vertices_id = vertices_el.get("id")
+	input_el = vertices_el.find("input")
+	vertices_input_source = input_el.get("source")
+	vertices_id_to_source[vertices_id] = vertices_input_source[1:]
+
+	# Now find what it is what
+	input_elarr = mesh_el.findall("polylist/input")
+	for input_el in input_elarr:
+		semantic = input_el.get("semantic")
+		source = input_el.get("source")
+		offset = input_el.get("offset")
+
+		if semantic == "VERTEX":
+			print("-- Found positions float_array")
+			positions_float_array = \
+				all_float_array[vertices_id_to_source[source[1:]]]
+			positions_offset = offset
+		elif semantic == "TEXCOORD":
+			print("-- Found uvs float_array")
+			uvs_float_array = all_float_array[source[1:]]
+			uvs_offset = offset
+
+	return (positions_float_array, int(positions_offset), 
+		uvs_float_array, int(uvs_offset))
+
+def search_in_array(arr, el):
+	""" XXX """
+	for i in range(0, len(arr)):
+		if arr[i] == el:
+			return i
+	return -1
+
+def parse_geometry(geometry_el):
+	""" XXX """
+
+	geom_name = geometry_el.get("name")
+	print("-- geometry: %s" % geom_name)
+
+	(positions_float_array, positions_offset, uvs_float_array, uvs_offset) = \
+		get_positions_and_uvs(geometry_el.find("mesh"))
+
+	# Get vcount
+	vcount = []
+	tokens = [x.strip() for x in 
+		geometry_el.find("mesh/polylist/vcount").text.split(" ")]
+
+	for token in tokens:
+		if token:
+			vcount.append(int(token))
+
+	face_count = len(vcount)
+
+	# 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
+	p = []
+	tokens = [x.strip() for x in 
+		geometry_el.find("mesh/polylist/p").text.split(" ")]
+
+	for token in tokens:
+		if token:
+			p.append(int(token))
+
+	# For every face
+	verts = []
+	indices = []
+	for fi in range(0, face_count):
+		v_num = vcount[fi]
+
+		if v_num > 3:
+			raise Exception("Only triangles are alowed")
+
+		# Get the positions for each vertex
+		for vi in range(0, 3):
+			index = p[fi * 3 * 3 + vi * 3 + positions_offset]
+			
+			pos = Vector(positions_float_array[index * 3], 
+				positions_float_array[index * 3 + 1], 
+				positions_float_array[index * 3 + 2])
+
+			index = p[fi * 3 * 3 + vi * 3 + uvs_offset]
+
+			uv = Vector(uvs_float_array[index * 2], 
+				uvs_float_array[index * 2 + 1], 0.0)
+			
+			vert = Vertex()
+			vert.position = pos
+			vert.uv = uv
+
+			i = search_in_array(verts, vert)
+			if i == -1:
+				verts.append(vert)
+				indices.append(len(verts) - 1)
+			else:
+				indices.append(i)
+
+	# Create geometry
+	geom = Mesh()
+	geom.vertices = verts
+	geom.indices = indices
+	geom.name = geom_name
+	return geom
+
+def write_mesh(mesh, directory):
+	""" XXX """
+	f = open(directory + "/" + mesh.name + ".mesh", "wb")
+	
+	# Magic
+	buff = pack("8s", b"ANKIMESH")
+
+	# Mesh name
+	buff += pack("I" + str(len(mesh.name)) + "s", len(mesh.name), 
+		mesh.name.encode("utf-8"))
+
+	# Verts num
+	buff += pack("I", len(mesh.vertices))
+
+	# Verts
+	for vert in mesh.vertices:
+		buff += pack("fff", vert.position.x, vert.position.y, vert.position.z)
+
+	# Tris num
+	buff += pack("I", int(len(mesh.indices) / 3))
+
+	# Indices
+	for i in mesh.indices:
+		buff += pack("I", int(i))
+
+	# Tex coords
+	buff += pack("I", len(mesh.vertices))
+	for vert in mesh.vertices:
+		buff += pack("ff", vert.uv.x, vert.uv.y)
+
+	# Vert weight
+	buff += pack("I", 0)
+
+	f.write(buff)
+	f.close()
+
+def main():
+	(infile, outdir) = parse_commandline()
+
+	print("-- Begin...")
+	tree = xml.parse(infile)
+
+	el_arr = tree.findall("library_geometries")
+	for el in el_arr:
+		geometries = parse_library_geometries(el)
+
+		for geom in geometries:
+			write_mesh(geom, outdir)
+
+if __name__ == "__main__":
+	main()