Просмотр исходного кода

Merge branch 'world' of https://github.com/taylor001/crown into world

Daniele Bartolini 12 лет назад
Родитель
Сommit
6dfa4e83c0

+ 19 - 2
engine/CMakeLists.txt

@@ -88,6 +88,7 @@ set (CROWN_INCLUDES
 	${CMAKE_SOURCE_DIR}/engine/compilers/package
 	${CMAKE_SOURCE_DIR}/engine/compilers/unit
 	${CMAKE_SOURCE_DIR}/engine/compilers/sprite
+	${CMAKE_SOURCE_DIR}/engine/physics
 )
 
 set (SRC
@@ -384,6 +385,22 @@ set (AUDIO_HEADERS
 	audio/OggDecoder.h
 )
 
+set (PHYSICS_SRC
+	physics/PhysicsWorld.cpp
+	physics/PhysicsGraphManager.cpp
+	physics/PhysicsGraph.cpp
+	physics/Actor.cpp
+)
+
+set (PHYSICS_HEADERS
+	physics/PhysicsTypes.h
+	physics/Physics.h
+	physics/PhysicsWorld.h
+	physics/PhysicsGraphManager.h
+	physics/PhysicsGraph.h
+	physics/Actor.h
+)
+
 set (COMPILER_SRC
 	compilers/Compiler.cpp
 	compilers/BundleCompiler.cpp
@@ -592,10 +609,10 @@ set (CROWN_SOURCES
 	${RENDERERS_SRC}
 	${RESOURCE_SRC}
 	${RPC_SRC}
-#	${NETWORK_SRC}
 	${OS_SRC}
 	${LUA_SRC}
 	${AUDIO_SRC}
+	${PHYSICS_SRC}
 	${COMPILER_SRC}
 )
 
@@ -614,10 +631,10 @@ set (CROWN_HEADERS
 	${RENDERERS_HEADERS}
 	${RESOURCE_HEADERS}
 	${RPC_HEADERS}
-#	${NETWORK_HEADERS}
 	${OS_HEADERS}
 	${LUA_HEADERS}
 	${AUDIO_HEADERS}
+	${PHYSICS_HEADERS}
 	${COMPILER_HEADERS}
 )
 

+ 8 - 0
engine/Device.cpp

@@ -162,6 +162,9 @@ void Device::init()
 	m_sound_renderer->init();
 	Log::d("SoundRenderer created.");
 
+	m_physx = CE_NEW(m_allocator, Physics)();
+	Log::d("Physics created.");
+
 	Log::d("Crown Engine initialized.");
 	Log::d("Initializing Game...");
 
@@ -192,6 +195,11 @@ void Device::shutdown()
 	// Shutdowns the game
 	m_lua_environment->call_global("shutdown", 0);
 
+	Log::d("Releasing Physics...");
+	if (m_physx)
+	{
+		CE_DELETE(m_allocator, m_physx);
+	}
 
 	Log::d("Releasing SoundRenderer...");
 	if (m_sound_renderer)

+ 4 - 0
engine/Device.h

@@ -32,6 +32,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "LinearAllocator.h"
 #include "Resource.h"
 #include "RPCHandler.h"
+#include "Physics.h"
 
 namespace crown
 {
@@ -153,6 +154,7 @@ public:
 	Touch*					touch();
 	Accelerometer*			accelerometer();
 	RPCServer*				rpc() { return m_rpc; }
+	physx::PxPhysics*		physx() { return m_physx->m_physics; };
 
 protected:
 
@@ -205,6 +207,8 @@ protected:
 	RPCStatsHandler			m_stats_handler;
 	RPCPingHandler			m_ping_handler;
 
+	Physics*				m_physx;
+
 	bool 					m_renderer_init_request;
 
 private:

+ 43 - 1
engine/Unit.cpp

@@ -30,6 +30,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Log.h"
 #include "UnitResource.h"
 #include "SceneGraphManager.h"
+#include "PhysicsGraphManager.h"
 
 namespace crown
 {
@@ -37,9 +38,10 @@ namespace crown
 typedef Id CameraId;
 typedef Id SpriteId;
 
-Unit::Unit(World& w, SceneGraph& sg, const UnitResource* ur, const Matrix4x4& pose)
+Unit::Unit(World& w, SceneGraph& sg, PhysicsGraph& pg, const UnitResource* ur, const Matrix4x4& pose)
 	: m_world(w)
 	, m_scene_graph(sg)
+	, m_physics_graph(pg)
 	, m_resource(ur)
 	, m_num_cameras(0)
 	, m_num_meshes(0)
@@ -65,6 +67,7 @@ void Unit::create(const Matrix4x4& pose)
 {
 	// Create the root node
 	int32_t root_node = m_scene_graph.create_node(-1, pose);
+	int32_t p_root_node = m_physics_graph.create_node(-1, pose);
 
 	// Create renderables
 	for (uint32_t i = 0; i < m_resource->num_renderables(); i++)
@@ -105,6 +108,16 @@ void Unit::create(const Matrix4x4& pose)
 		
 		add_camera(camera.name, cam);
 	}
+
+	// Create actors
+	for (uint32_t i = 0; i < m_resource->num_actors(); i++)
+	{
+		const int32_t actor_node = m_physics_graph.create_node(p_root_node, Vector3::ZERO, Quaternion::IDENTITY);
+		UnitActor actor = m_resource->get_actor(i);
+		ActorId actor_id = m_world.create_actor(m_physics_graph, actor_node, ActorType::DYNAMIC);
+
+		add_actor(actor.name, actor_id);
+	}
 }
 
 //-----------------------------------------------------------------------------
@@ -263,6 +276,14 @@ void Unit::add_sprite(StringId32 name, SpriteId sprite)
 	add_component(name, sprite, m_num_sprites, m_sprites);
 }
 
+//-----------------------------------------------------------------------------
+void Unit::add_actor(StringId32 name, ActorId actor)
+{
+	CE_ASSERT(m_num_actors < MAX_ACTOR_COMPONENTS, "Max actor number reached");
+
+	add_component(name, actor, m_num_actors, m_actors);
+}
+
 //-----------------------------------------------------------------------------
 Camera* Unit::camera(const char* name)
 {
@@ -323,4 +344,25 @@ Sprite*	Unit::sprite(uint32_t i)
 	return m_world.lookup_sprite(sprite);
 }
 
+//-----------------------------------------------------------------------------
+Actor* Unit::actor(const char* name)
+{
+	ActorId actor = find_component(name, m_num_actors, m_actors);
+
+	CE_ASSERT(actor.id != INVALID_ID, "Unit does not have actor with name '%s'", name);
+
+	return m_world.lookup_actor(actor);
+}
+
+//-----------------------------------------------------------------------------
+Actor* Unit::actor(uint32_t i)
+{
+	ActorId actor = find_component(i, m_num_actors, m_actors);
+
+	CE_ASSERT(actor.id != INVALID_ID, "Unit does not have actor with name '%d'", i);
+
+	return m_world.lookup_actor(actor);
+}	
+
+
 } // namespace crown

+ 19 - 6
engine/Unit.h

@@ -32,15 +32,12 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Matrix4x4.h"
 #include "Hash.h"
 #include "SceneGraph.h"
+#include "PhysicsGraph.h"
 #include "StringUtils.h"
 
 namespace crown
 {
 
-typedef Id CameraId;
-typedef	Id ComponentId;
-typedef Id UnitId;
-
 //-----------------------------------------------------------------------------
 struct ComponentType
 {
@@ -50,7 +47,7 @@ struct ComponentType
 		CAMERA,
 		MESH,
 		SPRITE,
-		SOUND
+		ACTOR
 	};
 };
 
@@ -60,24 +57,32 @@ struct Component
 	Id component;
 };
 
