Browse Source

Refactoring

Panagiotis Christopoulos Charitos 12 years ago
parent
commit
244fab225a

+ 1 - 1
bench/Main.cpp

@@ -81,7 +81,7 @@ void initSubsystems()
 	nwinit.majorVersion = 3;
 	nwinit.minorVersion = 0;
 #else
-	nwinit.majorVersion = 4;
+	nwinit.majorVersion = 3;
 	nwinit.minorVersion = 3;
 #endif
 	nwinit.depthBits = 0;

+ 2 - 2
include/anki/Config.h.cmake

@@ -108,8 +108,8 @@
 #define ANKI_MAX_INSTANCES 32
 
 // Renderer and rendering related config options
-#define ANKI_RENDERER_TILES_X_COUNT 16
-#define ANKI_RENDERER_TILES_Y_COUNT 16
+#define ANKI_RENDERER_MAX_TILES_X 16
+#define ANKI_RENDERER_MAX_TILES_Y 16
 
 #define ANKI_RENDERER_USE_MATERIAL_UBOS 0
 

+ 18 - 12
include/anki/renderer/Tiler.h

@@ -24,7 +24,7 @@ class Tiler
 
 public:
 	typedef std::bitset<
-		ANKI_RENDERER_TILES_X_COUNT * ANKI_RENDERER_TILES_Y_COUNT> Bitset;
+		ANKI_RENDERER_MAX_TILES_X * ANKI_RENDERER_MAX_TILES_Y> Bitset;
 
 	Tiler();
 	~Tiler();
@@ -38,32 +38,33 @@ public:
 	void updateTiles(Camera& cam);
 
 	/// Test against all tiles
+	/// @param[in]  collisionShape The collision shape to test
+	/// @param      nearPlane      If true check against the near plane as well
+	/// @param[out] mask           A bitmask that indicates the tiles that the
+	///                            give collision shape is inside
 	Bool test(
-		const CollisionShape& cs,
+		const CollisionShape& collisionShape,
 		Bool nearPlane,
 		Bitset* mask) const;
 
 private:
 	/// Tile planes
 	Vector<Plane> allPlanes;
-	Plane* planesI = nullptr;
-	Plane* planesJ = nullptr;
-	Plane* planesIW = nullptr;
-	Plane* planesJW = nullptr;
+	Plane* planesY = nullptr;
+	Plane* planesX = nullptr;
+	Plane* planesYW = nullptr;
+	Plane* planesXW = nullptr;
 	Plane* nearPlanesW = nullptr;
 	Plane* farPlanesW = nullptr;
 
-	/// The timestamp of the 4 planes update
-	Timestamp planes4UpdateTimestamp = getGlobTimestamp();
-
-	/// A texture of TILES_X_COUNT*TILES_Y_COUNT size and format XXX. Used to
+	/// A texture of tilesXCount * tilesYCount size and format RG32UI. Used to
 	/// calculate the near and far planes of the tiles
 	Texture fai;
 
-	/// Main FBO
+	/// Main FBO for the fai
 	Fbo fbo;
 
-	/// PBO
+	/// PBO buffer that is used to read the data of fai asynchronously
 	Pbo pbo;
 
 	/// Main shader program
@@ -72,8 +73,13 @@ private:
 	const ShaderProgramUniformVariable* depthMapUniform = nullptr; ///< Cache it
 
 	Renderer* r = nullptr;
+
+	/// Used to check if the camera is changed and we need to update the planes
 	const Camera* prevCam = nullptr;
 
+	/// Timestamp for the same reason as prevCam
+	Timestamp planes4UpdateTimestamp = getGlobTimestamp();
+
 	void initInternal(Renderer* r_);
 
 	void testRange(const CollisionShape& cs, Bool nearPlane,

+ 5 - 0
include/anki/util/Array.h

@@ -100,6 +100,11 @@ struct Array
 		return N;
 	}
 };
+
+/// 2D Array. @code Array2d<X, 10, 2> a; @endcode is equivelent to 
+/// @code X a[10][2];
+template<typename T, PtrSize I, PtrSize J>
+using Array2d = Array<Array<T, J>, I>;
 /// @}
 /// @}
 

+ 18 - 6
include/anki/util/File.h

