Bladeren bron

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

Daniele Bartolini 12 jaren geleden
bovenliggende
commit
cede6c9910
42 gewijzigde bestanden met toevoegingen van 423 en 32 verwijderingen
  1. 13 15
      engine/os/linux/OsWindow.cpp
  2. 4 2
      engine/os/linux/OsWindow.h
  3. 4 4
      engine/os/linux/main.cpp
  4. 22 8
      engine/physics/Actor.cpp
  5. 1 0
      engine/renderers/RenderWorld.cpp
  6. 2 2
      engine/renderers/RenderWorld.h
  7. 13 0
      engine/resource/PhysicsResource.cpp
  8. 11 0
      engine/resource/PhysicsResource.h
  9. 2 1
      engine/world/Unit.cpp
  10. 6 0
      engine/world/World.cpp
  11. 1 0
      engine/world/World.h
  12. 5 0
      samples/03.bounce/bounce.material
  13. 10 0
      samples/03.bounce/bounce.physics
  14. 19 0
      samples/03.bounce/bounce.unit
  15. 5 0
      samples/03.bounce/box.material
  16. 16 0
      samples/03.bounce/box.physics
  17. 19 0
      samples/03.bounce/box.unit
  18. 16 0
      samples/03.bounce/camera.unit
  19. 5 0
      samples/03.bounce/crown.config
  20. 33 0
      samples/03.bounce/level.package
  21. 153 0
      samples/03.bounce/lua/game.lua
  22. BIN
      samples/03.bounce/sounds/beep.sound
  23. BIN
      samples/03.bounce/sounds/birds1.sound
  24. BIN
      samples/03.bounce/sounds/birds2.sound
  25. BIN
      samples/03.bounce/sounds/birds3.sound
  26. BIN
      samples/03.bounce/sounds/birds4.sound
  27. BIN
      samples/03.bounce/sounds/footsteps.sound
  28. BIN
      samples/03.bounce/sounds/gunshoot.sound
  29. BIN
      samples/03.bounce/sounds/jump.sound
  30. BIN
      samples/03.bounce/sounds/mario.sound
  31. BIN
      samples/03.bounce/sounds/mono.sound
  32. BIN
      samples/03.bounce/sounds/mono1.sound
  33. BIN
      samples/03.bounce/sounds/sweep.sound
  34. BIN
      samples/03.bounce/sounds/untrue.sound
  35. 13 0
      samples/03.bounce/sprites/bounce.sprite
  36. 13 0
      samples/03.bounce/sprites/box.sprite
  37. 13 0
      samples/03.bounce/sprites/sun.sprite
  38. 5 0
      samples/03.bounce/sun.material
  39. 19 0
      samples/03.bounce/sun.unit
  40. BIN
      samples/03.bounce/textures/bounce.texture
  41. BIN
      samples/03.bounce/textures/box.texture
  42. BIN
      samples/03.bounce/textures/sun.texture

+ 13 - 15
engine/os/linux/OsWindow.cpp

@@ -42,12 +42,14 @@ void oswindow_set_window(Display* dpy, Window win)
 
 //-----------------------------------------------------------------------------
 OsWindow::OsWindow()
-	: m_resizable(true)
+	: m_x(0)
+	, m_y(0)
+	, m_width(0)
+	, m_height(0)
+	, m_resizable(true)
 	, m_x11_detectable_autorepeat(false)
 {
 	set_title("");
-
-	XGetWindowAttributes(m_x11_display, m_x11_window, &m_win_attr);
 }
 
 //-----------------------------------------------------------------------------
@@ -70,19 +72,15 @@ void OsWindow::hide()
 //-----------------------------------------------------------------------------
 void OsWindow::get_size(uint32_t& width, uint32_t& height)
 {
-	XGetWindowAttributes(m_x11_display, m_x11_window, &m_win_attr);
-
-	width = m_win_attr.width;
-	height = m_win_attr.height;
+	width = m_width;
+	height = m_height;
 }
 
 //-----------------------------------------------------------------------------
 void OsWindow::get_position(uint32_t& x, uint32_t& y)
 {
-	XGetWindowAttributes(m_x11_display, m_x11_window, &m_win_attr);
-
-	x = m_win_attr.x;
-	y = m_win_attr.y;
+	x = m_x;
+	y = m_y;
 }
 
 //-----------------------------------------------------------------------------