+//-----------------------------------------------------------------------------
 typedef Id UnitId;
+typedef Id CameraId;
 typedef Id MeshId;
 typedef Id SpriteId;
+typedef Id ActorId;
+
+typedef	Id ComponentId;
 
 class Camera;
 class Mesh;
 class Sprite;
+class Actor;
 class World;
 class SceneGraphManager;
+class PhysicsGraphManager;
 struct UnitResource;
 
 #define MAX_CAMERA_COMPONENTS 8
 #define MAX_MESH_COMPONENTS 8
 #define MAX_SPRITE_COMPONENTS 8
+#define MAX_ACTOR_COMPONENTS 8
 
 struct Unit
 {
-						Unit(World& w, SceneGraph& sg, const UnitResource* ur, const Matrix4x4& pose);
+						Unit(World& w, SceneGraph& sg, PhysicsGraph& pg, const UnitResource* ur, const Matrix4x4& pose);
 
 	void				set_id(const UnitId id);
 	UnitId				id();
@@ -107,6 +112,7 @@ struct Unit
 	void				add_camera(StringId32 name, CameraId camera);
 	void				add_mesh(StringId32 name, MeshId mesh);
 	void				add_sprite(StringId32 name, SpriteId sprite);
+	void				add_actor(StringId32 name, ActorId actor);
 
 	Camera*				camera(const char* name);
 	Camera*				camera(uint32_t i);
@@ -117,10 +123,14 @@ struct Unit
 	Sprite*				sprite(const char* name);
 	Sprite*				sprite(uint32_t i);
 
+	Actor*				actor(const char* name);
+	Actor*				actor(uint32_t i);	
+
 public:
 
 	World&				m_world;
 	SceneGraph&			m_scene_graph;
+	PhysicsGraph&		m_physics_graph;
 	const UnitResource*	m_resource;
 	UnitId				m_id;
 
@@ -132,6 +142,9 @@ public:
 
 	uint32_t			m_num_sprites;
 	Component			m_sprites[MAX_SPRITE_COMPONENTS];
+
+	uint32_t			m_num_actors;
+	Component 			m_actors[MAX_ACTOR_COMPONENTS];
 };
 
 } // namespace crown

