Bläddra i källkod

Rename tests to samples

Daniele Bartolini 13 år sedan
förälder
incheckning
a4ecc559eb
100 ändrade filer med 6070 tillägg och 0 borttagningar
  1. 47 0
      samples/CMakeLists.txt
  2. 4 0
      samples/chainsawbuffet/Globals.cpp
  3. 24 0
      samples/chainsawbuffet/Globals.h
  4. 41 0
      samples/chainsawbuffet/design.txt
  5. 22 0
      samples/chainsawbuffet/entities/Background.cpp
  6. 21 0
      samples/chainsawbuffet/entities/Background.h
  7. 57 0
      samples/chainsawbuffet/entities/Bullet.cpp
  8. 24 0
      samples/chainsawbuffet/entities/Bullet.h
  9. 69 0
      samples/chainsawbuffet/entities/Joystick.cpp
  10. 31 0
      samples/chainsawbuffet/entities/Joystick.h
  11. 161 0
      samples/chainsawbuffet/entities/Pg.cpp
  12. 39 0
      samples/chainsawbuffet/entities/Pg.h
  13. 31 0
      samples/chainsawbuffet/entities/SolidSceneNode.cpp
  14. 22 0
      samples/chainsawbuffet/entities/SolidSceneNode.h
  15. 94 0
      samples/chainsawbuffet/entities/Wall.cpp
  16. 22 0
      samples/chainsawbuffet/entities/Wall.h
  17. 103 0
      samples/chainsawbuffet/entities/Zombie.cpp
  18. 30 0
      samples/chainsawbuffet/entities/Zombie.h
  19. 149 0
      samples/chainsawbuffet/maain.cpp
  20. 57 0
      samples/chainsawbuffet/main.cpp
  21. 80 0
      samples/chainsawbuffet/scenes/ArenaScene.cpp
  22. 38 0
      samples/chainsawbuffet/scenes/ArenaScene.h
  23. 0 0
      samples/ciao.txt2
  24. 199 0
      samples/coll2d/coll2d.cpp
  25. 340 0
      samples/collision/collision.cpp
  26. 117 0
      samples/dictionary/dictionary.cpp
  27. 120 0
      samples/editor/CRWObjectModel.cpp
  28. 89 0
      samples/editor/CRWObjectModel.h
  29. 390 0
      samples/editor/Editor.cpp
  30. BIN
      samples/editor/res/arialbd.ttf
  31. BIN
      samples/editor/res/boom.bmp
  32. BIN
      samples/editor/res/closebutton_x.bmp
  33. BIN
      samples/editor/res/terrain.bmp
  34. 1 0
      samples/editor/res/testfile.txt
  35. 30 0
      samples/enumerators/DictionaryEnumerator.cpp
  36. 30 0
      samples/enumerators/ListEnumerator.cpp
  37. 0 0
      samples/filesystem/dir/texture.tga
  38. 1 0
      samples/filesystem/ebay
  39. 220 0
      samples/filesystem/filesystem.cpp
  40. 0 0
      samples/filesystem/regular
  41. 1 0
      samples/filesystem/sgi
  42. 245 0
      samples/fractal/fractal.cpp
  43. 45 0
      samples/generic/generic.cpp
  44. 246 0
      samples/intersection/intersection.cpp
  45. 885 0
      samples/minecrown/WorldTerrain.cpp
  46. 163 0
      samples/minecrown/WorldTerrain.h
  47. 471 0
      samples/minecrown/main.cpp
  48. 238 0
      samples/minecrown/perlin.cpp
  49. 49 0
      samples/minecrown/perlin.h
  50. 697 0
      samples/minecrown/vbo.cpp
  51. BIN
      samples/res/arialbd.ttf
  52. BIN
      samples/res/boom.bmp
  53. BIN
      samples/res/chainsawbuffet/bullets.bmp
  54. BIN
      samples/res/chainsawbuffet/bullets_alpha.bmp
  55. BIN
      samples/res/chainsawbuffet/grass.bmp
  56. BIN
      samples/res/chainsawbuffet/grass.jpg
  57. BIN
      samples/res/chainsawbuffet/joystick.bmp
  58. BIN
      samples/res/chainsawbuffet/pg_body.bmp
  59. BIN
      samples/res/chainsawbuffet/pg_head.bmp
  60. BIN
      samples/res/chainsawbuffet/pg_legs.bmp
  61. BIN
      samples/res/chainsawbuffet/stone_wall_texture.bmp
  62. BIN
      samples/res/chainsawbuffet/tiles.bmp
  63. BIN
      samples/res/chainsawbuffet/tiles.jpeg
  64. BIN
      samples/res/chainsawbuffet/zombie1.bmp
  65. BIN
      samples/res/closebutton_x.bmp
  66. BIN
      samples/res/crate.ctex
  67. BIN
      samples/res/crate.tga
  68. BIN
      samples/res/crw_dir_icon.bmp
  69. BIN
      samples/res/crw_file_icon.bmp
  70. 36 0
      samples/res/editor_editorwindow.xml
  71. 13 0
      samples/res/editor_mainwindow.xml
  72. BIN
      samples/res/grass.ctex
  73. BIN
      samples/res/grass.tga
  74. BIN
      samples/res/grasse.tga
  75. BIN
      samples/res/particle.bmp
  76. BIN
      samples/res/red_down.tga
  77. BIN
      samples/res/red_east.tga
  78. BIN
      samples/res/red_north.tga
  79. BIN
      samples/res/red_south.tga
  80. BIN
      samples/res/red_up.tga
  81. BIN
      samples/res/red_west.tga
  82. BIN
      samples/res/terrain.bmp
  83. BIN
      samples/res/test_texture0.ctex
  84. BIN
      samples/res/test_texture0.tga
  85. BIN
      samples/res/test_texture1.ctex
  86. BIN
      samples/res/test_texture1.tga
  87. BIN
      samples/res/test_texture2.ctex
  88. 1 0
      samples/res/testfile.txt
  89. BIN
      samples/res/times.ttf
  90. 12 0
      samples/res/window.xml
  91. 45 0
      samples/res/window_fractal.xml
  92. 30 0
      samples/res/window_listview.xml
  93. 33 0
      samples/res/window_loader.xml
  94. 37 0
      samples/signalslot/signalslot.cpp
  95. 120 0
      samples/string/string.cpp
  96. BIN
      samples/terrain/res/grass.tga
  97. BIN
      samples/terrain/res/red_down.tga
  98. BIN
      samples/terrain/res/red_east.tga
  99. BIN
      samples/terrain/res/red_north.tga
  100. BIN
      samples/terrain/res/red_south.tga

+ 47 - 0
samples/CMakeLists.txt

@@ -0,0 +1,47 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(tests)
+
+link_directories(${CROWN_BINARY_DIR})
+
+link_libraries(GLU pthread)
+add_executable(terrain terrain/terrain.cpp)
+add_executable(texturing texturing/texturing.cpp)
+add_executable(trash trash/trash.cpp)
+
+set (CHAINSAWBUFFET_SRC
+	chainsawbuffet/Globals.cpp
+	chainsawbuffet/Globals.h
+	chainsawbuffet/main.cpp
+	chainsawbuffet/entities/Background.cpp
+	chainsawbuffet/entities/Bullet.cpp
+	chainsawbuffet/entities/Joystick.cpp
+	chainsawbuffet/entities/Pg.cpp
+	chainsawbuffet/entities/SolidSceneNode.cpp
+	chainsawbuffet/entities/Wall.cpp
+	chainsawbuffet/entities/Zombie.cpp
+	chainsawbuffet/entities/Background.h
+	chainsawbuffet/entities/Bullet.h
+	chainsawbuffet/entities/Joystick.h
+	chainsawbuffet/entities/Pg.h
+	chainsawbuffet/entities/SolidSceneNode.h
+	chainsawbuffet/entities/Wall.h
+	chainsawbuffet/entities/Zombie.h
+	chainsawbuffet/scenes/ArenaScene.cpp
+	chainsawbuffet/scenes/ArenaScene.h
+)
+
+include_directories(chainsawbuffet chainsawbuffet/entities chainsawbuffet/scenes)
+add_executable(chain ${CHAINSAWBUFFET_SRC})
+
+add_executable(fs filesystem/filesystem.cpp)
+add_executable(textrenderer textrenderer/textrenderer.cpp)
+add_executable(collision collision/collision.cpp)
+
+target_link_libraries(terrain crown)
+target_link_libraries(texturing crown)
+target_link_libraries(trash crown)
+target_link_libraries(chain crown)
+target_link_libraries(fs crown)
+target_link_libraries(textrenderer crown)
+target_link_libraries(collision crown)

+ 4 - 0
samples/chainsawbuffet/Globals.cpp

@@ -0,0 +1,4 @@
+#include "Globals.h"
+#include "Joystick.h"
+
+Joystick* Globals::joystick = NULL;

+ 24 - 0
samples/chainsawbuffet/Globals.h

@@ -0,0 +1,24 @@
+#ifndef __GLOBALS_H__
+#define __GLOBALS_H__
+
+class Joystick;
+
+enum CollisionGroups
+{
+	CG_NONE = 0,
+	CG_ZOMBIE = 1,
+	CG_PG = 2,
+	CG_BULLET = 3,
+	CG_WALL = 4
+};
+
+class Globals
+{
+public:
+	static Joystick* joystick;
+
+private:
+	Globals() {};
+};
+
+#endif //__GLOBALS_H__

+ 41 - 0
samples/chainsawbuffet/design.txt

@@ -0,0 +1,41 @@
+ - Chainsaw Buffet - 
+ Le seguenti sono idee per fare brainstorming.
+ 
+ Che cosa deve colpire del gioco: ?violenza?
+ Che cosa invoglia a giocare: Completare i livelli per sbloccare altre modalità, Achievements, Storia di fondo tra i livelli
+ Importante: Ricordare che il target sono smartphone, partite possibilmente brevi ed intense
+ 
+ Idee di zombie:				Dove si trova				Descrizione
+ - Zombie normale				un pò da per tutto			Uno zombie normale che prosegue lentamente
+ - Zombie veloce				un pò da per tutto			Come quello normale, ma zoppica velocemente
+ - Zombie corridore				un pò da per tutto			Corre velocemente, attacca graffiando
+ - Zombie maniaco				Manicomio, ospedale			Abbastanza veloce, decidere l'attacco
+ - Zombie boscaiolo				Case di montagna, bosco		non molto veloce, attacca con la motosega e fa molto male
+ - Zombie poliziotto			Città						Velocità normale, attacca con la pistola o il manganello
+ 
+ Modalità di gioco:
+ - Survival classico: Si sceglie uno scenario e si sopravvive alle ondate.
+ - Avventura: Una quantità di scenari successivi sbloccabili ultimandoli in sequenza.
+   > Ogni scenario si può ripetere in diverse modalità:
+    Ricerca: Bisogna cercare tre oggetti prestabiliti che sono da qualche parte nello scenario o droppati da qualche mostro.
+    Salvataggio: Andare a prendere e portare fuori un personaggio intrappolato.
+	Pulizia: Ucciderne più possibile in un dato tempo. Si trovano power up in giro per la mappa per aumentare la violenza.
+	Difesa della campana: in un posto della mappa c'è una campana da difendere per un determinato tempo. Dopo tre rintocchi si fallisce.
+	
+ Gli scenari della modalità Survival devono essere prima sbloccati nella modalità Avventura
+ 
+ L'uccisione di diversi mostri di fila aumenta il livello di combo, il passare del tempo lo diminuisce. Raggiunto il livello massimo, si può attivare la modalità Bloodlust (berserk con motosega)
+ 
+ 
+ Roadmap:
+ 1.  Personaggio su schermo che si muove con wasd e punta verso il movimento [ok]
+ 2.  Joystick touch da trascinare col mouse [ok]
+ 3.  Grafica con cerchi e quadrati di abbozzo animazioni pg camminata, caricamento arma, altro... per provare sistema di animazione [ok]
+ 4.  Zombie normale con animazione camminata e attacco
+ 5.  Barile
+ 6.  Sistema fisico per gestire le collisioni tra zombie, pg e oggetti (barile)
+ 7.  Muri (rettangoli in pratica, simile al barile)
+ 8.  Abbozzo di ia zombie, ti insegue se ti vede sennò girovaga. Non vede attraverso i muri
+ 9.  Pistola con proiettili, collisione di oggetto ad alta velocità con oggetti e zombie
+ 10. Animazioni di colpito dello zombie (e del pg?)
+ 

+ 22 - 0
samples/chainsawbuffet/entities/Background.cpp

@@ -0,0 +1,22 @@
+#include "Background.h"
+
+Background::Background(Scene* scene, SceneNode* parent, real x, real y):
+	SceneNode(scene, parent, Vec3(x, y, 0), Angles(0, 0, 0), true)
+{
+	mBgSprite = Sprite::LoadSpriteFromImage("res/chainsawbuffet/tiles.bmp");
+}
+
+Background::~Background()
+{
+}
+
+void Background::Update(real dt)
+{
+	SceneNode::Update(dt);
+}
+
+void Background::Render()
+{
+	SceneNode::Render();
+	mBgSprite->draw(0, 0.0, 1.0, 1.0);
+}

+ 21 - 0
samples/chainsawbuffet/entities/Background.h

@@ -0,0 +1,21 @@
+#ifndef __BACKGROUND_H__
+#define __BACKGROUND_H__
+
+#include "Crown.h"
+
+using namespace Crown;
+
+class Background: public SceneNode
+{
+public:
+	Background(Scene* scene, SceneNode* parent, real x, real y);
+	virtual ~Background();
+
+	virtual void Update(real dt);
+	virtual void Render();
+
+private:
+	Auto<Sprite> mBgSprite;
+};
+
+#endif //__BACKGROUND_H__

+ 57 - 0
samples/chainsawbuffet/entities/Bullet.cpp

@@ -0,0 +1,57 @@
+#include "Bullet.h"
+#include "Globals.h"
+#include "Joystick.h"
+#include "ArenaScene.h"
+
+Bullet::Bullet(Scene* scene, SceneNode* parent, real x, real y, Vec3 direction, real speed):
+	PhysicNode(scene, parent, Vec3(x, y, 0), Angles(0, 0, 0), true, CG_BULLET), mHasCollided(false)
+{
+	//Load the body sprite
+	mTrailSprite = Sprite::LoadSpriteFromImage("res/chainsawbuffet/bullets.bmp", "res/chainsawbuffet/bullets_alpha.bmp", 1, 1, 1, 1, 1, 10, 3, 0, 0);
+	for(int i = 0; i < mTrailSprite->GetFrameCount(); i++)
+	{
+		mTrailSprite->GetFrame(i)->SetOffset(0, 1);
+	}
+	mTrailSprite->SetInterpolation(true);
+	mTrailSpriteAnimator.SetSprite(mTrailSprite.GetPointer());
+	mTrailSpriteAnimator.SetFrameInterval(0);
+	mTrailSpriteAnimator.SetScaleX(6);
+
+	SetUseIntegerCoordinatesForRendering(true);
+
+	SetVelocity(direction * speed);
+
+	Circle* c = new Circle(Vec2::ZERO, 2);
+	//SetShape(c);
+}
+
+Bullet::~Bullet()
+{
+}
+
+void Bullet::Collision(PhysicNode* other)
+{
+	if (!mHasCollided)
+	{
+		mHasCollided = true;
+		ArenaScene* arena = (ArenaScene*)GetCreator();
+		ParticleManager* manager = arena->GetParticleManager();
+		manager->AddEmitter(new ParticleEmitter(mPosition, 0.01, 0.2, GetVelocity().ToVec2().GetAngle() + Math::PI, Math::PI / 6));
+		SetVelocity(Vec3::ZERO);
+	}
+}
+
+void Bullet::Update(real dt)
+{
+	mTrailSpriteAnimator.SetAngle(GetVelocity().ToVec2().GetAngle() + Math::PI);
+	PhysicNode::Update(dt);
+}
+
+void Bullet::Render()
+{
+	PhysicNode::Render();
+	Renderer* r = GetDevice()->GetRenderer();
+	mTrailSpriteAnimator.Render();
+	r->DrawRectangle(Point2(-1, -1), Point2(2, 2), DM_FILL, Color4::BLACK, Color4::BLACK);
+	//mBodySpriteAnimator.Render();
+}

+ 24 - 0
samples/chainsawbuffet/entities/Bullet.h

@@ -0,0 +1,24 @@
+#ifndef __BULLET_H__
+#define __BULLET_H__
+
+#include "Crown.h"
+
+using namespace Crown;
+
+class Bullet: public PhysicNode
+{
+public:
+	Bullet(Scene* scene, SceneNode* parent, real x, real y, Vec3 direction, real speed);
+	virtual ~Bullet();
+
+	virtual void Update(real dt);
+	virtual void Render();
+	virtual void Collision(PhysicNode* other);
+
+private:
+	Auto<Sprite> mTrailSprite;
+	SpriteAnimator mTrailSpriteAnimator;
+	bool mHasCollided;
+};
+
+#endif //__BULLET_H__

+ 69 - 0
samples/chainsawbuffet/entities/Joystick.cpp

@@ -0,0 +1,69 @@
+#include "Joystick.h"
+#include "Globals.h"
+
+Joystick::Joystick(Scene* scene, Camera* camera):
+	SolidSceneNode(scene, NULL,  Vec3(0, 0, 0), Angles(0, 0, 0), true, CG_NONE), mDragging(false), 
+	mInitialPosition(80, 400, 0), mMouseStartDragPosition(0, 0, 0),
+	mDelta(0, 0, 0)
+{
+	Globals::joystick = this;
+	mJoystickSprite = Sprite::LoadSpriteFromImage("res/chainsawbuffet/joystick.bmp");
+	mJoystickSprite->GetFrame(0)->SetOffset(64, 64);
+
+	mPosition = mInitialPosition;
+
+	GetDevice()->GetInputManager()->RegisterMouseListener(this);
+}
+
+Joystick::~Joystick()
+{
+	Globals::joystick = NULL;
+	//delete mBodySprite;
+}
+
+const Vec3& Joystick::GetDelta() const
+{
+	return mDelta;
+}
+
+void Joystick::Render()
+{
+	//Do an update
+	mPosition = mInitialPosition + mDelta;
+
+	SolidSceneNode::Render();
+	mJoystickSprite->draw(0);
+}
+
+void Joystick::ButtonPressed(const MouseEvent& event)
+{
+	if (event.button == MB_LEFT)
+	{
+		Point2 mousePosition = GetDevice()->GetInputManager()->GetMouse()->GetCursorXY();
+		mMouseStartDragPosition = Vec3((real)mousePosition.x, (real)mousePosition.y, 0.0);
+
+		mDragging = ((mMouseStartDragPosition - mInitialPosition).GetSquaredLength() <= 60*60);
+	}
+}
+
+void Joystick::ButtonReleased(const MouseEvent& event)
+{
+	if (event.button == MB_LEFT)
+	{
+		mDragging = false;
+		mDelta = Vec3::ZERO;
+	}
+}
+
+void Joystick::CursorMoved(const MouseEvent& event)
+{
+	if (mDragging)
+	{
+		mDelta = GetDevice()->GetInputManager()->GetMouse()->GetCursorXY().ToVec3() - mMouseStartDragPosition;
+		if (mDelta.GetSquaredLength() > 900)
+		{
+			mDelta = mDelta.Normalize() * 30;
+		}
+	}
+}
+

+ 31 - 0
samples/chainsawbuffet/entities/Joystick.h

@@ -0,0 +1,31 @@
+#ifndef __JOYSTICK_H__
+#define __JOYSTICK_H__
+
+#include "SolidSceneNode.h"
+
+using namespace Crown;
+
+class Joystick: public SolidSceneNode, public MouseListener
+{
+public:
+	Joystick(Scene* scene, Camera* camera);
+	virtual ~Joystick();
+
+	virtual void Render();
+
+	virtual void ButtonPressed(const MouseEvent& event);
+	virtual void ButtonReleased(const MouseEvent& event);
+	virtual void CursorMoved(const MouseEvent& event);
+
+	//! Returns the Joystick delta
+	const Vec3& GetDelta() const;
+
+private:
+	Auto<Sprite> mJoystickSprite;
+	bool mDragging;
+	Vec3 mInitialPosition;
+	Vec3 mMouseStartDragPosition;
+	Vec3 mDelta;
+};
+
+#endif //__JOYSTICK_H__

+ 161 - 0
samples/chainsawbuffet/entities/Pg.cpp

@@ -0,0 +1,161 @@
+#include "Pg.h"
+#include "Globals.h"
+#include "Joystick.h"
+#include "Bullet.h"
+#include "ArenaScene.h"
+
+Pg::Pg(Scene* scene, Camera* camera):
+	PhysicNode(scene, camera, Vec3(400, 240, 0), Angles(0, 0, 0), true, CG_PG),
+	mSpeed(0.0), mDirection(1.0, 0.0, 0.0), mIsReloading(false), mBulletCounter(0), mBulletInterval(30)
+{
+	//Load the body sprite
+	mBodySprite = Sprite::LoadSpriteFromImage("res/chainsawbuffet/pg_body.bmp", 4, 1, 4, 0, 0, 46, 36, 0, 0);
+	for(int i = 0; i < mBodySprite->GetFrameCount(); i++)
+	{
+		mBodySprite->GetFrame(i)->SetOffset(13, 16);
+	}
+	mBodySprite->SetInterpolation(true);
+	mBodySpriteAnimator.SetSprite(mBodySprite.GetPointer());
+	mBodySpriteAnimator.SetFrameInterval(0);
+
+	//Load the reload sprite
+	mReloadSprite = Sprite::LoadSpriteFromImage("res/chainsawbuffet/pg_body.bmp", 4, 1, 4, 0, 36, 46, 36, 0, 0);
+	for(int i = 0; i < mReloadSprite->GetFrameCount(); i++)
+	{
+		mReloadSprite->GetFrame(i)->SetOffset(13, 16);
+	}
+	mReloadSprite->SetInterpolation(true);
+	mReloadSpriteAnimator.SetSprite(mReloadSprite.GetPointer());
+	mReloadSpriteAnimator.SetFrameInterval(10);
+
+	//Load the legs sprite
+	mLegsSprite = Sprite::LoadSpriteFromImage("res/chainsawbuffet/pg_legs.bmp", 16, 2, 10, 0, 0, 12, 10, 0, 0);
+	for(int i = 0; i < mLegsSprite->GetFrameCount(); i++)
+	{
+		mLegsSprite->GetFrame(i)->SetOffset(6, 5);
+	}
+	mLegsSpriteAnimator.SetSprite(mLegsSprite.GetPointer());
+	mLegsSpriteAnimator.SetFrameInterval(100);
+	mLegsSpriteAnimator.SetScaleX((real)2.8);
+	mLegsSpriteAnimator.SetScaleY((real)2.4);
+
+	SetUseIntegerCoordinatesForRendering(true);
+	GetDevice()->GetInputManager()->RegisterKeyboardListener(this);
+
+	/*Crown::Rectangle* r = new Crown::Rectangle();
+	r->SetFromCenterAndDimensions(Vec2::ZERO, 30, 30);
+	SetShape(r);*/
+	Circle* c = new Circle(Vec2::ZERO, 15);
+	//SetShape(c);
+}
+
+Pg::~Pg()
+{
+	//delete mBodySprite;
+}
+
+void Pg::Update(real dt)
+{
+	//Calculate the velocity based on joystick input before the parent's update, where it will be applied
+	Vec3 delta = Globals::joystick->GetDelta();
+	delta.y = -delta.y;
+	mSpeed = delta.GetLength() * (real)1.9;
+	if (mSpeed >= 0.001)
+	{
+		delta.Normalize();
+		mDirection = delta;
+	}
+	SetVelocity(mDirection * mSpeed * 3.5);
+
+	UpdateSpriteAnimators(dt);
+
+	if (mBulletCounter > 0)
+	{
+		mBulletCounter -= 1;
+	}
+
+	ArenaScene* arena = (ArenaScene*)GetCreator();
+	arena->GetMainCamera()->SetPosition(Vec3(mPosition.x, mPosition.y, arena->GetMainCamera()->GetPosition().z));
+
+	PhysicNode::Update(dt);
+}
+
+void Pg::UpdateSpriteAnimators(real dt)
+{
+	if (mSpeed > 0.01)
+	{
+		//2.8 is the x scale of the legs sprite
+		real legWalkDistancePixels = (real)(18 * 2.8);
+		real secondsToWalkLegDistance = legWalkDistancePixels / mSpeed;
+		real legFrameDurationSeconds = secondsToWalkLegDistance / mLegsSprite->GetFrameCount();
+		real bodyFrameDurationSeconds = secondsToWalkLegDistance / mBodySprite->GetFrameCount();
+		mLegsSpriteAnimator.SetFrameInterval((int)(GetDevice()->GetActualFps() * legFrameDurationSeconds));
+		mBodySpriteAnimator.SetFrameInterval((int)(GetDevice()->GetActualFps() * bodyFrameDurationSeconds));
+	}
+	else
+	{
+		mLegsSpriteAnimator.SetFrameInterval(0);
+		mLegsSpriteAnimator.SetFrameIndex(0);
+		mBodySpriteAnimator.SetFrameInterval(0);
+		mBodySpriteAnimator.SetFrameIndex(0);
+	}
+
+	real angle = mDirection.ToVec2().GetAngle();
+	mBodySpriteAnimator.SetAngle(angle);
+	mReloadSpriteAnimator.SetAngle(angle);
+	mLegsSpriteAnimator.SetAngle(angle);
+}
+
+void Pg::Render()
+{
+	PhysicNode::Render();
+	mLegsSpriteAnimator.Render();
+	if (mIsReloading)
+	{
+		mReloadSpriteAnimator.Render();
+		if (mReloadSpriteAnimator.GetFrameIndex() == 3)
+		{
+			mIsReloading = false;
+			mBodySpriteAnimator.SetFrameIndex(0);
+		}
+	}
+	else
+	{
+		mBodySpriteAnimator.Render();
+	}
+
+	//Renderer* r = GetDevice()->GetRenderer();
+	//Crown::Rectangle* rect = static_cast<Crown::Rectangle*>(GetShape());
+	//
+	//Vec2 min = rect->GetVertext(0) - mPosition.ToVec2();
+	//Vec2 size = rect->GetSize();
+	//if (mIsColliding)
+	//{
+	//	r->DrawRectangle(Point2(min.x, min.y), Point2(size.x, size.y), DM_BORDER, Color4::BLUE, Color4::BLUE);
+	//}
+	//else
+	//{
+	//	r->DrawRectangle(Point2(min.x, min.y), Point2(size.x, size.y), DM_BORDER);
+	//}
+	//mIsColliding = false;
+}
+
+void Pg::KeyPressed(const KeyboardEvent& event)
+{
+	if (event.key == 'C')
+	{
+		mIsReloading = true;
+		mReloadSpriteAnimator.SetFrameIndex(0);
+	}
+	if (event.key == ' ')
+	{
+		if (mBulletCounter == 0)
+		{
+			Vec3 pos = mPosition + mDirection * 30;
+			pos += Vec3(-mDirection.y, mDirection.x, 0.0) * 7;
+			
+			Bullet* b = new Bullet(GetCreator(), GetParent(), pos.x, pos.y, mDirection, 400);
+			mBulletCounter = mBulletInterval;
+		}
+	}
+}