@@ -120,10 +118,10 @@ void OsWindow::set_resizable(bool resizable)
 {
 	XSizeHints hints;
 	hints.flags = PMinSize | PMaxSize;
-	hints.min_width = resizable ? 1 : m_win_attr.width;
-	hints.min_height = resizable ? 1 : m_win_attr.height;
-	hints.max_width = resizable ? 65535 : m_win_attr.width;
-	hints.max_height = resizable ? 65535 : m_win_attr.height;
+	hints.min_width = resizable ? 1 : m_width;
+	hints.min_height = resizable ? 1 : m_height;
+	hints.max_width = resizable ? 65535 : m_width;
+	hints.max_height = resizable ? 65535 : m_height;
 
 	XSetWMNormalHints(m_x11_display, m_x11_window, &hints);
 

+ 4 - 2
engine/os/linux/OsWindow.h

@@ -70,8 +70,10 @@ public:
 
 public:
 
-	XWindowAttributes m_win_attr;
-
+	uint32_t		m_x;
+	uint32_t		m_y;
+	uint32_t		m_width;
+	uint32_t		m_height;
 	bool			m_resizable;
 
 	bool			m_x11_detectable_autorepeat;

+ 4 - 4
engine/os/linux/main.cpp

@@ -325,10 +325,10 @@ public:
 				{
 					const OsMetricsEvent& ev = event.metrics;
 					m_mouse->set_metrics(ev.width, ev.height);
-					m_window->m_win_attr.x = ev.x;
-					m_window->m_win_attr.y = ev.y;
-					m_window->m_win_attr.width = ev.width;
-					m_window->m_win_attr.height = ev.height;
+					m_window->m_x = ev.x;
+					m_window->m_y = ev.y;
+					m_window->m_width = ev.width;
+					m_window->m_height = ev.height;
 					break;
 				}
 				case OsEvent::EXIT:

+ 22 - 8
engine/physics/Actor.cpp

@@ -43,6 +43,7 @@ using physx::PxVec3;
 using physx::PxReal;
 using physx::PxRigidBody;
 using physx::PxRigidDynamic;
+using physx::PxRigidStatic;
 using physx::PxPlaneGeometry;
 using physx::PxSphereGeometry;
 using physx::PxBoxGeometry;
@@ -64,6 +65,7 @@ Actor::Actor(PxScene* scene, SceneGraph& sg, int32_t node, ActorType::Enum type,
 	, m_type(type)
 {
 	Matrix4x4 m = sg.world_pose(node);
+
 	PxMat44 pose((PxReal*)(m.to_float_ptr()));
 
 	switch (type)
@@ -96,14 +98,17 @@ Actor::Actor(PxScene* scene, SceneGraph& sg, int32_t node, ActorType::Enum type,
 	
 	create_box(Vector3(0, 0, 0), .5, .5, .5);
 
-	PxRigidBodyExt::setMassAndUpdateInertia(*static_cast<PxRigidDynamic*>(m_actor), 500.0f);
-
-	PxD6Joint* joint = PxD6JointCreate(*device()->physx(), m_actor, PxTransform(pose), NULL, PxTransform(pose));
-	joint->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
-	joint->setMotion(PxD6Axis::eY, PxD6Motion::eFREE);
-	//joint->setMotion(PxD6Axis::eZ, PxD6Motion::eFREE);
-	//joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
-	joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
+	if (type == ActorType::DYNAMIC_PHYSICAL || type == ActorType::DYNAMIC_KINEMATIC)
+	{
+		PxRigidBodyExt::setMassAndUpdateInertia(*static_cast<PxRigidDynamic*>(m_actor), 500.0f);
+
+		PxD6Joint* joint = PxD6JointCreate(*device()->physx(), m_actor, PxTransform(pose), NULL, PxTransform(pose));
+		joint->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
+		joint->setMotion(PxD6Axis::eY, PxD6Motion::eFREE);
+		//joint->setMotion(PxD6Axis::eZ, PxD6Motion::eFREE);
+		//joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
+		joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
+	}
 
 	m_scene->addActor(*m_actor);
 }
@@ -248,6 +253,14 @@ void Actor::update_pose()
 
 	switch (m_type)
 	{
+		case ActorType::STATIC:
+		{
+			// m_actor->setGlobalPose(world_transform);
+		}
+		case ActorType::DYNAMIC_PHYSICAL:
+		{
+			break;
+		}
 		case ActorType::DYNAMIC_KINEMATIC:
 		{
 			static_cast<PxRigidDynamic*>(m_actor)->setKinematicTarget(world_transform);
@@ -260,6 +273,7 @@ void Actor::update_pose()
 //-----------------------------------------------------------------------------
 void Actor::update(const Matrix4x4& pose)
 {
+
 	if (m_type == ActorType::DYNAMIC_PHYSICAL)
 	{
 		m_scene_graph.set_world_pose(m_node, pose);

+ 1 - 0
engine/renderers/RenderWorld.cpp

@@ -123,6 +123,7 @@ RenderWorld::~RenderWorld()
 //-----------------------------------------------------------------------------
 MeshId RenderWorld::create_mesh(MeshResource* mr, SceneGraph& sg, int32_t node)
 {
+	Log::i("create mesh omfg");
 	Mesh* mesh = CE_NEW(m_mesh_pool, Mesh)(sg, node, mr);
 	return m_mesh.create(mesh);
 }

+ 2 - 2
engine/renderers/RenderWorld.h

@@ -34,8 +34,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "RenderWorldTypes.h"
 
 #define MAX_MESHES 100
-#define MAX_SPRITES 256
-#define MAX_MATERIALS 256
+#define MAX_SPRITES 512
+#define MAX_MATERIALS 512
 #define MAX_GUIS 8
 
 namespace crown

+ 13 - 0
engine/resource/PhysicsResource.cpp

@@ -37,6 +37,15 @@ namespace crown
 namespace physics_resource
 {
 
+static uint32_t actor_type_to_enum(const char* type)
+{
+	if (string::strcmp("static", type) == 0) return PhysicsActorType::STATIC;
+	else if (string::strcmp("dynamic_physical", type) == 0) return PhysicsActorType::DYNAMIC_PHYSICAL;
+	else if (string::strcmp("dynamic_kinematic", type) == 0) return PhysicsActorType::DYNAMIC_KINEMATIC;
+
+	CE_FATAL("Bad actor type");
+}
+
 static uint32_t shape_type_to_enum(const char* type)
 {
 	const StringId32 th = hash::murmur2_32(type, string::strlen(type));
@@ -89,15 +98,19 @@ void parse_actor(JSONElement e, PhysicsActor& actor, List<PhysicsShape>& actor_s
 {
 	JSONElement name = e.key("name");
 	JSONElement node = e.key("node");
+	JSONElement type = e.key("type");
 	JSONElement shapes = e.key("shapes");
 
 	DynamicString actor_name;
 	DynamicString actor_node;
+	DynamicString actor_type;
 	name.string_value(actor_name);
 	node.string_value(actor_node);
+	type.string_value(actor_type);
 
 	actor.name = hash::murmur2_32(actor_name.c_str(), actor_name.length());
 	actor.node = hash::murmur2_32(actor_node.c_str(), actor_node.length());
+	actor.type = actor_type_to_enum(actor_type.c_str());
 	actor.num_shapes = shapes.size();
 
 	for (uint32_t i = 0; i < actor.num_shapes; i++)

+ 11 - 0
engine/resource/PhysicsResource.h

@@ -54,10 +54,21 @@ struct PhysicsController
 	float contact_offset;	// Skin around the object within which contacts will be generated. Use it to avoid numerical precision issues.
 };
 
+struct PhysicsActorType
+{
+	enum Enum
+	{
+		STATIC,
+		DYNAMIC_PHYSICAL,
+		DYNAMIC_KINEMATIC
+	};
+};
+
 struct PhysicsActor
 {
 	StringId32 name;
 	StringId32 node;
+	uint32_t type;
 	uint32_t num_shapes;
 };
 

+ 2 - 1
engine/world/Unit.cpp

@@ -207,7 +207,8 @@ void Unit::create_physics_objects()
 		for (uint32_t i = 0; i < pr->num_actors(); i++)
 		{
 			const PhysicsActor actor = pr->actor(i);
-			add_actor(actor.name, m_world.physics_world()->create_actor(m_scene_graph, m_scene_graph.node(actor.node), ActorType::DYNAMIC_PHYSICAL));
+			Log::i("node: %d", m_scene_graph.node(actor.node));
+			add_actor(actor.name, m_world.physics_world()->create_actor(m_scene_graph, m_scene_graph.node(actor.node), (ActorType::Enum)actor.type));
 		}
 	}
 }

+ 6 - 0
engine/world/World.cpp

@@ -231,6 +231,12 @@ GuiId World::create_window_gui(const char* name)
 	return m_render_world.create_gui(gr);
 }
 
+//-----------------------------------------------------------------------------
+GuiId World::create_world_gui(const Matrix4x4 pose, const uint32_t width, const uint32_t height)
+{
+	// Must be implemented
+}
+
 //-----------------------------------------------------------------------------
 void World::destroy_gui(GuiId id)
 {

+ 1 - 0
engine/world/World.h

@@ -94,6 +94,7 @@ public:
 	void								set_sound_volume(SoundId sound, const float vol);
 
 	GuiId								create_window_gui(const char* name);
+	GuiId								create_world_gui(const Matrix4x4 pose, const uint32_t width, const uint32_t height);
 	void								destroy_gui(GuiId id);
 	Gui*								lookup_gui(GuiId id);
 

+ 5 - 0
samples/03.bounce/bounce.material

@@ -0,0 +1,5 @@
+{
+	"texture_layers" : [
+		"textures/bounce"
+	]
+}

+ 10 - 0
samples/03.bounce/bounce.physics

@@ -0,0 +1,10 @@
+{
+	"controller" : {
+		"name" : "controller",
+		"height" : 0.01,
+		"radius" : 0.5,
+		"slope_limit" : 0.707,
+		"step_offset" : 0.1,
+		"contact_offset" : 0.01
+	}
+}

+ 19 - 0
samples/03.bounce/bounce.unit

@@ -0,0 +1,19 @@
+{
+	"renderables" : [
+		{
+			"name" : "bounce",
+			"node" : "root",
+			"type" : "sprite",
+			"resource" : "sprites/bounce",
+			"visible" : true
+		}
+	],
+	"nodes" : [
+		{
+			"name" : "root",
+			"parent" : null,
+			"position" : [0, 0, 0],
+			"rotation" : [0, 0, 1, 0]
+		}
+	]
+}

+ 5 - 0
samples/03.bounce/box.material

@@ -0,0 +1,5 @@
+{
+	"texture_layers" : [
+		"textures/box"
+	]
+}

+ 16 - 0
samples/03.bounce/box.physics

@@ -0,0 +1,16 @@
+{
+	"actors" : [
+		{
+			"name" : "actor_0",
+			"node" : "root",
+			"type" : "static",
+			"shapes" : [
+				{
+					"name" : "shape_0",
+					"type" : "sphere",
+					"radius" : 0.5
+				}
+			]
+		}
+	]
+}

+ 19 - 0
samples/03.bounce/box.unit

@@ -0,0 +1,19 @@
+{
+	"renderables" : [
+		{
+			"name" : "box",
+			"node" : "root",
+			"type" : "sprite",
+			"resource" : "sprites/box",
+			"visible" : true
+		}
+	],
+	"nodes" : [
+		{
+			"name" : "root",
+			"parent" : null,
+			"position" : [0, 0, 0],
+			"rotation" : [0, 0, 1, 0]
+		}
+	]
+}

+ 16 - 0
samples/03.bounce/camera.unit

@@ -0,0 +1,16 @@
+{
+	"cameras" : [
+		{
+			"name" : "camera",
+			"node" : "root"
+		}
+	],
+	"nodes" : [
+		{
+			"name" : "root",
+			"parent" : null,
+			"position" : [0, 0, 0],
+			"rotation" : [0, 0, 1, 0]
+		}
+	]
+}

+ 5 - 0
samples/03.bounce/crown.config

@@ -0,0 +1,5 @@
+{
+	"boot" : "lua/game",
+	"window_width" : 1000,
+	"window_height" : 625
+}

+ 33 - 0
samples/03.bounce/level.package

@@ -0,0 +1,33 @@
+{
+	"texture" : [
+		"textures/bounce",
+		"textures/box",
+		"textures/sun"
+	],
+	"unit" : [
+		"camera",
+		"bounce",
+		"box",
+		"sun"
+	],
+	"sprite" : [
+		"sprites/bounce",
+		"sprites/box",
+		"sprites/sun"
+	],
+	"sound" : [
+		"sounds/beep",
+		"sounds/gunshoot",
+		"sounds/footsteps",
+		"sounds/jump"
+	],
+	"physics" : [
+		"bounce",
+		"box"
+	],
+	"material" : [
+		"bounce",
+		"box",
+		"sun"
+	]
+}

+ 153 - 0
samples/03.bounce/lua/game.lua

@@ -0,0 +1,153 @@
+timer = 0.0
+cursor = false
+world = nil
+camera = nil
+up_pressed = false
+down_pressed = false
+left_pressed = false
+right_pressed = false
+camera_size = 1.0
+
+ovest = -10
+east = 10
+north = 10 / 1.6
+south = -10 / 1.6
+spd_x = 0
+spd_y = 0
+
+footsteps = nil
+speed = 3
+
+
+function spawn_terrain(x, y, dim)
+	for t = 0, dim, 2 do
+		World.spawn_unit(world, "box", Vector3(x + t, math.random(-3, 6) , 0))
+	end
+end
+
+function spawn_suns(x, y, dim)
+	for t=0, dim, 7 do
+		World.spawn_unit(world, "sun", Vector3(x + t, math.random(-3, 6) , 0))
+	end	
+end
+
+function update_player(world, unit, dt)
+
+	-- 3 m/s
+	speed = speed + 0.1 * dt;
+
+	if (Keyboard.button_pressed(Keyboard.w)) then up_pressed = true end
+	if (Keyboard.button_pressed(Keyboard.s)) then down_pressed = true end
+
+	if (Keyboard.button_released(Keyboard.w)) then up_pressed = false end
+	if (Keyboard.button_released(Keyboard.s)) then down_pressed = false end
+
+	if (Touch.pointer_down(1)) then up_pressed = true end
+	if (Touch.pointer_up(1)) then up_pressed = false end
+
+
+	contr = Unit.controller(unit)
+
+	if up_pressed then
+		spd_y = speed * dt
+	end
+
+	spd_x = speed * dt
+
+	Controller.move(contr, Vector3(spd_x, spd_y, 0.0))
+
+	spd_y = spd_y - 0.5 * dt
+
+	-- local k = 0
+	-- if spd_x > 0.0 then k = -1
+	-- elseif spd_x < 0.0 then k = 1 end
+
+	-- spd_x = spd_x + k * dt
+	-- if spd_x < 0.001 and spd_x > -0.001 then spd_x = 0.0 end
+end
+
+function update_camera(player_unit, camera_unit, camera)
+	local player_pos = Unit.world_position(player_unit, 0)
+	Camera.set_local_position(camera, camera_unit, Vector3(Vector3.x(player_pos), -south / 2.5, 1))
+end
+
+function init()
+	-- -- Set the title of the main window
+	Window.set_title("Hello world!")
+	-- Window.show_cursor(cursor)
+	-- -- Window.minimize();
+
+	package = Device.create_resource_package("level")
+	ResourcePackage.load(package)
+	ResourcePackage.flush(package)
+
+	world = Device.create_world()
+
+	-- Spawn camera
+	camera_unit = World.spawn_unit(world, "camera")
+	camera = Unit.camera(camera_unit, "camera")
+
+	-- Spawn dragon
+	dragon = World.spawn_unit(world, "bounce")
+
+	spawn_suns(15, -2, 400)
+	spawn_terrain(10, -3, 400)
+
+	Camera.set_near_clip_distance(camera, 0.01)
+	Camera.set_far_clip_distance(camera, 1000)
+	Camera.set_projection_type(camera, Camera.ORTHOGRAPHIC)
+	Camera.set_orthographic_metrics(camera, ovest, east, south, north)
+	Camera.set_viewport_metrics(camera, 0, 0, 1000, 625)
+
+	Camera.set_local_position(camera, camera_unit, Vector3(0, 0, 1))
+end
+
+function frame(dt)
+	Device.update_world(world, dt)
+
+	-- Update window's viewport
+	win_w, win_h = Window.get_size()
+	Camera.set_viewport_metrics(camera, 0, 0, win_w, win_h)
+
+	-- Stop the engine when the 'ESC' key is released
+	if Keyboard.button_released(Keyboard.ESCAPE) then
+		Device.stop()
+	end
+
+	-- -- Spawn balls when SPACE pressed
+	-- if Keyboard.button_pressed(Keyboard.SPACE) then
+	-- 	World.spawn_unit(world, "b")
+	-- end
+
+	-- Play gunshoot on left click
+	if Mouse.button_pressed(Mouse.LEFT) then
+		World.play_sound(world, "sounds/gunshoot")
+	end
+
+	-- Print FPS on window title bar
+	timer = timer + Device.last_delta_time()
+		if (timer >= 5) then
+		Window.set_title(1.0 / Device.last_delta_time())
+		timer = 0.0
+	end
+
+	-- Update the player
+	update_player(world, dragon, dt)
+
+	-- Update the camera
+	update_camera(dragon, camera_unit, camera)
+
+	-- Render world
+	Device.render_world(world, camera)
+end
+
+function shutdown()
+
+	--World.destroy_unit(world, dragon)
+	--World.destroy_unit(world, button)
+	--World.destroy_unit(world, camera_unit)
+	
+	ResourcePackage.unload(package)
+	Device.destroy_resource_package(package)
+	Device.destroy_world(world)
+end

BIN
samples/03.bounce/sounds/beep.sound


BIN
samples/03.bounce/sounds/birds1.sound


BIN
samples/03.bounce/sounds/birds2.sound


BIN
samples/03.bounce/sounds/birds3.sound


BIN
samples/03.bounce/sounds/birds4.sound


BIN
samples/03.bounce/sounds/footsteps.sound


BIN
samples/03.bounce/sounds/gunshoot.sound


BIN
samples/03.bounce/sounds/jump.sound


BIN
samples/03.bounce/sounds/mario.sound


BIN
samples/03.bounce/sounds/mono.sound


BIN
samples/03.bounce/sounds/mono1.sound


BIN
samples/03.bounce/sounds/sweep.sound


BIN
samples/03.bounce/sounds/untrue.sound


+ 13 - 0
samples/03.bounce/sprites/bounce.sprite

@@ -0,0 +1,13 @@
+{
+	"width" : 128,
+	"height" : 128,
+	"frames" : [
+		{
+			"name" : "bounce",
+			"region" : [0.0, 0.0, 1.0, 1.0],
+			"offset" : [0.0, 0.0],
+			"scale" : [1.0, 1.0],
+			"rotated" : false
+		}
+	]
+}

+ 13 - 0
samples/03.bounce/sprites/box.sprite

@@ -0,0 +1,13 @@
+{
+	"width" : 128,
+	"height" : 128,
+	"frames" : [
+		{
+			"name" : "box",
+			"region" : [0.0, 0.0, 1.0, 1.0],
+			"offset" : [0.0, 0.0],
+			"scale" : [1.0, 1.0],
+			"rotated" : false
+		}
+	]
+}

+ 13 - 0
samples/03.bounce/sprites/sun.sprite

@@ -0,0 +1,13 @@
+{
+	"width" : 128,
+	"height" : 128,
+	"frames" : [
+		{
+			"name" : "sun",
+			"region" : [0.0, 0.0, 1.0, 1.0],
+			"offset" : [0.0, 0.0],
+			"scale" : [1.0, 1.0],
+			"rotated" : false
+		}
+	]
+}

+ 5 - 0
samples/03.bounce/sun.material

@@ -0,0 +1,5 @@
+{
+	"texture_layers" : [
+		"textures/sun"
+	]
+}

+ 19 - 0
samples/03.bounce/sun.unit

@@ -0,0 +1,19 @@
+{
+	"renderables" : [
+		{
+			"name" : "sun",
+			"node" : "root",
+			"type" : "sprite",
+			"resource" : "sprites/sun",
+			"visible" : true
+		}
+	],
+	"nodes" : [
+		{
+			"name" : "root",
+			"parent" : null,
+			"position" : [0, 0, 0],
+			"rotation" : [0, 0, 1, 0]
+		}
+	]
+}

BIN
samples/03.bounce/textures/bounce.texture


BIN
samples/03.bounce/textures/box.texture


BIN
samples/03.bounce/textures/sun.texture