+ 26 - 5
engine/World.cpp

@@ -50,10 +50,13 @@ UnitId World::spawn_unit(const char* name, const Vector3& pos, const Quaternion&
 	UnitResource* ur = (UnitResource*) device()->resource_manager()->lookup(UNIT_EXTENSION, name);
 
 	// Create a new scene graph
-	SceneGraph* graph = m_graph_manager.create_scene_graph();
+	SceneGraph* sg = m_scenegraph_manager.create_scene_graph();
+
+	// Create a new physics graph
+	PhysicsGraph* pg = m_physicsgraph_manager.create_physics_graph();
 
 	// Allocate memory for unit
-	Unit* unit = CE_NEW(m_unit_pool, Unit)(*this, *graph, ur, Matrix4x4(rot, pos));
+	Unit* unit = CE_NEW(m_unit_pool, Unit)(*this, *sg, *pg, ur, Matrix4x4(rot, pos));
 
 	// Create Id for the unit
 	const UnitId unit_id = m_units.create(unit);
@@ -69,8 +72,8 @@ void World::destroy_unit(UnitId id)
 
 	Unit* unit = m_units.lookup(id);
 
-	// Destory unit's scene graph
-	m_graph_manager.destroy_scene_graph(&unit->m_scene_graph);
+	// Destry unit's scene graph
+	m_scenegraph_manager.destroy_scene_graph(&unit->m_scene_graph);
 
 	unit->destroy();
 	CE_DELETE(m_unit_pool, unit);
@@ -127,11 +130,17 @@ Sprite* World::lookup_sprite(SpriteId sprite)
 	return m_render_world.lookup_sprite(sprite);
 }
 
+//-----------------------------------------------------------------------------
+Actor* World::lookup_actor(ActorId actor)
+{
+	return m_physics_world.lookup_actor(actor);
+}
+
 //-----------------------------------------------------------------------------
 void World::update(float /*dt*/)
 {
 	// Update scene graphs
-	m_graph_manager.update();
+	m_scenegraph_manager.update();
 }
 
 //-----------------------------------------------------------------------------
@@ -192,6 +201,18 @@ void World::destroy_sprite(SpriteId id)
 	m_render_world.destroy_sprite(id);
 }
 
