Go to the documentation of this file.00001 #ifndef OPENTISSUE_KINEMATICS_SKINNING_SBS_SKINNING_SBS_H
00002 #define OPENTISSUE_KINEMATICS_SKINNING_SBS_SKINNING_SBS_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/containers/mesh/trimesh/trimesh.h>
00013 #include <OpenTissue/core/containers/mesh/trimesh/util/trimesh_util.h>
00014
00015 #include <OpenTissue/kinematics/skinning/sbs/skinning_center_of_rotation.h>
00016 #include <OpenTissue/kinematics/skinning/skinning_traits.h>
00017
00018 #include <OpenTissue/utility/gl/gl_draw_mesh.h>
00019
00020 #include <cassert>
00021 #include <vector>
00022
00023
00024
00025 namespace OpenTissue
00026 {
00027 namespace skinning
00028 {
00029
00030
00031 template<typename types>
00032 class SBS : public trimesh::TriMesh<types,SkinVertexTraits<types> ,SkinFaceTraits<types>, trimesh::TriMeshArrayKernel >
00033 {
00034 public:
00035
00036
00037 typedef int no_gpu_support;
00038
00039 typedef typename types::matrix3x3_type matrix3x3_type;
00040 typedef typename types::quaternion_type quaternion_type;
00041 typedef typename types::vector3_type vector3_type;
00042 typedef typename types::real_type real_type;
00043
00044
00045 typedef trimesh::TriMesh<types, SkinVertexTraits<types>, SkinFaceTraits<types>, OpenTissue::trimesh::TriMeshArrayKernel > base_mesh;
00046
00047 public:
00048 int m_material_idx;
00049
00050 public:
00051
00052 SBS()
00053 : m_material_idx(-1)
00054 {}
00055
00056 bool empty() const
00057 {
00058 return (!(base_mesh::size_faces()>0));
00059 }
00060
00061 template<typename skin_container_type>
00062 static void init_skin_render( skin_container_type & scont )
00063 {
00064 }
00065
00066 template<typename skin_container_type>
00067 static void cleanup_skin_render( skin_container_type & scont )
00068 {
00069 }
00070
00071
00072 template<typename skin_container_type>
00073 static void pre_render( skin_container_type & scont )
00074 {
00075 scont.m_rc_cached.clear();
00076 scont.m_rc_lut.clear();
00077 }
00078
00079 template<typename skin_container_type>
00080 static void post_render( skin_container_type & scont )
00081 {
00082 }
00083
00084
00093 template<typename skeleton_type, typename skin_container_type>
00094 void update( skeleton_type & skeleton, skin_container_type & scont )
00095 {
00096 typedef typename skeleton_type::bone_traits bone_traits;
00097 typedef typename types::coordsys_type coordsys_type;
00098
00099
00100 if(this->empty())
00101 return;
00102
00103 typedef typename skin_container_type::lut_type lut_type;
00104 typedef typename skeleton_type::bone_type bone_type;
00105 typedef std::vector<bone_type const *> bone_container_type;
00106
00107 typename base_mesh::vertex_iterator vertex = base_mesh::vertex_begin();
00108 typename base_mesh::vertex_iterator end = base_mesh::vertex_end();
00109 bone_container_type affecting_bones;
00110
00111 for(;vertex!=end;++vertex)
00112 {
00113 vertex->m_coord = vector3_type(0,0,0);
00114 vertex->m_normal = vector3_type(0,0,0);
00115
00116
00117
00118 if( vertex->m_influences > 1 )
00119 {
00120 matrix3x3_type Q;
00121 vector3_type r_c( 0, 0, 0 );
00122 vector3_type r_cTrans( 0, 0, 0 );
00123
00124
00125
00126 affecting_bones.clear();
00127
00128
00129
00130 coordsys_type bone_space_transform = bone_traits::convert( skeleton.get_bone( vertex->m_bone[0] )->bone_space_transform() );
00131
00132 quaternion_type pivot = bone_space_transform.Q();
00133 affecting_bones.push_back( skeleton.get_bone( vertex->m_bone[0] ) );
00134 quaternion_type Qlerp = vertex->m_weight[0] * pivot;
00135
00136
00137
00138
00139 for(int i= 1; i < vertex->m_influences; ++i)
00140 {
00141 bone_type const * bone = skeleton.get_bone( vertex->m_bone[i] );
00142 affecting_bones.push_back( bone );
00143
00144 coordsys_type bone_space_transform = bone_traits::convert( bone->bone_space_transform() );
00145
00146 quaternion_type q_ji = bone_space_transform.Q();
00147
00148
00149 real_type norm = pivot * q_ji;
00150 if( norm < 0)
00151 q_ji = -q_ji;
00152
00153 Qlerp += vertex->m_weight[i] * q_ji;
00154 }
00155 Q = normalize( Qlerp );
00156
00157
00158 typename lut_type::iterator lut_it = scont.m_rc_lut.find( vertex->m_key );
00159 if( lut_it != scont.m_rc_lut.end() )
00160 {
00161 r_c = scont.m_rc_cached[lut_it->second];
00162 }
00163 else
00164 {
00165
00166 r_c = center_of_rotation( skeleton, affecting_bones );
00167
00168
00169 scont.m_rc_cached.push_back( r_c );
00170 scont.m_rc_lut[vertex->m_key] = scont.m_rc_cached.size()-1;
00171 }
00172
00173
00174 for(int i= 0; i < vertex->m_influences; ++i)
00175 {
00176 vector3_type p = r_c;
00177 vector3_type n = vertex->m_original_normal;
00178 bone_type const * bone = skeleton.get_bone(vertex->m_bone[i]);
00179
00180 coordsys_type bone_space_transform = bone_traits::convert( bone->bone_space_transform() );
00181
00182
00183 bone_space_transform.xform_point( p );
00184 r_cTrans += vertex->m_weight[i] * p;
00185
00186
00187 bone_space_transform.xform_vector( n );
00188 vertex->m_normal += vertex->m_weight[i] * n;
00189 }
00190
00191
00192 vector3_type vr_c = vertex->m_original_coord - r_c;
00193 vertex->m_coord = (Q * vr_c) + r_cTrans;
00194 }
00195 else
00196 {
00197
00198 vertex->m_coord = vertex->m_original_coord;
00199 vertex->m_normal = vertex->m_original_normal;
00200 bone_type const * bone = skeleton.get_bone(vertex->m_bone[0]);
00201
00202 coordsys_type bone_space_transform = bone_traits::convert( bone->bone_space_transform() );
00203
00204 bone_space_transform.xform_point( vertex->m_coord );
00205 bone_space_transform.xform_vector( vertex->m_normal );
00206 }
00207 }
00208 }
00209
00210 };
00211
00212 }
00213 }
00214
00215
00216 #endif