瀏覽代碼

Add SceneGraphManager and eradicate memory leaks

Daniele Bartolini 12 年之前
父節點
當前提交
875030c862
共有 10 個文件被更改,包括 257 次插入74 次删除
  1. 2 0
      engine/CMakeLists.txt
  2. 17 7
      engine/RenderWorld.cpp
  3. 3 2
      engine/SceneGraph.cpp
  4. 4 1
      engine/SceneGraph.h
  5. 73 0
      engine/SceneGraphManager.cpp
  6. 58 0
      engine/SceneGraphManager.h
  7. 42 15
      engine/Unit.cpp
  8. 4 2
      engine/Unit.h
  9. 22 18
      engine/World.cpp
  10. 32 29
      engine/World.h

+ 2 - 0
engine/CMakeLists.txt

@@ -96,6 +96,7 @@ set (SRC
 	World.cpp
 	Unit.cpp
 	SceneGraph.cpp
+	SceneGraphManager.cpp
 	RenderWorld.cpp
 	Mesh.cpp
 	Sprite.cpp
@@ -109,6 +110,7 @@ set (HEADERS
 	World.h
 	Unit.h
 	SceneGraph.h
+	SceneGraphManager.h
 	RenderWorld.h
 	Mesh.h
 	Sprite.h

+ 17 - 7
engine/RenderWorld.cpp

@@ -87,8 +87,8 @@ static const char* texture_fragment =
 
 //-----------------------------------------------------------------------------
 RenderWorld::RenderWorld()
-	: m_mesh_pool(default_allocator(), MAX_MESHES, sizeof(Mesh))
-	, m_sprite_pool(default_allocator(), MAX_SPRITES, sizeof(Sprite))
+	: m_mesh_pool(default_allocator(), MAX_MESHES, sizeof(Mesh), CE_ALIGNOF(Mesh))
+	, m_sprite_pool(default_allocator(), MAX_SPRITES, sizeof(Sprite), CE_ALIGNOF(Sprite))
 {
 	Renderer* r = device()->renderer();
 
@@ -121,7 +121,7 @@ MeshId RenderWorld::create_mesh(ResourceId id, int32_t node, const Vector3& pos,
 	MeshResource* mr = (MeshResource*) device()->resource_manager()->data(id);
 
 	// Allocate memory for mesh
-	Mesh* mesh = (Mesh*) m_mesh_pool.allocate(sizeof(Mesh));
+	Mesh* mesh = CE_NEW(m_mesh_pool, Mesh);
 
 	// Create mesh id
 	const MeshId mesh_id = m_mesh.create(mesh);
@@ -131,8 +131,13 @@ MeshId RenderWorld::create_mesh(ResourceId id, int32_t node, const Vector3& pos,
 }
 
 //-----------------------------------------------------------------------------
-void RenderWorld::destroy_mesh(MeshId /*id*/)
+void RenderWorld::destroy_mesh(MeshId id)
 {
+	CE_ASSERT(m_mesh.has(id), "Mesh does not exist");
+
+	Mesh* mesh = m_mesh.lookup(id);
+	CE_DELETE(m_mesh_pool, mesh);
+	m_mesh.destroy(id);
 }
 
 //-----------------------------------------------------------------------------
@@ -149,7 +154,7 @@ SpriteId RenderWorld::create_sprite(ResourceId id, int32_t node, const Vector3&
 	SpriteResource* sr = (SpriteResource*) device()->resource_manager()->data(id);
 
 	// Allocate memory for sprite
-	Sprite* sprite = (Sprite*) m_sprite_pool.allocate(sizeof(Sprite));
+	Sprite* sprite = CE_NEW(m_sprite_pool, Sprite);
 
 	// Create sprite id
 	const SpriteId sprite_id = m_sprite.create(sprite);
@@ -159,9 +164,14 @@ SpriteId RenderWorld::create_sprite(ResourceId id, int32_t node, const Vector3&
 }
 
 //-----------------------------------------------------------------------------
-void RenderWorld::destroy_sprite(SpriteId /*id*/)
+void RenderWorld::destroy_sprite(SpriteId id)
 {
-	// Stub
+	CE_ASSERT(m_sprite.has(id), "Sprite does not exist");
+
+	Sprite* sprite = m_sprite.lookup(id);
+	sprite->destroy();
+	CE_DELETE(m_sprite_pool, sprite);
+	m_sprite.destroy(id);
 }
 
 //-----------------------------------------------------------------------------

+ 3 - 2
engine/SceneGraph.cpp

@@ -32,8 +32,9 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-SceneGraph::SceneGraph()
-	: m_world_poses(default_allocator())
+SceneGraph::SceneGraph(uint32_t index)
+	: m_index(index)
+	, m_world_poses(default_allocator())
 	, m_local_poses(default_allocator())
 	, m_parents(default_allocator())
 {

+ 4 - 1
engine/SceneGraph.h

@@ -35,7 +35,7 @@ namespace crown
 
 struct SceneGraph
 {
-					SceneGraph();
+					SceneGraph(uint32_t index);
 
 	/// Creates a new node with @a parent parent at position @a pos and rotation @a rot.
 	/// @note
@@ -73,6 +73,9 @@ struct SceneGraph
 
 public:
 
+	/// Index into SceneGraphManager
+	uint32_t		m_index;
+
 	List<Matrix4x4>	m_world_poses;
 	List<Matrix4x4>	m_local_poses;
 	List<int32_t>	m_parents;

+ 73 - 0
engine/SceneGraphManager.cpp

@@ -0,0 +1,73 @@
+/*
+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 "SceneGraphManager.h"
+#include "SceneGraph.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+SceneGraphManager::SceneGraphManager()
+	: m_graphs(default_allocator())
+{
+}
+
+//-----------------------------------------------------------------------------
+SceneGraphManager::~SceneGraphManager()
+{
+}
+
+//-----------------------------------------------------------------------------
+SceneGraph* SceneGraphManager::create_scene_graph()
+{
+	uint32_t index = m_graphs.size();
+	SceneGraph* sg = CE_NEW(default_allocator(), SceneGraph)(index);
+	m_graphs.push_back(sg);
+	return sg;
+}
+
+//-----------------------------------------------------------------------------
+void SceneGraphManager::destroy_scene_graph(SceneGraph* sg)
+{
+	CE_ASSERT_NOT_NULL(sg);
+
+	m_graphs[sg->m_index] = m_graphs[m_graphs.size() - 1];
+	m_graphs.pop_back();
+
+	CE_DELETE(default_allocator(), sg);
+}
+
+//-----------------------------------------------------------------------------
+void SceneGraphManager::update()
+{
+	for (uint32_t i = 0; i < m_graphs.size(); i++)
+	{
+		m_graphs[i]->update();
+	}
+}
+
+} // namespace crown

+ 58 - 0
engine/SceneGraphManager.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 "IdArray.h"
+
+namespace crown
+{
+
+class SceneGraph;
+
+/// Manages a collection of scene graphs.
+class SceneGraphManager
+{
+public:
+
+						SceneGraphManager();
+						~SceneGraphManager();
+
+	/// Creates a new scene graph
+	SceneGraph*			create_scene_graph();
+
+	/// Destroys the @a sg scene graph
+	void				destroy_scene_graph(SceneGraph* sg);
+
+	/// Updates all the scene graphs
+	void				update();
+
+private:
+
+	List<SceneGraph*>	m_graphs;
+};
+
+} // namespace crown

+ 42 - 15
engine/Unit.cpp

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Allocator.h"
 #include "Log.h"
 #include "UnitResource.h"
+#include "SceneGraphManager.h"
 
 namespace crown
 {
@@ -44,14 +45,19 @@ Unit::Unit()
 }
 
 //-----------------------------------------------------------------------------
-void Unit::create(World& world, UnitResource* ur, UnitId id, const Vector3& pos, const Quaternion& rot)
+void Unit::create(World& world, SceneGraphManager& sg_mgr, UnitResource* ur, UnitId id, const Vector3& pos, const Quaternion& rot)
 {
-	m_root_node = m_scene_graph.create_node(-1, pos, rot);
+	// Create the scene graph
+
+	m_scene_graph = sg_mgr.create_scene_graph();
+
+	// Create the root node
+	m_root_node = m_scene_graph->create_node(-1, pos, rot);
 
 	// Create renderables
 	for (uint32_t i = 0; i < ur->num_renderables(); i++)
 	{
-		int32_t node = m_scene_graph.create_node(m_root_node, Vector3::ZERO, Quaternion::IDENTITY);
+		int32_t node = m_scene_graph->create_node(m_root_node, Vector3::ZERO, Quaternion::IDENTITY);
 
 		UnitRenderable renderable = ur->get_renderable(i);
 
@@ -75,7 +81,7 @@ void Unit::create(World& world, UnitResource* ur, UnitId id, const Vector3& pos,
 	// Create cameras
 	for (uint32_t i = 0; i < ur->num_cameras(); i++)
 	{
-		int32_t cam_node = m_scene_graph.create_node(m_root_node, Vector3::ZERO, Quaternion::IDENTITY);
+		int32_t cam_node = m_scene_graph->create_node(m_root_node, Vector3::ZERO, Quaternion::IDENTITY);
 
 		UnitCamera camera = ur->get_camera(i);
 		CameraId cam = world.create_camera(cam_node, Vector3::ZERO, Quaternion::IDENTITY);
@@ -85,6 +91,7 @@ void Unit::create(World& world, UnitResource* ur, UnitId id, const Vector3& pos,
 	}
 
 	m_world = &world;
+	m_sg_manager = &sg_mgr;
 	m_resource = ur;
 	m_id = id;
 }
@@ -92,72 +99,92 @@ void Unit::create(World& world, UnitResource* ur, UnitId id, const Vector3& pos,
 //-----------------------------------------------------------------------------
 void Unit::destroy()
 {
+	// Destroy cameras
+	for (uint32_t i = 0; i < m_num_cameras; i++)
+	{
+		m_world->destroy_camera(m_cameras[i].component);
+	}
+
+	// Destroy meshes
+	for (uint32_t i = 0; i < m_num_meshes; i++)
+	{
+		m_world->destroy_mesh(m_meshes[i].component);
+	}
+
+	// Destroy sprites
+	for (uint32_t i = 0; i < m_num_sprites; i++)
+	{
+		m_world->destroy_sprite(m_sprites[i].component);
+	}
+
+	// Destroy scene graph
+	m_sg_manager->destroy_scene_graph(m_scene_graph);
 }
 
 //-----------------------------------------------------------------------------
 Vector3 Unit::local_position(int32_t node) const
 {
-	return m_scene_graph.local_position(node);
+	return m_scene_graph->local_position(node);
 }
 
 //-----------------------------------------------------------------------------
 Quaternion Unit::local_rotation(int32_t node) const
 {
-	return m_scene_graph.local_rotation(node);
+	return m_scene_graph->local_rotation(node);
 }
 
 //-----------------------------------------------------------------------------
 Matrix4x4 Unit::local_pose(int32_t node) const
 {
-	return m_scene_graph.local_pose(node);
+	return m_scene_graph->local_pose(node);
 }
 
 //-----------------------------------------------------------------------------
 Vector3 Unit::world_position(int32_t node) const
 {
-	return m_scene_graph.world_position(node);
+	return m_scene_graph->world_position(node);
 }
 
 //-----------------------------------------------------------------------------
 Quaternion Unit::world_rotation(int32_t node) const
 {
-	return m_scene_graph.world_rotation(node);
+	return m_scene_graph->world_rotation(node);
 }
 
 //-----------------------------------------------------------------------------
 Matrix4x4 Unit::world_pose(int32_t node) const
 {
-	return m_scene_graph.world_pose(node);
+	return m_scene_graph->world_pose(node);
 }
 
 //-----------------------------------------------------------------------------
 void Unit::set_local_position(const Vector3& pos, int32_t node)
 {
-	m_scene_graph.set_local_position(node, pos);
+	m_scene_graph->set_local_position(node, pos);
 }
 
 //-----------------------------------------------------------------------------
 void Unit::set_local_rotation(const Quaternion& rot, int32_t node)
 {
-	m_scene_graph.set_local_rotation(node, rot);
+	m_scene_graph->set_local_rotation(node, rot);
 }
 
 //-----------------------------------------------------------------------------
 void Unit::set_local_pose(const Matrix4x4& pose, int32_t node)
 {
-	m_scene_graph.set_local_pose(node, pose);
+	m_scene_graph->set_local_pose(node, pose);
 }
 
 //-----------------------------------------------------------------------------
 void Unit::link_node(int32_t child, int32_t parent)
 {
-	m_scene_graph.link(child, parent);
+	m_scene_graph->link(child, parent);
 }
 
 //-----------------------------------------------------------------------------
 void Unit::unlink_node(int32_t child)
 {
-	m_scene_graph.unlink(child);
+	m_scene_graph->unlink(child);
 }
 
 //-----------------------------------------------------------------------------

+ 4 - 2
engine/Unit.h

@@ -68,6 +68,7 @@ class Camera;
 class Mesh;
 class Sprite;
 class World;
+class SceneGraphManager;
 struct UnitResource;
 
 #define MAX_CAMERA_COMPONENTS 8
@@ -77,7 +78,7 @@ struct UnitResource;
 struct Unit
 {
 					Unit();
-	void			create(World& world, UnitResource* ur, UnitId id, const Vector3& pos, const Quaternion& rot);
+	void			create(World& world, SceneGraphManager& sg_mgr, UnitResource* ur, UnitId id, const Vector3& pos, const Quaternion& rot);
 	void			destroy();
 
 	Vector3			local_position(int32_t node = 0) const;
@@ -115,11 +116,12 @@ struct Unit
 public:
 
 	World*			m_world;
+	SceneGraphManager* m_sg_manager;
 	UnitResource*	m_resource;
 	UnitId			m_id;
 
 	int32_t			m_root_node;
-	SceneGraph		m_scene_graph;
+	SceneGraph*		m_scene_graph;
 
 	uint32_t		m_num_cameras;
 	Component		m_cameras[MAX_CAMERA_COMPONENTS];

+ 22 - 18
engine/World.cpp

@@ -56,22 +56,29 @@ UnitId World::spawn_unit(const char* name, const Vector3& pos, const Quaternion&
 
 	// Create Id for the unit
 	const UnitId unit_id = m_units.create(unit);
-	unit->create(*this, ur, unit_id, pos, rot);
+	unit->create(*this, m_graph_manager, ur, unit_id, pos, rot);
 
 	return unit_id;
 }
 
 //-----------------------------------------------------------------------------
-void World::destroy_unit(UnitId unit)
+void World::destroy_unit(UnitId id)
 {
-	CE_ASSERT(m_units.has(unit), "Unit does not exist");
+	CE_ASSERT(m_units.has(id), "Unit does not exist");
+
+	Unit* unit = m_units.lookup(id);
+
+	unit->destroy();
+	CE_DELETE(m_unit_pool, unit);
+	m_units.destroy(id);
 }
 
 //-----------------------------------------------------------------------------
 void World::destroy_unit(Unit* unit)
 {
 	CE_ASSERT_NOT_NULL(unit);
-	CE_DELETE(m_unit_pool, unit);
+
+	destroy_unit(unit->m_id);
 }
 
 //-----------------------------------------------------------------------------
@@ -189,15 +196,8 @@ Sprite* World::lookup_sprite(SpriteId sprite)
 //-----------------------------------------------------------------------------
 void World::update(Camera& camera, float dt)
 {
-	// Update all the units
-	for (uint32_t uu = 0; uu < m_units.size(); uu++)
-	{
-		Unit& unit = *m_units.m_objects[uu];
-		SceneGraph& graph = unit.m_scene_graph;
-
-		// Update unit's scene graph
-		graph.update();
-	}
+	// Update scene graphs
+	m_graph_manager.update();
 
 	// Update camera poses
 	for (uint32_t i = 0; i < m_unit_to_camera.size(); i++)
@@ -207,7 +207,7 @@ void World::update(Camera& camera, float dt)
 		Camera* cam = m_camera.lookup(utc.camera);
 		Unit* unit = m_units.lookup(utc.unit);
 
-		cam->m_world_pose = unit->m_scene_graph.world_pose(utc.node);
+		cam->m_world_pose = unit->m_scene_graph->world_pose(utc.node);
 	}
 
 	// Updates sound poses
@@ -218,7 +218,7 @@ void World::update(Camera& camera, float dt)
 		Sound& sound = m_sounds.lookup(uts.sound);
 		Unit* unit = m_units.lookup(uts.unit);
 
-		sound.world = unit->m_scene_graph.world_pose(uts.node);
+		sound.world = unit->m_scene_graph->world_pose(uts.node);
 	}
 
 	// Update sprites poses
@@ -229,7 +229,7 @@ void World::update(Camera& camera, float dt)
 		Unit* unit = lookup_unit(uts.unit);
 		Sprite* sprite = lookup_sprite(uts.sprite);
 
-		sprite->m_world_pose = unit->m_scene_graph.world_pose(uts.node);
+		sprite->m_world_pose = unit->m_scene_graph->world_pose(uts.node);
 	}
 
 	// Update render world
@@ -257,9 +257,13 @@ CameraId World::create_camera(int32_t node, const Vector3& pos, const Quaternion
 }
 
 //-----------------------------------------------------------------------------
-void World::destroy_camera(CameraId camera)
+void World::destroy_camera(CameraId id)
 {
-	m_camera.destroy(camera);
+	CE_ASSERT(m_camera.has(id), "Camera does not exist");
+
+	Camera* camera = m_camera.lookup(id);
+	CE_DELETE(m_camera_pool, camera);
+	m_camera.destroy(id);
 }
 
 //-----------------------------------------------------------------------------

+ 32 - 29
engine/World.h

@@ -36,6 +36,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "RenderWorld.h"
 #include "SoundRenderer.h"
 #include "PoolAllocator.h"
+#include "SceneGraphManager.h"
 
 namespace crown
 {
@@ -91,45 +92,45 @@ class Quaternion;
 class World
 {
 public:
-							World();
+										World();
 
-	UnitId					spawn_unit(const char* name, const Vector3& pos = Vector3::ZERO, const Quaternion& rot = Quaternion(Vector3(0, 1, 0), 0.0f));
-	void					destroy_unit(UnitId unit);
-	void					destroy_unit(Unit* unit);
+	UnitId								spawn_unit(const char* name, const Vector3& pos = Vector3::ZERO, const Quaternion& rot = Quaternion(Vector3(0, 1, 0), 0.0f));
+	void								destroy_unit(UnitId id);
+	void								destroy_unit(Unit* unit);
 
-	void					link_unit(UnitId child, UnitId parent, int32_t node);
-	void					unlink_unit(UnitId unit);
+	void								link_unit(UnitId child, UnitId parent, int32_t node);
+	void								unlink_unit(UnitId unit);
 
-	void					link_camera(CameraId camera, UnitId unit, int32_t node);
-	void					unlink_camera(CameraId camera);
+	void								link_camera(CameraId camera, UnitId unit, int32_t node);
+	void								unlink_camera(CameraId camera);
 
-	void					link_sprite(SpriteId sprite, UnitId unit, int32_t node);
-	void					unlink_sprite(SpriteId sprite);
+	void								link_sprite(SpriteId sprite, UnitId unit, int32_t node);
+	void								unlink_sprite(SpriteId sprite);
 
-	Unit*					lookup_unit(UnitId unit);
-	Camera*					lookup_camera(CameraId camera);
-	Mesh*					lookup_mesh(MeshId mesh);
-	Sprite*					lookup_sprite(SpriteId sprite);
+	Unit*								lookup_unit(UnitId unit);
+	Camera*								lookup_camera(CameraId camera);
+	Mesh*								lookup_mesh(MeshId mesh);
+	Sprite*								lookup_sprite(SpriteId sprite);
 
-	RenderWorld&			render_world();
-	void					update(Camera& camera, float dt);
+	RenderWorld&						render_world();
+	void								update(Camera& camera, float dt);
 
-	CameraId				create_camera(int32_t node, const Vector3& pos = Vector3::ZERO, const Quaternion& rot = Quaternion::IDENTITY);
-	void					destroy_camera(CameraId camera);
+	CameraId							create_camera(int32_t node, const Vector3& pos = Vector3::ZERO, const Quaternion& rot = Quaternion::IDENTITY);
+	void								destroy_camera(CameraId id);
 
-	MeshId					create_mesh(ResourceId id, int32_t node, const Vector3& pos = Vector3::ZERO, const Quaternion& rot = Quaternion::IDENTITY);
-	void					destroy_mesh(MeshId id);
+	MeshId								create_mesh(ResourceId id, int32_t node, const Vector3& pos = Vector3::ZERO, const Quaternion& rot = Quaternion::IDENTITY);
+	void								destroy_mesh(MeshId id);
 
-	SpriteId				create_sprite(ResourceId id, int32_t node = -1, const Vector3& pos = Vector3::ZERO, const Quaternion& rot = Quaternion::IDENTITY);
-	void					destroy_sprite(SpriteId id);
+	SpriteId							create_sprite(ResourceId id, int32_t node = -1, const Vector3& pos = Vector3::ZERO, const Quaternion& rot = Quaternion::IDENTITY);
+	void								destroy_sprite(SpriteId 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);
-	void					set_listener(const Vector3& pos, const Vector3& vel, const Vector3& or_up, const Vector3& or_at);
-	void					set_sound_position(SoundId sound, const Vector3& pos);
-	void					set_sound_range(SoundId sound, const float range);
-	void					set_sound_volume(SoundId sound, const float vol);
+	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);
+	void								set_listener(const Vector3& pos, const Vector3& vel, const Vector3& or_up, const Vector3& or_at);
+	void								set_sound_position(SoundId sound, const Vector3& pos);
+	void								set_sound_range(SoundId sound, const float range);
+	void								set_sound_volume(SoundId sound, const float vol);
 
 private:
 
@@ -140,6 +141,8 @@ private:
 	IdArray<MAX_CAMERAS, Camera*>		m_camera;
 	IdArray<MAX_SOUNDS, Sound> 			m_sounds;
 
+	SceneGraphManager					m_graph_manager;
+
 	// Connections
 	List<UnitToCamera>					m_unit_to_camera;
 	List<UnitToSound>					m_unit_to_sound;