+//-----------------------------------------------------------------------------
+ActorId	World::create_actor(PhysicsGraph& pg, int32_t node, ActorType::Enum type)
+{
+	return m_physics_world.create_actor(pg, node, type);
+}
+
+//-----------------------------------------------------------------------------
+void World::destroy_actor(ActorId id)
+{
+	m_physics_world.destroy_actor(id);
+}
+
 //-----------------------------------------------------------------------------
 SoundId World::play_sound(const char* name, const bool loop, const float volume, const Vector3& pos, const float range)
 {

+ 12 - 1
engine/World.h

@@ -34,9 +34,12 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Camera.h"
 #include "Vector.h"
 #include "RenderWorld.h"
+#include "PhysicsWorld.h"
 #include "SoundRenderer.h"
 #include "PoolAllocator.h"
 #include "SceneGraphManager.h"
+#include "PhysicsGraphManager.h"
+#include "PhysicsTypes.h"
 
 namespace crown
 {
@@ -50,6 +53,7 @@ typedef Id CameraId;
 typedef Id MeshId;
 typedef Id SoundId;
 typedef Id SpriteId;
+typedef Id ActorId;
 
 struct Sound
 {
@@ -72,6 +76,7 @@ struct UnitToSound
 
 class Mesh;
 class Sprite;
+class Actor;
 class Vector3;
 class Quaternion;
 
@@ -92,6 +97,7 @@ public:
 	Camera*								lookup_camera(CameraId camera);
 	Mesh*								lookup_mesh(MeshId mesh);
 	Sprite*								lookup_sprite(SpriteId sprite);
+	Actor*								lookup_actor(ActorId actor);
 
 	RenderWorld&						render_world();
 	void								update(float dt);
@@ -106,6 +112,9 @@ public:
 	SpriteId							create_sprite(ResourceId id, SceneGraph& sg, int32_t node);
 	void								destroy_sprite(SpriteId id);
 
+	ActorId								create_actor(PhysicsGraph& pg, int32_t node, ActorType::Enum type);
+	void								destroy_actor(ActorId id);
+
 	SoundId								play_sound(const char* name, const bool loop = false, const float volume = 1.0f, const Vector3& pos = Vector3::ZERO, const float range = 50.0f);
 	void								stop_sound(SoundId sound);
 	void								link_sound(SoundId sound, Unit* unit, int32_t node);
@@ -123,12 +132,14 @@ private:
 	IdArray<MAX_CAMERAS, Camera*>		m_cameras;
 	IdArray<MAX_SOUNDS, Sound> 			m_sounds;
 
-	SceneGraphManager					m_graph_manager;
+	SceneGraphManager					m_scenegraph_manager;
+	PhysicsGraphManager					m_physicsgraph_manager;
 
 	// Connections
 	List<UnitToSound>					m_unit_to_sound;
 
 	RenderWorld							m_render_world;
+	PhysicsWorld						m_physics_world;
 };
 
 } // namespace crown

+ 28 - 1
engine/compilers/unit/UnitCompiler.cpp

@@ -32,6 +32,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "UnitCompiler.h"
 #include "TempAllocator.h"
 #include "Log.h"
+#include "PhysicsTypes.h"
 
 namespace crown
 {
@@ -40,6 +41,7 @@ namespace crown
 UnitCompiler::UnitCompiler()
 	: m_renderable(default_allocator())
 	, m_camera(default_allocator())
+	, m_actor(default_allocator())
 {
 }
 
@@ -113,9 +115,34 @@ size_t UnitCompiler::compile_impl(Filesystem& fs, const char* resource_path)
 		}
 	}
 
+	// check for actors
+	if (root.has_key("actor"))
+	{
+		JSONElement actor = root.key("actor");
+		uint32_t num_actors = actor.size();
+
+		for (uint32_t i = 0; i < num_actors; i++)
+		{
+			JSONElement actor_name = actor[i].key("name");
+			JSONElement actor_type = actor[i].key("type");
+			JSONElement actor_shape = actor[i].key("shape");
+			JSONElement actor_active = actor[i].key("active");
+
+			UnitActor ua;
+			ua.name = hash::murmur2_32(actor_name.string_value(), actor_name.size(), 0);
+			ua.type = string::strcmp(actor_type.string_value(), "STATIC") == 0 ? UnitActor::STATIC : UnitActor::DYNAMIC;
+			ua.shape = string::strcmp(actor_shape.string_value(), "SPHERE") == 0 ? UnitActor::SPHERE :
+						string::strcmp(actor_shape.string_value(), "BOX") == 0 ? UnitActor::BOX : UnitActor::PLANE;
+			ua.active = actor_active.bool_value();
+
+			m_actor.push_back(ua);
+		}
+	}
+
 	return sizeof(UnitHeader) +
 			m_renderable.size() * sizeof(UnitRenderable) +
-			m_camera.size() * sizeof(UnitCamera);
+			m_camera.size() * sizeof(UnitCamera) +
+			m_actor.size() * sizeof(UnitActor);
 }
 
 //-----------------------------------------------------------------------------

+ 1 - 0
engine/compilers/unit/UnitCompiler.h

@@ -47,6 +47,7 @@ private:
 
 	List<UnitRenderable> m_renderable;
 	List<UnitCamera> m_camera;
+	List<UnitActor> m_actor;
 };
 
 } // namespace crown

+ 1 - 1
engine/core/math/MathUtils.h

@@ -29,7 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #undef min
 #undef max
 
-#include <cmath>
+#include <math.h>
 
 #include "Assert.h"
 #include "Types.h"

+ 132 - 0
engine/physics/Actor.cpp