@@ -11,7 +11,15 @@ namespace anki {
 /// @addtogroup filesystem
 /// @{
 
-/// An abstraction over typical files and files in ziped archives.
+/// An abstraction over typical files and files in ziped archives. This class
+/// can read from regular C files, zip files and on Android from the packed
+/// asset files.
+/// To identify the file:
+/// - If the path contains ".ankizip" (eg /path/to/arch.ankizip/path/file.ext) 
+///   it tries to open the archive and read the file from there.
+/// - If the filename starts with '$' it will try to load a system specific 
+///   file. For Android this is a file in the .apk
+/// - If the above are false then try to load a regular C file
 class File
 {
 private:
@@ -20,7 +28,7 @@ private:
 	{
 		FT_C = 1 << 0, ///< C file
 		FT_ZIP = 1 << 1, ///< Ziped file
-		FT_SPECIAL = 1 << 2 ///< For example file located in the android apk 
+		FT_SPECIAL = 1 << 2 ///< For example file is located in the android apk 
 	};
 
 public:
@@ -134,6 +142,10 @@ private:
 	/// Get the current machine's endianness
 	static Endianness getMachineEndianness();
 
+	/// Get the type of the file
+	FileType identifyFile(const char* filename,
+		std::string* archive, std::string* filenameInArchive);
+
 	/// Open a C file
 	void openCFile(const char* filename, U16 flags);
 
@@ -148,13 +160,13 @@ private:
 #endif
 };
 
-/// Directory exists?
-extern Bool directoryExists(const char* filename);
+/// Return true if directory exists?
+extern Bool directoryExists(const char* dir);
 
-/// rm -rf
+/// Equivalent to: rm -rf dir
 extern void removeDirectory(const char* dir);
 
-/// mkdir
+/// Equivalent to: mkdir dir
 extern void createDirectory(const char* dir);
 
 /// @}

+ 2 - 2
pack_data.sh

@@ -1,5 +1,5 @@
 #!/bin/sh
 rm data.ankizip
-cd data
-zip -r ../data.ankizip . -i '*.mtl' '*.mdl' '*.mesh' '*.scene' '*.ankitex' '*.tga' '*.ttf' '*.ogg' '*.glsl' '*.ankipart'
+cd assets
+zip -r ../data.ankizip . -i '*.ankimtl' '*.ankimdl' '*.ankimesh' '*.ankiscene' '*.ankitex' '*.tga' '*.ttf' '*.ogg' '*.glsl' '*.ankipart'
 cd -

+ 1 - 1
shaders/Pack.glsl

@@ -19,7 +19,7 @@ vec3 unpackNormal(in vec2 enc)
 	return normal;
 }
 