+ 39 - 0
samples/chainsawbuffet/entities/Pg.h

@@ -0,0 +1,39 @@
+#ifndef __PG_H__
+#define __PG_H__
+
+#include "Crown.h"
+
+using namespace Crown;
+
+class Pg: public PhysicNode, public KeyboardListener
+{
+public:
+	Pg(Scene* scene, Camera* camera);
+	virtual ~Pg();
+
+	virtual void Update(real dt);
+	virtual void Render();
+
+	virtual void KeyPressed(const KeyboardEvent& event);
+
+private:
+	Auto<Sprite> mBodySprite;
+	Auto<Sprite> mReloadSprite;
+	Auto<Sprite> mLegsSprite;
+	SpriteAnimator mBodySpriteAnimator;
+	SpriteAnimator mReloadSpriteAnimator;
+	SpriteAnimator mLegsSpriteAnimator;
+	Vec3 mDirection;
+	real mSpeed;
+	bool mIsColliding;
+
+	bool mIsReloading;
+
+	//bullet handling
+	int mBulletCounter;
+	int mBulletInterval;
+
+	void UpdateSpriteAnimators(real dt);
+};
+
+#endif //__PG_H__

+ 31 - 0
samples/chainsawbuffet/entities/SolidSceneNode.cpp

@@ -0,0 +1,31 @@
+#include "SolidSceneNode.h"
+
+using namespace Crown;
+
+SolidSceneNode::SolidSceneNode(Scene* creator, SceneNode* parent, const Vec3& position, const Angles& axis, bool visible, int collisionGroupId) :
+	PhysicNode(creator, parent, position, axis, visible, collisionGroupId)
+{
+	//This code should go in SceneNode? (when moving it there, check also the factory methods in Scene, such as AddCamera, AddSceneNode...)
+	if (parent == NULL)
+	{
+		creator->GetRootSceneNode()->AddChild(this);
+	}
+}
+
+SolidSceneNode::~SolidSceneNode()
+{
+
+}
+
+void SolidSceneNode::OnRegisterForRendering()
+{
+	if (this->IsVisible())
+	{
+		if (mCreator)
+		mCreator->RegisterNodeForRendering(this, RP_GUI);
+
+		SceneNode::OnRegisterForRendering();
+	}
+}
+
+

+ 22 - 0
samples/chainsawbuffet/entities/SolidSceneNode.h

@@ -0,0 +1,22 @@
+#ifndef __SOLID_SCENE_NODE_H__
+#define __SOLID_SCENE_NODE_H__
+
+#include "Crown.h"
+
+using namespace Crown;
+
+class SolidSceneNode: public PhysicNode
+{
+public:
+	//! Constructor
+	SolidSceneNode(Scene* creator, SceneNode* parent, const Vec3& position, const Angles& axis, bool visible, int collisionGroupId);
+
+	//! Destructor
+	virtual ~SolidSceneNode();
+
+	//! Tasks to perform when registering the node for rendering
+	virtual void OnRegisterForRendering();
+};
+
+#endif // __SOLID_SCENE_NODE_H__
+

+ 94 - 0
samples/chainsawbuffet/entities/Wall.cpp

@@ -0,0 +1,94 @@
+#include "Wall.h"
+#include "Globals.h"
+#include "Joystick.h"
+#include <GL/glew.h>	// FIXME
+
+Wall::Wall(Scene* scene, Camera* camera, real x, real y, real w, real h):
+	PhysicNode(scene, camera, Vec3(x, y, 0), Angles(0, 0, 0), true, CG_WALL)
+{
+	mStoneTexture = GetTextureManager()->Load("res/chainsawbuffet/stone_wall_texture.bmp");
+
+	SetUseIntegerCoordinatesForRendering(true);
+
+	Crown::Rect* r = new Crown::Rect();
+	r->SetFromCenterAndDimensions(Vec2::ZERO, w+5, h+5);
+	//SetShape(r);
+
+	SetInverseMass(0.0);
+
+	bool meshCreated;
+	mMesh = GetMeshManager()->Create("wall_mesh", meshCreated);
+
+	if (mMesh != NULL && meshCreated)
+	{
+		MeshChunk* chunk = new MeshChunk();
+		real halfSizeX, halfSizeY;
+		real sizeZ;
+		halfSizeX = w/2;
+		halfSizeY = h/2;
+		sizeZ = 80;
+		real texWidth = 512;
+		real texHeight = 512;
+		//Ceiling Face
+		chunk->mVertexList.Append(VertexData(Vec3(-halfSizeX, -halfSizeY, sizeZ), Vec3::ZAXIS, Vec2(                  0.0f,                    0.0f)));
+		chunk->mVertexList.Append(VertexData(Vec3( halfSizeX, -halfSizeY, sizeZ), Vec3::ZAXIS, Vec2(halfSizeX*2 / texWidth,                    0.0f)));
+		chunk->mVertexList.Append(VertexData(Vec3( halfSizeX,  halfSizeY, sizeZ), Vec3::ZAXIS, Vec2(halfSizeX*2 / texWidth, halfSizeY*2 / texHeight)));
+		chunk->mVertexList.Append(VertexData(Vec3(-halfSizeX,  halfSizeY, sizeZ), Vec3::ZAXIS, Vec2(                  0.0f, halfSizeY*2 / texHeight)));
+		
+		//Right Face
+		chunk->mVertexList.Append(VertexData(Vec3( halfSizeX,  halfSizeY,   0.0), Vec3::XAXIS, Vec2(halfSizeY*2 / texWidth,              0.0f)));
+		chunk->mVertexList.Append(VertexData(Vec3( halfSizeX,  halfSizeY, sizeZ), Vec3::XAXIS, Vec2(halfSizeY*2 / texWidth, sizeZ / texHeight)));
+		chunk->mVertexList.Append(VertexData(Vec3( halfSizeX, -halfSizeY, sizeZ), Vec3::XAXIS, Vec2(                  0.0f, sizeZ / texHeight)));
+		chunk->mVertexList.Append(VertexData(Vec3( halfSizeX, -halfSizeY,   0.0), Vec3::XAXIS, Vec2(                  0.0f,              0.0f)));
+
+		//Bottom Face
+		chunk->mVertexList.Append(VertexData(Vec3( halfSizeX, -halfSizeY,   0.0),-Vec3::YAXIS, Vec2(halfSizeX*2 / texWidth,              0.0f)));
+		chunk->mVertexList.Append(VertexData(Vec3( halfSizeX, -halfSizeY, sizeZ),-Vec3::YAXIS, Vec2(halfSizeX*2 / texWidth, sizeZ / texHeight)));
+		chunk->mVertexList.Append(VertexData(Vec3(-halfSizeX, -halfSizeY, sizeZ),-Vec3::YAXIS, Vec2(                  0.0f, sizeZ / texHeight)));
+		chunk->mVertexList.Append(VertexData(Vec3(-halfSizeX, -halfSizeY,   0.0),-Vec3::YAXIS, Vec2(                  0.0f,              0.0f)));
+
+		//Left Face
+		chunk->mVertexList.Append(VertexData(Vec3(-halfSizeX, -halfSizeY,   0.0),-Vec3::XAXIS, Vec2(                  0.0f,              0.0f)));
+		chunk->mVertexList.Append(VertexData(Vec3(-halfSizeX, -halfSizeY, sizeZ),-Vec3::XAXIS, Vec2(                  0.0f, sizeZ / texHeight)));
+		chunk->mVertexList.Append(VertexData(Vec3(-halfSizeX,  halfSizeY, sizeZ),-Vec3::XAXIS, Vec2(halfSizeY*2 / texWidth, sizeZ / texHeight)));
+		chunk->mVertexList.Append(VertexData(Vec3(-halfSizeX,  halfSizeY,   0.0),-Vec3::XAXIS, Vec2(halfSizeY*2 / texWidth,              0.0f)));
+
+		//Top Face
+		chunk->mVertexList.Append(VertexData(Vec3(-halfSizeX,  halfSizeY,   0.0), Vec3::YAXIS, Vec2(                  0.0f,              0.0f)));
+		chunk->mVertexList.Append(VertexData(Vec3(-halfSizeX,  halfSizeY, sizeZ), Vec3::YAXIS, Vec2(                  0.0f, sizeZ / texHeight)));
+		chunk->mVertexList.Append(VertexData(Vec3( halfSizeX,  halfSizeY, sizeZ), Vec3::YAXIS, Vec2(halfSizeX*2 / texWidth, sizeZ / texHeight)));
+		chunk->mVertexList.Append(VertexData(Vec3( halfSizeX,  halfSizeY,   0.0), Vec3::YAXIS, Vec2(halfSizeX*2 / texWidth,              0.0f)));
+
+		chunk->mFaceList.Append(FaceData( 0,  1,  2));
+		chunk->mFaceList.Append(FaceData( 0,  2,  3));
+		chunk->mFaceList.Append(FaceData( 4,  5,  6));
+		chunk->mFaceList.Append(FaceData( 4,  6,  7));
+		chunk->mFaceList.Append(FaceData( 8,  9, 10));
+		chunk->mFaceList.Append(FaceData( 8, 10, 11));
+		chunk->mFaceList.Append(FaceData(12, 13, 14));
+		chunk->mFaceList.Append(FaceData(12, 14, 15));
+		chunk->mFaceList.Append(FaceData(16, 17, 18));
+		chunk->mFaceList.Append(FaceData(16, 18, 19));
+
+		mMesh->AddMeshChunk(chunk);
+		mMesh->RecompileMesh();
+	}
+}
+
+Wall::~Wall()
+{
+}
+
+void Wall::Update(real dt)
+{
+	PhysicNode::Update(dt);
+}
+
+void Wall::Render()
+{
+	PhysicNode::Render();
+	Renderer* r = GetDevice()->GetRenderer();
+
+	r->SetTexture(0, mStoneTexture);
+	r->RenderVertexIndexBuffer(mMesh->GetVertexBuffer(), mMesh->GetIndexBuffer());
+}

+ 22 - 0
samples/chainsawbuffet/entities/Wall.h

@@ -0,0 +1,22 @@
+#ifndef __WALL_H__
+#define __WALL_H__
+
+#include "Crown.h"
+
+using namespace Crown;
+
+class Wall: public PhysicNode
+{
+public:
+	Wall(Scene* scene, Camera* camera, real x, real y, real w, real h);
+	virtual ~Wall();
+
+	virtual void Update(real dt);
+	virtual void Render();
+
+private:
+	Texture* mStoneTexture;
+	Mesh* mMesh;
+};
+
+#endif //__Wall_H__

+ 103 - 0
samples/chainsawbuffet/entities/Zombie.cpp

@@ -0,0 +1,103 @@
+#include "Zombie.h"
+#include "Pg.h"
+#include "Globals.h"
+
+Zombie::Zombie(Scene* scene, Camera* camera):
+	PhysicNode(scene, camera, Vec3(400, 240, 0), Angles(0, 0, 0), true, CG_ZOMBIE),
+	mSpeed((real)0.05), mDirection(1.0, 0.0, 0.0)
+{
+	//Load the body sprite
+	mBodySprite = Sprite::LoadSpriteFromImage("res/chainsawbuffet/zombie1.bmp", 4, 1, 4, 1, 1, 46, 36, 1, 1);
+	for(int i = 0; i < mBodySprite->GetFrameCount(); i++)
+	{
+		mBodySprite->GetFrame(i)->SetOffset(13, 16);
+	}
+	mBodySprite->SetInterpolation(true);
+	mBodySpriteAnimator.SetSprite(mBodySprite.GetPointer());
+	mBodySpriteAnimator.SetFrameInterval(30);
+	mBodySpriteAnimator.RandomizeFrameStart();
+
+	//	//Load the legs sprite
+	//mLegsSprite = Sprite::LoadSpriteFromImage("res/chainsawbuffet/Zombie_legs.bmp", 17, 2, 10, 0, 0, 12, 12, 0, 0);
+	//for(int i = 0; i < mLegsSprite->GetFrameCount(); i++)
+	//{
+	//	mLegsSprite->GetFrame(i)->SetOffset(6, 7);
+	//}
+	//mLegsSpriteAnimator.SetSprite(mLegsSprite.GetPointer());
+	//mLegsSpriteAnimator.SetFrameInterval(100);
+	//mLegsSpriteAnimator.SetScaleX(2.8);
+	//mLegsSpriteAnimator.SetScaleY(2.4);
+
+	SetUseIntegerCoordinatesForRendering(true);
+
+	mPosition.x = (real)(20 + rand() % 760);
+	mPosition.y = (real)(20 + rand() % 440);
+	mChangeDirectionInterval = rand() % 3000 + 1000;
+	real angle = (real)(Math::PI * 2 / 1000.0 * (rand() % 1000));
+	mDirection = Vec3(Math::Cos(angle), Math::Sin(angle), 0.0);
+
+	//Crown::Rectangle* r = new Crown::Rectangle();
+	//r->SetFromCenterAndDimensions(Vec2::ZERO, 30, 30);
+	//SetShape(r);
+	Circle* c = new Circle(Vec2::ZERO, 15);
+	//SetShape(c);
+}
+
+Zombie::~Zombie()
+{
+	
+}
+
+void Zombie::Collision(PhysicNode* other)
+{
+	//if (dynamic_cast<Pg*>(other) != NULL)
+	//{
+	//	Vec3 deltaPos = mPosition - other->GetPosition();
+	//	this->SetPosition(GetPosition() + deltaPos * 0.1);
+	mIsColliding = true;
+	//}
+}
+
+void Zombie::Update(real dt)
+{
+	mBodySpriteAnimator.SetFrameInterval(30/(dt*60));
+	PhysicNode::Update(dt);
+}
+
+void Zombie::Render()
+{
+	//Do an update
+	if (mChangeDirectionInterval == 0)
+	{
+		real angle = (real)(Math::PI * 2 / 1000.0 * (rand() % 1000));
+		mDirection = Vec3(Math::Cos(angle), Math::Sin(angle), 0.0);
+		mChangeDirectionInterval = rand() % 3000 + 1000;
+	}
+	mChangeDirectionInterval -= 1;
+
+	mPosition += mDirection * mSpeed;
+
+	real angle = mDirection.ToVec2().GetAngle();
+	mBodySpriteAnimator.SetAngle(angle);
+	mLegsSpriteAnimator.SetAngle(angle);
+
+	PhysicNode::Render();
+	//mLegsSpriteAnimator.Render();
+	mBodySpriteAnimator.Render();
+
+	//Renderer* r = GetDevice()->GetRenderer();
+	//Crown::Rectangle* rect = static_cast<Crown::Rectangle*>(GetShape());
+	//
+	//Vec2 min = rect->GetVertext(0) - mPosition.ToVec2();
+	//Vec2 size = rect->GetSize();
+	//if (mIsColliding)
+	//{
+	//	r->DrawRectangle(Point2(min.x, min.y), Point2(size.x, size.y), DM_BORDER, Color4::BLUE, Color4::BLUE);
+	//}
+	//else
+	//{
+	//	r->DrawRectangle(Point2(min.x, min.y), Point2(size.x, size.y), DM_BORDER);
+	//}
+	//mIsColliding = false;
+}
+

+ 30 - 0
samples/chainsawbuffet/entities/Zombie.h

@@ -0,0 +1,30 @@
+#ifndef __ZOMBIE_H__
+#define __ZOMBIE_H__
+
+#include "Crown.h"
+
+using namespace Crown;
+
+class Zombie: public PhysicNode
+{
+public:
+	Zombie(Scene* scene, Camera* camera);
+	virtual ~Zombie();
+
+	virtual void Update(real dt);
+	virtual void Render();
+
+	virtual void Collision(PhysicNode* other);
+
+private:
+	Auto<Sprite> mBodySprite;
+	Auto<Sprite> mLegsSprite;
+	SpriteAnimator mBodySpriteAnimator;
+	SpriteAnimator mLegsSpriteAnimator;
+	Vec3 mDirection;
+	real mSpeed;
+	int mChangeDirectionInterval;
+	bool mIsColliding;
+};
+
+#endif //__ZOMBIE_H__

+ 149 - 0
samples/chainsawbuffet/maain.cpp

@@ -0,0 +1,149 @@
+#include "TestApp.h"
+#include "ArenaScene.h"
+
+using namespace Crown;
+
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+//BEGIN_INCLUDE(all)
+#include <jni.h>
+#include <errno.h>
+
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+
+#include <android/sensor.h>
+#include <android/log.h>
+#include <android_native_app_glue.h>
+
+#include "Crown.h"
+using namespace Crown;
+
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
+#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
+
+static void foobar()
+{
+	ArenaScene* arena = new ArenaScene(800, 480);
+	GetDevice()->GetSceneManager()->SelectNextScene(arena);
+}
+
+/**
+ * Process the next main command.
+ */
+static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
+    switch (cmd) {
+        case APP_CMD_SAVE_STATE:
+            // The system has asked us to save our current state.  Do so.
+            break;
+        case APP_CMD_INIT_WINDOW:
+            // The window is being shown, get it ready.
+			GetDevice()->Init(480, 800, 32, true);
+			foobar();
+            break;
+        case APP_CMD_TERM_WINDOW:
+            // The window is being hidden or closed, clean it up.
+			GetDevice()->StopRunning();
+			GetDevice()->Shutdown();
+            break;
+        case APP_CMD_GAINED_FOCUS:
+            // When our app gains focus, we start monitoring the accelerometer.
+            GetDevice()->StartRunning();
+            break;
+        case APP_CMD_LOST_FOCUS:
+            // When our app loses focus, we stop monitoring the accelerometer.
+            // This is to avoid consuming battery while not being used.
+			GetDevice()->StopRunning();
+            // Also stop animating.
+            break;
+    }
+}
+
+/**
+ * This is the main entry point of a native application that is using
+ * android_native_app_glue.  It runs in its own thread, with its own
+ * event loop for receiving input events and doing other things.
+ */
+void android_main(struct android_app* state) {
+
+    // Make sure glue isn't stripped.
+    app_dummy();
+
+	LOGI("Entrato in android_main!!!");
+	GetDevice()->_InitAndroidApp(state);
+
+    state->userData = NULL;
+    state->onAppCmd = NULL; // Manual cmd handling
+    state->onInputEvent = NULL; // Manual input handling
+
+    // loop waiting for stuff to do.
+
+    while (1) {
+
+        int ident;
+        int events;
+        struct android_poll_source* source;
+		struct android_app* app = state;
+
+{ //////////////////////////////////////
+        if ((ident=ALooper_pollOnce(0, NULL, &events,
+                (void**)&source)) >= 0) {
+					if (source != NULL)
+					{
+					if (source->id == LOOPER_ID_MAIN)
+					{
+						//LOGI("Entrato in LOOPER_ID_MAIN");
+						int8_t cmd = android_app_read_cmd(app);
+						android_app_pre_exec_cmd(app, cmd);
+						engine_handle_cmd(app, cmd);
+						android_app_post_exec_cmd(app, cmd);
+						//LOGI("Uscito da LOOPER_ID_MAIN");
+					}
+					}
+					//LOGI("Uscito da source != NULL");
+		}
+
+} ///////////////////////////////////
+
+        // Check if we are exiting.
+        if (state->destroyRequested != 0) {
+            exit(0);
+        }
+
+        // Drawing is throttled to the screen update rate, so there
+        // is no need to do timing here.
+		if (GetDevice()->IsInit())
+		{
+			if (GetDevice()->IsRunning())
+			{
+				GetDevice()->GetInputManager()->GetTouch()->EventLoop();
+				GetDevice()->GetRenderer()->_BeginFrame();
+				GetDevice()->GetSceneManager()->UpdateScene(0.02);
+				GetDevice()->GetSceneManager()->RenderScene();
+				GetDevice()->GetRenderer()->_EndFrame();
+				GetDevice()->GetMainWindow()->Update();
+			}
+		}
+    }
+
+	Log::D("Crown: bye bye.");
+}
+//END_INCLUDE(all)
+
+
+

+ 57 - 0
samples/chainsawbuffet/main.cpp

@@ -0,0 +1,57 @@
+#include "ArenaScene.h"
+
+using namespace Crown;
+
+class WndCtrl: public KeyboardListener
+{
+public:
+
+	WndCtrl()
+	{
+		GetDevice()->GetInputManager()->RegisterKeyboardListener(this);
+	}
+
+	virtual void KeyReleased(const KeyboardEvent& event)
+	{
+		if (event.key == KC_ESCAPE)
+		{
+			GetDevice()->StopRunning();
+		}
+	}
+};
+
+int main(int argc, char** argv)
+{
+	int wndW = 800;
+	int wndH = 480;
+
+	if (argc == 3)
+	{
+		wndW = atoi(argv[1]);
+		wndH = atoi(argv[2]);
+	}
+
+	Device* mDevice = GetDevice();
+
+	if (!mDevice->Init(wndW, wndH, 32, false))
+	{
+		return 0;
+	}
+
+	WndCtrl ctrl;
+
+	ArenaScene* mainScene = new ArenaScene(wndW, wndH);
+	GetDevice()->GetSceneManager()->SelectNextScene(mainScene);
+
+	mDevice->GetMainWindow()->SetTitle("Crown Engine v0.1 - Chainsaw Buffet");
+
+	while (mDevice->IsRunning())
+	{
+		mDevice->Frame();
+	}
+
+	mDevice->Shutdown();
+
+	return 0;
+}
+

+ 80 - 0
samples/chainsawbuffet/scenes/ArenaScene.cpp

@@ -0,0 +1,80 @@
+#include "ArenaScene.h"
+#include "Globals.h"
+
+ArenaScene::ArenaScene(Crown::uint windowWidth, Crown::uint windowHeight) :
+	mPg(NULL), mJoystick(NULL), mParticleManager(NULL)
+{
+}
+
+ArenaScene::~ArenaScene()
+{
+	if (mPg)
+	{
+		delete mPg;
+	}
+	for(int i = 0; i < mZombies.GetSize(); i++)
+	{
+		delete mZombies[i];
+	}
+	for(int i = 0; i < mWalls.GetSize(); i++)
+	{
+		delete mWalls[i];
+	}
+	for(int i = 0; i < mBackgrounds.GetSize(); i++)
+	{
+		delete mBackgrounds[i];
+	}
+	if (mJoystick)
+	{
+		delete mJoystick;
+	}
+	if (mParticleManager)
+	{
+		delete mParticleManager;
+	}
+}
+
+void ArenaScene::OnLoad()
+{
+	Scene::OnLoad();
+
+	Renderer* renderer = GetDevice()->GetRenderer();
+	renderer->SetClearColor(Color4(0.6f, 0.6f, 0.6f, 1.0f));
+	renderer->_SetLighting(false);
+
+	//Initialize the collision groups. The nodes will insert themselves in the correct group
+	GetPhysicsManager()->AddGroupPairCollisionCheck(CG_ZOMBIE, CG_ZOMBIE);
+	GetPhysicsManager()->AddGroupPairCollisionCheck(CG_ZOMBIE, CG_WALL);
+	GetPhysicsManager()->AddGroupPairCollisionCheck(CG_PG, CG_ZOMBIE);
+	GetPhysicsManager()->AddGroupPairCollisionCheck(CG_PG, CG_WALL);
+	GetPhysicsManager()->AddGroupPairCollisionCheck(CG_BULLET, CG_ZOMBIE);
+	GetPhysicsManager()->AddGroupPairCollisionCheck(CG_BULLET, CG_WALL);
+	
+	mMainCamera = this->AddCamera(NULL, Vec3(400.0, 240.0, 240.0), Angles::ZERO, true, 90, 800.0/480.0, true);
+
+	mBackgrounds.Append(new Background(this, mMainCamera,   0, 0));
+	mBackgrounds.Append(new Background(this, mMainCamera, 256, 0));
+	mBackgrounds.Append(new Background(this, mMainCamera, 512, 0));
+	mBackgrounds.Append(new Background(this, mMainCamera, 768, 0));
+
+	mBackgrounds.Append(new Background(this, mMainCamera,   0, 256));
+	mBackgrounds.Append(new Background(this, mMainCamera, 256, 256));
+	mBackgrounds.Append(new Background(this, mMainCamera, 512, 256));
+	mBackgrounds.Append(new Background(this, mMainCamera, 768, 256));
+
+	mPg = new Pg(this, mMainCamera);
+	for(int i = 0; i < 50; i++)
+	{
+		mZombies.Append(new Zombie(this, mMainCamera));
+	}
+	mWalls.Append(new Wall(this, mMainCamera, 300, 300, 100, 100));
+	mParticleManager = new ParticleManager(this, mMainCamera);
+	mJoystick = new Joystick(this, mMainCamera);
+}
+
+void ArenaScene::RenderScene()
+{
+	Scene::RenderScene();
+}
+
+

+ 38 - 0
samples/chainsawbuffet/scenes/ArenaScene.h

@@ -0,0 +1,38 @@
+#ifndef __ARENA_SCENE_H__
+#define __ARENA_SCENE_H__
+
+#include "Pg.h"
+#include "Zombie.h"
+#include "Joystick.h"
+#include "Wall.h"
+#include "Background.h"
+
+using namespace Crown;
+
+class ArenaScene: public Scene
+{
+public:
+	ArenaScene(Crown::uint windowWidth, Crown::uint windowHeight);
+	virtual ~ArenaScene();
+
+	virtual void OnLoad();
+	
+	virtual void RenderScene();
+
+	inline Camera* GetMainCamera() const
+	 { return mMainCamera; }
+
+	inline ParticleManager* GetParticleManager() const
+	 { return mParticleManager; }
+
+private:
+	Camera* mMainCamera;
+	Pg* mPg;
+	List<Zombie*> mZombies;
+	List<Wall*> mWalls;
+	List<Background*> mBackgrounds;
+	Joystick* mJoystick;
+	ParticleManager* mParticleManager;
+}; 
+
+#endif //__ARENA_SCENE_H__

+ 0 - 0
samples/ciao.txt2


+ 199 - 0
samples/coll2d/coll2d.cpp