@@ -0,0 +1,132 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "Actor.h"
+#include "Vector3.h"
+#include "Quaternion.h"
+#include "Matrix4x4.h"
+#include "Unit.h"
+#include "PhysicsGraph.h"
+#include "Device.h"
+#include "Physics.h"
+
+#include "PxPhysicsAPI.h"
+
+namespace crown
+{
+	
+//-----------------------------------------------------------------------------
+Actor::Actor(PhysicsGraph& pg, int32_t node, ActorType::Enum type)
+	: m_physics_graph(pg)
+	, m_node(node)
+	, m_type(type)
+{
+	Vector3 pos = m_physics_graph.m_local_poses[node].translation();
+	physx::PxVec3 position(pos.x, pos.y, pos.z);
+
+	switch (type)
+	{
+		case ActorType::STATIC:
+		{
+			m_actor = device()->physx()->createRigidStatic(physx::PxTransform(position));
+			break;
+		}
+		case ActorType::DYNAMIC:
+		{
+			m_actor = device()->physx()->createRigidDynamic(physx::PxTransform(position));
+			break;
+		}
+		default:
+		{
+			CE_FATAL("Unable to recognize actor type");
+		}
+	}
+}
+
+//-----------------------------------------------------------------------------
+Vector3	Actor::local_position() const
+{
+	return m_physics_graph.local_position(m_node);
+}
+
+//-----------------------------------------------------------------------------
+Quaternion Actor::local_rotation() const
+{
+	return m_physics_graph.local_rotation(m_node);
+}
+
+//-----------------------------------------------------------------------------
+Matrix4x4 Actor::local_pose() const
+{
+	return m_physics_graph.local_pose(m_node);
+}
+
+//-----------------------------------------------------------------------------
+Vector3	Actor::world_position() const
+{
+	return m_physics_graph.world_position(m_node);
+}
+
+//-----------------------------------------------------------------------------
+Quaternion Actor::world_rotation() const
+{
+	return m_physics_graph.world_rotation(m_node);
+}
+
+//-----------------------------------------------------------------------------
+Matrix4x4 Actor::world_pose() const
+{
+	return m_physics_graph.world_pose(m_node);
+}
+
+//-----------------------------------------------------------------------------
+void Actor::set_local_position(Unit* unit, const Vector3& pos)
+{
+	unit->set_local_position(m_node, pos);
+}
+
+//-----------------------------------------------------------------------------
+void Actor::set_local_rotation(Unit* unit, const Quaternion& rot)
+{
+	unit->set_local_rotation(m_node, rot);
+}
+
+//-----------------------------------------------------------------------------
+void Actor::set_local_pose(Unit* unit, const Matrix4x4& pose)
+{
+	unit->set_local_pose(m_node, pose);
+}
+
+//-----------------------------------------------------------------------------
+void Actor::create_sphere(Vector3& position, float radius)
+{
+	// FIXME FIXME FIXME
+	physx::PxMaterial* mat = device()->physx()->createMaterial(0.5f, 0.5f, 0.1f);
+	m_actor->createShape(physx::PxSphereGeometry(radius), *mat);
+	// physx::PxRigidBodyExt::updateMassAndInertia(*m_actor, 1.0f);
+}
+
+} // namespace crown

+ 72 - 0
engine/physics/Actor.h

@@ -0,0 +1,72 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include "Types.h"
+#include "PhysicsTypes.h"
+
+#include "PxPhysics.h"
+#include "PxScene.h"
+#include "PxRigidActor.h"
+
+namespace crown
+{
+
+class Vector3;
+class Quaternion;
+class Matrix4x4;
+class Unit;
+class PhysicsGraph;
+
+struct Actor
+{
+					Actor(PhysicsGraph& pg, int32_t node, ActorType::Enum type);
+
+	Vector3			local_position() const;
+	Quaternion		local_rotation() const;
+	Matrix4x4		local_pose() const;
+
+	Vector3			world_position() const;
+	Quaternion		world_rotation() const;
+	Matrix4x4		world_pose() const;
+
+	void			set_local_position(Unit* unit, const Vector3& pos);
+	void			set_local_rotation(Unit* unit, const Quaternion& rot);
+	void			set_local_pose(Unit* unit, const Matrix4x4& pose);
+
+	void			create_sphere(Vector3& position, float radius);
+
+public:
+
+	physx::PxRigidActor* m_actor;
+
+	PhysicsGraph& m_physics_graph;
+	int32_t m_node;
+	ActorType::Enum m_type;
+};
+
+} // namespace crown

+ 76 - 0
engine/physics/Physics.h

