1 | // Copyright (C) 2016-2016 ChaosForge Ltd
|
---|
2 | // http://chaosforge.org/
|
---|
3 | //
|
---|
4 | // This file is part of Nova libraries.
|
---|
5 | // For conditions of distribution and use, see copying.txt file in root folder.
|
---|
6 |
|
---|
7 | #include "nv/engine/ragdoll_manager.hh"
|
---|
8 |
|
---|
9 | #include "nv/lua/lua_math.hh"
|
---|
10 |
|
---|
11 | using namespace nv;
|
---|
12 |
|
---|
13 | nv::ragdoll_manager::ragdoll_manager( model_manager* model )
|
---|
14 | : m_world( nullptr ), m_model( model )
|
---|
15 | {
|
---|
16 |
|
---|
17 | }
|
---|
18 |
|
---|
19 | void nv::ragdoll_manager::initialize( lua::state* state )
|
---|
20 | {
|
---|
21 | lua_resource_manager< ragdoll_data >::initialize( state );
|
---|
22 | }
|
---|
23 |
|
---|
24 | bool nv::ragdoll_manager::load_resource( lua::table_guard& table, shash64 id )
|
---|
25 | {
|
---|
26 | NV_ASSERT_ALWAYS( m_world, "Physics world not setup in ragdoll_manager!" );
|
---|
27 | bool result = false;
|
---|
28 | nv::string64 model_id = table.get_string64( "model" );
|
---|
29 | nv::resource< model > mr = m_model->get( model_id );
|
---|
30 | if ( !mr ) return false;
|
---|
31 | nv::resource< animator_bind_data > bindr;
|
---|
32 | if ( auto m = mr.lock() )
|
---|
33 | bindr = mr.lock()->bind_data;
|
---|
34 | if ( !bindr ) return false;
|
---|
35 |
|
---|
36 | ragdoll_data* d = new ragdoll_data;
|
---|
37 | {
|
---|
38 | nv::lua::table_guard root( table, 1 );
|
---|
39 | result = load_ragdoll( root, bindr, d, -1 );
|
---|
40 | }
|
---|
41 | if ( result )
|
---|
42 | {
|
---|
43 | if ( auto bind = bindr.lock() )
|
---|
44 | {
|
---|
45 | const nv::data_node_list& bl = bind->get_bone_list();
|
---|
46 | d->bone_mask.resize( bl.size(), true );
|
---|
47 | for ( nv::uint32 i = 1; i < d->parts.size(); ++i )
|
---|
48 | {
|
---|
49 | d->bone_mask[d->parts[i].bone_id] = false;
|
---|
50 | }
|
---|
51 | }
|
---|
52 |
|
---|
53 | add( id, d );
|
---|
54 | }
|
---|
55 | return result;
|
---|
56 | }
|
---|
57 |
|
---|
58 | void nv::ragdoll_manager::release( ragdoll_data* p )
|
---|
59 | {
|
---|
60 | for ( auto& part : p->parts )
|
---|
61 | m_world->release( part.shape );
|
---|
62 | }
|
---|
63 |
|
---|
64 | bool nv::ragdoll_manager::load_ragdoll( lua::table_guard& table, resource< animator_bind_data > rbind, ragdoll_data* data, int pindex )
|
---|
65 | {
|
---|
66 | if ( auto bind_data = rbind.lock() )
|
---|
67 | {
|
---|
68 | int index = data->parts.size();
|
---|
69 | data->parts.emplace_back();
|
---|
70 | auto& part = data->parts.back();
|
---|
71 | part.name = table.get_string_hash_64( "name" );
|
---|
72 | part.bone_id = nv::uint32( bind_data->get_bone_list().resolve( table.get_string_hash_64( "bone" ) ) );
|
---|
73 | NV_ASSERT( part.bone_id < 256, "Bone ID not found!" );
|
---|
74 | float radius = table.get_float( "radius" );
|
---|
75 | float length = 0.0f;
|
---|
76 | if ( table.has_field( "target" ) )
|
---|
77 | {
|
---|
78 | const auto& of = bind_data->get_bone_transforms().m_offsets;
|
---|
79 | int target = bind_data->get_bone_list().resolve( table.get_string_hash_64( "target" ) );
|
---|
80 | if ( target < 0 ) return false;
|
---|
81 | length = math::distance( of[part.bone_id].get_position(), of[target].get_position() );
|
---|
82 | }
|
---|
83 | else
|
---|
84 | {
|
---|
85 | length = table.get_float( "length" );
|
---|
86 | }
|
---|
87 | NV_ASSERT( radius > 0.0f && length > 0.0f, "Bad parameters!" );
|
---|
88 | part.shape = m_world->create_capsule( radius, length );
|
---|
89 | part.parent_idx = pindex;
|
---|
90 | part.mass = table.get_float( "mass", 1.0f );
|
---|
91 | part.cone_twist = false;
|
---|
92 | // Joints
|
---|
93 | if ( pindex != -1 )
|
---|
94 | {
|
---|
95 | part.cone_twist = table.get_string_hash_64("joint") == shash64( "cone_twist"_ls );
|
---|
96 | part.limits = table.get< vec3 >( "limits" );
|
---|
97 | }
|
---|
98 | uint32 child_count = table.get_size();
|
---|
99 | bool result = true;
|
---|
100 | if ( child_count > 0 )
|
---|
101 | {
|
---|
102 | for( uint32 i = 1; i <= child_count; ++i )
|
---|
103 | {
|
---|
104 | lua::table_guard child_table( table, i );
|
---|
105 | result = load_ragdoll( child_table, rbind, data, index );
|
---|
106 | if ( !result ) return false;
|
---|
107 | }
|
---|
108 | }
|
---|
109 | return result;
|
---|
110 | }
|
---|
111 | return false;
|
---|
112 | }
|
---|