@@ -0,0 +1,199 @@
+#include "Crown.h"
+#include <cstdlib>
+#include <GL/glew.h>
+
+using namespace Crown;
+
+void DrawCircle(const Circle& circle);
+void DrawLine(const Vec2& start, const Vec2& end);
+void DrawRectangle(const Crown::Rect& rect, const Color4& color);
+
+class WndCtrl: public KeyboardListener
+{
+public:
+
+	WndCtrl()
+	{
+		GetDevice()->GetInputManager()->RegisterKeyboardListener(this);
+	}
+
+	virtual void KeyReleased(const KeyboardEvent& event)
+	{
+		if (event.key == KC_ESCAPE)
+		{
+			GetDevice()->StopRunning();
+		}
+	}
+};
+
+class MainScene: public Scene, public MouseListener//, public KeyboardListener
+{
+
+public:
+
+	MainScene(uint windowWidth, uint windowHeight) :
+		c1(Vec2::ZERO, 0.0f),
+		c2(Vec2::ZERO, 0.0f)
+	{
+		GetDevice()->GetInputManager()->RegisterMouseListener(this);
+		//GetDevice()->GetInputManager()->RegisterKeyboardListener(this);
+	}
+
+	virtual ~MainScene()
+	{
+	}
+
+	virtual void ButtonPressed(const MouseEvent& event)
+	{
+		
+	}
+
+	virtual void OnLoad()
+	{
+		Crown::Renderer* renderer = Crown::GetDevice()->GetRenderer();
+		renderer->SetClearColor(Crown::Color4(0.6f, 0.6f, 0.6f, 1.0f));
+
+		c1.SetCenter(Vec2(300.0f, 300.0f));
+		c1.SetRadius(32.0f);
+
+		c2.SetCenter(Vec2(500.0f, 700.0f));
+		c2.SetRadius(16.0f);
+
+		ortho.BuildProjectionOrtho2dRH(1000, 625, 0, 10);
+	}
+
+	virtual void RenderScene()
+	{
+		Renderer* renderer = GetDevice()->GetRenderer();
+
+		renderer->_SetLighting(false);
+		renderer->_SetBlending(false);
+		renderer->_SetAlphaTest(false);
+		renderer->_SetBackfaceCulling(false);
+		renderer->_SetTexturing(0, false);
+		renderer->_SetTexturing(1, false);
+		renderer->_SetTexturing(2, false);
+
+		Scene::RenderScene();
+
+		renderer->SetMatrix(MT_PROJECTION, ortho);
+
+		glDisable(GL_CULL_FACE);
+
+		glColor4f(0, 1, 0, 1);
+
+		Crown::Rect r1;
+		r1.SetFromCenterAndDimensions(Vec2(400, 400), 100, 80);
+
+		c1.SetCenter(GetDevice()->GetInputManager()->GetMouse()->GetCursorXY().ToVec2());
+
+		Color4 color = Color4::LIME;
+
+		Vec2 penetration;
+		if (Intersection::TestCircleRect(c1, r1, penetration))
+		{
+			color = Color4::RED;
+		}
+
+		Circle cr1 = r1.ToCircle();
+		DrawCircle(cr1);
+
+		Rect rc1 = c1.ToRect();
+		DrawRectangle(rc1, color);
+
+		DrawRectangle(r1, color);
+		DrawCircle(c1);
+
+		glColor4f(0, 0, 1, 1);
+		DrawLine(c1.GetCenter(), c1.GetCenter() + penetration);
+
+		//DrawCircle(c2);
+
+		//Vec2 c1vel = GetDevice()->GetInputManager()->GetMouse()->GetCursorXY().ToVec2() - c1.GetCenter();
+		//Vec2 c2vel = Vec2(250.0f, -200.0f);
+
+		//DrawLine(c1.GetCenter(), c1.GetCenter() + c1vel);
+		//DrawLine(c2.GetCenter(), c2.GetCenter() + c2vel);
+
+		//real ct;
+		//if (Intersection::TestDynamicCircleCircle(c1, c1vel, c2, c2vel, ct))
+		//{
+		//	glColor4f(1, 0, 0, 1);
+
+		//	Circle cc1(c1.GetCenter() + c1vel * ct, c1.GetRadius());
+		//	Circle cc2(c2.GetCenter() + c2vel * ct, c2.GetRadius());
+
+		//	DrawCircle(cc1);
+		//	DrawCircle(cc2);
+		//}
+	}
+
+private:
+
+	Circle c1;
+	Circle c2;
+	Mat4 ortho;
+};
+
+int main(int argc, char** argv)
+{
+	int wndW = 1000;
+	int wndH = 625;
+
+	if (argc == 3)
+	{
+		wndW = atoi(argv[1]);
+		wndH = atoi(argv[2]);
+	}
+
+	Device* mDevice = GetDevice();
+
+	if (!mDevice->Init(wndW, wndH, 32, false))
+	{
+		return 0;
+	}
+
+	WndCtrl ctrl;
+
+	MainScene* mainScene = new MainScene(wndW, wndH);
+	GetDevice()->GetSceneManager()->SelectNextScene(mainScene);
+
+	mDevice->GetMainWindow()->SetTitle("Crown Engine v0.1 - Collision 2D Test");
+
+	mDevice->Run();
+
+	mDevice->Shutdown();
+
+	return 0;
+}
+
+void DrawCircle(const Circle& circle)
+{
+	float step = (360.0f / 16.0f) * Math::DEG_TO_RAD;
+	glBegin(GL_TRIANGLE_FAN);
+	glVertex2fv(circle.GetCenter().ToFloatPtr());
+	for (int i = 0; i <= 16; i++)
+	{
+		Vec2 vert = circle.GetCenter() + (Vec2(Math::Cos((float)i * step), Math::Sin((float)i * step)) * circle.GetRadius());
+		glVertex2fv(vert.ToFloatPtr());
+	}
+	glEnd();
+}
+
+void DrawLine(const Vec2& start, const Vec2& end)
+{
+	glBegin(GL_LINES);
+	glVertex2fv(start.ToFloatPtr());
+	glVertex2fv(end.ToFloatPtr());
+	glEnd();
+}
+
+void DrawRectangle(const Crown::Rect& rect, const Color4& color)
+{
+	Renderer* r = GetDevice()->GetRenderer();
+	
+	Vec2 min = rect.GetVertext(0);
+	Vec2 size = rect.GetSize();
+	r->DrawRectangle(Point2(min.x, min.y), Point2(size.x, size.y), DM_BORDER, color);
+}
+

+ 340 - 0
samples/collision/collision.cpp

@@ -0,0 +1,340 @@
+#include "Crown.h"
+#include <cstdlib>
+#include <GL/glu.h>
+
+using namespace Crown;
+
+class WndCtrl: public KeyboardListener
+{
+public:
+
+	WndCtrl()
+	{
+		GetDevice()->GetInputManager()->RegisterKeyboardListener(this);
+	}
+
+	virtual void KeyReleased(const KeyboardEvent& event)
+	{
+		if (event.key == KC_ESCAPE)
+		{
+			GetDevice()->StopRunning();
+		}
+	}
+};
+
+class MainScene: public MouseListener//, public KeyboardListener
+{
+
+public:
+
+	MainScene()
+	{
+		GetDevice()->GetInputManager()->RegisterMouseListener(this);
+		//GetDevice()->GetInputManager()->RegisterKeyboardListener(this);
+
+		sphereCount = 0;
+	}
+
+	virtual ~MainScene()
+	{
+		if (quadric)
+			gluDeleteQuadric(quadric);
+	}
+
+	virtual void ButtonPressed(const MouseEvent& event)
+	{
+		if (event.button == MB_LEFT)
+		{
+			if (sphereCount < 12)
+			{
+				sphere[sphereCount].c = cam->GetPosition();
+				velocity[sphereCount] = cam->GetLookAt() * 0.7f;
+				sphereCount++;
+			}
+		}
+
+		if (event.button == MB_RIGHT)
+		{
+			sphereCount = 0;
+		}
+	}
+
+	virtual void OnLoad()
+	{
+		Crown::Renderer* renderer = Crown::GetDevice()->GetRenderer();
+		renderer->SetClearColor(Crown::Color4(0.0f, 0.0f, 0.0f, 1.0f));
+
+		// Add a movable camera
+		cam = new MovableCamera(Vec3::ZERO, Angles::ZERO, true, 90.0f, 1.6f, 0.01, 2.5, true);
+
+		if (cam)
+		{
+			cam->SetActive(true);
+			cam->SetSpeed(0.1);
+			cam->SetFarClipDistance(1000.0f);
+			cam->SetPosition(Vec3(0, 10, 15));
+
+		}
+
+		grass = GetTextureManager()->Load("res/texturewhichdoesnotexists.ctex");
+
+		dplane = GetMeshManager()->LoadPlane("3dplane", 128.0f, 128.0f);
+
+		ray.origin = Vec3(0, 0, 10);
+		ray.direction = Vec3(0, 0, -1);
+
+		for (int i = 0; i < 12; i++)
+		{
+			sphere[i].r = 1.5f;
+		}
+
+		plane[0].n			= Vec3(0, 1, 0);
+		plane[0].d			= 0;
+
+		plane[1].n 			= Vec3(0, 0, 1);
+		plane[1].d			= 0;
+
+		plane[2].n			= Vec3(1, 0, 0);
+		plane[2].d			= 0;
+
+		gravity				= Vec3(0, -0.003, 0);
+
+		quadric = gluNewQuadric();
+	}
+
+	virtual void RenderScene()
+	{
+		Renderer* renderer = GetDevice()->GetRenderer();
+
+		renderer->_SetLighting(false);
+		renderer->_SetBlending(false);
+		renderer->_SetAlphaTest(false);
+		renderer->_SetBackfaceCulling(false);
+		renderer->_SetTexturing(0, false);
+		renderer->_SetTexturing(1, false);
+		renderer->_SetTexturing(2, false);
+
+		cam->Render();
+
+		for (int i = 0; i < sphereCount; i++)
+		{
+			velocity[i] += gravity;
+			for (int j = 0; j < 3; j++)
+			{
+				real itt;
+				Vec3 intersectionPoint;
+				if (Intersection::TestDynamicSpherePlane(sphere[i], velocity[i], plane[j], itt, intersectionPoint))
+				{
+					real velLength = velocity[i].GetLength();
+
+					velocity[i].Normalize();
+					Vec3 nuovo = ((2.0f * (-velocity[i].Dot(plane[j].n))) * plane[j].n) + velocity[i];
+					velocity[i] = nuovo * velLength * 0.7f;
+				}
+			}
+		}
+
+		for (int i = 0; i < sphereCount; i++)
+		{
+			if (velocity[i] == Vec3::ZERO)
+			{
+				velocity[i].Zero();
+			}
+			sphere[i].c += velocity[i];
+		}
+
+		if (cam->IsActive())
+		{
+			ray.origin = cam->GetPosition();
+			ray.direction = cam->GetLookAt();
+		}
+
+		renderer->SetMatrix(MT_MODEL, Mat4::IDENTITY);
+
+		for (int j = 0; j < sphereCount; j++)
+		{
+			// Draw spheres
+			glColor3f(1, 0, 0);
+			tr.LoadIdentity();
+			tr.SetTranslation(sphere[j].c);
+			renderer->SetMatrix(MT_MODEL, tr);
+			gluSphere(quadric, sphere[j].r, 64, 64);
+		}
+
+//		tr.SetTranslation(sphere[1].c);
+//		renderer->SetMatrix(MT_MODEL, tr);
+//		gluSphere(quadric, sphere[1].r, 64, 64);
+
+//		tr.SetTranslation(sphere[2].c);
+//		renderer->SetMatrix(MT_MODEL, tr);
+//		gluSphere(quadric, sphere[2].r, 64, 64);
+		// End Draw spheres
+
+//		// Draw velocity segments
+//		glColor3f(1, 0, 0);
+//		renderer->SetMatrix(MT_MODEL, Mat4::IDENTITY);
+
+//		glBegin(GL_LINES);
+//		glVertex3fv(sphere[0].c.ToFloatPtr());
+//		glVertex3fv((sphere[0].c + velocity[0]).ToFloatPtr());
+//		glEnd();
+
+//		glBegin(GL_LINES);
+//		glVertex3fv(sphere[1].c.ToFloatPtr());
+//		glVertex3fv((sphere[1].c + velocity[1]).ToFloatPtr());
+//		glEnd();
+
+//		glBegin(GL_LINES);
+//		glVertex3fv(sphere[2].c.ToFloatPtr());
+//		glVertex3fv((sphere[2].c + velocity[2]).ToFloatPtr());
+//		glEnd();
+//		// End Draw velocity segments
+
+//		// Draw end spheres
+//		glColor3f(1.0, 0.0, 0.0);
+//		tr.LoadIdentity();
+//		tr.SetTranslation(sphere[0].c + velocity[0]);
+//		renderer->SetMatrix(MT_MODEL, tr);
+//		gluSphere(quadric, sphere[0].r, 64, 64);
+
+//		tr.SetTranslation(sphere[1].c + velocity[1]);
+//		renderer->SetMatrix(MT_MODEL, tr);
+//		gluSphere(quadric, sphere[1].r, 64, 64);
+
+//		tr.SetTranslation(sphere[2].c + velocity[2]);
+//		renderer->SetMatrix(MT_MODEL, tr);
+//		gluSphere(quadric, sphere[2].r, 64, 64);
+//		// End Draw end spheres
+
+//		// Draw spheres at collision time
+//		glColor3f(0.0, 1.0, 0.0);
+//		real it;
+//		if (Intersection::TestDynamicSphereSphere(sphere[0], velocity[0], sphere[1], velocity[1], it))
+//		{
+//			tr.LoadIdentity();
+
+//			tr.SetTranslation(sphere[0].c + (velocity[0] * it));
+//			renderer->SetMatrix(MT_MODEL, tr);
+//			gluSphere(quadric, sphere[0].r, 64, 64);
+
+
+//			tr.SetTranslation(sphere[1].c + (velocity[1] * it));
+//			renderer->SetMatrix(MT_MODEL, tr);
+//			gluSphere(quadric, sphere[1].r, 64, 64);
+//		}
+
+//		if (Intersection::TestDynamicSpherePlane(sphere[2], velocity[2], plane, it))
+//		{
+//			tr.LoadIdentity();
+
+//			tr.SetTranslation(sphere[2].c + (velocity[2] * it));
+//			renderer->SetMatrix(MT_MODEL, tr);
+//			gluSphere(quadric, sphere[2].r, 64, 64);
+//		}
+//		// End Draw spheres at collision time
+
+		renderer->_SetTexture(0, grass);
+		renderer->_SetTexturing(0, true);
+		renderer->_SetTextureMode(0, grass->GetMode(), grass->GetBlendColor());
+		renderer->_SetTextureFilter(0, grass->GetFilter());
+
+		tr.BuildRotationX(Math::PI / 2.0f);
+		tr.SetTranslation(Vec3(0, 0, 0));
+		renderer->SetMatrix(MT_MODEL, tr);
+		renderer->RenderVertexIndexBuffer(dplane->GetVertexBuffer(), dplane->GetIndexBuffer());
+
+		tr.LoadIdentity();
+		tr.SetTranslation(Vec3(0, 0, 0));
+		renderer->SetMatrix(MT_MODEL, tr);
+		renderer->RenderVertexIndexBuffer(dplane->GetVertexBuffer(), dplane->GetIndexBuffer());
+
+		tr.BuildRotationY(Math::PI / 2.0f);
+		tr.SetTranslation(Vec3(0, 0, 0));
+		renderer->SetMatrix(MT_MODEL, tr);
+		renderer->RenderVertexIndexBuffer(dplane->GetVertexBuffer(), dplane->GetIndexBuffer());
+	}
+
+private:
+
+	Mesh* dplane;
+	Mat4 ortho;
+	Mat4 crateModel;
+	Mat4 tr;
+	Texture* grass;
+
+	Ray ray;
+	Plane plane[3];
+	Sphere sphere[12];
+	Vec3 velocity[12];
+	Vec3 gravity;
+	GLUquadric* quadric;
+	MovableCamera* cam;
+	int sphereCount;
+};
+
+int main(int argc, char** argv)
+{
+	int wndW = 1000;
+	int wndH = 625;
+
+	if (argc == 3)
+	{
+		wndW = atoi(argv[1]);
+		wndH = atoi(argv[2]);
+	}
+
+	Device* mDevice = GetDevice();
+
+	if (!mDevice->Init(wndW, wndH, 32, false))
+	{
+		return 0;
+	}
+
+	WndCtrl ctrl;
+
+	MainScene scene;
+	scene.OnLoad();
+
+	mDevice->GetMainWindow()->SetTitle("Crown Engine v0.1 - Collision Test");
+
+	while (mDevice->IsRunning())
+	{
+		InputManager* mInputManager = GetDevice()->GetInputManager();
+
+		if (mInputManager)
+		{
+			if (mInputManager->IsMouseAvailable())
+			{
+				if (mInputManager->IsMouseAvailable())
+				{
+					mInputManager->GetMouse()->EventLoop();
+				}
+				if (mInputManager->IsKeyboardAvailable())
+				{
+					mInputManager->GetKeyboard()->EventLoop();
+				}
+				if (mInputManager->IsTouchAvailable())
+				{
+					mInputManager->GetTouch()->EventLoop();
+				}
+			}
+		}
+
+		mDevice->GetMainWindow()->EventLoop();
+
+		GetDevice()->GetRenderer()->_BeginFrame();
+
+		scene.RenderScene();
+
+		GetDevice()->GetRenderer()->_EndFrame();
+
+		mDevice->GetMainWindow()->Update();
+	}
+
+	mDevice->Shutdown();
+
+	mDevice->Shutdown();
+
+	return 0;
+}
+

+ 117 - 0
samples/dictionary/dictionary.cpp

@@ -0,0 +1,117 @@
+#include <iostream>
+#include <stdio.h>
+#include "Timer.h"
+
+//#define RBTREE_VERIFY
+#include "Dictionary.h"
+#include "Str.h"
+
+#include <map>
+
+using namespace std;
+using namespace Crown;
+
+void timeCompareWithStlMap();
+void dictRemove();
+
+int main()
+{
+	timeCompareWithStlMap();
+	dictRemove();
+	
+  getchar();
+}
+
+void dictRemove()
+{
+	Dictionary<int, Crown::Str> dict;
+	
+	for(int i=0; i<20; i++)
+	{
+		dict[i] = "item " + Str(i*5);
+	}
+	
+	dict.Remove(7);
+	
+	cout << "Dictionary with item 10 removed:" << endl;
+	
+	Dictionary<int, Crown::Str>::Enumerator e = dict.getBegin();
+	while (e.next())
+	{
+		cout << "dict[" << e.current().key << "] = " << e.current().value.c_str() << endl;
+	}
+	
+	dict.Clear();
+}
+
+void timeCompareWithStlMap()
+{
+  Timer* tim = Timer::GetInstance();
+  tim->Reset();
+  int k = 1000000;
+  int dictAddTime, dictRemoveTime, mapAddTime, mapRemoveTime;
+  int dictFindTime, mapFindTime;
+
+  map<int, int> stlmap;
+  Dictionary<int, int> dict;
+
+  //------Dict performance test------
+  tim->Reset();
+  for(int i=0; i<k; i++)
+  {
+    dict[i] = i;
+    //dict.add(i, i);
+  }
+  dictAddTime = tim->GetMicroseconds();
+  cout << "Elements added to Dictionary: " << dict.GetSize() << endl;
+
+  tim->Reset();
+  for(int i=0; i<k; i++)
+  {
+    assert(dict[i] == i);
+  }
+  dictFindTime = tim->GetMicroseconds();
+  cout << "Elements searched" << endl;
+
+  tim->Reset();
+  for(int i=0; i<k; i++)
+  {
+    dict.Remove(i);
+  }
+  dictRemoveTime = tim->GetMicroseconds();
+  cout << "Elements after removal on Dictionary: " << dict.GetSize() << endl;
+
+  //------Map performance test------
+  tim->Reset();
+  for(int i=0; i<k; i++)
+  {
+    stlmap[i] = i;
+    //stlmap.insert(map<int, int>::value_type(i, i));
+  }
+  mapAddTime = tim->GetMicroseconds();
+  cout << "Elements added to StlMap: " << stlmap.size() << endl;
+
+  tim->Reset();
+  for(int i=0; i<k; i++)
+  {
+    assert(stlmap[i] == i);
+  }
+  mapFindTime = tim->GetMicroseconds();
+  cout << "Elements searched" << endl;
+
+  tim->Reset();
+  for(int i=0; i<k; i++)
+  {
+    stlmap.erase(i);
+  }
+  mapRemoveTime = tim->GetMicroseconds();
+  cout << "Elements after removal on StlMap: " << stlmap.size() << endl;
+
+  cout << "Dictionary:" << endl;
+  cout << "Add: " << dictAddTime << " us, Remove: " << dictRemoveTime << " us, Find: " << dictFindTime << " us" << endl;
+  cout << "Add: " << 1.0f*dictAddTime/k << " us/add, Remove: " << 1.0*dictRemoveTime/k << " us/remove, Find: " << 1.0*dictFindTime/k << " us/find" << endl;
+
+  cout << "StlMap:" << endl;
+  cout << "Add: " << mapAddTime << " us, Remove: " << mapRemoveTime << " us, Find: " << mapFindTime << " us" << endl;
+  cout << "Add: " << 1.0f*mapAddTime/k << " us/add, Remove: " << 1.0*mapRemoveTime/k << " us/remove, Find: " << 1.0*mapFindTime/k << " us/find" << endl;		
+}

+ 120 - 0
samples/editor/CRWObjectModel.cpp

@@ -0,0 +1,120 @@
+#include "CRWObjectModel.h"
+
+CRWDescriptor::CRWDescriptor(CRWObjectModel* crwObjectModel, CRWDescriptor* parent, const Crown::Descriptor& descriptor, Crown::uint offset):
+	mCRWObjectModel(crwObjectModel), mParent(parent), mChildren(NULL), mDescriptorOffset(offset)
+{
+	AddProperty(new UIntProperty("ID", &mID));
+	AddProperty(new UShortProperty("Type", &mType));
+	AddProperty(new StrProperty("Name", &mName));
+	AddProperty(new UIntProperty("ContentOffset", &mContentOffset));
+	AddProperty(new UIntProperty("ContentSize", &mContentSize));
+	AddProperty(new UShortProperty("Flags", &mFlags));
+	AddProperty(new UIntProperty("DescriptorOffset", &mDescriptorOffset));
+
+	AddProperty(new GenericListProperty("Children", &mChildrenGenericWrapper));
+
+	mID = descriptor.ID;
+	mType = descriptor.type;
+	mName = descriptor.name;
+	mContentOffset = descriptor.contentOffset;
+	mContentSize = descriptor.contentSize;
+	mDescriptorOffset = offset;
+}
+
+CRWDescriptor::~CRWDescriptor()
+{
+	delete mChildren;
+}
+
+Crown::Str CRWDescriptor::ToStr() const
+{
+	return "CRWDescriptor\"" + mName + "\"";
+}
+
+void CRWDescriptor::OnGetProperty(const Crown::Str& name)
+{
+	if (name == "Children")
+	{
+		if (mChildren == NULL)
+		{
+			GetChildren();
+			mChildrenGenericWrapper = new Crown::ListGenericWrapper<CRWDescriptor*>(mChildren);
+		}
+	}
+}
+
+Generic CRWDescriptor::GetPropertyValue(const Str& name) const
+{
+	return WithProperties::GetPropertyValue(name);
+}
+
+Crown::Str CRWDescriptor::GetFullName()
+{
+	Crown::Str name;
+	name = mName;
+	
+	if (!mParent)
+		return "/" + name;
+	else
+		return mParent->GetFullName() + "/" + name;
+}
+
+CRWObjectModel* CRWDescriptor::GetCRWObjectModel()
+{
+	return mCRWObjectModel;
+}
+
+Crown::List<CRWDescriptor*>* CRWObjectModel::LoadChildren(CRWDescriptor* crwDescriptor)
+{
+	Crown::Str path = "/";
+	if (crwDescriptor)
+	{
+		path = crwDescriptor->GetFullName();
+	}
+
+	Crown::List<CRWDescriptor*>* list = new Crown::List<CRWDescriptor*>();
+	//If seek fails, the path is not a directory and therefore there's no children
+	if (!mDecoder->Seek(path))
+		return list;
+
+	while (mDecoder->NextDescriptor())
+	{
+		const Crown::Descriptor& descriptor = mDecoder->GetDescriptor();
+		Crown::uint offset = mDecoder->GetDescriptorOffset();
+		list->Append(new CRWDescriptor(this, crwDescriptor, descriptor, offset));
+	}
+
+	return list;
+}
+
+CRWObjectModel::CRWObjectModel(Crown::CRWDecoder* decoder):
+	mDecoder(decoder), mRoot(NULL)
+{
+	GetRoot();
+}
+
+CRWObjectModel::~CRWObjectModel()
+{
+}
+
+Str CRWObjectModel::GetCRWLibraryPath()
+{
+	return mDecoder->GetLibraryPath();
+}
+
+Generic CRWObjectModel::GetPropertyValue(const Str& name) const
+{
+	if (name == "Root")
+	{
+		//This does not generate leaks because Generic stores the pointer in a Shared<>
+		return new ListGenericWrapper<CRWDescriptor*>(mRoot.GetPointer());
+	}
+	return Generic();
+}
+
+void CRWObjectModel::SetPropertyValue(const Str& name, const Generic& value)
+{
+
+}
+
+

+ 89 - 0
samples/editor/CRWObjectModel.h

@@ -0,0 +1,89 @@
+#ifndef __CRWOBJECTMODEL_H__
+#define	__CRWOBJECTMODEL_H__
+
+#include "Crown.h"
+
+using namespace Crown;
+
+class CRWObjectModel;
+
+class CRWDescriptor: public WithProperties
+{
+public:
+	CRWDescriptor(CRWObjectModel* crwObjectModel, CRWDescriptor* parent, const Descriptor& descriptor, uint offset);
+	virtual ~CRWDescriptor();
+
+	const List<CRWDescriptor*>& GetChildren();
+
+	Str GetFullName();
+	CRWObjectModel* GetCRWObjectModel();
+	inline ushort GetType()
+	 { return mType; }
+
+	Str ToStr() const;
+
+	virtual void OnGetProperty(const Str& name);
+
+	virtual Generic GetPropertyValue(const Str& name) const;
+
+
+private:
+	CRWObjectModel* mCRWObjectModel;
+	CRWDescriptor* mParent;
+	List<CRWDescriptor*>* mChildren;
+	Shared<IList<Generic> > mChildrenGenericWrapper;
+
+	//Descriptor Properties
+	uint mID;
+	ushort mType;
+	Str mName;
+	uint mContentOffset;
+	uint mContentSize;
+	//TODO: Use uchar
+	ushort mFlags;
+	uint mDescriptorOffset;
+
+	friend class CRWObjectModel;
+};
+
+class CRWObjectModel: public IWithProperties
+{
+public:
+	CRWObjectModel(CRWDecoder* decoder);
+	virtual ~CRWObjectModel();
+
+	inline const IList<CRWDescriptor*>* GetRoot()
+	{
+		if (mRoot.IsNull())
+			mRoot = LoadChildren(NULL);
+		return mRoot.GetPointer();
+	}
+
+	Str GetCRWLibraryPath();
+
+	virtual Generic GetPropertyValue(const Str& name) const;
+	virtual void SetPropertyValue(const Str& name, const Generic& value);
+
+	virtual Str ToStr() const
+	{
+		return "CRWObjectModel";
+	}
+
+private:
+	CRWDecoder* mDecoder;
+	Shared<IList<CRWDescriptor*> > mRoot;
+
+	List<CRWDescriptor*>* LoadChildren(CRWDescriptor* descriptor);
+
+	friend class CRWDescriptor;
+};
+
+inline const List<CRWDescriptor*>& CRWDescriptor::GetChildren()
+{
+	if (!mChildren)
+		mChildren = mCRWObjectModel->LoadChildren(this);
+	return *mChildren;
+}
+
+#endif	/* __CRWOBJECTMODEL_H__ */
+