@@ -0,0 +1,76 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include "PxFoundation.h"
+#include "PxPhysics.h"
+#include "PxCooking.h"
+#include "PxDefaultAllocator.h"
+#include "PxDefaultErrorCallback.h"
+
+namespace crown
+{
+
+static physx::PxDefaultErrorCallback 	g_physx_error_callback;
+static physx::PxDefaultAllocator 		g_physx_allocator_callback;
+
+struct Physics
+{
+	Physics();
+	~Physics();
+
+public:
+
+	physx::PxFoundation* m_foundation;
+	physx::PxPhysics* m_physics;
+	physx::PxCooking* m_cooking;
+};
+
+//-----------------------------------------------------------------------------
+inline Physics::Physics()
+	: m_foundation(NULL)
+	, m_physics(NULL)
+	, m_cooking(NULL)
+{
+	m_foundation = PxCreateFoundation(PX_PHYSICS_VERSION, g_physx_allocator_callback, g_physx_error_callback);
+	CE_ASSERT_NOT_NULL(m_foundation);
+
+	m_physics = PxCreatePhysics(PX_PHYSICS_VERSION, *m_foundation, physx::PxTolerancesScale());
+	CE_ASSERT_NOT_NULL(m_physics);
+
+	m_cooking = PxCreateCooking(PX_PHYSICS_VERSION, *m_foundation, physx::PxCookingParams());
+	CE_ASSERT_NOT_NULL(m_cooking);
+}
+
+//-----------------------------------------------------------------------------
+inline Physics::~Physics()
+{
+	m_physics->release();
+	m_foundation->release();
+}
+
+} // namespace crown

+ 135 - 0
engine/physics/PhysicsGraph.cpp

@@ -0,0 +1,135 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "PhysicsGraph.h"
+#include "Vector3.h"
+#include "Quaternion.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+PhysicsGraph::PhysicsGraph(int32_t index)
+	: m_index(index)
+	, m_local_poses(default_allocator()) 
+	, m_world_poses(default_allocator())
+	, m_sg_nodes(default_allocator())
+{
+}
+
+//-----------------------------------------------------------------------------
+int32_t	PhysicsGraph::create_node(int32_t node, const Vector3& pos, const Quaternion& rot)
+{
+	Matrix4x4 pose(rot, pos);
+	return create_node(node, pose);	
+}
+
+//-----------------------------------------------------------------------------
+int32_t PhysicsGraph::create_node(int32_t node, const Matrix4x4& pose)
+{
+	CE_ASSERT(node >= -1, "node must be >= -1");
+
+	m_world_poses.push_back(pose);
+	m_sg_nodes.push_back(node);
+
+	return m_world_poses.size() - 1;
+}
+
+//-----------------------------------------------------------------------------
+Vector3	PhysicsGraph::local_position(int32_t node) const
+{
+	return m_local_poses[node].translation();
+}
+
+//-----------------------------------------------------------------------------
+Quaternion PhysicsGraph::local_rotation(int32_t node) const
+{
+	return m_local_poses[node].to_quaternion();
+
+}
+
+//-----------------------------------------------------------------------------
+Matrix4x4 PhysicsGraph::local_pose(int32_t node) const
+{
+	return m_local_poses[node];
+}
+
+
+//-----------------------------------------------------------------------------
+void PhysicsGraph::set_local_position(int32_t node, const Vector3& pos)
+{
+	Matrix4x4& local_pose = m_local_poses[node];
+	local_pose.set_translation(pos);
+}
+
+//-----------------------------------------------------------------------------
+void PhysicsGraph::set_local_rotation(int32_t node, const Quaternion& rot)
+{
+	Matrix4x4& local_pose = m_local_poses[node];
+
+	Vector3 local_translation = local_pose.translation();
+	local_pose = rot.to_matrix4x4();
+	local_pose.set_translation(local_translation);
+}
+
+//-----------------------------------------------------------------------------
+void PhysicsGraph::set_local_pose(int32_t node, const Matrix4x4& pose)
+{
+	m_local_poses[node] = pose;
+}
+
+//-----------------------------------------------------------------------------
+Vector3	PhysicsGraph::world_position(int32_t node) const
+{
+	return m_world_poses[node].translation();
+}
+
+//-----------------------------------------------------------------------------
+Quaternion PhysicsGraph::world_rotation(int32_t node) const
+{
+	return m_world_poses[node].to_quaternion();
+}
+
+//-----------------------------------------------------------------------------
+Matrix4x4 PhysicsGraph::world_pose(int32_t node) const
+{
+	return m_world_poses[node];
+}
+
+//-----------------------------------------------------------------------------
+void PhysicsGraph::clear()
+{
+	m_world_poses.clear();
+	m_sg_nodes.clear();
+}
+
+//-----------------------------------------------------------------------------
+void PhysicsGraph::update()
+{
+	// TODO
+}
+
+} // namespace crown

