Преглед на файлове

world: add skinned meshes support

Part-of: #276
Daniele Bartolini преди 11 месеца
родител
ревизия
04660dddc7
променени са 4 файла, в които са добавени 60 реда и са изтрити 7 реда
  1. 42 5
      src/world/render_world.cpp
  2. 9 1
      src/world/render_world.h
  3. 8 0
      src/world/types.h
  4. 1 1
      src/world/world.cpp

+ 42 - 5
src/world/render_world.cpp

@@ -21,6 +21,7 @@
 #include "world/material.h"
 #include "world/material.h"
 #include "world/material_manager.h"
 #include "world/material_manager.h"
 #include "world/render_world.h"
 #include "world/render_world.h"
+#include "world/scene_graph.h"
 #include "world/shader_manager.h"
 #include "world/shader_manager.h"
 #include "world/unit_manager.h"
 #include "world/unit_manager.h"
 #include <bgfx/bgfx.h>
 #include <bgfx/bgfx.h>
@@ -64,6 +65,7 @@ RenderWorld::RenderWorld(Allocator &a
 	, MaterialManager &mm
 	, MaterialManager &mm
 	, UnitManager &um
 	, UnitManager &um
 	, Pipeline &pl
 	, Pipeline &pl
+	, SceneGraph &sg
 	)
 	)
 	: _marker(RENDER_WORLD_MARKER)
 	: _marker(RENDER_WORLD_MARKER)
 	, _resource_manager(&rm)
 	, _resource_manager(&rm)
@@ -71,6 +73,7 @@ RenderWorld::RenderWorld(Allocator &a
 	, _material_manager(&mm)
 	, _material_manager(&mm)
 	, _unit_manager(&um)
 	, _unit_manager(&um)
 	, _pipeline(&pl)
 	, _pipeline(&pl)
+	, _scene_graph(&sg)
 	, _debug_drawing(false)
 	, _debug_drawing(false)
 	, _mesh_manager(a, this)
 	, _mesh_manager(a, this)
 	, _sprite_manager(a, this)
 	, _sprite_manager(a, this)
@@ -138,6 +141,16 @@ void RenderWorld::mesh_set_geometry(MeshInstance mesh, StringId64 mesh_resource,
 	_mesh_manager.set_geometry(mesh, mr, geometry);
 	_mesh_manager.set_geometry(mesh, mr, geometry);
 }
 }
 
 
+void RenderWorld::mesh_set_skeleton(MeshInstance mesh, const AnimationSkeletonInstance *bones)
+{
+	CE_ASSERT(mesh.i < _mesh_manager._data.size, "Index out of bounds");
+	_mesh_manager._data.skeleton[mesh.i] = (const AnimationSkeletonInstance *)bones;
+
+	UnitId unit = _mesh_manager._data.unit[mesh.i];
+	TransformInstance ti = _scene_graph->instance(unit);
+	_scene_graph->set_local_pose(ti, MATRIX4X4_IDENTITY);
+}
+
 Material *RenderWorld::mesh_material(MeshInstance mesh)
 Material *RenderWorld::mesh_material(MeshInstance mesh)
 {
 {
 	CE_ASSERT(mesh.i < _mesh_manager._data.size, "Index out of bounds");
 	CE_ASSERT(mesh.i < _mesh_manager._data.size, "Index out of bounds");
@@ -428,13 +441,13 @@ void RenderWorld::render(const Matrix4x4 &view)
 		bgfx::setUniform(_u_light_range, &lid.range[ll]);
 		bgfx::setUniform(_u_light_range, &lid.range[ll]);
 		bgfx::setUniform(_u_light_intensity, &lid.intensity[ll]);
 		bgfx::setUniform(_u_light_intensity, &lid.intensity[ll]);
 
 
-		_mesh_manager.draw(VIEW_MESH);
+		_mesh_manager.draw(VIEW_MESH, *_scene_graph);
 	}
 	}
 
 
 	_sprite_manager.draw(VIEW_SPRITE_0);
 	_sprite_manager.draw(VIEW_SPRITE_0);
 
 
 	// Render outlines.
 	// Render outlines.
-	_mesh_manager.draw(VIEW_SELECTION, selection_draw_override);
+	_mesh_manager.draw(VIEW_SELECTION, *_scene_graph, selection_draw_override);
 	_sprite_manager.draw(VIEW_SELECTION, selection_draw_override);
 	_sprite_manager.draw(VIEW_SELECTION, selection_draw_override);
 }
 }
 
 