+ 390 - 0
samples/editor/Editor.cpp

@@ -0,0 +1,390 @@
+#include "Crown.h"
+#include "CRWObjectModel.h"
+#include <cstdlib>
+#include <iostream>
+
+using namespace Crown;
+
+class WndCtrl: public KeyboardListener
+{
+public:
+
+	WndCtrl()
+	{
+		GetDevice()->GetInputManager()->RegisterKeyboardListener(this);
+	}
+
+	virtual void KeyReleased(const KeyboardEvent& event)
+	{
+		if (event.key == KC_ESCAPE)
+		{
+			GetDevice()->StopRunning();
+		}
+	}
+};
+
+void LoadXWMLAndLogResponse(WindowsManager* windowsManager, Str xwmlFile, WindowContext* context)
+{
+	XWMLReader xwml;
+	Window* window;
+
+	Filesystem* fs = GetFilesystem();
+	FilesystemEntry info;
+	if (!fs->GetInfo(xwmlFile, info))
+	{
+		MessageWindow* mw = new MessageWindow(windowsManager, "Load XWML", "Could not find file '" + xwmlFile + "'", MWR_OK, NULL);
+		windowsManager->DoModalWindow(mw);
+		return;
+	}
+
+	window = xwml.LoadFile(xwmlFile, windowsManager, context);
+
+	if (window == NULL)
+		Log::E("Could not load XWML file '" + info.osPath + "'");
+	else
+		Log::I("Successfully loaded XWML file '" + info.osPath + "'");
+}
+
+class CRWUtils
+{
+	public:
+		static void CreateExampleCRW(Str crwFilePath)
+		{
+			CRWDecoder mDecoder;
+
+			Stream* testimage = GetFilesystem()->OpenStream("res/terrain.bmp", SOM_READ);
+			//FileStream* testfile = new FileStream("../../res/testfile.txt", SOM_READ);
+			Stream* testfile = GetFilesystem()->OpenStream("res/testfile.txt", SOM_READ);
+
+			mDecoder.New(crwFilePath);
+
+			mDecoder.AddRawData("/", "file 1.txt", testfile, RF_NORMAL);
+			testfile->Seek(0, SM_SeekFromBegin);
+
+			mDecoder.AddDirectory("/", "docs");
+
+			mDecoder.AddRawData("/docs", "file 2.txt", testfile, RF_NORMAL);
+			testfile->Seek(0, SM_SeekFromBegin);
+
+			mDecoder.AddDirectory("/docs", "images");
+			mDecoder.AddRawData("/docs/images", "terrain.bmp", testimage, RF_NORMAL);
+			mDecoder.AddDirectory("/docs", "todo");
+			mDecoder.AddDirectory("/docs/todo", "asd1");
+			mDecoder.AddDirectory("/docs/todo", "asd2");
+			mDecoder.AddDirectory("/docs/images", "lll");
+			mDecoder.AddDirectory("/docs/todo", "asd3");
+			mDecoder.AddDirectory("/docs/todo", "asd4");
+			mDecoder.AddDirectory("/docs/todo", "asd5");
+			mDecoder.AddDirectory("/docs/todo", "asd6");
+
+			for (int i=0; i<5; i++)
+			{
+				Str s = "info" + Str(i) + ".txt";
+				mDecoder.AddRawData("/", s.c_str(), testfile, RF_NORMAL);
+				testfile->Seek(0, SM_SeekFromBegin);
+			}
+
+			GetFilesystem()->Close(testimage);
+			GetFilesystem()->Close(testfile);
+
+			mDecoder.Close();
+		}
+};
+
+//----------------------------------
+//            Windows
+//----------------------------------
+
+class EditorWindow: public Window
+{
+  public:
+    EditorWindow(WindowsManager* wm, int x, int y, int width, int height, const Str& crwFilePath):
+      Window(wm, x, y, width, height, "Editor: " + crwFilePath)
+    {
+			mDecoder.Load(crwFilePath);
+			mObjModel = new CRWObjectModel(&mDecoder);
+
+			TreeView* tw = new TreeView(GetContentWidget());
+
+			//The CRW Object Model exposes the CRW content through a hierarchy of IWithProperties objects
+			//that is suitable to be viewed in a TreeView
+			//Create a ListGenericWrapper to expose the list as a Generic List
+			ListGenericWrapper<CRWDescriptor*>* wrapper = new ListGenericWrapper<CRWDescriptor*>(mObjModel->GetRoot());
+			tw->SetItems(wrapper);
+    }
+
+		virtual ~EditorWindow()
+		{
+			delete mObjModel;
+		}
+
+  private:
+		CRWDecoder mDecoder;
+		CRWObjectModel* mObjModel;
+};
+
+class UpperCaseConverter: public Converter
+{
+public:
+	virtual Generic Convert(Generic source)
+	{
+		Str str = source.asStr();
+		str.MakeUpper();
+		return str;
+	}
+};
+
+class CrwIconConverter: public Converter
+{
+public:
+	virtual Generic Convert(Generic source)
+	{
+		//source is a CRWDescriptor, return the correct icon ImageSource (a path, probably)
+		ushort type;
+		if (!source.asUShort(type))
+		{
+			return "<Unknown>";
+		}
+		if (type == RT_Directory)
+		{
+			return "res/crw_dir_icon.bmp";
+		}
+		if (type == RT_RawData)
+		{
+			return "res/crw_file_icon.bmp";
+		}
+		return "res/crw_unknown.bmp";
+	}
+};
+
+class CrwDescriptorToFullPathConverter: public Converter
+{
+public:
+	virtual Generic Convert(Generic source)
+	{
+		//source is a CRWDescriptor, return the correct icon ImageSource (a path, probably)
+		CRWDescriptor* descr;
+		if (!source.asType(&descr))
+		{
+			return "";
+		}
+		return descr->GetCRWObjectModel()->GetCRWLibraryPath() + descr->GetFullName();
+	}
+};
+
+class EditorWindowContext: public WindowContext
+{
+public:
+  EditorWindowContext(WindowsManager* windowsManager, const Str& crwFilePath):
+		WindowContext(windowsManager), twCrwLibrary(NULL)
+  {
+		mDecoder.Load(crwFilePath);
+		mObjModel = new CRWObjectModel(&mDecoder);
+
+		AddProperty(new IWithPropertiesProperty("CrwObjectModel", (IWithProperties**)&mObjModel));
+
+		RegisterAction("UpdateCrwFilePreview", CreateDelegate(this, &EditorWindowContext::UpdateCrwFilePreview));
+		RegisterConverter("UpperCaseConverter", new UpperCaseConverter);
+		RegisterConverter("CrwIconConverter", new CrwIconConverter);
+		RegisterConverter("CrwDescriptorToFullPathConverter", new CrwDescriptorToFullPathConverter);
+  }
+
+	virtual ~EditorWindowContext()
+	{
+		delete mObjModel;
+	}
+
+	void OnLoad()
+	{
+		twCrwLibrary = (TreeView*)FindWidgetByName("twCrwLibrary");
+		NotifyChangeEventArgs args("twCrwLibrary");
+		NotifyChange(&args);
+	}
+
+	virtual Generic GetPropertyValue(const Str& name) const
+	{
+		if (name == "twCrwLibrary")
+		{
+			return twCrwLibrary;
+		}
+		else
+		{
+			return WindowContext::GetPropertyValue(name);
+		}
+	}
+
+	
+	void UpdateCrwFilePreview(Widget* src, List<Str>* /*args*/)
+	{
+		//if (twCrwLibrary->GetSelectedIndex() != 2)
+		//{
+		//	twCrwLibrary->SetSelectedIndex(2);
+		//}
+		//twCrwLibrary->PrintLoop(0);
+	}
+
+	virtual Str ToStr() const
+	{
+		return "EditorWindowContext";
+	}
+
+private:
+	TreeView* twCrwLibrary;
+	CRWDecoder mDecoder;
+	CRWObjectModel* mObjModel;
+};
+
+class MainWindowContext: public WindowContext
+{
+  public:
+    MainWindowContext(WindowsManager* windowsManager):
+		  WindowContext(windowsManager)
+    {
+			RegisterAction("NewLibrary", CreateDelegate(this, &MainWindowContext::NewLibraryAction));
+			RegisterAction("OpenLibrary", CreateDelegate(this, &MainWindowContext::OpenLibraryAction));
+    }
+
+		void OnLoad()
+		{
+			btnClose = (Button*)FindWidgetByName("btnClose");
+			btnNewLibrary = (Button*)FindWidgetByName("btnNewLibrary");
+			btnOpenLibrary = (Button*)FindWidgetByName("btnOpenLibrary");
+		}
+
+		void NewLibraryAction(Widget* src, List<Str>* /*args*/)
+		{
+			Window* wnd = new TextInputWindow(
+				GetWindowsManager(),
+				"New CRW", "Please insert the new CRW name:",
+				"library",
+				new Delegate2<MainWindowContext, void, bool, Str>(this, &MainWindowContext::NewLibraryCallback, false, Str(""))
+				);
+			GetWindowsManager()->DoModalWindow(wnd);
+		}
+
+		void OpenLibraryAction(Widget* src, List<Str>* /*args*/)
+		{
+			Window* wnd = new TextInputWindow(
+				GetWindowsManager(),
+				"Open CRW", "Please insert the CRW name to open:",
+				"library",
+				new Delegate2<MainWindowContext, void, bool, Str>(this, &MainWindowContext::OpenCrwCallback, false, Str(""))
+				);
+			GetWindowsManager()->DoModalWindow(wnd);
+		}
+
+		void NewLibraryCallback(bool cancelled, Str name)
+		{
+			if (!cancelled)
+			{
+				Log::I("Creating new CRW: " + name + ".crw");
+
+				Str crwFilePath = "res/" + name + ".crw";
+
+				CRWUtils::CreateExampleCRW(crwFilePath);
+				new EditorWindow(GetWindowsManager(), 100, 15, 250, 200, crwFilePath);
+			}
+			else
+				Log::I("New CRW creation cancelled.");
+		}
+
+		void OpenCrwCallback(bool cancelled, Str name)
+		{
+			if (!cancelled)
+			{
+				Log::I("Opening CRW: " + name + ".crw");
+
+				Str crwFilePath = "res/" + name + ".crw";
+
+				//Verify the existence of crwFilePath
+				if (!GetFilesystem()->Exists(crwFilePath))
+				{
+					Log::I("CRW file specified does not exist");
+				}
+				else
+				{
+					//new EditorWindow(GetWindowsManager(), 100, 15, 250, 200, crwFilePath);
+					WindowsManager* windowsManager = GetWindowsManager();
+					LoadXWMLAndLogResponse(windowsManager, "res/editor_editorwindow.xml", new EditorWindowContext(windowsManager, crwFilePath));
+				}
+			}
+			else
+				Log::I("Opening CRW cancelled.");
+		}
+
+	private:
+		Button* btnClose;
+		Button* btnNewLibrary;
+		Button* btnOpenLibrary;
+};
+
+class MainScene: public Scene
+{
+public:
+	MainScene(Crown::uint windowWidth, Crown::uint windowHeight)
+	{
+	}
+
+	virtual ~MainScene()
+	{
+	}
+
+	virtual void OnLoad()
+	{
+		Renderer* renderer = GetDevice()->GetRenderer();
+		renderer->SetClearColor(Color4(0.6f, 0.6f, 0.6f, 1.0f));
+
+		//Mat4 matrix(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f);
+		//renderer->SetMatrix(MT_MODEL, matrix);
+
+		//Mat4 matrix1;
+		//glGetFloatv(GL_MODELVIEW_MATRIX, matrix1.ToFloatPtr());
+
+		mWindowsManager = new WindowsManager(this);
+
+		LoadXWMLAndLogResponse(mWindowsManager, "res/editor_mainwindow.xml", new MainWindowContext(mWindowsManager));
+	}
+
+	virtual void RenderScene()
+	{
+		Scene::RenderScene();
+	}
+
+private:
+	WindowsManager* mWindowsManager;
+}; 
+
+int main(int argc, char** argv)
+{
+	int wndW = 1024;
+	int wndH = 768;
+
+	if (argc == 3)
+	{
+		wndW = atoi(argv[1]);
+		wndH = atoi(argv[2]);
+	}
+
+	Device* mDevice = GetDevice();
+
+	if (!mDevice->Init(wndW, wndH, 32, false))
+	{
+		return 0;
+	}
+
+	WndCtrl ctrl;
+
+	MainScene* mainScene = new MainScene(wndW, wndH);
+	GetDevice()->GetSceneManager()->SelectNextScene(mainScene);
+
+	mDevice->GetMainWindow()->SetTitle("Crown Engine v0.1 - Editor Test");
+
+	mDevice->Run();
+
+	mDevice->Shutdown();
+
+	return 0;
+}
+
+
+

BIN
samples/editor/res/arialbd.ttf


BIN
samples/editor/res/boom.bmp


BIN
samples/editor/res/closebutton_x.bmp


BIN
samples/editor/res/terrain.bmp


+ 1 - 0
samples/editor/res/testfile.txt

@@ -0,0 +1 @@
+<text file content, prova 123 lol asd> 

+ 30 - 0
samples/enumerators/DictionaryEnumerator.cpp

@@ -0,0 +1,30 @@
+#include "Dictionary.h"
+#include <iostream>
+#include <stdio.h>
+
+using namespace std;
+
+int main()
+{
+  Dictionary<int, int> dict;
+  int k = 20;
+
+  for(int i=0; i<k; i++)
+    dict[i] = 10*i;
+
+  Dictionary<int, int>::Enumerator e = dict.getBegin();
+  while (e.next())
+  {
+    cout << "[" << e.current().key << "," << e.current().value << "] ";
+  }
+  cout << endl;
+
+  Dictionary<int, int>::Enumerator eb = dict.getEnd();
+  while (eb.prev())
+  {
+    cout << "[" << eb.current().key << "," << eb.current().value << "] ";
+  }
+  cout << endl;
+
+  getchar();
+}

+ 30 - 0
samples/enumerators/ListEnumerator.cpp

@@ -0,0 +1,30 @@
+#include "List.h"
+#include <iostream>
+#include <stdio.h>
+
+using namespace std;
+
+int main()
+{
+  List<int> list;
+  int k = 20;
+
+  for(int i=0; i<k; i++)
+    list.Append(i);
+
+  EnumeratorHelper<int> e = list.getBegin();
+  while (e.next())
+  {
+    cout << e.current() << " ";
+  }
+  cout << endl;
+
+  EnumeratorHelper<int> eb = list.getEnd();
+  while (eb.prev())
+  {
+    cout << eb.current() << " ";
+  }
+  cout << endl;
+
+  getchar();
+}

+ 0 - 0
samples/filesystem/dir/texture.tga


+ 1 - 0
samples/filesystem/ebay

@@ -0,0 +1 @@
+/home/dani/Desktop/ebay.txt

+ 220 - 0
samples/filesystem/filesystem.cpp

@@ -0,0 +1,220 @@
+#include "Crown.h"
+#include "OS.h"
+#include <iostream>
+#include <cstring>
+#include <stdio.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+using namespace Crown;
+
+class ResourceLoader
+{
+public:
+
+					ResourceLoader() : mDone(false), mProcessed(0)
+					{
+					}
+
+					~ResourceLoader()
+					{
+					}
+
+	void			Load(char* name)
+					{
+						mResourceQueue.Append(name);
+						mProcessed = 0;
+					}
+
+
+	void			Flush()
+					{
+						pthread_create(&thread_id, NULL, &(ResourceLoader::ThreadStarter), this);
+					}
+
+	void			LoadAll()
+					{
+						for (int i = 0; i < mResourceQueue.GetSize(); i++)
+						{
+							GetFilesystem()->Close(GetFilesystem()->OpenStream(mResourceQueue[i], SOM_READ));
+							mProcessed++;
+							sleep(1);
+						}
+
+						mResourceQueue.Clear();
+
+						mDone = true;
+					}
+
+	bool			IsDone() const { return mDone; }
+
+	int				GetProcessed() const { return mProcessed; }
+	int				GetPending() const { return mResourceQueue.GetSize(); }
+
+private:
+
+	volatile bool	mDone;
+	volatile int	mProcessed;
+	pthread_t		thread_id;
+
+	List<char*>		mResourceQueue;
+
+	static void*	ThreadStarter(void* instance)
+					{
+						reinterpret_cast<ResourceLoader*>(instance)->LoadAll();
+					}
+};
+
+int main()
+{
+	Device* device = GetDevice();
+
+	Filesystem* fs = GetFilesystem();
+
+	fs->Init(Str::EMPTY, Str::EMPTY);
+
+	fs->PrintReport();
+
+	char path[256];
+
+//	do
+//	{
+//		std::cin >> path;
+
+//		FilesystemEntry info;
+//		if (fs->GetInfo(fs->GetRootPath(), path, info))
+//		{
+//			info.PrintReport();
+//		}
+//	}
+//	while (strcmp(path, "=exit") != 0);
+
+//	do
+//	{
+//		std::cin >> path;
+
+//		const char* extension = Filesystem::GetExtension(path);
+
+//		std::cout << "extension: ";
+//		printf("%s\n", extension);
+//	}
+//	while (strcmp(path, "=exit") != 0);
+
+	fs->CreateFile("ciao.txt2");
+	fs->CreateDir("pippo");
+
+	ResourceLoader loader;
+
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+	loader.Load("res/red_north.tga");
+	loader.Load("res/red_up.tga");
+	loader.Load("res/red_down.tga");
+	loader.Load("res/red_west.tga");
+	loader.Load("res/red_east.tga");
+	loader.Load("res/red_south.tga");
+
+
+
+	int pending = loader.GetPending();
+
+	printf("%d\n", pending);
+
+	getchar();
+
+	loader.Flush();
+
+	while (pending != loader.GetProcessed())
+	{
+		printf("%d/%d\n", loader.GetProcessed(), pending);
+
+		sleep(2);
+	}
+
+	return 0;
+}
+

+ 0 - 0
samples/filesystem/regular


+ 1 - 0
samples/filesystem/sgi

@@ -0,0 +1 @@
+/home/dani/Desktop/sgi/

+ 245 - 0
samples/fractal/fractal.cpp

@@ -0,0 +1,245 @@
+#include <cstdlib>
+#include <iostream>
+#include "TestApp.h"
+#include "TestScene.h"
+
+using namespace Crown;
+
+Image* gImage = NULL;
+TexturePtr gTexture;
+Sprite* gSprite;
+float aspectRatio;
+float minX;
+float maxX;
+float minY;
+float maxY;
+float sizeX;
+float sizeY;
+float panX;
+float panY;
+
+float centerX;
+float centerY;
+
+class AllWindowsContext: public WindowContext, public WeakReferenced
+{
+public:
+	AllWindowsContext(WindowsManager* windowsManager):
+	  WindowContext(windowsManager)
+  {
+		sizeX = 2.0f;
+		centerX = 0.0f;
+		centerY = 0.0f;
+		CalculateSizeParams();
+
+		RegisterAction("Generate", CreateDelegate(this, &AllWindowsContext::Generate));
+		RegisterAction("MoveLeft", CreateDelegate(this, &AllWindowsContext::MoveLeft));
+		RegisterAction("MoveRight", CreateDelegate(this, &AllWindowsContext::MoveRight));
+		RegisterAction("MoveUp", CreateDelegate(this, &AllWindowsContext::MoveUp));
+		RegisterAction("MoveDown", CreateDelegate(this, &AllWindowsContext::MoveDown));
+
+		RegisterAction("ZoomPlus", CreateDelegate(this, &AllWindowsContext::ZoomPlus));
+		RegisterAction("ZoomMinus", CreateDelegate(this, &AllWindowsContext::ZoomMinus));
+  }
+
+	virtual ~AllWindowsContext()
+	{
+
+	}
+
+	void OnLoad()
+	{
+		GetAssociatedWindow()->SetBindingContext(this);
+	}
+
+	void MoveLeft(Widget* /*src*/, List<Str>* /*args*/)
+	{
+		centerX -= panX;
+		CalculateSizeParams();
+		Regenerate();
+	}
+
+	void MoveRight(Widget* /*src*/, List<Str>* /*args*/)
+	{
+		centerX += panX;
+		CalculateSizeParams();
+		Regenerate();
+	}
+
+	void MoveUp(Widget* /*src*/, List<Str>* /*args*/)
+	{
+		centerY += panY;
+		CalculateSizeParams();
+		Regenerate();
+	}
+
+	void MoveDown(Widget* /*src*/, List<Str>* /*args*/)
+	{
+		centerY -= panY;
+		CalculateSizeParams();
+		Regenerate();
+	}
+
+	void ZoomPlus(Widget* /*src*/, List<Str>* /*args*/)
+	{
+		sizeX /= 1.3f;
+		CalculateSizeParams();
+		Regenerate();
+	}
+
+	void ZoomMinus(Widget* /*src*/, List<Str>* /*args*/)
+	{
+		sizeX *= 1.3f;
+		CalculateSizeParams();
+		Regenerate();
+	}
+
+	void Regenerate()
+	{
+		Generate(NULL, NULL);
+	}
+
+	void Generate(Widget* /*src*/, List<Str>* /*args*/)
+	{
+		/*Color c;
+		c.r = (rand() % 1000) / 1000.0f;
+		c.g = (rand() % 1000) / 1000.0f;
+		c.b = (rand() % 1000) / 1000.0f;
+		gImage->SetUniformColorImage(c);*/
+
+		float cX = 0.0f;
+		float cY = 0.0f;
+
+		int maxIterations = 150;
+
+		for(uint py = 0; py < gImage->GetHeight(); py++)
+		{
+			cY = minY + py * sizeY / gImage->GetHeight();
+			for(uint px = 0; px < gImage->GetWidth(); px++)
+			{
+				cX = minX + px * sizeX / gImage->GetWidth();
+
+				//Iterate some times
+				float x = 0.0f;
+				float y = 0.0f;
+				int i = 0;
+				while (i < maxIterations && (x * x + y * y < 2))
+				{
+					float xTmp = x * x - y * y + cX;
+					y = 2*x*y + cY;
+					x = xTmp;
+
+					i++;
+				}
+
+				if (i < maxIterations)
+				{
+					int comp = (int)(i * 255.0f / maxIterations);
+					gImage->SetPixel(px, py, Color(comp, comp, 255 - comp));
+				}
+				else
+				{
+					gImage->SetPixel(px, py, Color::BLACK);
+				}
+			}
+		}
+
+		gTexture->LoadFromImage(gImage);
+	}
+
+	void CalculateSizeParams()
+	{
+		sizeY = sizeX * aspectRatio;
+		minX = -sizeX / 2.0f + centerX;
+		maxX = +sizeX / 2.0f + centerY;
+
+		minY = -sizeY / 2.0f + centerY;
+		maxY = +sizeY / 2.0f + centerY;
+
+		panX = sizeX / 10.0f;
+		panY = sizeY / 10.0f;
+	}
+
+private:
+	
+};
+
+class MainScene: public TestScene, public WeakReferenced
+{
+public:
+	MainScene(Crown::uint windowWidth, Crown::uint windowHeight) :
+		TestScene(windowWidth, windowHeight)
+	{
+		aspectRatio = (float)windowHeight / windowWidth;
+		sizeX = 2.0f;
+		sizeY = sizeX * aspectRatio;
+		minX = -sizeX / 2.0f;
+		maxX = +sizeX / 2.0f;
+
+		minY = -sizeY / 2.0f;
+		maxY = +sizeY / 2.0f;
+
+		panX = sizeX / 10.0f;
+		panY = sizeY / 10.0f;
+
+		gImage = new Image(IT_2D, PF_RGB_8, windowWidth, windowHeight, NULL);
+		bool created;
+		gTexture = GetDevice()->GetRenderer()->GetTextureManager()->Create("fractal_tex", created);
+		gTexture->LoadFromImage(gImage);
+
+		gSprite = new Sprite();
+		Frame* f = new Frame();
+		f->Set(gTexture);
+		gSprite->AddFrame(f);
+	}
+	virtual ~MainScene()
+	{
+
+	}
+
+	void LoadXWMLAndLogResponse(Str xwmlFile)
+	{
+		XWMLReader xwml;
+		Window* window;
+
+		Filesystem* fs = GetDevice()->GetFilesystem();
+		FilesystemEntry info;
+		if (!fs->GetInfo(xwmlFile, info))
+		{
+			MessageWindow* mw = new MessageWindow(mWindowsManager, "Load XWML", "Could not find file '" + xwmlFile + "'", MWR_OK, NULL);
+			mWindowsManager->DoModalWindow(mw);
+			return;
+		}
+
+		window = xwml.LoadFile(xwmlFile, mWindowsManager, new AllWindowsContext(mWindowsManager));
+
+		if (window == NULL)
+			Log::E("Could not load XWML file '" + info.GetAbsolutePath() + "'");
+		else
+			Log::I("Successfully loaded XWML file '" + info.GetAbsolutePath() + "'");
+	}
+
+	virtual void OnLoad()
+	{
+		TestScene::OnLoad();
+
+		Renderer* renderer = GetDevice()->GetRenderer();
+		renderer->SetClearColor(Color(0.6f, 0.6f, 0.6f, 1.0f));
+
+		mWindowsManager = new WindowsManager(this);
+
+		LoadXWMLAndLogResponse("res/window_fractal.xml");
+	}
+
+	virtual void RenderScene()
+	{
+		gSprite->draw(0);
+
+		TestScene::RenderScene();
+	}
+
+private:
+	WindowsManager* mWindowsManager;
+}; 
+
+CROWN_APP_AND_MAIN(TestApp, MainScene, 1024, 768, "Crown Engine v0.1 - XWMLReader Test");

+ 45 - 0
samples/generic/generic.cpp

@@ -0,0 +1,45 @@
+#include "Generic.h"
+#include <iostream>
+#include <stdio.h>
+#include "Str.h"
+
+using namespace std;
+using namespace Crown;
+
+int main()
+{
+	Generic g1(5), g2(5.4f);
+	Generic g3("[Lol asd]");
+	Generic g4("-2147483648");
+	Generic g5("4294967295");
+	Generic g6("3.1415");
+
+	Str s1, s2, s3;
+	g1.asStr(s1);
+	g2.asStr(s2);
+	g3.asStr(s3);
+	int i1 = 0;
+	unsigned int ui1 = 0;
+	float f1 = 0.0f;
+	g4.asInt(i1);
+	g5.asUInt(ui1);
+	g6.asFloat(f1);
+
+	GenericList list;
+	list.Append("xD");
+	list.Append(1);
+	list.Append(true);
+	list.Append(15.4f);
+
+	Generic gList = list;
+
+	Str sList;
+	gList.asStr(sList);
+
+	cout << s1.c_str() <<" "<< s2.c_str() <<" "<< s3.c_str() << endl;
+	cout << i1 << " " << ui1 << " " << f1 << endl;
+	cout << sList.c_str() << endl;
+	cout << list.ToStr().c_str() << endl;
+
+  getchar();
+}