+ 68 - 0
engine/physics/PhysicsGraph.h

@@ -0,0 +1,68 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include "Types.h"
+#include "Matrix4x4.h"
+#include "List.h"
+
+namespace crown
+{
+
+struct PhysicsGraph
+{
+					PhysicsGraph(int32_t index);
+
+	int32_t			create_node(int32_t node, const Vector3& pos, const Quaternion& rot);
+	int32_t			create_node(int32_t node, const Matrix4x4& pose);
+
+	Vector3			local_position(int32_t node) const;
+	Quaternion		local_rotation(int32_t node) const;
+	Matrix4x4		local_pose(int32_t node) const;
+
+	void			set_local_position(int32_t node, const Vector3& pos);
+	void			set_local_rotation(int32_t node, const Quaternion& rot);
+	void			set_local_pose(int32_t node, const Matrix4x4& pose);
+
+	Vector3			world_position(int32_t node) const;
+	Quaternion		world_rotation(int32_t node) const;
+	Matrix4x4		world_pose(int32_t node) const;
+
+	void			clear();
+
+	void			update();
+
+public:
+
+	uint32_t		m_index;
+
+	List<Matrix4x4> m_local_poses;
+	List<Matrix4x4>	m_world_poses;
+	List<uint32_t> 	m_sg_nodes;
+};
+
+} // namespace crown

+ 74 - 0
engine/physics/PhysicsGraphManager.cpp

@@ -0,0 +1,74 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "PhysicsGraphManager.h"
+#include "PhysicsGraph.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+PhysicsGraphManager::PhysicsGraphManager()
+	: m_graphs(default_allocator())
+{
+
+}
+
+//-----------------------------------------------------------------------------
+PhysicsGraphManager::~PhysicsGraphManager()
+{
+}
+
+//-----------------------------------------------------------------------------
+PhysicsGraph* PhysicsGraphManager::create_physics_graph()
+{
+	uint32_t index = m_graphs.size();
+	PhysicsGraph* pg = CE_NEW(default_allocator(), PhysicsGraph)(index);
+	m_graphs.push_back(pg);
+	return pg;
+}
+
+//-----------------------------------------------------------------------------
+void PhysicsGraphManager::destroy_physics_graph(PhysicsGraph* pg)
+{
+	CE_ASSERT_NOT_NULL(pg);
+
+	m_graphs[pg->m_index] = m_graphs[m_graphs.size() - 1];
+	m_graphs.pop_back();
+
+	CE_DELETE(default_allocator(), pg);
+}
+
+//-----------------------------------------------------------------------------
+void PhysicsGraphManager::update()
+{
+	for (uint32_t i = 0; i < m_graphs.size(); i++)
+	{
+		m_graphs[i]->update();
+	}
+}
+
+};

+ 58 - 0
engine/physics/PhysicsGraphManager.h

@@ -0,0 +1,58 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include "List.h"
+
+namespace crown
+{
+
+class PhysicsGraph;
+
+/// Manages a collection of physics graphs.
+class PhysicsGraphManager
+{
+public:
+
+						PhysicsGraphManager();
+						~PhysicsGraphManager();
+
+	/// Creates a new physics graph
+	PhysicsGraph*		create_physics_graph();
+
+	/// Destroys the @a sg physics graph
+	void				destroy_physics_graph(PhysicsGraph* pg);
+
+	/// Updates all the physics graphs
+	void				update();
+
+private:
+
+	List<PhysicsGraph*>	m_graphs;
+};
+
+} // namespace crown

+ 48 - 0
engine/physics/PhysicsTypes.h

@@ -0,0 +1,48 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+//-----------------------------------------------------------------------------
+struct ActorType
+{
+	enum Enum
+	{
+		STATIC,
+		DYNAMIC
+	};
+};
+
+//-----------------------------------------------------------------------------
+struct ShapeType
+{
+	enum Enum
+	{
+		SPHERE,
+		BOX,
+		PLANE
+	};
+};

+ 92 - 0
engine/physics/PhysicsWorld.cpp