@@ -516,6 +529,7 @@ void RenderWorld::MeshManager::allocate(u32 num)
 		+ num*sizeof(Material *) + alignof(Material *)
 		+ num*sizeof(Material *) + alignof(Material *)
 		+ num*sizeof(Matrix4x4) + alignof(Matrix4x4)
 		+ num*sizeof(Matrix4x4) + alignof(Matrix4x4)
 		+ num*sizeof(OBB) + alignof(OBB)
 		+ num*sizeof(OBB) + alignof(OBB)
+		+ num*sizeof(AnimationSkeletonInstance *) + alignof(AnimationSkeletonInstance *)
 #if CROWN_CAN_RELOAD
 #if CROWN_CAN_RELOAD
 		+ num*sizeof(MaterialResource *) + alignof(MaterialResource *)
 		+ num*sizeof(MaterialResource *) + alignof(MaterialResource *)
 #endif
 #endif
@@ -535,8 +549,9 @@ void RenderWorld::MeshManager::allocate(u32 num)
 	new_data.material      = (Material **          )memory::align_top(new_data.mesh + num,     alignof(Material *));
 	new_data.material      = (Material **          )memory::align_top(new_data.mesh + num,     alignof(Material *));
 	new_data.world         = (Matrix4x4 *          )memory::align_top(new_data.material + num, alignof(Matrix4x4));
 	new_data.world         = (Matrix4x4 *          )memory::align_top(new_data.material + num, alignof(Matrix4x4));
 	new_data.obb           = (OBB *                )memory::align_top(new_data.world + num,    alignof(OBB));
 	new_data.obb           = (OBB *                )memory::align_top(new_data.world + num,    alignof(OBB));
+	new_data.skeleton      = (const AnimationSkeletonInstance **)memory::align_top(new_data.obb + num, alignof(AnimationSkeletonInstance *));
 #if CROWN_CAN_RELOAD
 #if CROWN_CAN_RELOAD
-	new_data.material_resource = (const MaterialResource **)memory::align_top(new_data.obb + num, alignof(MaterialResource *));
+	new_data.material_resource = (const MaterialResource **)memory::align_top(new_data.skeleton + num, alignof(MaterialResource *));
 #endif
 #endif
 
 
 	memcpy(new_data.unit, _data.unit, _data.size * sizeof(UnitId));
 	memcpy(new_data.unit, _data.unit, _data.size * sizeof(UnitId));
@@ -546,6 +561,7 @@ void RenderWorld::MeshManager::allocate(u32 num)
 	memcpy(new_data.material, _data.material, _data.size * sizeof(Material *));
 	memcpy(new_data.material, _data.material, _data.size * sizeof(Material *));
 	memcpy(new_data.world, _data.world, _data.size * sizeof(Matrix4x4));
 	memcpy(new_data.world, _data.world, _data.size * sizeof(Matrix4x4));
 	memcpy(new_data.obb, _data.obb, _data.size * sizeof(OBB));
 	memcpy(new_data.obb, _data.obb, _data.size * sizeof(OBB));
+	memcpy(new_data.skeleton, _data.skeleton, _data.size * sizeof(AnimationSkeletonInstance *));
 #if CROWN_CAN_RELOAD
 #if CROWN_CAN_RELOAD
 	memcpy(new_data.material_resource, _data.material_resource, _data.size * sizeof(MaterialResource *));
 	memcpy(new_data.material_resource, _data.material_resource, _data.size * sizeof(MaterialResource *));
 #endif
 #endif