+ 246 - 0
samples/intersection/intersection.cpp

@@ -0,0 +1,246 @@
+#include "Crown.h"
+#include <cstdlib>
+#include <GL/glu.h>
+
+using namespace Crown;
+
+class WndCtrl: public KeyboardListener
+{
+public:
+
+	WndCtrl()
+	{
+		GetDevice()->GetInputManager()->RegisterKeyboardListener(this);
+	}
+
+	virtual void KeyReleased(const KeyboardEvent& event)
+	{
+		if (event.key == KC_ESCAPE)
+		{
+			GetDevice()->StopRunning();
+		}
+	}
+};
+
+class MainScene: public Scene, public KeyboardListener, public MouseListener
+{
+
+public:
+
+	MainScene(uint windowWidth, uint windowHeight)
+	{
+		GetDevice()->GetInputManager()->RegisterMouseListener(this);
+		GetDevice()->GetInputManager()->RegisterKeyboardListener(this);
+	}
+
+	virtual ~MainScene()
+	{
+		if (quadric)
+			gluDeleteQuadric(quadric);
+	}
+
+	virtual void ButtonReleased(const MouseEvent& event)
+	{
+		if (event.button == MB_LEFT)
+		{
+			GLint view[4];
+			GLdouble proj[16], model[16];
+
+			glGetDoublev(GL_MODELVIEW_MATRIX, model);
+			glGetDoublev(GL_PROJECTION_MATRIX, proj);
+			glGetIntegerv(GL_VIEWPORT, view);
+
+			int x = event.x;
+			int y = event.y;
+
+			// Adjust y wndCoord
+			y = (625 - y);
+
+			double sX, sY, sZ;
+			double eX, eY, eZ;
+
+			gluUnProject(x, y, 0.0f, model, proj, view, &sX, &sY, &sZ);
+			gluUnProject(x, y, 1.0f, model, proj, view, &eX, &eY, &eZ);
+
+			Vec3 dir = Vec3(eX, eY, eZ) - Vec3(sX, sY, sZ);
+
+			dir.Normalize();
+
+			ray.origin = cam->GetPosition();
+			ray.direction = dir;
+
+			//std::cout << x << " " << y << std::endl;
+			//std::cout << "Ori: " << ray.origin.ToStr().c_str() << std::endl;
+			//std::cout << "Dir: " << ray.direction.ToStr().c_str() << std::endl;
+		}
+	}
+
+	virtual void KeyPressed(const KeyboardEvent& event)
+	{
+		if (event.key == KC_UP)
+		{
+			ray.origin += Vec3(0, 0, -0.1);
+		}
+
+		if (event.key == KC_DOWN)
+		{
+			ray.origin += Vec3(0, 0, 0.1);
+		}
+
+		if (event.key == KC_LCONTROL)
+		{
+			cam->SetActive(!cam->IsActive());
+		}
+	}
+		
+
+	virtual void OnLoad()
+	{
+		Scene::OnLoad();
+
+		Crown::Renderer* renderer = Crown::GetDevice()->GetRenderer();
+		renderer->SetClearColor(Crown::Color4(0.0f, 0.0f, 0.0f, 1.0f));
+
+		// Add a movable camera
+		cam = AddMovableCamera();
+
+		if (cam)
+		{
+			cam->SetActive(true);
+			cam->SetSpeed(0.1);
+			cam->SetFarClipDistance(1000.0f);
+			//cam->SetPosition(Vec3(25, 0, 15));
+
+		}
+
+		grid = GetMeshManager()->LoadGrid("grid", 32);
+
+		ray.origin = Vec3(0, 0, 10);
+		ray.direction = Vec3(0, 0, -1);
+
+		sphere[0].c = Vec3(0, 0, 0);
+		sphere[0].r = 2.0f;
+
+		sphere[1].c = Vec3(3, -1, -5);
+		sphere[1].r = 1.0f;
+
+		sphere[2].c = Vec3(-5, 3, 2);
+		sphere[2].r = 3.0f;
+
+		quadric = gluNewQuadric();
+	}
+
+	virtual void RenderScene()
+	{
+		Renderer* renderer = GetDevice()->GetRenderer();
+
+		renderer->_SetLighting(false);
+		renderer->_SetBlending(false);
+		renderer->_SetAlphaTest(false);
+		Scene::RenderScene();
+
+		renderer->SetMatrix(MT_MODEL, Mat4::IDENTITY);
+		renderer->_SetTexturing(0, false);
+		renderer->_SetTexturing(1, false);
+		renderer->_SetTexturing(2, false);
+
+		if (cam->IsActive())
+		{
+			ray.origin = cam->GetPosition();
+			ray.direction = cam->GetLookAt();
+			//std::cout << ray.direction.ToStr().c_str() << std::endl;
+		}
+
+		int sphereIndex = -1;
+		real lastDist = 1000000.0f;
+		// Check ray-sphere intersection
+		for (int i = 0; i < 3; i++)
+		{
+			real dist;
+			if (Intersection::TestRaySphere(ray, sphere[i], dist))
+			{
+				if (dist <= lastDist)
+				{
+					lastDist = dist;
+					sphereIndex = i;
+				}
+			}
+		}
+
+		for (int i = 0; i < 3; i++)
+		{
+			if (sphereIndex == i)
+			{
+				glColor3f(1, 0, 0);
+			}
+			else
+			{
+				glColor3f(0, 1, 0);
+			}
+
+			tr.LoadIdentity();
+			tr.SetTranslation(sphere[i].c);
+			renderer->SetMatrix(MT_MODEL, tr);
+			gluSphere(quadric, sphere[i].r, 64, 64);
+		}
+
+		renderer->SetMatrix(MT_MODEL, Mat4::IDENTITY);
+		glColor3f(0, 0, 1);
+		glBegin(GL_LINES);
+		glVertex3fv(ray.origin.ToFloatPtr());
+		glVertex3fv((ray.origin + ray.direction).ToFloatPtr());
+		glEnd();
+
+		tr.SetTranslation(Vec3(0, -2, 0));
+		renderer->SetMatrix(MT_MODEL, tr);
+		renderer->RenderMesh(grid.GetPointer());
+	}
+
+private:
+
+	MeshPtr grid;
+	Mat4 ortho;
+	Mat4 crateModel;
+	Mat4 tr;
+
+	Ray ray;
+	Sphere sphere[3];
+	GLUquadric* quadric;
+	MovableCamera* cam;
+	Mouse* mouse;
+	Keyboard* keyboard;
+	InputManager* input;
+};
+
+int main(int argc, char** argv)
+{
+	int wndW = 1000;
+	int wndH = 625;
+
+	if (argc == 3)
+	{
+		wndW = atoi(argv[1]);
+		wndH = atoi(argv[2]);
+	}
+
+	Device* mDevice = GetDevice();
+
+	if (!mDevice->Init(wndW, wndH, 32, false))
+	{
+		return 0;
+	}
+
+	WndCtrl ctrl;
+
+	MainScene* mainScene = new MainScene(wndW, wndH);
+	GetDevice()->GetSceneManager()->SelectNextScene(mainScene);
+
+	mDevice->GetMainWindow()->SetTitle("Crown Engine v0.1 - Intersection Test");
+
+	mDevice->Run();
+
+	mDevice->Shutdown();
+
+	return 0;
+}
+

+ 885 - 0
samples/minecrown/WorldTerrain.cpp

@@ -0,0 +1,885 @@
+#include "WorldTerrain.h"
+#include <time.h>
+#include <cstdlib>
+#include "Crown.h"
+#include "perlin.h"
+#include <iostream>
+
+using namespace Crown;
+
+int perlinSeed;
+extern MovableCamera* cam;
+
+void DrawWiredCube(float x, float y, float z, float size);
+
+WorldTerrain::WorldTerrain()
+{
+	Clear();
+
+	mChunkX = 0;
+	mChunkZ = 0;
+	mChunkH = 0;
+
+	mDrawGrid = true;
+	
+	
+	
+	mPlayerChunkX = (CHUNKS_COUNT+1)/2.0f;
+	mPlayerChunkZ = (CHUNKS_COUNT+1)/2.0f;
+	mPlayerChunkH = CHUNKS_COUNT_H;
+	mPlayerPosition = Vec3((mPlayerChunkX + 0.5) * CHUNK_SIZE, mPlayerChunkH * CHUNK_SIZE, (mPlayerChunkZ + 0.5) * CHUNK_SIZE);
+
+	for(int x = 0; x < CHUNKS_COUNT; x++)
+	{
+		for(int z = 0; z < CHUNKS_COUNT; z++)
+		{
+			for(int h = 0; h < CHUNKS_COUNT_H; h++)
+			{
+					mChunks[x][z][h] = new Chunk(this);
+			}
+		}
+	}
+
+	BMPImageLoader bmp;
+	Image* image = bmp.LoadFile("res/terrain.bmp");
+	mTerrainTexture = new GLTexture();
+	//mTerrainTexture->SetWrap(TW_CLAMP_TO_EDGE);
+	mTerrainTexture->SetGenerateMipMaps(true);
+	mTerrainTexture->SetFilter(TF_ANISOTROPIC);
+	mTerrainTexture->CreateFromImage(image);
+
+	delete image;
+
+	GLfloat fogColor[4] = {0.457f, 0.754f, 1.0f, 1.0f};//{0.5, 0.5, 0.5, 1.0}; 
+
+	glEnable (GL_FOG);
+	glFogi (GL_FOG_MODE, GL_LINEAR);
+	glFogf(GL_FOG_START, 0.0f);
+	glFogf(GL_FOG_END, 10.0f);
+	glFogfv (GL_FOG_COLOR, fogColor);
+	glHint (GL_FOG_HINT, GL_NICEST);
+
+	glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
+
+	mViewDistance = 128;
+	CycleViewDistance();
+}
+
+WorldTerrain::~WorldTerrain()
+{
+	for(int x = 0; x < CHUNKS_COUNT; x++)
+	{
+		for(int z = 0; z < CHUNKS_COUNT; z++)
+		{
+			for(int h = 0; h < CHUNKS_COUNT_H; h++)
+			{
+
+					delete mChunks[x][z][h];
+			}
+		}
+	}
+
+	delete mTerrainTexture;
+}
+
+void WorldTerrain::Clear()
+{
+	for(int x = 0; x < WORLD_SIZE; x++)
+	{
+		for(int z = 0; z < WORLD_SIZE; z++)
+		{
+			for(int h = 0; h < WORLD_SIZE_H; h++)
+			{
+				mBlocks[x][z][h].opaque = false;
+				mBlocks[x][z][h].faceVisibility = FV_NONE;
+				mBlocks[x][z][h].light = 4;
+			}
+		}
+	}
+}
+
+void WorldTerrain::RandomMap(int groundLevel, int seed, int octaves, int freq)
+{
+	Clear();
+
+	Perlin per(octaves, freq, WORLD_SIZE_H/2, seed);
+
+	for(int x = 0; x < WORLD_SIZE; x++)
+	{
+		for(int z = 0; z < WORLD_SIZE; z++)
+		{
+			int height = per.Get(x * 1.0f / WORLD_SIZE, z * 1.0f / WORLD_SIZE) - groundLevel;
+			if (height < 0)
+				height /= 6;
+			height = (WORLD_SIZE_H / 2) + height;
+			for(int h = 0; h < height; h++)
+				mBlocks[x][z][h].opaque = true;
+		}
+	}
+
+	int px = (int) (cam->GetPosition().x / CubeSize);
+	int pz = (int) (cam->GetPosition().z / CubeSize);
+	int ph = WORLD_SIZE_H-1;
+
+	while(ph > 1 && !mBlocks[px][pz][ph-1].opaque)
+		ph--;
+
+	ph++;
+
+	mPlayerChunkX = px / CHUNK_SIZE;
+	mPlayerChunkZ = pz / CHUNK_SIZE;
+	mPlayerChunkH = ph / CHUNK_SIZE;
+
+	cam->SetPosition(Vec3(px*CubeSize, ph*CubeSize, pz*CubeSize));
+
+
+	RecalculateVisibleBlocksSides();
+	RecalculateSunlight();
+
+	RegenerateTerrain();
+}
+
+void WorldTerrain::UpdateVisibleNeighbourBlocks(Crown::uint xC, Crown::uint zC, Crown::uint hC)
+{
+	for(int x = xC-1; x < (int)xC+2; x++)
+	{
+		if (x < 0 || x >= WORLD_SIZE)
+			continue;
+		for(int z = zC-1; z < (int)zC+2; z++)
+		{
+			if (z < 0 || z >= WORLD_SIZE)
+				continue;
+			for(int h = hC-1; h < (int)hC+2; h++)
+			{
+				if (h<0 || h>=WORLD_SIZE_H)
+					continue;
+				Block& b = mBlocks[x][z][h];
+				b.faceVisibility = FV_NONE;
+				if (b.opaque)
+				{
+					if (x == 0 || !mBlocks[x-1][z][h].opaque)
+						b.faceVisibility |= FV_LEFT;
+				
+					if (z == 0 || !mBlocks[x][z-1][h].opaque)
+						b.faceVisibility |= FV_BACK;
+
+					if (h == 0 || !mBlocks[x][z][h-1].opaque)
+						b.faceVisibility |= FV_BOTTOM;
+
+					if (x == WORLD_SIZE-1 || !mBlocks[x+1][z][h].opaque)
+						b.faceVisibility |= FV_RIGHT;
+
+					if (z == WORLD_SIZE-1 || !mBlocks[x][z+1][h].opaque)
+						b.faceVisibility |= FV_FRONT;
+
+					if (h == WORLD_SIZE_H-1 || !mBlocks[x][z][h+1].opaque)
+						b.faceVisibility |= FV_TOP;
+				}
+
+				Crown::uint cx = x / CHUNK_SIZE;
+				Crown::uint cz = z / CHUNK_SIZE;
+				Crown::uint ch = h / CHUNK_SIZE;
+
+				if (cx < 0 || cz < 0 || ch < 0 || cx >= CHUNKS_COUNT || cz >= CHUNKS_COUNT || ch >= CHUNKS_COUNT_H)
+					continue;
+
+				if (b.faceVisibility == FV_NONE)
+					mChunks[cx][cz][ch]->BlockRemoved(x, z, h);
+				else
+					mChunks[cx][cz][ch]->BlockRevealed(x, z, h);
+			}
+		}
+	}
+}
+
+void WorldTerrain::RecalculateVisibleBlocksSides()
+{
+	for(int x = 0; x < WORLD_SIZE; x++)
+	{
+		for(int z = 0; z < WORLD_SIZE; z++)
+		{
+			for(int h = 0; h < WORLD_SIZE_H; h++)
+			{
+				Block& b = mBlocks[x][z][h];
+				Crown::uint fv = FV_NONE;
+				if (b.opaque)
+				{
+					if (x == 0 || !mBlocks[x-1][z][h].opaque)
+						fv |= FV_LEFT;
+					if (x == WORLD_SIZE-1 || !mBlocks[x+1][z][h].opaque)
+						fv |= FV_RIGHT;
+				
+					if (z == 0 || !mBlocks[x][z-1][h].opaque)
+						fv |= FV_BACK;
+					if (z == WORLD_SIZE-1 || !mBlocks[x][z+1][h].opaque)
+						fv |= FV_FRONT;
+
+					if (h == 0 || !mBlocks[x][z][h-1].opaque)
+						fv |= FV_BOTTOM;
+					if (h == WORLD_SIZE_H-1 || !mBlocks[x][z][h+1].opaque)
+						fv |= FV_TOP;
+				}
+				b.faceVisibility = fv;
+			}
+		}
+	}
+}
+
+void WorldTerrain::RecalculateSunlight()
+{
+	for(int x = 0; x < WORLD_SIZE; x++)
+	{
+		for(int z = 0; z < WORLD_SIZE; z++)
+		{
+			mBlocks[x][z][WORLD_SIZE_H-1].light = 15;
+		}
+	}
+
+	for(int x = 0; x < WORLD_SIZE; x++)
+	{
+		for(int z = 0; z < WORLD_SIZE; z++)
+		{
+			for(int h = WORLD_SIZE_H-2; h > 0 && !mBlocks[x][z][h].opaque; h--)
+			{
+				mBlocks[x][z][h].light = 15;
+			}
+		}
+	}
+}
+
+void WorldTerrain::RegenerateTerrain()
+{
+
+	for(int x = 0; x < CHUNKS_COUNT; x++)
+	{
+		for(int z = 0; z < CHUNKS_COUNT; z++)
+		{
+			for(int h = 0; h < CHUNKS_COUNT_H; h++)
+			{
+					mChunks[x][z][h]->AssignLocation(x*CHUNK_SIZE	, z*CHUNK_SIZE, h*CHUNK_SIZE);
+			}
+		}
+	}
+}
+
+void WorldTerrain::Render()
+{
+	glEnable(GL_TEXTURE_2D);
+	Renderer* r = GetDevice()->GetRenderer();
+	r->SetTexture(1, mTerrainTexture);
+	//mTerrainTexture->MakeCurrent();
+
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glEnableClientState(GL_NORMAL_ARRAY);
+	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+	glEnableClientState(GL_COLOR_ARRAY);
+	
+	mChunkRegenerationSlots = 30;
+
+	for(int x = 0; x < CHUNKS_COUNT; x++)
+	{
+		for(int z = 0; z < CHUNKS_COUNT; z++)
+		{
+			for(int h = 0; h < CHUNKS_COUNT_H; h++)
+			{
+					mChunks[x][z][h]->Render();
+			}
+		}
+	}
+
+	
+	glDisableClientState(GL_VERTEX_ARRAY);
+	glDisableClientState(GL_NORMAL_ARRAY);
+	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+	glDisableClientState(GL_COLOR_ARRAY);
+
+	glDisable(GL_TEXTURE_2D);
+}
+
+void WorldTerrain::SetPlayerPosition(Vec3 newPosition)
+{
+	newPosition /= CubeSize;
+	Crown::uint chunkX = (Crown::uint) (newPosition.x / (CHUNK_SIZE)) - mChunkX;
+	Crown::uint chunkZ = (Crown::uint) (newPosition.z / (CHUNK_SIZE)) - mChunkZ;
+	Crown::uint chunkH = (Crown::uint) (newPosition.y / (CHUNK_SIZE)) - mChunkH;
+
+	mPlayerPosition = newPosition;
+
+	if (chunkX > (CHUNKS_COUNT+1)/2  && (mChunkX + CHUNKS_COUNT) * CHUNK_SIZE < WORLD_SIZE)
+	{
+		//Fai uno spostamento verso x+
+		Chunk* tempChunks[CHUNKS_COUNT][CHUNKS_COUNT_H];
+
+		mChunkX += 1;
+
+		ExtractChunksFromX(tempChunks, 0);
+
+		//Slide all chunks behind in the -x direction
+		for(int x = 0; x < CHUNKS_COUNT-1; x++)
+		{
+			for(int z = 0; z < CHUNKS_COUNT; z++)
+			{
+				for(int h = 0; h < CHUNKS_COUNT_H; h++)
+				{
+						Chunk* c = mChunks[x+1][z][h];
+						mChunks[x][z][h] = c;
+						c->mRelX--;
+						c->UpdateShouldRender();
+				}
+			}
+		}
+
+		ReplaceChunksInX(tempChunks, CHUNKS_COUNT-1);
+	}
+	else if (chunkX < (CHUNKS_COUNT+1)/2  && mChunkX > 0)
+	{
+		//Fai uno spostamento verso x-
+		Chunk* tempChunks[CHUNKS_COUNT][CHUNKS_COUNT_H];
+
+		mChunkX -= 1;
+
+		ExtractChunksFromX(tempChunks, CHUNKS_COUNT-1);
+
+		for(int x = CHUNKS_COUNT-1; x > 0; x--)
+		{
+			for(int z = 0; z < CHUNKS_COUNT; z++)
+			{
+				for(int h = 0; h < CHUNKS_COUNT_H; h++)
+				{
+						Chunk* c = mChunks[x-1][z][h];
+						mChunks[x][z][h] = c;
+						c->mRelX++;
+						c->UpdateShouldRender();
+				}
+			}
+		}
+
+		ReplaceChunksInX(tempChunks, 0);
+	}
+	else if (chunkZ > (CHUNKS_COUNT+1)/2  && (mChunkZ + CHUNKS_COUNT) * CHUNK_SIZE < WORLD_SIZE)
+	{
+		//Fai uno spostamento verso z+
+		Chunk* tempChunks[CHUNKS_COUNT][CHUNKS_COUNT_H];
+
+		mChunkZ += 1;
+
+		ExtractChunksFromZ(tempChunks, 0);
+
+		for(int z = 0; z < CHUNKS_COUNT-1; z++)
+		{
+			for(int x = 0; x < CHUNKS_COUNT; x++)
+			{
+				for(int h = 0; h < CHUNKS_COUNT_H; h++)
+				{
+						Chunk* c = mChunks[x][z+1][h];
+						mChunks[x][z][h] = c;
+						c->mRelZ--;
+						c->UpdateShouldRender();
+				}
+			}
+		}
+
+		ReplaceChunksInZ(tempChunks, CHUNKS_COUNT-1);	
+	}
+	else if (chunkZ < (CHUNKS_COUNT+1)/2  && mChunkZ > 0)
+	{
+		//Fai uno spostamento verso z-
+		Chunk* tempChunks[CHUNKS_COUNT][CHUNKS_COUNT_H];
+
+		mChunkZ -= 1;
+
+		ExtractChunksFromZ(tempChunks, CHUNKS_COUNT-1);
+
+		for(int z = CHUNKS_COUNT-1; z > 0; z--)
+		{
+			for(int x = 0; x < CHUNKS_COUNT; x++)
+			{
+				for(int h = 0; h < CHUNKS_COUNT_H; h++)
+				{
+						Chunk* c = mChunks[x][z-1][h];
+						mChunks[x][z][h] = c;
+						c->mRelZ++;
+						c->UpdateShouldRender();
+				}
+			}
+		}
+
+		ReplaceChunksInZ(tempChunks, 0);
+	}
+	else if (chunkX != mPlayerChunkX || chunkZ != mPlayerChunkZ || chunkH != mPlayerChunkH)
+	{
+		if (chunkX >= CHUNKS_COUNT || chunkZ >= CHUNKS_COUNT || chunkH >= CHUNKS_COUNT_H)
+			return;
+		Crown::uint xOff = chunkX - mPlayerChunkX;
+		Crown::uint zOff = chunkZ - mPlayerChunkZ;
+		Crown::uint hOff = chunkH - mPlayerChunkH;
+		mPlayerChunkX = chunkX;
+		mPlayerChunkZ = chunkZ;
+		mPlayerChunkH = chunkH;
+		//Just update the ShouldDraw of chunks
+
+		for(int x = 0; x < CHUNKS_COUNT; x++)
+		{
+			for(int z = 0; z < CHUNKS_COUNT; z++)
+			{
+				for(int h = 0; h < CHUNKS_COUNT_H; h++)
+				{
+						mChunks[x][z][h]->UpdateShouldRender();
+						mChunks[x][z][h]->mRelX -= xOff;
+						mChunks[x][z][h]->mRelZ -= zOff;
+						mChunks[x][z][h]->mRelH -= hOff;
+				}
+			}
+		}
+	}
+}
+
+void WorldTerrain::LOL()
+{
+	Crown::uint x = rand() % CHUNK_SIZE;
+	Crown::uint z = rand() % CHUNK_SIZE;
+
+	Crown::uint h = 0;
+	while (h < WORLD_SIZE_H-1 && mBlocks[x][z][h+1].opaque)
+		h++;
+
+	mBlocks[x][z][h].opaque = false;
+	
+	UpdateVisibleNeighbourBlocks(x, z, h);
+}
+
+void WorldTerrain::CycleViewDistance()
+{
+	if (mViewDistance == 256)
+		mViewDistance = 32;
+	else
+		mViewDistance <<= 1;
+
+	std::cout << "View distance changed: " << mViewDistance << std::endl;
+	
+	cam->SetFarClipDistance(mViewDistance);
+	glFogf(GL_FOG_START, mViewDistance*CubeSize*0.35);
+	glFogf(GL_FOG_END, mViewDistance*CubeSize);
+}
+
+void WorldTerrain::ExtractChunksFromX(Chunk* destChunks[CHUNKS_COUNT][CHUNKS_COUNT_H], Crown::uint x)
+{
+	for(int z = 0; z < CHUNKS_COUNT; z++)
+	{
+		for(int h = 0; h < CHUNKS_COUNT_H; h++)
+		{
+				destChunks[z][h] = mChunks[x][z][h];
+		}
+	}
+}
+
+void WorldTerrain::ReplaceChunksInX(Chunk* srcChunks[CHUNKS_COUNT][CHUNKS_COUNT_H], Crown::uint x)
+{
+	for(int z = 0; z < CHUNKS_COUNT; z++)
+	{
+		for(int h = 0; h < CHUNKS_COUNT_H; h++)
+		{
+				Chunk* c;
+				c = srcChunks[z][h];
+				mChunks[x][z][h] = c;
+				c->AssignLocation((mChunkX + x) * CHUNK_SIZE, c->mZ, c->mH);
+		}
+	}
+}
+
+void WorldTerrain::ExtractChunksFromZ(Chunk* destChunks[CHUNKS_COUNT][CHUNKS_COUNT_H], Crown::uint z)
+{
+	for(int x = 0; x < CHUNKS_COUNT; x++)
+	{
+		for(int h = 0; h < CHUNKS_COUNT_H; h++)
+		{
+				destChunks[x][h] = mChunks[x][z][h];
+		}
+	}
+}
+
+void WorldTerrain::ReplaceChunksInZ(Chunk* srcChunks[CHUNKS_COUNT][CHUNKS_COUNT_H], Crown::uint z)
+{
+	for(int x = 0; x < CHUNKS_COUNT; x++)
+	{
+		for(int h = 0; h < CHUNKS_COUNT_H; h++)
+		{
+				Chunk* c;
+				c = srcChunks[x][h];
+				mChunks[x][z][h] = c;
+				c->AssignLocation(c->mX, (mChunkZ + z) * CHUNK_SIZE, c->mH);
+		}
+	}
+}
+
+//------------CHUNK-------------
+Chunk::Chunk(WorldTerrain* terrain):
+	mWorldTerrain(terrain), mX(0), mZ(0), mH(0), mRelX(0), mRelZ(0), mRelH(0), mIsDirty(false), mShouldRender(false),
+	mCandidateBlocks(0),
+	mVertexBuffer(NULL), mIndexBuffer(NULL),
+	mVertex(NULL), mVertexCount(0)
+{
+	for(int i = 0; i < 6; i++)
+	{
+		mIndices[i] = NULL;
+		mIndicesCount[i] = 0;
+	}
+
+	mVertexBuffer = GetDevice()->GetRenderer()->CreateVertexBuffer();
+	mIndexBuffer = GetDevice()->GetRenderer()->CreateIndexBuffer();
+}
+
+Chunk::~Chunk()
+{
+	delete[] mVertex;
+	for(int i = 0; i < 6; i++)
+		if (mIndices[i] != NULL)
+		{
+			delete[] mIndices[i];
+			mIndices[i] = NULL;
+		}
+}
+
+void Chunk::Render()
+{
+	Box box;
+	box.min = Vec3(mX*CubeSize, mH*CubeSize, mZ*CubeSize);
+	box.max = Vec3((mX+CHUNK_SIZE)*CubeSize, (mH+CHUNK_SIZE)*CubeSize, (mZ+CHUNK_SIZE)*CubeSize);
+
+	//Vec3 minToMax = box.max - box.min;
+	//Compensate imprecise frustum culling
+	//box.min -= minToMax/(18*1.6);
+	//box.max += minToMax/(18*1.6);
+
+	if (mShouldRender)// && cam->GetFrustum().IntersectsBox(box))
+	{
+		if (mWorldTerrain->mDrawGrid)
+		{
+			glColor3f(0.6f, 0.6f, 1.0f);
+			DrawWiredCube(mX*CubeSize, mH*CubeSize, mZ*CubeSize, 16*CubeSize);
+			glColor3f(1.0f, 1.0f, 1.0f);
+		}
+
+		if (mCandidateBlocks > 0)
+		{
+
+			if (mIsDirty && mWorldTerrain->mChunkRegenerationSlots > 0)
+			{
+				mWorldTerrain->mChunkRegenerationSlots--;
+				mIsDirty = false;
+				mWorldTerrain->RegeneratedChunks++;
+				RegenerateChunk();
+			}
+
+			if (mVertexBuffer == NULL || mIndexBuffer == NULL)
+				return;
+
+			mVertexBuffer->MakeCurrent();
+			mIndexBuffer->MakeCurrent();
+		
+			if (mRelX >= 0)
+				glDrawElements(GL_TRIANGLES, mIndicesCount[FB_LEFT], GL_UNSIGNED_INT, (void*) (mIndicesOffsets[FB_LEFT]*sizeof(Crown::uint)));
+			if (mRelX <= 0)
+				glDrawElements(GL_TRIANGLES, mIndicesCount[FB_RIGHT], GL_UNSIGNED_INT, (void*) (mIndicesOffsets[FB_RIGHT]*sizeof(Crown::uint)));
+
+			if (mRelZ >= 0)
+				glDrawElements(GL_TRIANGLES, mIndicesCount[FB_BACK], GL_UNSIGNED_INT, (void*) (mIndicesOffsets[FB_BACK]*sizeof(Crown::uint)));
+			if (mRelZ <= 0)
+				glDrawElements(GL_TRIANGLES, mIndicesCount[FB_FRONT], GL_UNSIGNED_INT, (void*) (mIndicesOffsets[FB_FRONT]*sizeof(Crown::uint)));
+
+			if (mRelH >= 0)
+				glDrawElements(GL_TRIANGLES, mIndicesCount[FB_BOTTOM], GL_UNSIGNED_INT, (void*) (mIndicesOffsets[FB_BOTTOM]*sizeof(Crown::uint)));
+			if (mRelH <= 0)
+				glDrawElements(GL_TRIANGLES, mIndicesCount[FB_TOP], GL_UNSIGNED_INT, (void*) (mIndicesOffsets[FB_TOP]*sizeof(Crown::uint)));
+		}
+	}
+
+	if (mVertex)
+	{
+		delete[] mVertex;
+		mVertex = NULL;
+		for(int i = 0; i < 6; i++)
+		{
+			if (mIndices[i] != NULL)
+			{
+				delete[] mIndices[i];
+				mIndices[i] = NULL;
+			}
+		}
+	}
+}
+
+void Chunk::UpdateShouldRender()
+{
+	float d = (float) (pow(mRelX*CHUNK_SIZE + CHUNK_SIZE / (mRelX < 0 ? -2.0 : 2.0), 2) +
+										 pow(mRelZ*CHUNK_SIZE + CHUNK_SIZE / (mRelZ < 0 ? -2.0 : 2.0), 2));
+
+	if (d > pow((float)mWorldTerrain->mViewDistance + 2*CHUNK_SIZE, 2))
+		mShouldRender = false;
+	else
+		mShouldRender = true;
+}
+
+void Chunk::Dirty()
+{
+	mIsDirty = true;
+}
+
+void Chunk::AssignLocation(Crown::uint x, Crown::uint z, Crown::uint h)
+{
+	mX = x;
+	mZ = z;
+	mH = h;
+
+	int xTo = mX + CHUNK_SIZE;
+	int zTo = mZ + CHUNK_SIZE;
+	int hTo = mH + CHUNK_SIZE;
+
+	mCandidateBlocks = 0;
+
+	mBlocksToRender.Clear();
+
+	for(int x = mX; x < xTo; x++)
+	{
+		for(int z = mZ; z < zTo; z++)
+		{
+			for(int h = mH; h < hTo; h++)
+			{
+				Block& b = mWorldTerrain->mBlocks[x][z][h];
+				if (!b.opaque || b.faceVisibility == 0)
+					continue;
+
+				BlockToRender bt = {&b, x, z, h};
+				mBlocksToRender.Append(bt);
+				mCandidateBlocks++;
+			}
+		}
+	}
+
+	mRelX = mX / CHUNK_SIZE - (mWorldTerrain->mChunkX + mWorldTerrain->mPlayerChunkX);
+	mRelZ = mZ / CHUNK_SIZE - (mWorldTerrain->mChunkZ + mWorldTerrain->mPlayerChunkZ);
+	mRelH = mH / CHUNK_SIZE - (mWorldTerrain->mChunkH + mWorldTerrain->mPlayerChunkH);
+
+	mIsDirty = true;
+	UpdateShouldRender();
+}
+
+void Chunk::BlockRemoved(Crown::uint x, Crown::uint z, Crown::uint h)
+{
+	Block* block = &mWorldTerrain->mBlocks[x][z][h];
+	for(int i = 0; i<mBlocksToRender.GetSize(); i++)
+	{
+		if (mBlocksToRender[i].block == block)
+		{
+			mBlocksToRender[i] = mBlocksToRender[mBlocksToRender.GetSize()-1];
+			mBlocksToRender.Remove(mBlocksToRender.GetSize()-1);
+			mCandidateBlocks--;
+			mIsDirty = true;
+			return;
+		}
+	}
+}
+
+void Chunk::BlockRevealed(Crown::uint x, Crown::uint z, Crown::uint h)
+{
+	mIsDirty = true;
+	Block* block = &mWorldTerrain->mBlocks[x][z][h];
+	for(int i = 0; i<mBlocksToRender.GetSize(); i++)
+	{
+		if (mBlocksToRender[i].block == block)
+		{
+			return;
+		}
+	}
+	BlockToRender bt = {block, x, z, h};
+	mBlocksToRender.Append(bt);
+	mCandidateBlocks++;
+}
+
+void Chunk::RegenerateChunk()
+{
+	mVertexCount = 0;
+	for(int i = 0; i < 6; i++)
+		mIndicesCount[i] = 0;
+
+	if (mCandidateBlocks == 0)
+	{
+		mCandidateBlocks = 0;
+		mVertexBuffer->SetVertexData((VertexBufferMode) (VBM_NORMAL_COORDS | VBM_TEXTURE_COORDS | VBM_COLOR_COORDS), NULL, 0);
+		mIndexBuffer->SetIndexData(NULL, 0);
+		return;
+	}
+
+	if (mVertex != NULL)
+		delete[] mVertex;
+	for(int i = 0; i < 6; i++)
+		if (mIndices[i] != NULL)
+			delete[] mIndices[i];
+
+	mVertex = new VertexData[mCandidateBlocks * 24];
+	for(int i = 0; i < 6; i++)
+		mIndices[i] = new Crown::uint[mCandidateBlocks * 36];
+
+	for(int i = 0; i<mBlocksToRender.GetSize(); i++)
+	{
+		BlockToRender& bt = mBlocksToRender[i];
+		Block* b = bt.block;
+
+		uchar light;
+
+		if (b->faceVisibility & FV_TOP)
+		{
+			if (bt.h < WORLD_SIZE_H-1)
+				light = mWorldTerrain->mBlocks[bt.x][bt.z][bt.h+1].light;
+			AddFace(bt.x, bt.z, bt.h, FB_TOP, light);
+		}
+
+		if (b->faceVisibility & FV_BOTTOM)
+		{
+			if (bt.h > 0)
+				light = mWorldTerrain->mBlocks[bt.x][bt.z][bt.h-1].light;
+			AddFace(bt.x, bt.z, bt.h, FB_BOTTOM, light);
+		}
+
+		if (b->faceVisibility & FV_LEFT)
+		{
+			if (bt.x > 0)
+				light = mWorldTerrain->mBlocks[bt.x-1][bt.z][bt.h].light;
+			AddFace(bt.x, bt.z, bt.h, FB_LEFT, light);
+		}
+
+		if (b->faceVisibility & FV_RIGHT)
+		{
+			if (bt.x < WORLD_SIZE_H-1)
+				light = mWorldTerrain->mBlocks[bt.x+1][bt.z][bt.h].light;
+			AddFace(bt.x, bt.z, bt.h, FB_RIGHT, light);
+		}
+
+		if (b->faceVisibility & FV_FRONT)
+		{
+			if (bt.z < WORLD_SIZE_H-1)
+				light = mWorldTerrain->mBlocks[bt.x][bt.z+1][bt.h].light;
+			AddFace(bt.x, bt.z, bt.h, FB_FRONT, light);
+		}
+
+		if (b->faceVisibility & FV_BACK)
+		{
+			if (bt.z > 0)
+				light = mWorldTerrain->mBlocks[bt.x][bt.z-1][bt.h].light;
+			AddFace(bt.x, bt.z, bt.h, FB_BACK, light);
+		}
+	}
+
+	mVertexBuffer->SetVertexData((VertexBufferMode) (VBM_NORMAL_COORDS | VBM_TEXTURE_COORDS | VBM_COLOR_COORDS), (float*)mVertex, mVertexCount);
+	int totIndicesCount = 0;
+	for(int i = 0; i < 6; i++)
+		totIndicesCount += mIndicesCount[i];
+
+	mIndexBuffer->SetIndexData(NULL, totIndicesCount);
+	totIndicesCount = 0;
+	for(int i = 0; i < 6; i++)
+	{
+		mIndicesOffsets[i] = totIndicesCount;
+		if (mIndicesCount[i] > 0)
+		{
+			mIndexBuffer->SetIndexSubData(mIndices[i], totIndicesCount, mIndicesCount[i]);
+			totIndicesCount += mIndicesCount[i];
+		}
+	}
+}
+
+void Chunk::AddFace(int x, int z, int h, FaceBuffer face, uchar light)
+{
+	float xx = x * CubeSize;
+	float zz = z * CubeSize;
+	float hh = h * CubeSize;
+
+	FaceMaterial faceMaterial = GetMaterial(0, face);
+
+	float lightFactor = light / 15.0f;
+	AddFace(faceMaterial, Vec3(xx, hh, zz), lightFactor, mIndices[face], mIndicesCount[face]);
+}
+
+void Chunk::AddFace(const FaceMaterial& faceMaterial, Vec3 traslation, float lightFactor, Crown::uint* index, Crown::uint& indicesCount)
+{
+	Crown::uint firstIdx = mVertexCount;
+	
+	VertexData vd;
+	
+	vd = faceMaterial.vd0;
+	vd.position += traslation;
+	//vd.color *= lightFactor;
+	memcpy(&mVertex[mVertexCount], &vd, sizeof(VertexData));
+	mVertexCount++;
+	
+	vd = faceMaterial.vd1;
+	vd.position += traslation;
+	//vd.color *= lightFactor;
+	memcpy(&mVertex[mVertexCount], &vd, sizeof(VertexData));
+	mVertexCount++;
+	
+	vd = faceMaterial.vd2;
+	vd.position += traslation;
+	//vd.color *= lightFactor;
+	memcpy(&mVertex[mVertexCount], &vd, sizeof(VertexData));
+	mVertexCount++;
+	
+	vd = faceMaterial.vd3;
+	vd.position += traslation;
+	//vd.color *= lightFactor;
+	memcpy(&mVertex[mVertexCount], &vd, sizeof(VertexData));
+	mVertexCount++;
+	
+	index[indicesCount++] = firstIdx;
+	index[indicesCount++] = firstIdx+1;
+	index[indicesCount++] = firstIdx+2;
+
+	index[indicesCount++] = firstIdx;
+	index[indicesCount++] = firstIdx+2;
+	index[indicesCount++] = firstIdx+3;
+}
+
+
+void DrawWiredCube(float x, float y, float z, float size)
+{
+	glBegin(GL_LINES);
+
+	glVertex3f(x, y, z);
+	glVertex3f(x, y, z + size);
+
+	glVertex3f(x + size, y, z);
+	glVertex3f(x + size, y, z + size);
+
+	glVertex3f(x, y + size, z);
+	glVertex3f(x, y + size, z + size);
+
+	glVertex3f(x + size, y + size, z);
+	glVertex3f(x + size, y + size, z + size);
+
+	glVertex3f(x					 , y, z);
+	glVertex3f(x + size, y, z);
+
+	glVertex3f(x					 , y, z + size);
+	glVertex3f(x + size, y, z + size);
+
+	glVertex3f(x					 , y + size , z);
+	glVertex3f(x + size, y + size , z);
+
+	glVertex3f(x					 , y + size , z + size);
+	glVertex3f(x + size, y + size , z + size);
+
+	glVertex3f(x, y						, z);
+	glVertex3f(x, y + size, z);
+
+	glVertex3f(x + size, y					 , z);
+	glVertex3f(x + size, y + size, z);
+
+	glVertex3f(x, y						, z + size);
+	glVertex3f(x, y + size, z + size);
+
+	glVertex3f(x + size, y					 , z + size);
+	glVertex3f(x + size, y + size, z + size);
+
+	glEnd();
+}
+

