Developer Documentation
Loading...
Searching...
No Matches
SkinT_impl.hh
1/* ========================================================================= *
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 * ========================================================================= */
41
42/*===========================================================================*\
43 *
44 * $Revision: 21010 $
45 * $Date: 2015-07-16 10:52:48 +0200 (Do, 16 Jul 2015) $
46 *
47\*===========================================================================*/
48
49
50
51
52
53#ifdef USE_OPENMP
54#include <omp.h>
55#endif
56#define SKINT_C
57
58//-----------------------------------------------------------------------------
59
60template<typename MeshT>
61SkinT<MeshT>::SkinT(SkeletonT<PointT> *_skeleton, MeshT *_mesh, int _objectID) :
62 BaseSkin(_objectID),
63 skeleton_(_skeleton),
64 mesh_(_mesh),
65 objectId_(_objectID),
66 lastmethod_(Blending::M_LBS),
67 weightsComputed_(false)
68
69{
70}
71
72//-----------------------------------------------------------------------------
73
74template<typename MeshT>
76{
77
78}
79
80//-----------------------------------------------------------------------------
81
82template<typename MeshT>
84{
85 return skeleton_;
86}
87
88//-----------------------------------------------------------------------------
89
98template<typename MeshT>
100{
101 // create the skins properties
104
105 //make sure properties are there
106 if( !mesh_->get_property_handle(propDefaultPose, DEFAULTPOSE_PROP) )
107 mesh_->add_property(propDefaultPose, DEFAULTPOSE_PROP);
108
109 if (! mesh_->get_property_handle(propWeights, SKIN_WEIGHTS_PROP))
110 mesh_->add_property(propWeights, SKIN_WEIGHTS_PROP);
111
112 // backup the default pose
113 for(typename MeshT::VertexIter it = mesh_->vertices_begin(); it != mesh_->vertices_end(); ++it)
114 mesh_->property(propDefaultPose, *it) = DefaultPose(mesh_->point(*it), mesh_->normal(*it));
115}
116
117//-----------------------------------------------------------------------------
118
119template<typename MeshT>
121{
122 deformSkin(lastAnimationHandle_, lastmethod_);
123}
124
125//-----------------------------------------------------------------------------
126
157template<typename MeshT>
158void SkinT<MeshT>::deformSkin(const AnimationHandle &_hAni, Blending::Method _method)
159{
160 // Do not transform skin if skin weights were not computed before
161 // as the mesh entirely disappears since all vertices collapse to origin
162 if(!weightsComputed_) {
163 return;
164 }
165
166 lastAnimationHandle_ = _hAni;
167 lastmethod_ = _method;
168
169 // first get the properties
172
173 if(!mesh_->get_property_handle(propDefaultPose, DEFAULTPOSE_PROP) ||
174 !mesh_->get_property_handle(propWeights, SKIN_WEIGHTS_PROP))
175 return; // missing properties
176
177 Pose* pose = skeleton_->pose(_hAni);
178
179 #ifndef USE_OPENMP
180 int verticesWithoutWeights = 0;
181 #endif
182
183 // for every vertex
184 typename MeshT::VertexIter it;
185#ifdef USE_OPENMP
186 std::vector< OpenMesh::VertexHandle > vhandles; vhandles.clear(); vhandles.reserve(mesh_->n_vertices());
187 for(it = mesh_->vertices_begin(); it != mesh_->vertices_end(); ++it){vhandles.push_back(*it);}
188 int vhcount = (int) vhandles.size();
189 #pragma omp parallel for
190 for (int vhindex = 0; vhindex < vhcount; vhindex++)
191#else
192 for(it = mesh_->vertices_begin(); it != mesh_->vertices_end(); ++it)
193#endif
194 {
195 #ifdef USE_OPENMP
196 const OpenMesh::VertexHandle currentVertexH = vhandles[vhindex];
197 #else
198 const OpenMesh::VertexHandle currentVertexH = *it;
199 #endif
200
201 // based on its position in the default pose
202 OpenMesh::Vec3d default_point = mesh_->property(propDefaultPose, currentVertexH).point,
203 default_normal = mesh_->property(propDefaultPose, currentVertexH).normal;
204
205 OpenMesh::Vec3d point(0, 0, 0), normal(0, 0, 0); // the new position and normal
206
207 if( _method == Blending::M_LBS ) {
208
209 // Linear blend skinning
210 SkinWeights &weights = mesh_->property(propWeights, currentVertexH);
211
212 #ifndef USE_OPENMP
213 if (weights.size() == 0)
214 {
215 verticesWithoutWeights++;
216 }
217 #endif
218
219 SkinWeights::iterator it_w;
220 for(it_w = weights.begin(); it_w != weights.end(); ++it_w)
221 {
222 const Matrix &unified = pose->unifiedMatrix(it_w->first);
223
224 point += it_w->second * unified.transform_point(default_point);
225 normal += it_w->second * unified.transform_vector(default_normal);
226 }
227
228 }else if( _method == Blending::M_DBS ) {
229 // Dual quaternion blend skinning
230
231 std::vector<double> weightVector;
232 std::vector<DualQuaternion> dualQuaternions;
233
234 SkinWeights &weights = mesh_->property(propWeights, currentVertexH);
235 SkinWeights::iterator it_w;
236
237 for(it_w = weights.begin(); it_w != weights.end(); ++it_w){
238 weightVector.push_back( it_w->second );
239 dualQuaternions.push_back( pose->unifiedDualQuaternion(it_w->first) );
240 }
241
242 DualQuaternion dq = DualQuaternion::interpolate(weightVector, dualQuaternions);
243
244 point = dq.transform_point(default_point);
245 normal = dq.transform_vector(default_normal);
246
247 } else {
248 std::cerr << "ERROR: Unknown skinning method!" << std::endl;
249 }
250
251 mesh_->set_point(currentVertexH, point);
252 mesh_->set_normal(currentVertexH, normal);
253 }
254
255 #ifndef USE_OPENMP
256 if ( verticesWithoutWeights > 0 )
257 std::cerr << "Deform skin: " << verticesWithoutWeights << " vertices without skin weights." << std::endl;
258 #endif
259
260 mesh_->update_face_normals();
261}
262
263//-----------------------------------------------------------------------------
264
268template<typename MeshT>
270{
271 // create the skins properties
273
274 // try to restore the default pose
275 if(mesh_->get_property_handle(propDefaultPose, DEFAULTPOSE_PROP))
276 {
277 typename MeshT::VertexIter it;
278 for(it = mesh_->vertices_begin(); it != mesh_->vertices_end(); ++it)
279 {
280 mesh_->set_point(*it, mesh_->property(propDefaultPose, *it).point);
281 mesh_->set_normal(*it, mesh_->property(propDefaultPose, *it).normal);
282 }
283 mesh_->remove_property(propDefaultPose);
284 }
285
286 // Remove the skin weights
288 mesh_->remove_property(propSkinWeights);
289}
290
291//-----------------------------------------------------------------------------
292
DualQuaternion class for representing rigid motions in 3d.
Vec3 transform_point(const Vec3 &_point) const
Transform a point with the dual quaternion.
Vec3 transform_vector(const Vec3 &_point) const
Transform a vector with the dual quaternion.
VectorT< T, 3 > transform_vector(const VectorT< T, 3 > &_v) const
transform vector (x',y',z',0) = A * (x,y,z,0)
VectorT< T, 3 > transform_point(const VectorT< T, 3 > &_v) const
transform point (x',y',z',1) = M * (x,y,z,1)
A handle used to refer to an animation or to a specific frame in an animation.
Abstract base class for the skin template, wrapping all template versions of the skin.
Definition BaseSkin.hh:63
std::map< unsigned int, double > SkinWeights
Stores the joint weights per vertex.
Definition BaseSkin.hh:94
void update_face_normals()
Update normal vectors for all faces.
A general pose, used to store the frames of the animation.
Definition PoseT.hh:59
const Matrix & unifiedMatrix(size_t _joint)
Returns the unified matrix.
const DualQuaternion & unifiedDualQuaternion(size_t _joint)
Returns a dual quaternion holding the unified matrix represented as dual quaternion.
General skin class, used to bind skeleton and mesh and deform the mesh.
Definition SkinT.hh:15
void deformSkin()
Attach the given mesh as skin to this skeleton.
SkinT(SkeletonT< PointT > *_skeleton, MeshT *_mesh, int _objectID)
constructor
Definition SkinT_impl.hh:61
void releaseSkin()
The given mesh will be reset to its default pose and all skin properties are removed.
Skeleton * skeleton()
Attach the given mesh as skin to this skeleton.
Definition SkinT_impl.hh:83
void attachSkin()
Attach the given mesh as skin to this skeleton.
Definition SkinT_impl.hh:99
Holds the skins default pose.
Definition BaseSkin.hh:79
Handle for a vertex entity.
Definition Handles.hh:121