@@ -579,6 +595,7 @@ MeshInstance RenderWorld::MeshManager::create(UnitId unit, const MeshResource *m
 	_data.material[last] = _render_world->_material_manager->get(mat_res);
 	_data.material[last] = _render_world->_material_manager->get(mat_res);
 	_data.world[last]    = tr;
 	_data.world[last]    = tr;
 	_data.obb[last]      = mg->obb;
 	_data.obb[last]      = mg->obb;
+	_data.skeleton[last] = NULL;
 #if CROWN_CAN_RELOAD
 #if CROWN_CAN_RELOAD
 	_data.material_resource[last] = mat_res;
 	_data.material_resource[last] = mat_res;
 #endif
 #endif
@@ -616,6 +633,7 @@ void RenderWorld::MeshManager::destroy(MeshInstance inst)
 	_data.material[inst.i] = _data.material[last];
 	_data.material[inst.i] = _data.material[last];
 	_data.world[inst.i]    = _data.world[last];
 	_data.world[inst.i]    = _data.world[last];
 	_data.obb[inst.i]      = _data.obb[last];
 	_data.obb[inst.i]      = _data.obb[last];
+	_data.skeleton[inst.i] = _data.skeleton[last];
 #if CROWN_CAN_RELOAD
 #if CROWN_CAN_RELOAD
 	_data.material_resource[inst.i] = _data.material_resource[last];
 	_data.material_resource[inst.i] = _data.material_resource[last];
 #endif
 #endif
@@ -650,6 +668,7 @@ void RenderWorld::MeshManager::swap(u32 inst_a, u32 inst_b)
 	exchange(_data.material[inst_a], _data.material[inst_b]);
 	exchange(_data.material[inst_a], _data.material[inst_b]);
 	exchange(_data.world[inst_a],    _data.world[inst_b]);
 	exchange(_data.world[inst_a],    _data.world[inst_b]);
 	exchange(_data.obb[inst_a],      _data.obb[inst_b]);
 	exchange(_data.obb[inst_a],      _data.obb[inst_b]);
+	exchange(_data.skeleton[inst_a], _data.skeleton[inst_b]);
 #if CROWN_CAN_RELOAD
 #if CROWN_CAN_RELOAD
 	exchange(_data.material_resource[inst_a], _data.material_resource[inst_b]);
 	exchange(_data.material_resource[inst_a], _data.material_resource[inst_b]);
 #endif
 #endif
@@ -702,10 +721,28 @@ void RenderWorld::MeshManager::destroy()
 	_allocator->deallocate(_data.buffer);
 	_allocator->deallocate(_data.buffer);
 }
 }
 
 