+ 163 - 0
samples/minecrown/WorldTerrain.h

@@ -0,0 +1,163 @@
+#ifndef __WORLD_TERRAIN_H__
+#define __WORLD_TERRAIN_H__
+
+#include "Crown.h"
+#include "WorldMaterial.h"
+
+using namespace Crown;
+
+#define WORLD_SIZE 512//1024
+#define WORLD_SIZE_H 128
+#define CHUNK_SIZE 16
+#define CHUNKS_COUNT 32 //Deve essere dispari
+#define CHUNKS_COUNT_H (WORLD_SIZE_H/CHUNK_SIZE)
+
+class WorldTerrain;
+
+enum FaceVisibility
+{
+	FV_NONE		= 0,
+	FV_TOP		= 1,
+	FV_BOTTOM	= 2,
+	FV_LEFT		= 4,
+	FV_RIGHT	= 8,
+	FV_FRONT	= 16,
+	FV_BACK		= 32
+};
+
+enum FaceBuffer
+{
+	FB_TOP = 0,
+	FB_BOTTOM = 1,
+	FB_LEFT = 2,
+	FB_RIGHT = 3,
+	FB_FRONT = 4,
+	FB_BACK = 5
+};
+
+struct Block
+{
+	bool opaque;
+	uchar light;
+	uchar faceVisibility;
+};
+
+struct BlockToRender
+{
+	Block* block;
+	Crown::uint x, z, h;
+};
+
+class Chunk {
+
+public:
+	Chunk(WorldTerrain* terrain);
+	~Chunk();
+
+	void Render();
+
+	void Dirty();
+
+	void AssignLocation(Crown::uint x, Crown::uint z, Crown::uint h);
+	void UpdateShouldRender();
+
+	void BlockRemoved(Crown::uint x, Crown::uint z, Crown::uint h);
+	void BlockRevealed(Crown::uint x, Crown::uint z, Crown::uint h);
+
+private:
+	WorldTerrain* mWorldTerrain;
+	int mX, mZ, mH;
+	int mRelX, mRelZ, mRelH;
+	bool mIsDirty;
+	bool mShouldRender;
+	Crown::uint mCandidateBlocks;
+
+	List<BlockToRender> mBlocksToRender;
+
+	VertexBuffer* mVertexBuffer;
+	IndexBuffer* mIndexBuffer;
+
+	VertexData* mVertex;
+	Crown::uint mVertexCount;
+	Crown::uint* mIndices[6];
+	Crown::uint mIndicesCount[6];
+	Crown::uint mIndicesOffsets[6];
+
+	void AddFace(int x, int z, int h, FaceBuffer orientation, uchar light);
+	void AddFace(const FaceMaterial& faceMaterial, Vec3 traslation, float lightFactor, Crown::uint* index, Crown::uint& indicesCount);
+	void RegenerateChunk();
+
+	friend class WorldTerrain;
+};
+
+
+class WorldTerrain
+{
+
+public:
+	
+	WorldTerrain();
+
+	~WorldTerrain();
+
+	void RandomMap(int groundLevel, int seed, int octaves, int freq);
+
+	void Render();
+
+	void SetPlayerPosition(Vec3 newPosition);
+
+	inline Vec3 GetPlayerPosition() const
+	{
+		return mPlayerPosition;
+	}
+
+	void LOL();
+
+	//params
+	void ToggleGrid() { mDrawGrid = !mDrawGrid; }
+
+	void CycleViewDistance();
+
+	//Debug infos
+	int RegeneratedChunks;
+
+private:
+
+	Block mBlocks[WORLD_SIZE][WORLD_SIZE][WORLD_SIZE_H];
+	Chunk* mChunks[CHUNKS_COUNT][CHUNKS_COUNT][CHUNKS_COUNT_H];
+	Texture* mTerrainTexture;
+
+	int mChunkRegenerationSlots;
+
+	Vec3 mPlayerPosition;
+	Crown::uint mChunkX;
+	Crown::uint mChunkZ;
+	Crown::uint mChunkH;
+
+	// Player chunks relative to mChunkX, mChunkZ, mChunkH
+	Crown::uint mPlayerChunkX;
+	Crown::uint mPlayerChunkZ;
+	Crown::uint mPlayerChunkH;
+
+	bool mDrawGrid;
+	int mViewDistance;
+
+
+	void ExtractChunksFromX(Chunk* destChunks[CHUNKS_COUNT][CHUNKS_COUNT_H], Crown::uint x);
+	void ReplaceChunksInX(Chunk* srcChunks[CHUNKS_COUNT][CHUNKS_COUNT_H], Crown::uint x);
+	void ExtractChunksFromZ(Chunk* destChunks[CHUNKS_COUNT][CHUNKS_COUNT_H], Crown::uint z);
+	void ReplaceChunksInZ(Chunk* srcChunks[CHUNKS_COUNT][CHUNKS_COUNT_H], Crown::uint z);
+
+	void RegenerateTerrain();
+
+	void RecalculateVisibleBlocksSides();
+	void RecalculateSunlight();
+	void UpdateVisibleNeighbourBlocks(Crown::uint x, Crown::uint z, Crown::uint h);
+
+	void Clear();
+
+	friend class Chunk;
+};
+
+
+#endif //__WORLD_TERRAIN_H__

+ 471 - 0
samples/minecrown/main.cpp

@@ -0,0 +1,471 @@
+#include "Crown.h"
+#include <time.h>
+#include <cstdlib>
+#include <iostream>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+
+#include "WorldTerrain.h"
+#include "perlin.h"
+
+void DrawAxis();
+void DrawGrid(float xStart, float zStart, float xStep, float zStep);
+void DrawCube(float x, float y, float z);
+void DrawVoxelGrid(float xStart, float yStart, float zStart, float xStep, float yStep, float zStep);
+
+using namespace Crown;
+
+MovableCamera* cam;
+WorldTerrain* terrain;
+int groundLevel = 0;
+int seed;
+int octaves = 4, freq = 2;
+int currentFog = 10;
+float fogDensity = 0.1f;
+
+bool attached = true;
+
+class MainScene: public Crown::Scene, EventReceiver {
+
+public:
+
+	MainScene()
+	{
+		GetDevice()->GetEventDispatcher()->RegisterEventReceiver(this);
+		mDevice = GetDevice();
+	}
+
+	virtual ~MainScene()
+	{
+		if (terrain)
+			delete terrain;
+	}
+
+	void HandleEvent(const Event& event)
+	{
+		if (event.event_type == ET_KEYBOARD)
+		{
+			if (event.keyboard.type == KET_RELEASED)
+			{
+				if (event.keyboard.key == KK_ESCAPE)
+				{
+
+					if (mDevice) {
+						mDevice->StopRunning();
+					}
+				}
+
+				if (event.keyboard.key == KK_SPACE) {
+					
+					seed = rand();
+					terrain->RandomMap(groundLevel, seed, octaves, freq);
+				}
+
+				if (event.keyboard.key == KK_UP) {
+					
+					groundLevel += 1;
+					terrain->RandomMap(groundLevel, seed, octaves, freq);
+				}
+
+				if (event.keyboard.key == KK_DOWN) {
+					
+					groundLevel -= 1;
+					terrain->RandomMap(groundLevel, seed, octaves, freq);
+				}
+
+				if (event.keyboard.key == KK_R) {
+					
+					octaves += 1;
+					terrain->RandomMap(groundLevel, seed, octaves, freq);
+				}
+
+				if (event.keyboard.key == KK_F) {
+					
+					if (octaves > 1)
+						octaves -= 1;
+					terrain->RandomMap(groundLevel, seed, octaves, freq);
+				}
+
+				if (event.keyboard.key == KK_T) {
+					
+					freq += 1;
+					terrain->RandomMap(groundLevel, seed, octaves, freq);
+				}
+
+				if (event.keyboard.key == KK_G) {
+					
+					if (freq > 1)
+						freq -= 1;
+					terrain->RandomMap(groundLevel, seed, octaves, freq);
+				}
+
+				if (event.keyboard.key == KK_Y) {
+					
+
+					currentFog+=10;
+					glFogf(GL_FOG_END, currentFog);
+				}
+
+				if (event.keyboard.key == KK_H) {
+					
+					currentFog-=10;
+					glFogf(GL_FOG_END, currentFog);
+				}
+
+				if (event.keyboard.key == KK_1) {
+					
+					terrain->ToggleGrid();
+				}
+
+				if (event.keyboard.key == KK_2) {
+					
+					terrain->CycleViewDistance();
+				}
+
+				if (event.keyboard.key == KK_3) {
+					
+					static bool fogActive = true;
+					if (fogActive)
+						glDisable(GL_FOG);
+					else
+						glEnable(GL_FOG);
+					fogActive = ! fogActive;
+				}
+
+				if (event.keyboard.key == KK_0) {
+					
+					attached = !attached;
+				}
+
+			}
+
+			if (event.keyboard.key == KK_Q)
+			{
+				terrain->LOL();
+			}
+		}
+	}
+
+	virtual void OnLoad() {
+
+		SceneNode* sn = new SceneNode(this, NULL, Vec3(), Angles(), true);
+
+		cam = AddMovableCamera(
+		sn,
+		Vec3((CHUNKS_COUNT+2)/2.0f*CHUNK_SIZE*CubeSize, CHUNKS_COUNT_H*0.7*CHUNK_SIZE*CubeSize, (CHUNKS_COUNT+2)/2.0f*CHUNK_SIZE*CubeSize),
+		//Vec3(0, 1.5*CHUNK_SIZE*CubeSize, 0),
+		Angles(0, 0, 0),
+		true,
+		90.0f,
+		1.59f,
+		true,
+		1.5,
+		1);
+		cam->SetActive(true);
+		cam->SetSpeed(0.1);
+		cam->SetFarClipDistance(150.0f);
+
+		GetDevice()->GetRenderer()->SetClearColor(Color(0.457f, 0.754f, 1.0f, 1.0f));
+
+		srand(time(NULL));
+		seed = rand();
+		terrain = new WorldTerrain();
+		terrain->RandomMap(groundLevel, seed, octaves, freq);
+		
+		timer = Crown::Timer::GetInstance();
+		beforeTime = timer->GetMilliseconds();
+	}
+
+	virtual void RenderScene() {
+
+		Scene::RenderScene();
+
+		cam->Render();
+
+		Mat4 identity;
+		identity.LoadIdentity();
+
+		GetDevice()->GetRenderer()->SetMatrix(MT_MODEL, identity);
+
+		DrawAxis();
+
+		if (attached)
+			terrain->SetPlayerPosition(cam->GetPosition());
+
+		terrain->Render();
+
+		if (timer->GetMilliseconds() - beforeTime > 1000)
+		{
+			Renderer* renderer = mDevice->GetRenderer();
+			Str title = "Fps: " + Str(renderer->GetFPS()) + " - Regenerated Chunks: " + Str(terrain->RegeneratedChunks) + " - Px: " + Str(terrain->GetPlayerPosition().x) + ", Px: " + Str(terrain->GetPlayerPosition().z);
+			terrain->RegeneratedChunks = 0;
+			GetDevice()->GetMainWindow()->SetTitle(title.c_str());
+			beforeTime = timer->GetMilliseconds();
+		}
+	}
+
+	Device* mDevice;
+	Crown::Timer* timer;
+	Crown::ulong beforeTime;
+};
+
+
+int main(int argc, char** argv) {
+
+	int wndW, wndH;
+	wndW = 1024;
+	wndH = 768;
+	bool full = false;
+
+	if (argc == 3) {
+		wndW = atoi(argv[1]);
+		wndH = atoi(argv[2]);
+	}
+
+	Device* device = GetDevice();
+
+
+	if (!device->Init(wndW, wndH, 32, false)) {
+
+		return 0;
+	}
+
+	Renderer* renderer = device->GetRenderer();
+	SceneManager* smgr = device->GetSceneManager();
+	ResourceManager* resman = device->GetResourceManager();
+
+	device->GetMainWindow()->SetTitle("Crown Engine v0.1");
+	device->GetMainWindow()->GetCursorControl()->SetVisible(true);
+	device->GetMainWindow()->SetFullscreen(full);
+
+	Scene* scene = new MainScene();
+	
+	smgr->SelectNextScene(scene);
+
+	device->Run();
+
+	device->Shutdown();
+
+//	Scene* scene = new Scene();
+//
+//	cam = scene->AddMovableCamera(
+//		0,
+//		Vec3((CHUNKS_COUNT+2)/2.0f*CHUNK_SIZE*CubeSize, CHUNKS_COUNT_H*0.7*CHUNK_SIZE*CubeSize, (CHUNKS_COUNT+2)/2.0f*CHUNK_SIZE*CubeSize),
+//		//Vec3(0, 1.5*CHUNK_SIZE*CubeSize, 0),
+//		Angles(0, 0, 0),
+//		Vec3(1, 1, 1),
+//		true,
+//		90.0f,
+//		1.59f,
+//		true,
+//		1.5,
+//		1);
+//	cam->SetActive(true);
+//	cam->SetSpeed(0.1);
+//	cam->SetFarClipDistance(150.0f);
+//
+//	std::cout << "Entity count: " << scene->GetEntityCount() << std::endl;
+//	std::cout << "Light count: " << scene->GetLightCount() << std::endl;
+//	std::cout << "Sizeof RenderWindow: " << sizeof(RenderWindow) << std::endl;
+///*
+//	Material material;
+//	material.mAmbient = Color(0.1, 0.1, 0.1, 1);
+//	material.mDiffuse = Color(1, 1, 1, 1);
+//	material.mSpecular = Color(0, 0, 0, 1);
+//	material.mShininess = 128;
+//	material.mSeparateSpecularColor = true;
+//	material.mTexturing = false;
+//	material.mLighting = true;
+//
+//	renderer->SetMaterial(material);
+//*/
+//	Mat4 identity;
+//	identity.LoadIdentity();
+//
+//	renderer->SetClearColor(Color(0.457f, 0.754f, 1.0f, 1.0f));
+//
+//	Mat4 ortho;
+//	ortho.BuildProjectionOrthoRH(wndW, wndH, 1, -1);
+//
+//	Mat4 perspective;
+//	perspective.BuildProjectionPerspectiveRH(90.0f, 1.59f, 0.1f, 100.0f);
+//
+//	Mat4 text;
+//	text.LoadIdentity();
+//	text.SetTranslation(Vec3(400, 350, 0));
+//
+//
+//	//Crown::Font font;
+//	//Image* testImg = font.LoadFont("tests/font/arialbd.ttf");
+//
+//	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+//
+//	srand(time(NULL));
+//	seed = rand();
+//	terrain = new WorldTerrain();
+//	terrain->RandomMap(groundLevel, seed, octaves, freq);
+//	//terrain->RandomMap1();
+//
+//	while (device->IsRunning()) {
+//
+//		WindowEventHandler::GetInstance()->ManageEvents();
+//		GetDevice()->GetMainWindow()->GetRenderContext()->MakeCurrent();
+//
+//		// ----------- Begin Scene -----------
+//		renderer->_BeginFrame();
+//
+//		renderer->SetMatrix(MT_PROJECTION, ortho);
+//		//renderer->SetMatrix(MT_MODEL, text);
+//
+//		glDisable(GL_LIGHTING);
+//		glColor3f(1, 1, 1);
+//
+//		cam->Render();
+//
+//		renderer->SetMatrix(MT_MODEL, identity);
+//
+//		DrawAxis();
+//
+//		if (attached)
+//			terrain->SetPlayerPosition(cam->GetPosition());
+//
+//		terrain->Render();
+//
+//		renderer->_EndFrame();
+//		// ----------- End Scene -------------
+//
+//		GetDevice()->GetMainWindow()->Update();
+//		GetDevice()->GetMainWindow()->SetTitle(Str(renderer->GetFPS()).c_str());
+//	}
+//
+//	delete terrain;
+//
+//	device->Shutdown();
+
+	return 0;
+}
+
+void DrawAxis() {
+
+	glBegin(GL_LINES);
+	glColor3f(1, 0, 0);
+	glVertex3f(0, 0, 0);
+	glVertex3f(1000, 0, 0);
+	glColor3f(0, 1, 0);
+	glVertex3f(0, 0, 0);
+	glVertex3f(0, 1000, 0);
+	glColor3f(0, 0, 1);
+	glVertex3f(0, 0, 0);
+	glVertex3f(0, 0, 1000);
+	glEnd();
+}
+
+void DrawGrid(float xStart, float zStart, float xStep, float zStep) {
+
+	glColor3f(.5f, .5f, .5f);
+	const unsigned int steps = 128;
+	for (unsigned int i = 0; i <= steps; i++) {
+		glBegin(GL_LINES);
+		glVertex3f(xStart + xStep * (float)i, -1.0f, zStart);
+		glVertex3f(xStart + xStep * (float)i, -1.0f, zStart-steps*zStep);
+		glEnd();
+
+		glBegin(GL_LINES);
+		glVertex3f(xStart, -1.0f, zStart - zStep * (float)i);
+		glVertex3f(xStart+steps*xStep, -1.0f, zStart - zStep * (float)i);
+		glEnd();
+	}
+}
+
+void DrawCube(float x, float y, float z) {
+
+	glBegin(GL_QUADS);
+
+	
+	//top
+	glColor3f(.3f, .0f, .0f);
+	glVertex3f(x           , y + CubeSize, z);
+	glColor3f(.25f, .0f, .0f);
+	glVertex3f(x + CubeSize, y + CubeSize, z);
+	glColor3f(.3f, .0f, .0f);
+	glVertex3f(x + CubeSize, y + CubeSize, z - CubeSize);
+	glColor3f(.25f, .0f, .0f);
+	glVertex3f(x           , y + CubeSize, z - CubeSize);
+
+	//bottom
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x           , y, z);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x           , y, z - CubeSize);
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x + CubeSize, y, z - CubeSize);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x + CubeSize, y, z);
+
+	//left
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x, y           , z);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x, y + CubeSize, z);
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x, y + CubeSize, z - CubeSize);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x, y           , z - CubeSize);
+
+	//right
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x + CubeSize, y           , z);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x + CubeSize, y           , z - CubeSize);
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x + CubeSize, y + CubeSize, z - CubeSize);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x + CubeSize, y + CubeSize, z);
+
+	//front
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x           , y           , z);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x + CubeSize, y           , z);
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x + CubeSize, y + CubeSize, z);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x           , y + CubeSize, z);
+
+	//back
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x           , y           , z - CubeSize);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x           , y + CubeSize, z - CubeSize);
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x + CubeSize, y + CubeSize, z - CubeSize);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x + CubeSize, y           , z - CubeSize);
+
+	glEnd();
+}
+
+void DrawVoxelGrid(float xStart, float yStart, float zStart, float xStep, float yStep, float zStep) {
+
+	glColor3f(.5f, .5f, .5f);
+
+	const unsigned int steps = 16;
+	glBegin(GL_LINES);
+	for (unsigned int i = 0; i <= steps; i++) {
+		
+		for(unsigned int j = 0; j <= steps; j++) {
+			glVertex3f(xStart + xStep * (float)i, j * yStep, zStart);
+			glVertex3f(xStart + xStep * (float)i, j * yStep, zStart-steps*zStep);
+
+			glVertex3f(xStart + xStep * (float)j, yStart, zStart - zStep * (float)i);
+			glVertex3f(xStart + xStep * (float)j, yStart+steps*yStep, zStart - zStep * (float)i);
+
+			glVertex3f(xStart, j * yStep, zStart - zStep * (float)i);
+			glVertex3f(xStart+steps*xStep, j * yStep, zStart - zStep * (float)i);
+		}
+		
+	}
+	glEnd();
+}
+

