openscenegraph
MorphGeometry
Go to the documentation of this file.
1/* -*-c++-*-
2 * Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
3 *
4 * This library is open source and may be redistributed and/or modified under
5 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
6 * (at your option) any later version. The full license is in LICENSE file
7 * included with this distribution, and on the openscenegraph.org website.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * OpenSceneGraph Public License for more details.
13*/
14
15#ifndef OSGANIMATION_MORPHGEOMETRY_H
16#define OSGANIMATION_MORPHGEOMETRY_H
17
18#include <osgAnimation/Export>
19#include <osgAnimation/AnimationUpdateCallback>
20#include <osgAnimation/MorphTransformSoftware>
21#include <osg/Geometry>
22#include <algorithm>
23
24namespace osgAnimation
25{
26
27 class OSGANIMATION_EXPORT MorphGeometry : public osg::Geometry
28 {
29
30 public:
31
32 enum Method
33 {
34 NORMALIZED,
35 RELATIVE
36 };
37
38 class MorphTarget
39 {
40 protected:
41 osg::ref_ptr<osg::Geometry> _geom;
42 float _weight;
43 public:
44 MorphTarget(osg::Geometry* geom, float w = 1.0) : _geom(geom), _weight(w) {}
45 void setWeight(float weight) { _weight = weight; }
46 float getWeight() const { return _weight; }
47 osg::Geometry* getGeometry() { return _geom.get(); }
48 const osg::Geometry* getGeometry() const { return _geom.get(); }
49 void setGeometry(osg::Geometry* geom) { _geom = geom; }
50 };
51
52 typedef std::vector<MorphTarget> MorphTargetList;
53
54 MorphGeometry();
55 MorphGeometry(const osg::Geometry& b);
56 MorphGeometry(const MorphGeometry& b, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
57
58 virtual osg::Object* cloneType() const { return new MorphGeometry(); }
59 virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new MorphGeometry(*this,copyop); }
60 virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const MorphGeometry*>(obj)!=NULL; }
61 virtual const char* libraryName() const { return "osgAnimation"; }
62 virtual const char* className() const { return "MorphGeometry"; }
63
64 // set implementation of rig method
65 inline void setMorphTransformImplementation(MorphTransform*mt) { _morphTransformImplementation=mt; }
66 inline MorphTransform* getMorphTransformImplementation() { return _morphTransformImplementation.get(); }
67 inline const MorphTransform* getMorphTransformImplementation() const { return _morphTransformImplementation.get(); }
68
69 /** Set the morphing method. */
70 inline void setMethod(Method method) { _method = method; }
71 /** Get the morphing method. */
72 inline Method getMethod() const { return _method; }
73
74 /** Set flag for morphing normals. */
75 inline void setMorphNormals(bool morphNormals) { _morphNormals = morphNormals; }
76 /** Get the flag for morphing normals. */
77 inline bool getMorphNormals() const { return _morphNormals; }
78
79 /** Get the list of MorphTargets.*/
80 inline const MorphTargetList& getMorphTargetList() const { return _morphTargets; }
81
82 /** Get the list of MorphTargets. Warning if you modify this array you will have to call dirty() */
83 inline MorphTargetList& getMorphTargetList() { return _morphTargets; }
84
85 /** Return the \c MorphTarget at position \c i.*/
86 inline const MorphTarget& getMorphTarget( unsigned int i ) const { return _morphTargets[i]; }
87
88 /** Return the \c MorphTarget at position \c i.*/
89 inline MorphTarget& getMorphTarget( unsigned int i ) { return _morphTargets[i]; }
90
91 /** Set source of vertices for this morph geometry */
92 inline void setVertexSource(osg::Vec3Array *v) { _positionSource=v; }
93
94 /** Get source of vertices for this morph geometry */
95 inline osg::Vec3Array * getVertexSource() const { return _positionSource.get(); }
96
97 /** Set source of normals for this morph geometry */
98 inline void setNormalSource(osg::Vec3Array *n) { _normalSource=n; }
99
100 /** Get source of normals for this morph geometry */
101 inline osg::Vec3Array * getNormalSource() const { return _normalSource.get(); }
102
103 /** Add a \c MorphTarget to the \c MorphGeometry.
104 * If \c MorphTarget is not \c NULL and is not contained in the \c MorphGeometry
105 * then increment its reference count, add it to the MorphTargets list and
106 * dirty the bounding sphere to force it to be recomputed on the next
107 * call to \c getBound().
108 * @param morphTarget The \c MorphTarget to be added to the \c MorphGeometry.
109 * @param weight The weight to be added to the \c MorphGeometry.
110 * @return \c true for success; \c false otherwise.
111 */
112 virtual void addMorphTarget( osg::Geometry *morphTarget, float weight = 1.0 )
113 {
114 _morphTargets.push_back(MorphTarget(morphTarget, weight));
115 _dirty = true;
116 }
117
118 virtual void removeMorphTarget( osg::Geometry *morphTarget )
119 {
120 for(MorphTargetList::iterator iterator = _morphTargets.begin() ; iterator != _morphTargets.end() ; ++ iterator)
121 {
122 if(iterator->getGeometry() == morphTarget)
123 {
124 _morphTargets.erase(iterator);
125 break;
126 }
127 }
128 }
129
130 virtual void removeMorphTarget( const std::string& name )
131 {
132 for(MorphTargetList::iterator iterator = _morphTargets.begin() ; iterator != _morphTargets.end() ; ++ iterator)
133 {
134 if(iterator->getGeometry() && iterator->getGeometry()->getName() == name)
135 {
136 _morphTargets.erase(iterator);
137 break;
138 }
139 }
140
141 }
142
143 /** update a morph target at index setting its current weight to morphWeight */
144 inline void setWeight(unsigned int index, float morphWeight)
145 {
146 if (index < _morphTargets.size())
147 {
148 _morphTargets[index].setWeight(morphWeight);
149 dirty();
150 }
151 }
152
153 /** Set the MorphGeometry dirty.*/
154 inline void dirty(bool b=true) { _dirty = b; }
155 inline bool isDirty() const { return _dirty; }
156
157 /** for retrocompatibility */
158 void transformSoftwareMethod() { (*_morphTransformImplementation.get())(*this); }
159
160 protected:
161 osg::ref_ptr<MorphTransform> _morphTransformImplementation;
162 /// Do we need to recalculate the morphed geometry?
163 bool _dirty;
164
165 Method _method;
166 MorphTargetList _morphTargets;
167
168 osg::ref_ptr<osg::Vec3Array> _positionSource;
169 osg::ref_ptr<osg::Vec3Array> _normalSource;
170
171 /// Do we also morph between normals?
172 bool _morphNormals;
173 };
174
175 class OSGANIMATION_EXPORT UpdateMorph : public AnimationUpdateCallback<osg::NodeCallback>
176 {
177 public:
178 typedef std::vector<std::string> TargetNames;
179 typedef std::map< int, osg::ref_ptr<osgAnimation::FloatTarget> > WeightTargets;
180
181 META_Object(osgAnimation, UpdateMorph);
182
183 UpdateMorph(const std::string& name = "");
184 UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop);
185
186 void addTarget(const std::string& name) { _targetNames.push_back(name); }
187 unsigned int getNumTarget() const { return _targetNames.size(); }
188 const std::string& getTargetName(unsigned int index) { return _targetNames[index]; }
189 void removeTarget(const std::string& name)
190 {
191 TargetNames::iterator found = std::find(_targetNames.begin(), _targetNames.end(), name);
192 if(found != _targetNames.end())
193 _targetNames.erase(found);
194 }
195
196 // for serialization
197 const std::vector<std::string>& getTargetNames() const { return _targetNames; }
198 std::vector<std::string>& getTargetNames() { return _targetNames; }
199
200 void setTargetNames(const TargetNames& targetNames) { _targetNames.assign(targetNames.begin(), targetNames.end()); }
201
202 /** Callback method called by the NodeVisitor when visiting a node.*/
203 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
204 bool needLink() const;
205 bool link(osgAnimation::Channel* channel);
206 int link(Animation* animation);
207
208 protected:
209 WeightTargets _weightTargets;
210 TargetNames _targetNames;
211 };
212
213 struct UpdateMorphGeometry : public osg::DrawableUpdateCallback
214 {
215 UpdateMorphGeometry() {}
216
217 UpdateMorphGeometry(const UpdateMorphGeometry& org, const osg::CopyOp& copyop):
218 osg::Object(org, copyop),
219 osg::Callback(org, copyop),
220 osg::DrawableUpdateCallback(org, copyop) {}
221
222 META_Object(osgAnimation, UpdateMorphGeometry);
223
224 virtual void update(osg::NodeVisitor*, osg::Drawable* drw)
225 {
226 MorphGeometry* geom = dynamic_cast<MorphGeometry*>(drw);
227 if (!geom)
228 return;
229
230 if (!geom->getMorphTransformImplementation())
231 {
232 geom->setMorphTransformImplementation( new MorphTransformSoftware);
233 }
234
235 MorphTransform& implementation = *geom->getMorphTransformImplementation();
236 (implementation)(*geom);
237 }
238 };
239}
240
241#endif