-void RenderWorld::MeshManager::draw(u8 view, DrawOverride draw_override)
+void RenderWorld::MeshManager::draw(u8 view, SceneGraph &scene_graph, DrawOverride draw_override)
 {
 {
 	for (u32 ii = 0; ii < _data.first_hidden; ++ii) {
 	for (u32 ii = 0; ii < _data.first_hidden; ++ii) {
-		bgfx::setTransform(to_float_ptr(_data.world[ii]));
+		if (_data.skeleton[ii] != NULL) {
+			AnimationSkeletonInstance *skeleton = (AnimationSkeletonInstance *)_data.skeleton[ii];
+
+			for (u32 b = 0; b < skeleton->num_bones; ++b) {
+				TransformInstance bone_ti = scene_graph.instance(skeleton->bone_lookup[b]);
+				skeleton->bones[b] = skeleton->offsets[b] * scene_graph.world_pose(bone_ti);
+			}
+
+			TransformInstance ti = scene_graph.instance(_data.unit[ii]);
+			Matrix4x4 world_pose = scene_graph.world_pose(ti);
+			skeleton->bones[0] = world_pose;
+
+			bgfx::setTransform(skeleton->bones, skeleton->num_bones);
+		} else {
+			TransformInstance ti = scene_graph.instance(_data.unit[ii]);
+			Matrix4x4 world_pose = scene_graph.world_pose(ti);
+			bgfx::setTransform(to_float_ptr(world_pose));
+		}
+
 		bgfx::setVertexBuffer(0, _data.mesh[ii].vbh);
 		bgfx::setVertexBuffer(0, _data.mesh[ii].vbh);
 		bgfx::setIndexBuffer(_data.mesh[ii].ibh);
 		bgfx::setIndexBuffer(_data.mesh[ii].ibh);
 
 

+ 9 - 1
src/world/render_world.h

@@ -8,7 +8,9 @@
 #include "core/containers/types.h"
 #include "core/containers/types.h"
 #include "core/math/types.h"
 #include "core/math/types.h"
 #include "core/strings/string_id.h"
 #include "core/strings/string_id.h"
+#include "device/pipeline.h"
 #include "resource/mesh_resource.h"
 #include "resource/mesh_resource.h"
+#include "resource/mesh_skeleton_resource.h"
 #include "resource/shader_resource.h"
 #include "resource/shader_resource.h"
 #include "resource/types.h"
 #include "resource/types.h"
 #include "world/types.h"
 #include "world/types.h"
@@ -28,6 +30,7 @@ struct RenderWorld
 		, MaterialManager &mm
 		, MaterialManager &mm
 		, UnitManager &um
 		, UnitManager &um
 		, Pipeline &pl
 		, Pipeline &pl
+		, SceneGraph &sg
 		);
 		);
 
 
 	///
 	///
@@ -46,6 +49,9 @@ struct RenderWorld
 	/// mesh_resource.
 	/// mesh_resource.
 	void mesh_set_geometry(MeshInstance mesh, StringId64 mesh_resource, StringId32 geometry);
 	void mesh_set_geometry(MeshInstance mesh, StringId64 mesh_resource, StringId32 geometry);
 
 
+	///
+	void mesh_set_skeleton(MeshInstance mesh, const AnimationSkeletonInstance *bones);
+
 	/// Returns the material of the @a mesh.
 	/// Returns the material of the @a mesh.
 	Material *mesh_material(MeshInstance mesh);
 	Material *mesh_material(MeshInstance mesh);
 
 
@@ -193,6 +199,7 @@ struct RenderWorld
 			Material **material;
 			Material **material;
 			Matrix4x4 *world;
 			Matrix4x4 *world;
 			OBB *obb;
 			OBB *obb;
+			const AnimationSkeletonInstance **skeleton;
 #if CROWN_CAN_RELOAD
 #if CROWN_CAN_RELOAD
 			const MaterialResource **material_resource;
 			const MaterialResource **material_resource;
 #endif
 #endif
@@ -243,7 +250,7 @@ struct RenderWorld
 		void swap(u32 inst_a, u32 inst_b);
 		void swap(u32 inst_a, u32 inst_b);
 
 
 		///
 		///
-		void draw(u8 view, DrawOverride draw_override = NULL);
+		void draw(u8 view, SceneGraph &scene_graph, DrawOverride draw_override = NULL);
 
 
 		///
 		///
 		MeshInstance make_instance(u32 i)
 		MeshInstance make_instance(u32 i)
@@ -395,6 +402,7 @@ struct RenderWorld
 	MaterialManager *_material_manager;
 	MaterialManager *_material_manager;
 	UnitManager *_unit_manager;
 	UnitManager *_unit_manager;
 	Pipeline *_pipeline;
 	Pipeline *_pipeline;
+	SceneGraph *_scene_graph;
 
 
 	bgfx::UniformHandle _u_light_position;
 	bgfx::UniformHandle _u_light_position;
 	bgfx::UniformHandle _u_light_direction;
 	bgfx::UniformHandle _u_light_direction;

+ 8 - 0
src/world/types.h

@@ -479,4 +479,12 @@ struct PhysicsTransformEvent
 
 
 typedef u32 AnimationId;
 typedef u32 AnimationId;
 
 
+struct AnimationSkeletonInstance
+{
+	u32 num_bones;
+	const Matrix4x4 *offsets;
+	UnitId *bone_lookup;
+	Matrix4x4 *bones;
+};
+
 } // namespace crown
 } // namespace crown

+ 1 - 1
src/world/world.cpp

@@ -64,7 +64,7 @@ World::World(Allocator &a
 {
 {
 	_lines = create_debug_line(true);
 	_lines = create_debug_line(true);
 	_scene_graph   = CE_NEW(*_allocator, SceneGraph)(*_allocator, um);
 	_scene_graph   = CE_NEW(*_allocator, SceneGraph)(*_allocator, um);
-	_render_world  = CE_NEW(*_allocator, RenderWorld)(*_allocator, rm, sm, mm, um, pl);
+	_render_world  = CE_NEW(*_allocator, RenderWorld)(*_allocator, rm, sm, mm, um, pl, *_scene_graph);
 	_physics_world = CE_NEW(*_allocator, PhysicsWorld)(*_allocator, rm, um, *_lines);
 	_physics_world = CE_NEW(*_allocator, PhysicsWorld)(*_allocator, rm, um, *_lines);
 	_sound_world   = CE_NEW(*_allocator, SoundWorld)(*_allocator);
 	_sound_world   = CE_NEW(*_allocator, SoundWorld)(*_allocator);
 	_script_world  = CE_NEW(*_allocator, ScriptWorld)(*_allocator, um, rm, env, *this);
 	_script_world  = CE_NEW(*_allocator, ScriptWorld)(*_allocator, um, rm, env, *this);