-#if GL_ES
+#if GL_ES || __VERSION__ < 400
 // Vectorized version. See clean one at <= r1048
 uint packUnorm4x8(in vec4 v)
 {

+ 2 - 2
src/gl/ShaderProgram.cpp

@@ -377,9 +377,9 @@ void ShaderProgram::create(const char* vertSource, const char* tcSource,
 
 	if(major == 3)
 	{
-		preprocSrc += "#extension GL_ARB_shading_language_420pack : enable\n"
+		/*preprocSrc += "#extension GL_ARB_shading_language_420pack : enable\n"
 			"#extension GL_ARB_shading_language_packing : enable\n"
-			"#extension GL_ARB_gpu_shader5 : enable\n";
+			"#extension GL_ARB_gpu_shader5 : enable\n";*/
 	}
 
 #else

+ 38 - 34
src/renderer/Is.cpp

@@ -9,11 +9,8 @@
 namespace anki {
 
 //==============================================================================
-// Consts
-
-static const U TILES_X_COUNT = ANKI_RENDERER_TILES_X_COUNT;
-static const U TILES_Y_COUNT = ANKI_RENDERER_TILES_Y_COUNT;
-static const U TILES_COUNT = TILES_X_COUNT * TILES_Y_COUNT;
+// Misc                                                                        =
+//==============================================================================
 
 //==============================================================================
 /// Check if the prev ground light vector is almost equal to the current
@@ -101,12 +98,12 @@ struct WriteLightsJob: ThreadJob
 	std::atomic<U32>* spotLightsCount = nullptr;
 	std::atomic<U32>* spotTexLightsCount = nullptr;
 		
-	Array<Array<std::atomic<U32>, TILES_X_COUNT>, TILES_Y_COUNT>*
-		tilePointLightsCount = nullptr;
-	Array<Array<std::atomic<U32>, TILES_X_COUNT>, TILES_Y_COUNT>*
-		tileSpotLightsCount = nullptr;
-	Array<Array<std::atomic<U32>, TILES_X_COUNT>, TILES_Y_COUNT>*
-		tileSpotTexLightsCount = nullptr;
+	Array2d<std::atomic<U32>, 
+		ANKI_RENDERER_MAX_TILES_Y, 
+		ANKI_RENDERER_MAX_TILES_X>
+		* tilePointLightsCount = nullptr,
+		* tileSpotLightsCount = nullptr,
+		* tileSpotTexLightsCount = nullptr;
 
 	Tiler* tiler = nullptr;
 	Is* is = nullptr;
@@ -284,7 +281,9 @@ struct WriteLightsJob: ThreadJob
 		tiler->test(light.getSpatialCollisionShape(), true, &bitset);
 
 		// Bin to the correct tiles
-		for(U t = 0; t < TILES_COUNT; t++)
+		PtrSize tilesCount = 
+			is->r->getTilesCount().x() * is->r->getTilesCount().y();
+		for(U t = 0; t < tilesCount; t++)
 		{
 			// If not in tile bye
 			if(!bitset.test(t))
@@ -292,8 +291,8 @@ struct WriteLightsJob: ThreadJob
 				continue;
 			}
 
-			U x = t % TILES_X_COUNT;
-			U y = t / TILES_X_COUNT;
+			U x = t % is->r->getTilesCount().x();
+			U y = t / is->r->getTilesCount().x();
 
 			U tilePos = (*tilePointLightsCount)[y][x].fetch_add(1);
 
@@ -312,7 +311,9 @@ struct WriteLightsJob: ThreadJob
 		tiler->test(light.getSpatialCollisionShape(), true, &bitset);
 
 		// Bin to the correct tiles
-		for(U t = 0; t < TILES_COUNT; t++)
+		PtrSize tilesCount = 
+			is->r->getTilesCount().x() * is->r->getTilesCount().y();
+		for(U t = 0; t < tilesCount; t++)
 		{
 			// If not in tile bye
 			if(!bitset.test(t))
@@ -320,8 +321,8 @@ struct WriteLightsJob: ThreadJob
 				continue;
 			}
 
-			U x = t % TILES_X_COUNT;
-			U y = t / TILES_X_COUNT;
+			U x = t % is->r->getTilesCount().x();
+			U y = t / is->r->getTilesCount().x();
 
 			if(light.getShadowEnabled())
 			{
@@ -352,7 +353,7 @@ struct WriteLightsJob: ThreadJob
 		PtrSize offset;
 
 		// Calc the start of the tile
-		offset = (tileY * TILES_X_COUNT + tileX) * tileSize;
+		offset = (tileY * is->r->getTilesCount().x() + tileX) * tileSize;
 
 		// Skip the lightsCount header
 		offset += sizeof(Vec4);
@@ -438,9 +439,10 @@ void Is::initInternal(const RendererInitializer& initializer)
 	//
 	std::stringstream pps;
 
-	pps << "\n#define TILES_X_COUNT " << TILES_X_COUNT
-		<< "\n#define TILES_Y_COUNT " << TILES_Y_COUNT 
-		<< "\n#define TILES_COUNT " << TILES_COUNT
+	pps << "\n#define TILES_X_COUNT " << r->getTilesCount().x()
+		<< "\n#define TILES_Y_COUNT " << r->getTilesCount().y()
+		<< "\n#define TILES_COUNT " 
+		<< (r->getTilesCount().x() * r->getTilesCount().y())
 		<< "\n#define RENDERER_WIDTH " << r->getWidth()
 		<< "\n#define RENDERER_HEIGHT " << r->getHeight()
 		<< "\n#define MAX_POINT_LIGHTS_PER_TILE " << (U32)maxPointLightsPerTile
@@ -708,16 +710,16 @@ void Is::lightPass()
 	std::atomic<U32> spotLightsAtomicCount(0);
 	std::atomic<U32> spotTexLightsAtomicCount(0);
 
-	Array<Array<std::atomic<U32>, TILES_X_COUNT>, TILES_Y_COUNT>
-		tilePointLightsCount;
-	Array<Array<std::atomic<U32>, TILES_X_COUNT>, TILES_Y_COUNT>
-		tileSpotLightsCount;
-	Array<Array<std::atomic<U32>, TILES_X_COUNT>, TILES_Y_COUNT>
+	Array2d<std::atomic<U32>, 
+		ANKI_RENDERER_MAX_TILES_Y, 
+		ANKI_RENDERER_MAX_TILES_X> 
+		tilePointLightsCount,
+		tileSpotLightsCount,
 		tileSpotTexLightsCount;
 
-	for(U y = 0; y < TILES_Y_COUNT; y++)
+	for(U y = 0; y < r->getTilesCount().y(); y++)
 	{
-		for(U x = 0; x < TILES_X_COUNT; x++)
+		for(U x = 0; x < r->getTilesCount().x(); x++)
 		{
 			tilePointLightsCount[y][x].store(0);
 			tileSpotLightsCount[y][x].store(0);
@@ -762,15 +764,16 @@ void Is::lightPass()
 	threadPool.waitForAllJobsToFinish();
 
 	// Write the light count for each tile
-	for(U y = 0; y < TILES_Y_COUNT; y++)
+	for(U y = 0; y < r->getTilesCount().y(); y++)
 	{
-		for(U x = 0; x < TILES_X_COUNT; x++)
+		for(U x = 0; x < r->getTilesCount().x(); x++)
 		{
 			const PtrSize tileSize = calcTileSize();
 			UVec4* vec;
 
 			vec = (UVec4*)(
-				&tilesClientBuffer[0] + (y * TILES_X_COUNT + x) * tileSize);
+				&tilesClientBuffer[0] + (y * r->getTilesCount().x() + x) 
+				* tileSize);
 
 			vec->x() = tilePointLightsCount[y][x].load();
 			clamp(vec->x(), maxPointLightsPerTile);
@@ -822,7 +825,7 @@ void Is::lightPass()
 		rejectProg->findUniformVariable("depthMap").set(
 			r->getMs().getDepthFai());
 
-		glDispatchCompute(TILES_X_COUNT, TILES_Y_COUNT, 1);
+		glDispatchCompute(r->getTilesCount().x(), r->getTilesCount().y(), 1);
 
 		tilesBuffer.setTarget(GL_UNIFORM_BUFFER);
 	}
@@ -867,7 +870,8 @@ void Is::lightPass()
 	lightPassProg->findUniformVariable("shadowMapArr").set(sm.sm2DArrayTex);
 
 	quadVao.bind();
-	glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, TILES_COUNT);
+	glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 
+		r->getTilesCount().x() * r->getTilesCount().y());
 }
 
 //==============================================================================
@@ -974,7 +978,7 @@ PtrSize Is::calcTileSize() const
 //==============================================================================
 PtrSize Is::calcTilesUboSize() const
 {
-	return calcTileSize() * TILES_COUNT;
+	return calcTileSize() * r->getTilesCount().x() * r->getTilesCount().y();
 }
 
 } // end namespace anki

+ 40 - 30
src/renderer/Tiler.cpp

@@ -10,6 +10,10 @@
 
 namespace anki {
 
+//==============================================================================
+// Misc                                                                        =
+//==============================================================================
+
 //==============================================================================
 #define CHECK_PLANE_PTR(p_) \
 	ANKI_ASSERT(p_ < &tiler->allPlanes[tiler->allPlanes.size()]);
@@ -35,10 +39,13 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 
 		if(frustumChanged)
 		{
+			// Re-calculate the planes in local space
+
 			const F32 fx = cam->getFovX();
 			const F32 fy = cam->getFovY();
 			const F32 n = cam->getNear();
 
+			// Calculate l6 and o6 used to rotate the planes
 			F32 l = 2.0 * n * tan(fx / 2.0);
 			F32 l6 = l / tiler->r->getTilesCount().x();
 			F32 o = 2.0 * n * tan(fy / 2.0);
@@ -53,9 +60,9 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 			{
 				calcPlaneI(i, o6);
 
-				CHECK_PLANE_PTR(&tiler->planesIW[i]);
-				CHECK_PLANE_PTR(&tiler->planesI[i]);
-				tiler->planesIW[i] = tiler->planesI[i].getTransformed(trf);
+				CHECK_PLANE_PTR(&tiler->planesYW[i]);
+				CHECK_PLANE_PTR(&tiler->planesY[i]);
+				tiler->planesYW[i] = tiler->planesY[i].getTransformed(trf);
 			}
 
 			// Then the right looking planes
@@ -67,9 +74,9 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 			{
 				calcPlaneJ(j, l6);
 
-				CHECK_PLANE_PTR(&tiler->planesJW[j]);
-				CHECK_PLANE_PTR(&tiler->planesJ[j]);
-				tiler->planesJW[j] = tiler->planesJ[j].getTransformed(trf);
+				CHECK_PLANE_PTR(&tiler->planesXW[j]);
+				CHECK_PLANE_PTR(&tiler->planesX[j]);
+				tiler->planesXW[j] = tiler->planesX[j].getTransformed(trf);
 			}
 		}
 		else
@@ -83,9 +90,9 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 
 			for(U i = start; i < end; i++)
 			{
-				CHECK_PLANE_PTR(&tiler->planesIW[i]);
-				CHECK_PLANE_PTR(&tiler->planesI[i]);
-				tiler->planesIW[i] = tiler->planesI[i].getTransformed(trf);
+				CHECK_PLANE_PTR(&tiler->planesYW[i]);
+				CHECK_PLANE_PTR(&tiler->planesY[i]);
+				tiler->planesYW[i] = tiler->planesY[i].getTransformed(trf);
 			}
 
 			// Then the right looking planes
@@ -95,9 +102,9 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 
 			for(U j = start; j < end; j++)
 			{
-				CHECK_PLANE_PTR(&tiler->planesJW[j]);
-				CHECK_PLANE_PTR(&tiler->planesJ[j]);
-				tiler->planesJW[j] = tiler->planesJ[j].getTransformed(trf);
+				CHECK_PLANE_PTR(&tiler->planesXW[j]);
+				CHECK_PLANE_PTR(&tiler->planesX[j]);
+				tiler->planesXW[j] = tiler->planesX[j].getTransformed(trf);
 			}
 		}
 
@@ -145,7 +152,7 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 	{
 		Vec3 a, b;
 		const F32 n = cam->getNear();
-		Plane& plane = tiler->planesI[i];
+		Plane& plane = tiler->planesY[i];
 		CHECK_PLANE_PTR(&plane);
 
 		a = Vec3(0.0, 
@@ -163,7 +170,7 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadJob
 	{
 		Vec3 a, b;
 		const F32 n = cam->getNear();
-		Plane& plane = tiler->planesJ[j];
+		Plane& plane = tiler->planesX[j];
 		CHECK_PLANE_PTR(&plane);
 
 		a = Vec3((I(j + 1) - I(tiler->r->getTilesCount().x()) / 2) * l6, 
@@ -247,12 +254,12 @@ void Tiler::initInternal(Renderer* r_)
 
 	allPlanes.resize(planesCount);
 
-	planesJ = &allPlanes[0];
-	planesI = planesJ + r->getTilesCount().x() - 1;
+	planesX = &allPlanes[0];
+	planesY = planesX + r->getTilesCount().x() - 1;
 
-	planesJW = planesI + r->getTilesCount().y() - 1;
-	planesIW = planesJW + r->getTilesCount().x() - 1;
-	nearPlanesW = planesIW + r->getTilesCount().y() - 1;
+	planesXW = planesY + r->getTilesCount().y() - 1;
+	planesYW = planesXW + r->getTilesCount().x() - 1;
+	nearPlanesW = planesYW + r->getTilesCount().y() - 1;
 	farPlanesW = nearPlanesW + r->getTilesCount().x() * r->getTilesCount().y();
 }
 
@@ -298,7 +305,7 @@ void Tiler::updateTiles(Camera& cam)
 	Array<UpdatePlanesPerspectiveCameraJob, ThreadPool::MAX_THREADS> jobs;
 	U32 camTimestamp = cam.getFrustumable()->getFrustumableTimestamp();
 
-	// Transform only the planes when:
+	// Do a job that transforms only the planes when:
 	// - it is the same camera as before and
 	// - the camera frustum have not changed
 	Bool frustumChanged =
@@ -325,11 +332,13 @@ void Tiler::updateTiles(Camera& cam)
 		break;
 	}
 
+	// Update timestamp
 	if(frustumChanged)
 	{
 		planes4UpdateTimestamp = getGlobTimestamp();
 	}
 
+	// Sync threads
 	threadPool.waitForAllJobsToFinish();
 
 	// 
@@ -346,6 +355,7 @@ Bool Tiler::test(
 {
 	Bitset bitset;
 
+	/// Call the recursive function
 	testRange(cs, nearPlane, 0, r->getTilesCount().y(), 0, 
 		r->getTilesCount().x(), bitset);
 
@@ -359,17 +369,17 @@ Bool Tiler::test(
 
 //==============================================================================
 void Tiler::testRange(const CollisionShape& cs, Bool nearPlane,
-	U iFrom, U iTo, U jFrom, U jTo, Bitset& bitset) const
+	U yFrom, U yTo, U xFrom, U xTo, Bitset& bitset) const
 {
-	U mi = (iTo - iFrom) / 2;
-	U mj = (jTo - jFrom) / 2;
+	U mi = (yTo - yFrom) / 2;
+	U mj = (xTo - xFrom) / 2;
 
 	ANKI_ASSERT(mi == mj && "Change the algorithm if they are not the same");
 
 	// Handle final
 	if(mi == 0 || mj == 0)
 	{
-		U tileId = iFrom * r->getTilesCount().x() + jFrom;
+		U tileId = yFrom * r->getTilesCount().x() + xFrom;
 
 		Bool inside = true;
 
@@ -404,11 +414,11 @@ void Tiler::testRange(const CollisionShape& cs, Bool nearPlane,
 		return;
 	}
 
-	// Find the correct top lookin plane (i)
-	const Plane& topPlane = planesIW[iFrom + mi - 1];
+	// Pick the correct top lookin plane (y)
+	const Plane& topPlane = planesYW[yFrom + mi - 1];
 
-	// Find the correct right looking plane (j)
-	const Plane& rightPlane = planesJW[jFrom + mj - 1];
+	// Pick the correct right looking plane (x)
+	const Plane& rightPlane = planesXW[xFrom + mj - 1];
 
 	// Do the checks
 	Bool inside[2][2] = {{false, false}, {false, false}};
@@ -459,8 +469,8 @@ void Tiler::testRange(const CollisionShape& cs, Bool nearPlane,
 			if(inside[i][j])
 			{
 				testRange(cs, nearPlane,
-					iFrom + (i * mi), iFrom + ((i + 1) * mi),
-					jFrom + (j * mj), jFrom + ((j + 1) * mj),
+					yFrom + (i * mi), yFrom + ((i + 1) * mi),
+					xFrom + (j * mj), xFrom + ((j + 1) * mj),
 					bitset);
 			}
 		}

+ 11 - 1
src/scene/SceneGraph.cpp

@@ -224,11 +224,21 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 
 	ANKI_COUNTER_START_TIMER(C_SCENE_UPDATE_TIME);
 
+	//
+	// Sync point. Here we wait for all scene's threads
+	//
+
+	// XXX
+
+	//
+	// Reset the frame mem pool
+	//
+	frameAlloc.reset();
+
 	deleteNodesMarkedForDeletion();
 
 	ThreadPool& threadPool = ThreadPoolSingleton::get();
 	(void)threadPool;
-	frameAlloc.reset();
 
 	// XXX Do that in parallel
 	physics.update(prevUpdateTime, crntTime);

+ 1 - 1
src/util/CMakeLists.txt

@@ -1,4 +1,4 @@
-SET(ANKI_UTIL_SOURCES Assert.cpp Exception.cpp Functions.cpp StringList.cpp File.cpp Allocator.cpp Memory.cpp System.cpp)
+SET(ANKI_UTIL_SOURCES Assert.cpp Exception.cpp Functions.cpp StringList.cpp File.cpp Allocator.cpp Memory.cpp System.cpp HighRezTimer.cpp)
 
 IF(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
 	SET(ANKI_UTIL_SOURCES ${ANKI_UTIL_SOURCES} HighRezTimerPosix.cpp FilePosix.cpp)

+ 90 - 44
src/util/File.cpp

@@ -9,6 +9,12 @@
 #	include <android_native_app_glue.h>
 #	include <android/asset_manager.h>
 #endif
+#if ANKI_POSIX
+#	include <sys/stat.h>
+#	include <sys/types.h>
+#	include <dirent.h>
+#	include <cerrno>
+#endif
 
 namespace anki {
 
@@ -41,55 +47,27 @@ void File::open(const char* filename, U16 flags_)
 	ANKI_ASSERT((flags_ & OF_READ) != (flags_ & OF_WRITE));
 
 	//
-	// In the following lines determine the file type and open it
+	// Determine the file type and open it
 	//
 
-#if ANKI_OS == ANKI_OS_ANDROID
-	if(filename[0] == '$')
+	std::string archive, filenameInArchive;
+	FileType ft = identifyFile(filename, &archive, &filenameInArchive);
+
+	switch(ft)
 	{
+#if ANKI_OS == ANKI_OS_ANDROID
+	case FT_SPECIAL:
 		openAndFile(filename, flags_);
-	}
-	else
+		break;
 #endif
-	{
-		const char* aext = ".ankizip";
-		const char* ptrToArchiveExt = strstr(filename, aext);
-
-		if(ptrToArchiveExt == nullptr)
-		{
-			// It's a C file
-			openCFile(filename, flags_);
-		}
-		else
-		{
-			// Maybe it's a file in a zipped archive
-
-			PtrSize fnameLen = strlen(filename);
-			PtrSize extLen = strlen(aext);
-			PtrSize archLen = (PtrSize)(ptrToArchiveExt - filename) + extLen;
-
-			if(archLen + 1 >= fnameLen)
-			{
-				throw ANKI_EXCEPTION("Wrong file inside the archive");
-			}
-
-			std::string archive(filename, archLen);
-
-			if(directoryExists(archive.c_str()))
-			{
-				// It's a directory so failback to C file
-				openCFile(filename, flags_);
-			}
-			else
-			{
-				// It's a ziped file
-
-				std::string filenameInArchive(
-					filename + archLen + 1, fnameLen - archLen);
-
-				openZipFile(archive.c_str(), filenameInArchive.c_str(), flags_);
-			}
-		}
+	case FT_C:
+		openCFile(filename, flags_);
+		break;
+	case FT_ZIP:
+		openZipFile(archive.c_str(), filenameInArchive.c_str(), flags_);
+		break;
+	default:
+		ANKI_ASSERT(0);
 	}
 
 	//
@@ -553,6 +531,74 @@ void File::seek(PtrSize offset, SeekOrigin origin)
 	}
 }
 
+//==============================================================================
+File::FileType File::identifyFile(const char* filename, 
+	std::string* archive_, std::string* filenameInArchive_)
+{
+	ANKI_ASSERT(filename && strlen(filename) > 1);
+
+#if ANKI_OS == ANKI_OS_ANDROID
+	if(filename[0] == '$')
+	{
+		return FT_SPECIAL;
+	}
+	else
+#endif
+	{
+		static const char aext[] = {".ankizip"};
+		const char* ptrToArchiveExt = strstr(filename, aext);
+
+		if(ptrToArchiveExt == nullptr)
+		{
+			// It's a C file
+			return FT_C;
+		}
+		else
+		{
+			// Maybe it's a file in a zipped archive
+
+			PtrSize fnameLen = strlen(filename);
+			const PtrSize extLen = sizeof(aext) - 1;
+			PtrSize archLen = (PtrSize)(ptrToArchiveExt - filename) + extLen;
+
+			if(archLen + 1 >= fnameLen)
+			{
+				throw ANKI_EXCEPTION("To sort archived filename");
+			}
+
+			std::string archive(filename, archLen);
+
+			if(directoryExists(archive.c_str()))
+			{
+				// It's a directory so failback to C file
+				return FT_C;
+			}
+			else
+			{
+				// It's a ziped file
+
+				std::string filenameInArchive(
+					filename + archLen + 1, fnameLen - archLen);
+
+				if(archive_)
+				{
+					*archive_ = archive;
+				}
+
+				if(filenameInArchive_)
+				{
+					*filenameInArchive_ = filenameInArchive;
+				}
+
+				return FT_ZIP;
+			}
+		}
+	}
+
+	ANKI_ASSERT(0);
+	return FT_C;
+}
+
 //==============================================================================
 File::Endianness File::getMachineEndianness()
 {

+ 1 - 0
src/util/FilePosix.cpp

@@ -47,6 +47,7 @@ Bool directoryExists(const char* filename)
 	}
 }
 
+//==============================================================================
 void removeDirectory(const char* dirname)
 {
 	DIR* dir;

+ 36 - 0
src/util/HighRezTimer.cpp

@@ -0,0 +1,36 @@
+#include "anki/util/HighRezTimer.h"
+#include "anki/util/Assert.h"
+
+namespace anki {
+
+//==============================================================================
+void HighRezTimer::start()
+{
+	ANKI_ASSERT(startTime == 0);
+	ANKI_ASSERT(stopTime == 0);
+	startTime = getCurrentTime();
+	stopTime = 0.0;
+}
+
+//==============================================================================
+void HighRezTimer::stop()
+{
+	ANKI_ASSERT(startTime != 0.0);
+	ANKI_ASSERT(stopTime == 0.0);
+	stopTime = getCurrentTime();
+}
+
+//==============================================================================
+HighRezTimer::Scalar HighRezTimer::getElapsedTime() const
+{
+	if(stopTime == 0.0)
+	{
+		return getCurrentTime() - startTime;
+	}
+	else
+	{
+		return stopTime - startTime;
+	}
+}
+
+} // end namespace anki

+ 7 - 37
src/util/HighRezTimerPosix.cpp

@@ -62,43 +62,6 @@ static U32 getMs()
 	return ticks;
 }
 
-//==============================================================================
-void HighRezTimer::start()
-{
-	ANKI_ASSERT(startTime == 0);
-	ANKI_ASSERT(stopTime == 0);
-	startTime = getCurrentTime();
-	stopTime = 0.0;
-}
-
-//==============================================================================
-void HighRezTimer::stop()
-{
-	ANKI_ASSERT(startTime != 0.0);
-	ANKI_ASSERT(stopTime == 0.0);
-	stopTime = getCurrentTime();
-}
-
-//==============================================================================
-HighRezTimer::Scalar HighRezTimer::getElapsedTime() const
-{
-	if(stopTime == 0.0)
-	{
-		return getCurrentTime() - startTime;
-	}
-	else
-	{
-		return stopTime - startTime;
-	}
-}
-
-//==============================================================================
-HighRezTimer::Scalar HighRezTimer::getCurrentTime()
-{
-	// Scalar(ticks) / 1000.0
-	return Scalar(getMs()) * 0.001;
-}
-
 //==============================================================================
 void HighRezTimer::sleep(Scalar sec)
 {
@@ -146,4 +109,11 @@ void HighRezTimer::sleep(Scalar sec)
 	} while(wasError && (errno == EINTR));
 }
 
+//==============================================================================
+HighRezTimer::Scalar HighRezTimer::getCurrentTime()
+{
+	// Scalar(ticks) / 1000.0
+	return Scalar(getMs()) * 0.001;
+}
+
 } // end namespace anki

+ 14 - 12
testapp/Main.cpp

@@ -128,7 +128,7 @@ void init()
 #endif
 
 	// camera
-	cam = new PerspectiveCamera("main-camera", &scene, nullptr,
+	scene.newSceneNode(cam, "main-camera", nullptr,
 		Movable::MF_NONE);
 	const F32 ang = 45.0;
 	cam->setAll(
@@ -148,7 +148,8 @@ void init()
 		{
 			std::string name = "plight" + std::to_string(i) + std::to_string(j);
 
-			PointLight* point = new PointLight(name.c_str(), &scene, nullptr,
+			PointLight* point;
+			scene.newSceneNode(point, name.c_str(), nullptr,
 				Movable::MF_NONE);
 			point->setRadius(0.5);
 			point->setDiffuseColor(Vec4(randFloat(6.0) - 2.0, 
@@ -166,7 +167,8 @@ void init()
 #endif
 
 #if 1
-	SpotLight* spot = new SpotLight("spot0", &scene, nullptr, Movable::MF_NONE);
+	SpotLight* spot;
+	scene.newSceneNode(spot, "spot0", nullptr, Movable::MF_NONE);
 	spot->setOuterAngle(toRad(45.0));
 	spot->setInnerAngle(toRad(15.0));
 	spot->setLocalTransform(Transform(Vec3(8.27936, 5.86285, 1.85526),
@@ -177,7 +179,7 @@ void init()
 	spot->setShadowEnabled(true);
 
 
-	spot = new SpotLight("spot1", &scene, nullptr, Movable::MF_NONE);
+	scene.newSceneNode(spot, "spot1", nullptr, Movable::MF_NONE);
 	spot->setOuterAngle(toRad(45.0));
 	spot->setInnerAngle(toRad(15.0));
 	spot->setLocalTransform(Transform(Vec3(5.3, 4.3, 3.0),
@@ -199,9 +201,9 @@ void init()
 	{
 		Vec3 lightPos = vaseLightPos[i];
 
-		PointLight* point =
-			new PointLight(("vase_plight" + std::to_string(i)).c_str(),
-			&scene, nullptr, Movable::MF_NONE, 
+		PointLight* point;
+		scene.newSceneNode(point, ("vase_plight" + std::to_string(i)).c_str(),
+			nullptr, Movable::MF_NONE, 
 			(i != 100) ? "textures/lens_flare/flares0.ankitex" : nullptr);
 		point->setRadius(2.0);
 		point->setLocalOrigin(lightPos);
@@ -225,13 +227,13 @@ void init()
 		scene.getEventManager().newEvent(mevent, 0.0, 2.0, point, moveData);
 		mevent->enableBits(Event::EF_REANIMATE);
 
-		ParticleEmitter* pe = new ParticleEmitter(
-			("pe" + std::to_string(i)).c_str(), &scene, nullptr,
+		ParticleEmitter* pe;
+		scene.newSceneNode(pe,
+			("pe" + std::to_string(i)).c_str(), nullptr,
 			Movable::MF_NONE, "particles/smoke.ankipart");
 		pe->setLocalOrigin(lightPos);
 
-		pe = new ParticleEmitter(
-			("pef" + std::to_string(i)).c_str(), &scene, nullptr,
+		scene.newSceneNode(pe, ("pef" + std::to_string(i)).c_str(), nullptr,
 			Movable::MF_NONE, "particles/fire.ankipart");
 		pe->setLocalOrigin(lightPos);
 	}
@@ -239,7 +241,7 @@ void init()
 
 #if 1
 	// horse
-	horse = new ModelNode("horse", &scene, nullptr,
+	scene.newSceneNode(horse, "horse", nullptr,
 		Movable::MF_NONE, "models/horse/horse.ankimdl");
 	horse->setLocalTransform(Transform(Vec3(-2, 0, 0), Mat3::getIdentity(),
 		0.7));