@@ -0,0 +1,92 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "PhysicsWorld.h"
+#include "Vector3.h"
+#include "Actor.h"
+#include "Device.h"
+#include "Physics.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+PhysicsWorld::PhysicsWorld()
+	: m_scene(NULL)
+	, m_actor_pool(default_allocator(), MAX_ACTORS, sizeof(Actor), CE_ALIGNOF(Actor))
+{
+	physx::PxSceneDesc scene_desc(device()->physx()->getTolerancesScale());
+	scene_desc.gravity = physx::PxVec3(0.0f, -9.81f, 0.0f);
+	m_scene = device()->physx()->createScene(scene_desc);
+}
+
+//-----------------------------------------------------------------------------
+PhysicsWorld::~PhysicsWorld()
+{
+	m_scene->release();
+}
+
+//-----------------------------------------------------------------------------
+ActorId	PhysicsWorld::create_actor(PhysicsGraph& pg, int32_t node, ActorType::Enum type)
+{
+	Actor* actor = CE_NEW(m_actor_pool, Actor)(pg, node, type);
+
+	m_scene->addActor(*actor->m_actor);
+
+	return m_actor.create(actor);
+}
+
+//-----------------------------------------------------------------------------
+void PhysicsWorld::destroy_actor(ActorId id)
+{
+	CE_ASSERT(m_actor.has(id), "Actor does not exist");
+
+	Actor* actor = m_actor.lookup(id);
+	CE_DELETE(m_actor_pool, actor);
+
+	m_scene->removeActor(*actor->m_actor);
+
+	m_actor.destroy(id);
+}
+
+//-----------------------------------------------------------------------------
+Actor* PhysicsWorld::lookup_actor(ActorId id)
+{
+	CE_ASSERT(m_actor.has(id), "Actor does not exist");
+
+	return m_actor.lookup(id);
+}
+
+
+//-----------------------------------------------------------------------------
+void PhysicsWorld::update(float dt)
+{
+	m_scene->simulate(dt);
+
+	while (!m_scene->fetchResults());
+}
+
+} // namespace crown

+ 67 - 0
engine/physics/PhysicsWorld.h

@@ -0,0 +1,67 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include "IdArray.h"
+#include "PoolAllocator.h"
+#include "PhysicsTypes.h"
+
+#include "PxScene.h"
+
+#define MAX_ACTORS 1024
+
+namespace crown
+{
+
+typedef Id ActorId;
+
+class Vector3;
+class Actor;
+class PhysicsGraph;
+
+//-----------------------------------------------------------------------------
+class PhysicsWorld
+{
+public:
+
+				PhysicsWorld();
+				~PhysicsWorld();
+
+	ActorId		create_actor(PhysicsGraph& pg, int32_t node, ActorType::Enum type);
+	void		destroy_actor(ActorId id);
+	Actor*		lookup_actor(ActorId id);
+
+	void		update(float dt);
+
+public:
+
+	physx::PxScene* m_scene;
+
+	PoolAllocator m_actor_pool;
+	IdArray<MAX_ACTORS, Actor*> m_actor;
+};
+}

+ 27 - 0
engine/resource/UnitResource.h

@@ -31,6 +31,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Bundle.h"
 #include "Allocator.h"
 #include "File.h"
+#include "PhysicsTypes.h"
 
 namespace crown
 {
@@ -42,6 +43,8 @@ struct UnitHeader
 	uint32_t renderables_offset;
 	uint32_t num_cameras;
 	uint32_t cameras_offset;
+	uint32_t num_actors;
+	uint32_t actors_offset;
 };
 
 struct UnitRenderable
@@ -57,6 +60,14 @@ struct UnitCamera
 	uint32_t name;
 };
 
+struct UnitActor
+{
+	uint32_t name;
+	enum {STATIC, DYNAMIC} type;
+	enum {SPHERE, BOX, PLANE} shape;
+	bool active;
+};
+
 struct UnitResource
 {
 	//-----------------------------------------------------------------------------
@@ -122,6 +133,22 @@ struct UnitResource
 		return begin[i];
 	}
 
+	//-----------------------------------------------------------------------------
+	uint32_t num_actors() const
+	{
+		return ((UnitHeader*) this)->num_actors;
+	}
+
+	//-----------------------------------------------------------------------------
+	const UnitActor& get_actor(uint32_t i) const
+	{
+		CE_ASSERT(i < num_actors(), "Index out of bounds");
+
+		UnitHeader* h = (UnitHeader*) this;
+		UnitActor* begin = (UnitActor*) (((char*) this) + h->actors_offset);
+		return begin[i];
+	}
+
 private:
 
 	// Disable construction