+ 238 - 0
samples/minecrown/perlin.cpp

@@ -0,0 +1,238 @@
+/* coherent noise function over 1, 2 or 3 dimensions */
+/* (copyright Ken Perlin) */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "perlin.h"
+
+#define B SAMPLE_SIZE
+#define BM (SAMPLE_SIZE-1)
+
+#define N 0x1000
+#define NP 12   /* 2^N */
+#define NM 0xfff
+
+#define s_curve(t) ( t * t * (3.0f - 2.0f * t) )
+#define lerp(t, a, b) ( a + t * (b - a) )
+
+#define setup(i,b0,b1,r0,r1)\
+	t = vec[i] + N;\
+	b0 = ((int)t) & BM;\
+	b1 = (b0+1) & BM;\
+	r0 = t - (int)t;\
+	r1 = r0 - 1.0f;
+
+float Perlin::noise1(float arg)
+{
+	int bx0, bx1;
+	float rx0, rx1, sx, t, u, v, vec[1];
+
+	vec[0] = arg;
+
+	if (mStart)
+  {
+    srand(mSeed);
+		mStart = false;
+		init();
+	}
+
+	setup(0, bx0,bx1, rx0,rx1);
+
+	sx = s_curve(rx0);
+
+	u = rx0 * g1[ p[ bx0 ] ];
+	v = rx1 * g1[ p[ bx1 ] ];
+
+	return lerp(sx, u, v);
+}
+
+float Perlin::noise2(float vec[2])
+{
+	int bx0, bx1, by0, by1, b00, b10, b01, b11;
+	float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
+	int i, j;
+
+	if (mStart)
+  {
+    srand(mSeed);
+		mStart = false;
+		init();
+	}
+
+	setup(0,bx0,bx1,rx0,rx1);
+	setup(1,by0,by1,ry0,ry1);
+
+	i = p[bx0];
+	j = p[bx1];
+
+	b00 = p[i + by0];
+	b10 = p[j + by0];
+	b01 = p[i + by1];
+	b11 = p[j + by1];
+
+	sx = s_curve(rx0);
+	sy = s_curve(ry0);
+
+  #define at2(rx,ry) ( rx * q[0] + ry * q[1] )
+
+	q = g2[b00];
+	u = at2(rx0,ry0);
+	q = g2[b10];
+	v = at2(rx1,ry0);
+	a = lerp(sx, u, v);
+
+	q = g2[b01];
+	u = at2(rx0,ry1);
+	q = g2[b11];
+	v = at2(rx1,ry1);
+	b = lerp(sx, u, v);
+
+	return lerp(sy, a, b);
+}
+
+float Perlin::noise3(float vec[3])
+{
+	int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+	float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
+	int i, j;
+
+	if (mStart)
+  {
+    srand(mSeed);
+		mStart = false;
+		init();
+	}
+
+	setup(0, bx0,bx1, rx0,rx1);
+	setup(1, by0,by1, ry0,ry1);
+	setup(2, bz0,bz1, rz0,rz1);
+
+	i = p[ bx0 ];
+	j = p[ bx1 ];
+
+	b00 = p[ i + by0 ];
+	b10 = p[ j + by0 ];
+	b01 = p[ i + by1 ];
+	b11 = p[ j + by1 ];
+
+	t  = s_curve(rx0);
+	sy = s_curve(ry0);
+	sz = s_curve(rz0);
+
+  #define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
+
+	q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
+	q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
+	a = lerp(t, u, v);
+
+	q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
+	q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
+	b = lerp(t, u, v);
+
+	c = lerp(sy, a, b);
+
+	q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
+	q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
+	a = lerp(t, u, v);
+
+	q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
+	q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
+	b = lerp(t, u, v);
+
+	d = lerp(sy, a, b);
+
+	return lerp(sz, c, d);
+}
+
+void Perlin::normalize2(float v[2])
+{
+	float s;
+
+	s = (float)sqrt(v[0] * v[0] + v[1] * v[1]);
+  s = 1.0f/s;
+	v[0] = v[0] * s;
+	v[1] = v[1] * s;
+}
+
+void Perlin::normalize3(float v[3])
+{
+	float s;
+
+	s = (float)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+  s = 1.0f/s;
+
+	v[0] = v[0] * s;
+	v[1] = v[1] * s;
+	v[2] = v[2] * s;
+}
+
+void Perlin::init(void)
+{
+	int i, j, k;
+
+	for (i = 0 ; i < B ; i++)
+  {
+		p[i] = i;
+		g1[i] = (float)((rand() % (B + B)) - B) / B;
+		for (j = 0 ; j < 2 ; j++)
+			g2[i][j] = (float)((rand() % (B + B)) - B) / B;
+		normalize2(g2[i]);
+		for (j = 0 ; j < 3 ; j++)
+			g3[i][j] = (float)((rand() % (B + B)) - B) / B;
+		normalize3(g3[i]);
+	}
+
+	while (--i)
+  {
+		k = p[i];
+		p[i] = p[j = rand() % B];
+		p[j] = k;
+	}
+
+	for (i = 0 ; i < B + 2 ; i++)
+  {
+		p[B + i] = p[i];
+		g1[B + i] = g1[i];
+		for (j = 0 ; j < 2 ; j++)
+			g2[B + i][j] = g2[i][j];
+		for (j = 0 ; j < 3 ; j++)
+			g3[B + i][j] = g3[i][j];
+	}
+
+}
+
+
+float Perlin::perlin_noise_2D(float vec[2])
+{
+  int terms    = mOctaves;
+	float freq   = mFrequency;
+	float result = 0.0f;
+  float amp = mAmplitude;
+
+  vec[0]*=mFrequency;
+  vec[1]*=mFrequency;
+
+	for( int i=0; i<terms; i++ )
+	{
+		result += noise2(vec)*amp;
+		vec[0] *= 2.0f;
+		vec[1] *= 2.0f;
+    amp*=0.5f;
+	}
+
+	return result;
+}
+
+
+
+Perlin::Perlin(int octaves,float freq,float amp,int seed)
+{
+  mOctaves = octaves;
+  mFrequency = freq;
+  mAmplitude = amp;
+  mSeed = seed;
+  mStart = true;
+}
+

+ 49 - 0
samples/minecrown/perlin.h

@@ -0,0 +1,49 @@
+#ifndef PERLIN_H_
+
+#define PERLIN_H_
+
+#include <stdlib.h>
+
+#define SAMPLE_SIZE 1024
+
+class Perlin
+{
+public:
+
+  Perlin(int octaves,float freq,float amp,int seed);
+
+
+  inline float Get(float x,float y)
+  {
+    float vec[2];
+    vec[0] = x;
+    vec[1] = y;
+    return perlin_noise_2D(vec);
+  };
+
+private:
+  void init_perlin(int n,float p);
+  float perlin_noise_2D(float vec[2]);
+
+  float noise1(float arg);
+  float noise2(float vec[2]);
+  float noise3(float vec[3]);
+  void normalize2(float v[2]);
+  void normalize3(float v[3]);
+  void init(void);
+
+  int   mOctaves;
+  float mFrequency;
+  float mAmplitude;
+  int   mSeed;
+
+  int p[SAMPLE_SIZE + SAMPLE_SIZE + 2];
+  float g3[SAMPLE_SIZE + SAMPLE_SIZE + 2][3];
+  float g2[SAMPLE_SIZE + SAMPLE_SIZE + 2][2];
+  float g1[SAMPLE_SIZE + SAMPLE_SIZE + 2];
+  bool  mStart;
+
+};
+
+#endif
+

+ 697 - 0
samples/minecrown/vbo.cpp

@@ -0,0 +1,697 @@
+#include "Crown.h"
+#include <time.h>
+#include <cstdlib>
+#include <iostream>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+#include "Types.h"
+
+#define HMSIZE 256
+#define CubeSize 2/3.0f
+
+void DrawAxis();
+void DrawGrid(float xStart, float zStart, float xStep, float zStep);
+void DrawWiredCube(float x, float y, float z);
+void DrawCube(float x, float y, float z);
+void DrawVoxelGrid(float xStart, float yStart, float zStart, float xStep, float yStep, float zStep);
+
+using namespace Crown;
+
+enum Visibility
+{
+	V_Visible,
+	V_Hidden_Opt,
+	V_Hidden,
+};
+
+enum FaceOrientation
+{
+	FO_TOP,
+	FO_BOTTOM,
+	FO_LEFT,
+	FO_RIGHT,
+	FO_FRONT,
+	FO_BACK
+};
+
+struct Block {
+	Visibility visible;
+};
+
+class Chunk {
+
+public:
+	Chunk() {
+		Clear();
+		vb = NULL;
+		ib = NULL;
+	}
+
+	void Clear() {
+
+		mVertexCount = 0;
+		mVertexList.Clear();
+
+		for(int x = 0; x < HMSIZE; x++) {
+			for(int z = 0; z < HMSIZE; z++) {
+				for(int h = 0; h < HMSIZE; h++) {
+					mBlocks[x][z][h].visible = V_Hidden;
+				}
+			}
+		}
+	}
+
+	void Render() {
+
+		vb->MakeCurrent();
+		ib->MakeCurrent();
+		ib->Render(Vec3(0, 0, 0), Vec3(0, 0, 0), 0.0f);
+	}
+
+	void RandomMap() {
+
+		srand(time(NULL));
+		Clear();
+
+		for(int n = 0; n < 100; n++) {
+			int xmin, xmax, zmin, zmax;
+			int a, b;
+			a = rand()%HMSIZE;
+			b = rand()%HMSIZE;
+			xmin = Math::Min(a, b);
+			xmax = Math::Max(a, b);
+
+			a = rand()%HMSIZE;
+			b = rand()%HMSIZE;
+			zmin = Math::Min(a, b);
+			zmax = Math::Max(a, b);
+
+			for(int x = xmin; x < xmax; x++) {
+				for(int z = zmin; z < zmax; z++) {
+
+					int h = 0;
+					while (mBlocks[x][z][h].visible == V_Visible)
+						h++;
+					mBlocks[x][z][h].visible = V_Visible;
+				}
+			}
+		}
+
+		RegenerateVertexList();
+	}
+
+	void RegenerateVertexList() {
+
+		mVertexCount = 0;
+		mVertexList.Clear();
+
+		for(int x = 0; x < HMSIZE; x++) {
+			for(int z = 0; z < HMSIZE; z++) {
+				for(int h = 0; h < HMSIZE; h++) {
+
+					if (mBlocks[x][z][h].visible == V_Visible)
+						GenerateFaces(x, z, h);
+				}
+			}
+		}
+
+		if (!vb)
+			vb = GetDevice()->GetRenderer()->CreateVertexBuffer();
+		if (!ib)
+			ib = GetDevice()->GetRenderer()->CreateIndexBuffer();
+
+		vb->SetVertexData(VBM_COLOR_COORDS, mVertexList.GetData(), mVertexCount);
+
+		List<unsigned int> indexes;
+		for(int i=0; i<mVertexCount; i++)
+			indexes.Append(i);
+		ib->SetIndexData(indexes.GetData(), mVertexCount);
+
+		mVertexList.Clear();
+	}
+
+	void GenerateFaces(int x, int z, int h) {
+
+		AddFace(x, z, h, FO_TOP   , x  , z  , h+1);
+		AddFace(x, z, h, FO_BOTTOM, x  , z  , h-1);
+		AddFace(x, z, h, FO_LEFT  , x-1, z  , h);
+		AddFace(x, z, h, FO_RIGHT , x+1, z  , h);
+		AddFace(x, z, h, FO_FRONT , x  , z+1, h);
+		AddFace(x, z, h, FO_BACK  , x  , z-1, h);
+	}
+
+	void AddFace(int x, int z, int h, FaceOrientation orientation, int x1, int z1, int h1) {
+
+		if (!(x1 < 0 || x1 > HMSIZE-1 || z1 < 0 || z1 > HMSIZE-1 || h1 < 0 || h1 > HMSIZE-1))
+			if (mBlocks[x1][z1][h1].visible == V_Visible)
+				return;
+
+		float xx = x * CubeSize;
+		float zz = z * CubeSize;
+		float hh = h * CubeSize;
+
+		switch (orientation) {
+
+			case FO_TOP:
+				AppendVertex(xx           , hh + CubeSize, zz);
+				AppendColor(.3f, .0f, .0f);
+				AppendVertex(xx + CubeSize, hh + CubeSize, zz);
+				AppendColor(.25f, .0f, .0f);
+				AppendVertex(xx + CubeSize, hh + CubeSize, zz - CubeSize);
+				AppendColor(.3f, .0f, .0f);
+				AppendVertex(xx           , hh + CubeSize, zz - CubeSize);
+				AppendColor(.25f, .0f, .0f);
+				break;
+
+			case FO_BOTTOM:
+				AppendVertex(xx           , hh, zz);
+				AppendColor(.0f, .0f, .3f);
+				AppendVertex(xx           , hh, zz - CubeSize);
+				AppendColor(.0f, .0f, .25f);
+				AppendVertex(xx + CubeSize, hh, zz - CubeSize);
+				AppendColor(.0f, .0f, .3f);
+				AppendVertex(xx + CubeSize, hh, zz);
+				AppendColor(.0f, .0f, .25f);
+				break;
+
+			case FO_LEFT:
+				AppendVertex(xx, hh           , zz);
+				AppendColor(.0f, .0f, .3f);
+				AppendVertex(xx, hh + CubeSize, zz);
+				AppendColor(.0f, .0f, .25f);
+				AppendVertex(xx, hh + CubeSize, zz - CubeSize);
+				AppendColor(.0f, .0f, .3f);
+				AppendVertex(xx, hh           , zz - CubeSize);
+				AppendColor(.0f, .0f, .25f);
+				break;
+
+			case FO_RIGHT:
+				AppendVertex(xx + CubeSize, hh           , zz);
+				AppendColor(.0f, .0f, .3f);
+				AppendVertex(xx + CubeSize, hh           , zz - CubeSize);
+				AppendColor(.0f, .0f, .25f);
+				AppendVertex(xx + CubeSize, hh + CubeSize, zz - CubeSize);
+				AppendColor(.0f, .0f, .3f);
+				AppendVertex(xx + CubeSize, hh + CubeSize, zz);
+				AppendColor(.0f, .0f, .25f);
+				break;
+
+			case FO_FRONT:
+				AppendVertex(xx           , hh           , zz);
+				AppendColor(.0f, .0f, .3f);
+				AppendVertex(xx + CubeSize, hh           , zz);
+				AppendColor(.0f, .0f, .25f);
+				AppendVertex(xx + CubeSize, hh + CubeSize, zz);
+				AppendColor(.0f, .0f, .3f);
+				AppendVertex(xx           , hh + CubeSize, zz);
+				AppendColor(.0f, .0f, .25f);
+				break;
+
+			case FO_BACK:
+				AppendVertex(xx           , hh           , zz - CubeSize);
+				AppendColor(.0f, .0f, .3f);
+				AppendVertex(xx           , hh + CubeSize, zz - CubeSize);
+				AppendColor(.0f, .0f, .25f);
+				AppendVertex(xx + CubeSize, hh + CubeSize, zz - CubeSize);
+				AppendColor(.0f, .0f, .3f);
+				AppendVertex(xx + CubeSize, hh           , zz - CubeSize);
+				AppendColor(.0f, .0f, .25f);
+				break;
+
+		}
+
+		mVertexCount += 4;
+	}
+
+	void AppendVertex(float x, float y, float z) {
+
+		mVertexList.Append(x);
+		mVertexList.Append(y);
+		mVertexList.Append(z);
+	}
+
+	void AppendColor(float r, float g, float b) {
+
+		mVertexList.Append(r);
+		mVertexList.Append(g);
+		mVertexList.Append(b);
+	}
+
+	void Optimize() {
+		
+		for(int x = 1; x < HMSIZE-1; x++) {
+			for(int y = 1; y < HMSIZE-1; y++) {
+				for(int z = 1; z < HMSIZE-1; z++) {
+					if (mBlocks[x][y][z].visible == V_Visible) {
+						if (mBlocks[x-1][y][z].visible != V_Visible && mBlocks[x-1][y][z].visible != V_Hidden_Opt)
+							continue;
+						if (mBlocks[x+1][y][z].visible != V_Visible && mBlocks[x+1][y][z].visible != V_Hidden_Opt)
+							continue;
+						if (mBlocks[x][y-1][z].visible != V_Visible && mBlocks[x][y-1][z].visible != V_Hidden_Opt)
+							continue;
+						if (mBlocks[x][y+1][z].visible != V_Visible && mBlocks[x][y+1][z].visible != V_Hidden_Opt)
+							continue;
+						if (mBlocks[x][y][z-1].visible != V_Visible && mBlocks[x][y][z-1].visible != V_Hidden_Opt)
+							continue;
+						if (mBlocks[x][y][z+1].visible != V_Visible && mBlocks[x][y][z+1].visible != V_Hidden_Opt)
+							continue;
+						mBlocks[x][y][z].visible = V_Hidden_Opt;
+					}
+				}
+			}
+		}
+
+		for(int x = 1; x < HMSIZE-1; x++) {
+			for(int y = 1; y < HMSIZE-1; y++) {
+				for(int z = 1; z < HMSIZE-1; z++) {
+					if (mBlocks[x][y][z].visible == V_Hidden_Opt) {
+						mBlocks[x][y][z].visible = V_Hidden;
+					}
+				}
+			}
+		}
+	}
+
+private:
+
+	Block mBlocks[HMSIZE][HMSIZE][HMSIZE];
+	List<float> mVertexList;
+	int mVertexCount;
+	VertexBuffer* vb;
+	IndexBuffer* ib;
+};
+
+Chunk chunk;
+
+class InputReceiver : public EventReceiver {
+
+public:
+
+	InputReceiver() {
+		mDevice = GetDevice();
+		mDevice->GetEventDispatcher()->RegisterEventReceiver(this);
+	}
+
+	void HandleEvent(const Event& event) {
+
+		if (event.event_type == ET_KEYBOARD) {
+			if (event.keyboard.type == KET_RELEASED) {
+				if (event.keyboard.key == KK_ESCAPE) {
+
+					if (mDevice) {
+						mDevice->StopRunning();
+					}
+				}
+
+				if (event.keyboard.key == KK_SPACE) {
+
+					chunk.RandomMap();
+				}
+			}
+		}
+	}
+
+private:
+
+	Device* mDevice;
+};
+
+int main(int argc, char** argv) {
+
+	int wndW, wndH;
+	wndW = 1280;
+	wndH = 800;
+	bool full = false;
+
+	if (argc == 3) {
+		wndW = atoi(argv[1]);
+		wndH = atoi(argv[2]);
+	}
+
+	Device* device = GetDevice();
+
+
+	if (!device->Init(wndW, wndH, 32, false)) {
+
+		return 0;
+	}
+
+	InputReceiver ir;
+
+	Renderer* renderer = device->GetRenderer();
+	SceneManager* smgr = device->GetSceneManager();
+	ResourceManager* resman = device->GetResourceManager();
+
+	device->GetMainWindow()->SetTitle("Crown Engine v0.1");
+	device->GetMainWindow()->GetCursorControl()->SetVisible(true);
+	device->GetMainWindow()->SetFullscreen(full);
+
+	Scene* scene = new Scene();
+
+	MovableCamera* cam;
+	cam = scene->AddMovableCamera(
+		0,
+		Vec3(0.0f, 3.0f, HMSIZE*CubeSize),
+		Angles(0, 0, 0),
+		Vec3(1, 1, 1),
+		true,
+		90.0f,
+		1.59f,
+		true,
+		0.5,
+		1);
+	cam->SetActive(true);
+	cam->SetSpeed(0.1);
+	cam->SetFarClipDistance(150.0f);
+
+	std::cout << "Entity count: " << scene->GetEntityCount() << std::endl;
+	std::cout << "Light count: " << scene->GetLightCount() << std::endl;
+	std::cout << "Sizeof RenderWindow: " << sizeof(RenderWindow) << std::endl;
+/*
+	Material material;
+	material.mAmbient = Color(0.1, 0.1, 0.1, 1);
+	material.mDiffuse = Color(1, 1, 1, 1);
+	material.mSpecular = Color(0, 0, 0, 1);
+	material.mShininess = 128;
+	material.mSeparateSpecularColor = true;
+	material.mTexturing = false;
+	material.mLighting = true;
+
+	renderer->SetMaterial(material);
+*/
+	Mat4 identity;
+	identity.LoadIdentity();
+
+	renderer->SetClearColor(Color(1.0f, 1.0f, 1.0f, 1.0f));
+
+	Mat4 ortho;
+	ortho.BuildProjectionOrthoRH(wndW, wndH, 1, -1);
+
+	Mat4 perspective;
+	perspective.BuildProjectionPerspectiveRH(90.0f, 1.59f, 0.1f, 100.0f);
+
+	Mat4 text;
+	text.LoadIdentity();
+	text.SetTranslation(Vec3(400, 350, 0));
+
+
+	//Crown::Font font;
+	//Image* testImg = font.LoadFont("tests/font/arialbd.ttf");
+
+	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+	chunk.RandomMap();
+
+
+////struct MyVertex
+//// {
+////   float x, y, z;        //Vertex
+////	 float r, g, b;
+////   //float nx, ny, nz;     //Normal
+////   //float s0, t0;         //Texcoord0
+//// };
+////
+//// MyVertex pvertex[4];
+//// //VERTEX 0
+//// pvertex[0].x = 0.0;
+//// pvertex[0].y = 0.0;
+//// pvertex[0].z = 0.0;
+//// pvertex[0].r = 1.0f;
+//// pvertex[0].g = 0.0f;
+//// pvertex[0].b = 0.0f;
+////
+//// //VERTEX 1
+//// pvertex[1].x = 1.0;
+//// pvertex[1].y = 0.0;
+//// pvertex[1].z = 0.0;
+//// pvertex[1].r = 1.0f;
+//// pvertex[1].g = 1.0f;
+//// pvertex[1].b = 0.0f;
+////
+//// //VERTEX 2
+//// pvertex[2].x = 1.0;
+//// pvertex[2].y = 1.0;
+//// pvertex[2].z = 0.0;
+//// pvertex[2].r = 0.0f;
+//// pvertex[2].g = 1.0f;
+//// pvertex[2].b = 0.0f;
+////
+//// pvertex[3].x = 0.0;
+//// pvertex[3].y = 1.0;
+//// pvertex[3].z = 0.0;
+//// pvertex[3].r = 0.0f;
+//// pvertex[3].g = 1.0f;
+//// pvertex[3].b = 0.0f;
+////
+////
+//// uint VertexVBOID;
+//// uint IndexVBOID;
+////
+//// glGenBuffers(1, &VertexVBOID);
+//// glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
+//// glBufferData(GL_ARRAY_BUFFER, sizeof(MyVertex)*4, pvertex, GL_DYNAMIC_DRAW);
+////
+//// ushort pindices[4];
+//// pindices[0] = 0;
+//// pindices[1] = 1;
+//// pindices[2] = 2;
+//// pindices[3] = 3;
+////
+//// glGenBuffers(1, &IndexVBOID);
+//// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
+//// glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ushort)*4, pindices, GL_DYNAMIC_DRAW);
+////
+//// //Define this somewhere in your header file
+//// #define BUFFER_OFFSET(i) ((char *)NULL + (i))
+
+
+
+	while (device->IsRunning()) {
+
+		WindowEventHandler::GetInstance()->ManageEvents();
+		GetDevice()->GetMainWindow()->GetRenderContext()->MakeCurrent();
+
+		// ----------- Begin Scene -----------
+		renderer->BeginScene();
+
+		renderer->SetMatrix(MT_PROJECTION, ortho);
+		//renderer->SetMatrix(MT_MODEL, text);
+
+		glDisable(GL_LIGHTING);
+		glColor3f(1, 1, 1);
+
+		//glDrawPixels(testImg->GetWidth(), testImg->GetHeight(), GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, testImg->GetBuffer());
+
+		cam->Render();
+
+		//renderer->SetMatrix(MT_PROJECTION, perspective);
+
+		renderer->SetMatrix(MT_MODEL, identity);
+
+		DrawAxis();
+		//DrawGrid(-0.0f, 0.0f, 2/3.0f, 2/3.0f);
+		//DrawVoxelGrid(0.0f, 0.0f, 0.0f, 2/3.0f, 2/3.0f, 2/3.0f);
+
+		chunk.Render();
+		////glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
+		////glEnableClientState(GL_VERTEX_ARRAY);
+		////glVertexPointer(3, GL_FLOAT, sizeof(MyVertex), BUFFER_OFFSET(0));   //The starting point of the VBO, for the vertices
+		////
+		////glEnableClientState(GL_COLOR_ARRAY);
+		////glColorPointer(3, GL_FLOAT, sizeof(MyVertex), BUFFER_OFFSET(12));
+
+		////glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
+		//////To render, we can either use glDrawElements or glDrawRangeElements
+		//////The is the number of indices. 3 indices needed to make a single triangle
+		////glDrawElements(GL_QUADS, 4, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));   //The starting point of the IBO
+
+		renderer->EndScene();
+		// ----------- End Scene -------------
+
+		GetDevice()->GetMainWindow()->Update();
+		GetDevice()->GetMainWindow()->SetTitle(Str(renderer->GetFPS()).c_str());
+	}
+
+	//glDeleteBuffers(1, &VertexVBOID);
+	//glDeleteBuffers(1, &IndexVBOID);
+
+
+	//delete testImg;
+
+	device->Shutdown();
+
+	//delete testImg;
+
+	return 0;
+
+}
+
+void DrawAxis() {
+
+	glBegin(GL_LINES);
+	glColor3f(1, 0, 0);
+	glVertex3f(0, 0, 0);
+	glVertex3f(1, 0, 0);
+	glColor3f(0, 1, 0);
+	glVertex3f(0, 0, 0);
+	glVertex3f(0, 1, 0);
+	glColor3f(0, 0, 1);
+	glVertex3f(0, 0, 0);
+	glVertex3f(0, 0, 1);
+	glEnd();
+}
+
+void DrawGrid(float xStart, float zStart, float xStep, float zStep) {
+
+	glColor3f(.5f, .5f, .5f);
+	const unsigned int steps = 128;
+	for (unsigned int i = 0; i <= steps; i++) {
+		glBegin(GL_LINES);
+		glVertex3f(xStart + xStep * (float)i, -1.0f, zStart);
+		glVertex3f(xStart + xStep * (float)i, -1.0f, zStart-steps*zStep);
+		glEnd();
+
+		glBegin(GL_LINES);
+		glVertex3f(xStart, -1.0f, zStart - zStep * (float)i);
+		glVertex3f(xStart+steps*xStep, -1.0f, zStart - zStep * (float)i);
+		glEnd();
+	}
+}
+
+void DrawWiredCube(float x, float y, float z) {
+
+	glColor3f(.5f, .5f, .5f);
+
+	glBegin(GL_LINES);
+
+	glVertex3f(x, y, z);
+	glVertex3f(x, y, z - CubeSize);
+
+	glVertex3f(x + CubeSize, y, z);
+	glVertex3f(x + CubeSize, y, z - CubeSize);
+
+	glVertex3f(x, y + CubeSize, z);
+	glVertex3f(x, y + CubeSize, z - CubeSize);
+
+	glVertex3f(x + CubeSize, y + CubeSize, z);
+	glVertex3f(x + CubeSize, y + CubeSize, z - CubeSize);
+
+	glVertex3f(x					 , y, z);
+	glVertex3f(x + CubeSize, y, z);
+
+	glVertex3f(x					 , y, z - CubeSize);
+	glVertex3f(x + CubeSize, y, z - CubeSize);
+
+	glVertex3f(x					 , y + CubeSize , z);
+	glVertex3f(x + CubeSize, y + CubeSize , z);
+
+	glVertex3f(x					 , y + CubeSize , z - CubeSize);
+	glVertex3f(x + CubeSize, y + CubeSize , z - CubeSize);
+
+	glVertex3f(x, y						, z);
+	glVertex3f(x, y + CubeSize, z);
+
+	glVertex3f(x + CubeSize, y					 , z);
+	glVertex3f(x + CubeSize, y + CubeSize, z);
+
+	glVertex3f(x, y						, z - CubeSize);
+	glVertex3f(x, y + CubeSize, z - CubeSize);
+
+	glVertex3f(x + CubeSize, y					 , z - CubeSize);
+	glVertex3f(x + CubeSize, y + CubeSize, z - CubeSize);
+
+	glEnd();
+}
+
+void DrawCube(float x, float y, float z) {
+
+	glBegin(GL_QUADS);
+
+	
+	//top
+	glColor3f(.3f, .0f, .0f);
+	glVertex3f(x           , y + CubeSize, z);
+	glColor3f(.25f, .0f, .0f);
+	glVertex3f(x + CubeSize, y + CubeSize, z);
+	glColor3f(.3f, .0f, .0f);
+	glVertex3f(x + CubeSize, y + CubeSize, z - CubeSize);
+	glColor3f(.25f, .0f, .0f);
+	glVertex3f(x           , y + CubeSize, z - CubeSize);
+
+	//bottom
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x           , y, z);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x           , y, z - CubeSize);
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x + CubeSize, y, z - CubeSize);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x + CubeSize, y, z);
+
+	//left
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x, y           , z);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x, y + CubeSize, z);
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x, y + CubeSize, z - CubeSize);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x, y           , z - CubeSize);
+
+	//right
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x + CubeSize, y           , z);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x + CubeSize, y           , z - CubeSize);
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x + CubeSize, y + CubeSize, z - CubeSize);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x + CubeSize, y + CubeSize, z);
+
+	//front
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x           , y           , z);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x + CubeSize, y           , z);
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x + CubeSize, y + CubeSize, z);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x           , y + CubeSize, z);
+
+	//back
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x           , y           , z - CubeSize);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x           , y + CubeSize, z - CubeSize);
+	glColor3f(.0f, .0f, .3f);
+	glVertex3f(x + CubeSize, y + CubeSize, z - CubeSize);
+	glColor3f(.0f, .0f, .25f);
+	glVertex3f(x + CubeSize, y           , z - CubeSize);
+
+	glEnd();
+}
+
+void DrawVoxelGrid(float xStart, float yStart, float zStart, float xStep, float yStep, float zStep) {
+
+	glColor3f(.5f, .5f, .5f);
+
+	const unsigned int steps = 16;
+	glBegin(GL_LINES);
+	for (unsigned int i = 0; i <= steps; i++) {
+		
+		for(unsigned int j = 0; j <= steps; j++) {
+			glVertex3f(xStart + xStep * (float)i, j * yStep, zStart);
+			glVertex3f(xStart + xStep * (float)i, j * yStep, zStart-steps*zStep);
+
+			glVertex3f(xStart + xStep * (float)j, yStart, zStart - zStep * (float)i);
+			glVertex3f(xStart + xStep * (float)j, yStart+steps*yStep, zStart - zStep * (float)i);
+
+			glVertex3f(xStart, j * yStep, zStart - zStep * (float)i);
+			glVertex3f(xStart+steps*xStep, j * yStep, zStart - zStep * (float)i);
+		}
+		
+	}
+	glEnd();
+}
+

BIN
samples/res/arialbd.ttf


BIN
samples/res/boom.bmp


BIN
samples/res/chainsawbuffet/bullets.bmp


BIN
samples/res/chainsawbuffet/bullets_alpha.bmp


BIN
samples/res/chainsawbuffet/grass.bmp


BIN
samples/res/chainsawbuffet/grass.jpg


BIN
samples/res/chainsawbuffet/joystick.bmp


BIN
samples/res/chainsawbuffet/pg_body.bmp


BIN
samples/res/chainsawbuffet/pg_head.bmp


BIN
samples/res/chainsawbuffet/pg_legs.bmp


BIN
samples/res/chainsawbuffet/stone_wall_texture.bmp


BIN
samples/res/chainsawbuffet/tiles.bmp


BIN
samples/res/chainsawbuffet/tiles.jpeg


BIN
samples/res/chainsawbuffet/zombie1.bmp


BIN
samples/res/closebutton_x.bmp


BIN
samples/res/crate.ctex


BIN
samples/res/crate.tga


BIN
samples/res/crw_dir_icon.bmp


BIN
samples/res/crw_file_icon.bmp


+ 36 - 0
samples/res/editor_editorwindow.xml

@@ -0,0 +1,36 @@
+<Window Name="editorWindow" Title="Editor Window" Height="400" Width="850">
+  <StackLayout Orientation="Horizontal" >
+    <TreeView Name="twCrwLibrary" Width="200" BindingContext="{Bind CrwObjectModel}" Items="{Bind Root}" OnSelectionChanged="{Action UpdateCrwFilePreview}">
+	  <TreeView.ItemTemplate Items="{Bind Children}" ItemTemplate="{Bind ItemTemplate,Source=LogicalParent}">
+	    <StackLayout Orientation="Horizontal">
+		  <ImageWidget DesiredSize="16,16" Margins="2,2,2,2" ImageSource="{Bind Type,Converter=CrwIconConverter}" />
+		  <Label Text="{Bind Name}" Height="18"/>
+		</StackLayout>
+	  </TreeView.ItemTemplate>
+	</TreeView>
+	
+	<StackLayout Width="200" BindingContext="{Bind twCrwLibrary.SelectedItem,Source=Widget}" FitToChildren="Vertically" Margins="2,2,2,-1">
+	  <StackLayout Orientation="Horizontal">
+		<Label Text="ID: " DesiredSize="{Bind MinimumSize,Source=Self}" />
+		<Label Text="{Bind ID}" HorizontalTextAlign="Left" />
+	  </StackLayout>
+	  <StackLayout Orientation="Horizontal">
+		<Label Text="Name: " DesiredSize="{Bind MinimumSize,Source=Self}" />
+		<Label Text="{Bind Name}" />
+	  </StackLayout>
+	  <StackLayout Orientation="Horizontal">
+		<Label Text="Type: " DesiredSize="{Bind MinimumSize,Source=Self}" />
+		<Label Text="{Bind Type}" HorizontalTextAlign="Left" />
+	  </StackLayout>
+	  <StackLayout Orientation="Horizontal">
+		<Label Text="Offset: " DesiredSize="{Bind MinimumSize,Source=Self}" />
+		<Label Text="{Bind ContentOffset}" HorizontalTextAlign="Left" />
+	  </StackLayout>
+	  <StackLayout Orientation="Horizontal">
+		<Label Text="Size: " DesiredSize="{Bind MinimumSize,Source=Self}" />
+		<Label Text="{Bind ContentSize}" HorizontalTextAlign="Left" />
+	  </StackLayout>
+	  <ImageWidget DesiredSize="100, 100" ImageSource="{Bind BindingContext,Source=Self,Converter=CrwDescriptorToFullPathConverter}" />
+	</StackLayout>
+  </StackLayout>
+</Window>

+ 13 - 0
samples/res/editor_mainwindow.xml

@@ -0,0 +1,13 @@
+<Window Name="mainWindow" Title="Main Window" DesiredSize="90, 80">
+  <StackLayout Orientation="Vertical">
+    <Button Name="btnNewLibrary" Margins="0,0,0,1" OnClick="{Action NewLibrary}">
+      <Label Text="New Library" HorizontalTextAlign="Center" />
+    </Button>
+	<Button Name="btnOpenLibrary" Margins="0,1,0,1" OnClick="{Action OpenLibrary}">
+      <Label Text="Open Library" HorizontalTextAlign="Center" />
+    </Button>
+    <Button Name="btnClose" Margins="0,1,0,0" OnClick="{Action QuitApplication}">
+      <Label Text="Close" HorizontalTextAlign="Center" />
+    </Button>
+  </StackLayout>
+</Window>

BIN
samples/res/grass.ctex


BIN
samples/res/grass.tga


BIN
samples/res/grasse.tga


BIN
samples/res/particle.bmp


BIN
samples/res/red_down.tga


BIN
samples/res/red_east.tga


BIN
samples/res/red_north.tga


BIN
samples/res/red_south.tga


BIN
samples/res/red_up.tga


BIN
samples/res/red_west.tga


BIN
samples/res/terrain.bmp


BIN
samples/res/test_texture0.ctex


BIN
samples/res/test_texture0.tga


BIN
samples/res/test_texture1.ctex


BIN
samples/res/test_texture1.tga


BIN
samples/res/test_texture2.ctex


+ 1 - 0
samples/res/testfile.txt

@@ -0,0 +1 @@
+<text file content, prova 123 lol asd> 

BIN
samples/res/times.ttf


+ 12 - 0
samples/res/window.xml

@@ -0,0 +1,12 @@
+<Window Name="mainWindow" Title="A Window">
+  <StackLayout Margins="2, 0, 2, 0">
+    <Button Name="btnQuit" OnClick="{Action QuitApplication}" DesiredSize="35, 15">
+	  <Label Name="lblCaption" Text="Close" />
+	</Button>
+    <Button Name="btnNew" OnClick="{Action NewLibrary}" Margins="0, 15, 0, 0" DesiredSize="70, 20">
+	  <Label Name="lblCaption" Text="New Library" />
+	</Button>
+  </StackLayout>
+</Window>
+
+

+ 45 - 0
samples/res/window_fractal.xml

@@ -0,0 +1,45 @@
+<Window Name="loaderWindow" Title="Fractal" DesiredSize="200, 176">
+  <StackLayout Margins="2, 2, 2, 2">
+	<Label Text="Interactions:" Height="25" />
+	<Button OnClick="{Action Generate}" Height="25">
+	  <Label Text="Generate" HorizontalTextAlign="Center" />
+	</Button>
+	
+	<StackLayout Orientation="Horizontal">
+	  <Button OnClick="{Action MoveLeft}" DesiredSize="25, 25">
+	    <Label Text="<" HorizontalTextAlign="Center" />
+	  </Button>
+	  
+	  <StackLayout Orientation="Vertical" FitToChildren="Both">
+	    <Button OnClick="{Action MoveUp}" DesiredSize="25, 25">
+	      <Label Text="^" HorizontalTextAlign="Center" />
+	    </Button>
+	    
+	    <Button OnClick="{Action MoveDown}" DesiredSize="25, 25">
+	      <Label Text="v" HorizontalTextAlign="Center" />
+	    </Button>
+	  </StackLayout>
+	
+	  <Button OnClick="{Action MoveRight}" DesiredSize="25, 25">
+	    <Label Text=">" HorizontalTextAlign="Center" />
+	  </Button>
+	  
+	  <StackLayout Orientation="Vertical" FitToChildren="Both" Margins="25,0,0,0">
+	    <Button OnClick="{Action ZoomPlus}" DesiredSize="25, 25">
+	      <Label Text="z+" HorizontalTextAlign="Center" />
+	    </Button>
+	    
+	    <Button OnClick="{Action ZoomMinus}" DesiredSize="25, 25">
+	      <Label Text="z-" HorizontalTextAlign="Center" />
+	    </Button>
+	  </StackLayout>
+	  
+	</StackLayout>
+	
+	<Button OnClick="{Action QuitApplication}" Height="25">
+	  <Label Text="Quit" HorizontalTextAlign="Center" />
+	</Button>
+  </StackLayout>
+</Window>
+
+

+ 30 - 0
samples/res/window_listview.xml

@@ -0,0 +1,30 @@
+<Window Name="listviewWindow" Title="List View Window" DesiredSize="300, 300">
+  <StackLayout Orientation="Horizontal">
+    <ListView Name="lwFruits" Items="{Bind FruitsList}">
+	  <ListView.ItemTemplate>
+	    <StackLayout Margins="4,4,4,4">
+		  <StackLayout Orientation="Horizontal">
+		    <Label Text="Name: " />
+			<Label Text="{Bind fruitName}" />
+		  </StackLayout>
+		  <StackLayout Orientation="Horizontal">
+		    <Label Text="Cost: " />
+			<Label Text="{Bind fruitPrice}" />
+			<Label Text="€" />
+		  </StackLayout>
+		</StackLayout>
+	  </ListView.ItemTemplate>
+	</ListView>
+    <StackLayout Margins="2, -1, 2, -1" Orientation="Horizontal" FitToChildren="Vertically">
+	  <Label Text="Price:" Width="0" />
+      <Button Height="20" Margins="4,0,0,0" OnClick="{Action IncreaseFruitPrice}" >
+		<Label Text="Increase" />
+	  </Button>
+	  <Button Height="20" Margins="4,0,0,0" OnClick="{Action DecreaseFruitPrice}" >
+		<Label Text="Decrease" />
+	  </Button>
+    </StackLayout>
+  </StackLayout>
+</Window>
+
+

+ 33 - 0
samples/res/window_loader.xml

@@ -0,0 +1,33 @@
+<Window Name="loaderWindow" Title="Load a XWML file" DesiredSize="200, 176">
+  <StackLayout Margins="2, 2, 2, 2">
+	<Label Text="Insert the XWML file:" />
+    <TextBox Name="tbXWMLFilepath" Text="<insert xwml filename>" />
+    <Button Name="btnLoad" OnClick="{Action LoadXWMLFromFilepath}" Margins="0, 4, 0, 0">
+	  <Label Name="lblCaption" Text="Load XWML" HorizontalTextAlign="Center" />
+	</Button>
+	<Label Text="Examples:" Margins="0, 5, 0, 0" />
+	<StackLayout Orientation="Horizontal" FitToChildren="Both">
+	  <Label Name="lblExample1" Text="res/window.xml" />
+	  <Button DesiredSize="10, 10" Margins="3,0,0,0" OnClick="{Action CopyProperty('lblExample1.Text','tbXWMLFilepath.Text')}">
+	    <Label Text="+" />
+	  </Button>
+	</StackLayout>
+	<StackLayout Orientation="Horizontal" FitToChildren="Both">
+	  <Label Name="lblExample2" Text="res/window_listview.xml" />
+	  <Button DesiredSize="10, 10" Margins="3,0,0,0" OnClick="{Action CopyProperty('lblExample2.Text','tbXWMLFilepath.Text')}">
+	    <Label Text="+" />
+	  </Button>
+	</StackLayout>
+	<StackLayout Orientation="Horizontal" FitToChildren="Both">
+	  <Label Name="lblExample3" Text="res/window_loader.xml" />
+	  <Button DesiredSize="10, 10" Margins="3,0,0,0" OnClick="{Action CopyProperty('lblExample3.Text','tbXWMLFilepath.Text')}">
+	    <Label Text="+" />
+	  </Button>
+	</StackLayout>
+	<Button OnClick="{Action QuitApplication}">
+	  <Label Text="Quit" HorizontalTextAlign="Center" />
+	</Button>
+  </StackLayout>
+</Window>
+
+

+ 37 - 0
samples/signalslot/signalslot.cpp

@@ -0,0 +1,37 @@
+#include "SignalSlot.h"
+#include <iostream>
+
+using namespace std;
+using namespace Crown;
+
+class A
+{
+  public:
+    void OnEvent(void* obj, const char* args)
+    {
+      cout << "Mr.Tambourine said '" << args << "'" << endl;
+    }
+
+    A():
+      mSlot(this, &A::OnEvent)
+    { }
+
+    void fakabuu(Signal<const char*>& signal)
+    {
+      mSlot.Attach(signal);
+    }
+
+  private:
+    Slot<A, const char*> mSlot;
+};
+
+int main() {
+
+  Signal<const char*> mySignal;
+  A a;
+  a.fakabuu(mySignal);
+
+  mySignal.Fire(NULL, "She sells sea shells by the sea shore!");
+
+	return 0;
+}

+ 120 - 0
samples/string/string.cpp

@@ -0,0 +1,120 @@
+#include <iostream>
+#include "../core/containers/Str.h"
+
+using namespace Crown;
+using namespace std;
+
+template<typename T>
+void TestResult(T actual, T expected);
+void SplitTest();
+void RemoveTest();
+void ReplaceTest();
+
+int tests = 0;
+int successes = 0;
+
+int main() {
+
+	SplitTest();
+
+	cout << endl;
+
+	RemoveTest();
+
+	cout << endl;
+
+	ReplaceTest();
+
+	cout << endl;
+	cout << "Test result: " << successes << "/" << tests << endl;
+	cout << endl;
+
+	return 0;
+}
+
+void SplitTest()
+{
+	Str str = " abc def ghi,e asdgfe ", rebuilt;
+	List<Str> split;
+
+	str.Split(' ', split);
+
+	for(int i = 0; i < split.GetSize(); i++)
+	{
+		rebuilt += split[i];
+		if (i < split.GetSize()-1)
+			rebuilt += " ";
+	}
+
+	cout << " = Split test = " << endl;
+	cout << "- Split count ";
+	TestResult<int>(split.GetSize(), 6);
+
+	cout << "- Rebuilding split string ";
+	TestResult<const Str&>(rebuilt, str);
+}
+
+void RemoveTest()
+{
+	Str str = "il gatto salta di notte";
+	Str strBegin = str;
+	Str strEnd = str;
+	Str strMiddle = str;
+
+	strBegin.Remove(0, 3);
+	strEnd.Remove(strEnd.GetLength()-6, strEnd.GetLength());
+	strMiddle.Remove(3, 9);
+
+	cout << " = Remove test = " << endl;
+
+	cout << "- Remove from begin ";
+	TestResult<const Str&>(strBegin, "gatto salta di notte");
+	cout << str.c_str() << " -> " << strBegin.c_str() << endl << endl;
+
+	cout << "- Remove from end ";
+	TestResult<const Str&>(strEnd, "il gatto salta di");
+	cout << str.c_str() << " -> " << strEnd.c_str() << endl << endl;
+
+	cout << "- Remove from middle ";
+	TestResult<const Str&>(strMiddle, "il salta di notte");
+	cout << str.c_str() << " -> " << strMiddle.c_str() << endl << endl;
+}
+
+void ReplaceTest()
+{
+	Str str = "il gatto salta di notte";
+	Str strBegin = str;
+	Str strEnd = str;
+	Str strMiddle = str;
+
+	strBegin.Replace("il gatto", "la gatta non");
+	strEnd.Replace("notte", "largo anticipo");
+	strMiddle.Replace("salta", "dorme");
+
+	cout << " = Replace test = " << endl;
+
+	cout << "- Replace from begin ";
+	TestResult<const Str&>(strBegin, "la gatta non salta di notte");
+	cout << str.c_str() << " -> " << strBegin.c_str() << endl << endl;
+
+	cout << "- Replace from end ";
+	TestResult<const Str&>(strEnd, "il gatto salta di largo anticipo");
+	cout << str.c_str() << " -> " << strEnd.c_str() << endl << endl;
+
+	cout << "- Replace from middle ";
+	TestResult<const Str&>(strMiddle, "il gatto dorme di notte");
+	cout << str.c_str() << " -> " << strMiddle.c_str() << endl << endl;
+}
+
+template<typename T>
+void TestResult(T actual, T expected)
+{
+	tests++;
+	if (actual == expected)
+	{
+		cout << "[Ok]" << endl;
+		successes++;
+	}
+	else
+		cout << "[Failure]" << endl;
+}

BIN
samples/terrain/res/grass.tga


BIN
samples/terrain/res/red_down.tga


BIN
samples/terrain/res/red_east.tga


BIN
samples/terrain/res/red_north.tga


BIN
samples/terrain/res/red_south.tga


Vissa filer visades inte eftersom för många filer har ändrats