Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/Tools/MayaExport/src/blendshape.cpp @ 10

Last change on this file since 10 was 6, checked in by anonymous, 17 years ago

=…

File size: 8.2 KB
Line 
1////////////////////////////////////////////////////////////////////////////////
2// blendshape.cpp
3// Author     : Francesco Giordana
4// Start Date : January 13, 2005
5// Copyright  : (C) 2006 by Francesco Giordana
6// Email      : fra.giordana@tiscali.it
7////////////////////////////////////////////////////////////////////////////////
8
9/*********************************************************************************
10*                                                                                *
11*   This program is free software; you can redistribute it and/or modify         *
12*   it under the terms of the GNU Lesser General Public License as published by  *
13*   the Free Software Foundation; either version 2 of the License, or            *
14*   (at your option) any later version.                                          *
15*                                                                                *
16**********************************************************************************/
17
18#include "blendshape.h"
19#include "submesh.h"
20
21namespace OgreMayaExporter
22{
23        // Constructor
24        BlendShape::BlendShape()
25        {
26                m_pBlendShapeFn = NULL;
27                clear();
28        }
29
30        // Destructor
31        BlendShape::~BlendShape()
32        {
33                clear();
34        }
35
36        // Clear blend shape data
37        void BlendShape::clear()
38        {
39                if (m_pBlendShapeFn)
40                        delete m_pBlendShapeFn;
41                m_pBlendShapeFn = NULL;
42                m_origEnvelope = 0;
43                m_origWeights.clear();
44                m_poses.clear();
45                m_target = T_MESH;
46                m_index = 0;
47        }
48
49        // Load blend shape deformer from Maya
50        MStatus BlendShape::load(MObject &blendShapeObj)
51        {
52                // Create a Fn for relative Maya blend shape deformer
53                m_pBlendShapeFn = new MFnBlendShapeDeformer(blendShapeObj);
54                // Save original envelope value for the deformer
55                m_origEnvelope = m_pBlendShapeFn->envelope();
56                // Save original target weights
57                m_origWeights.clear();
58                MIntArray indexList;
59                m_pBlendShapeFn->weightIndexList(indexList);
60                int i;
61                for (i=0; i<indexList.length(); i++)
62                {
63                        m_origWeights.push_back(m_pBlendShapeFn->weight(indexList[i]));
64                }
65                return MS::kSuccess;
66        }
67
68        // Load blend shape poses
69        MStatus BlendShape::loadPoses(MDagPath& meshDag,ParamList &params,
70                std::vector<vertex> &vertices,long numVertices,long offset,long targetIndex)
71        {
72                MStatus stat;
73                int i,j;
74                // Set blend shape target
75                if (params.useSharedGeom)
76                        m_target = T_MESH;
77                else
78                        m_target = T_SUBMESH;
79                m_index = targetIndex;
80                // Set blend shape deformer envelope to 1 to get target shapes
81                m_pBlendShapeFn->setEnvelope(1);
82                // Set weight to 0 for all targets
83                MIntArray indexList;
84                m_pBlendShapeFn->weightIndexList(indexList);
85                for (i=0; i<indexList.length(); i++)
86                {
87                        m_pBlendShapeFn->setWeight(indexList[i],0);
88                }
89                // Get pose names
90                MStringArray poseNames;
91                MString cmd = "aliasAttr -q " + m_pBlendShapeFn->name();
92                MGlobal::executeCommand(cmd,poseNames,false,false);
93                // Get all poses: set iteratively weight to 1 for current target shape and keep 0 for the other targets
94                for (i=0; i<indexList.length(); i++)
95                {
96                        MString poseName = "pose" + i;
97                        // get pose name
98                        bool foundName = false;
99                        for (j=1; j<poseNames.length() && !foundName; j+=2)
100                        {
101                                int idx = -1;
102                                sscanf(poseNames[j].asChar(),"weight[%d]",&idx);
103                                if (idx == i)
104                                {
105                                        poseName = poseNames[j-1];
106                                        foundName = true;
107                                        std::cout << "pose num: " << i << " name: " << poseName.asChar() << "\n";
108                                        std::cout.flush();
109                                }
110                        }
111                        // set weight to 1
112                        m_pBlendShapeFn->setWeight(indexList[i],1);
113                        // load the pose
114                        stat = loadPose(meshDag,params,vertices,numVertices,offset,poseName);
115                        if (stat != MS::kSuccess)
116                        {
117                                std::cout << "Failed loading target pose " << indexList[i] << "\n";
118                                std::cout.flush();
119                        }
120                        // set weight to 0
121                        m_pBlendShapeFn->setWeight(indexList[i],0);
122                }
123                // Set blend shape envelope to 0
124                m_pBlendShapeFn->setEnvelope(0);
125                // Restore targets weights
126                for (i=0; i<indexList.length(); i++)
127                {
128                        m_pBlendShapeFn->setWeight(indexList[i],m_origWeights[i]);
129                }
130                return MS::kSuccess;
131        }
132
133        // Load a single blend shape pose
134        MStatus BlendShape::loadPose(MDagPath& meshDag,ParamList &params,
135                std::vector<vertex> &vertices,long numVertices,long offset,MString poseName)
136        {
137                int i;
138                // get the mesh Fn
139                MFnMesh mesh(meshDag);
140                // create a new pose
141                pose p;
142                p.poseTarget = m_target;
143                p.index = m_index;
144                p.name = poseName.asChar();
145                // get vertex positions
146                MFloatPointArray points;
147                if (params.exportWorldCoords)
148                        mesh.getPoints(points,MSpace::kWorld);
149                else
150                        mesh.getPoints(points,MSpace::kObject);
151                // calculate vertex offsets
152                for (i=0; i<numVertices; i++)
153                {
154                        vertexOffset vo;
155                        vertex v = vertices[offset+i];
156                        vo.x = points[v.index].x * params.lum - v.x;
157                        vo.y = points[v.index].y * params.lum - v.y;
158                        vo.z = points[v.index].z * params.lum - v.z;
159                        vo.index = offset+i;
160                        if (fabs(vo.x) < PRECISION)
161                                vo.x = 0;
162                        if (fabs(vo.y) < PRECISION)
163                                vo.y = 0;
164                        if (fabs(vo.z) < PRECISION)
165                                vo.z = 0;
166                        if ((vo.x!=0) || (vo.y!=0) || (vo.z!=0))
167                                p.offsets.push_back(vo);
168                }
169                // add pose to pose list
170                if (p.offsets.size() > 0)
171                        m_poses.push_back(p);
172                if (params.bsBB)
173                {
174                        // update bounding boxes of loaded submeshes
175                        for (i=0; i<params.loadedSubmeshes.size(); i++)
176                        {
177                                MFnMesh mesh(params.loadedSubmeshes[i]->m_dagPath);
178                                MPoint min = mesh.boundingBox().min();
179                                MPoint max = mesh.boundingBox().max();
180                                MBoundingBox bbox(min,max);
181                                if (params.exportWorldCoords)
182                                        bbox.transformUsing(params.loadedSubmeshes[i]->m_dagPath.inclusiveMatrix());
183                                min = bbox.min() * params.lum;
184                                max = bbox.max() * params.lum;
185                                MBoundingBox newbbox(min,max);
186                                params.loadedSubmeshes[i]->m_boundingBox.expand(newbbox);
187                        }
188                }
189                // pose loaded succesfully
190                return MS::kSuccess;
191        }
192
193        // Load a blend shape animation track
194        Track BlendShape::loadTrack(float start,float stop,float rate,ParamList& params,int startPoseId)
195        {
196                MStatus stat;
197                int i;
198                MString msg;
199                std::vector<float> times;
200                // Create a track for current clip
201                Track t;
202                t.m_type = TT_POSE;
203                t.m_target = m_target;
204                t.m_index = m_index;
205                t.m_vertexKeyframes.clear();
206                // Calculate times from clip sample rate
207                times.clear();
208                if (rate <= 0)
209                {
210                        std::cout << "invalid sample rate for the clip (must be >0), we skip it\n";
211                        std::cout.flush();
212                        return t;
213                }
214                float time;
215                for (time=start; time<stop; time+=rate)
216                        times.push_back(time);
217                times.push_back(stop);
218                // Get animation length
219                float length=0;
220                if (times.size() >= 0)
221                        length = times[times.size()-1] - times[0];
222                if (length < 0)
223                {
224                        std::cout << "invalid time range for the clip, we skip it\n";
225                        std::cout.flush();
226                        return t;
227                }
228                // Evaluate animation curves at selected times
229                for (i=0; i<times.size(); i++)
230                {
231                        // Set time to wanted sample time
232                        MAnimControl::setCurrentTime(MTime(times[i],MTime::kSeconds));
233                        // Load a keyframe at current time
234                        vertexKeyframe key = loadKeyframe(times[i]-times[0],params,startPoseId);
235                        // Add keyframe to joint track
236                        t.addVertexKeyframe(key);
237                }
238                // Clip successfully loaded
239                return t;
240        }
241
242
243        // Load a blend shape animation keyframe
244        vertexKeyframe BlendShape::loadKeyframe(float time,ParamList& params,int startPoseId)
245        {
246                int i;
247                // Create keyframe
248                vertexKeyframe key;
249                key.time = time;
250                key.poserefs.clear();
251                // Read weights of all poses at current time
252                // Get blend shape deformer envelope
253                float envelope = m_pBlendShapeFn->envelope();
254                // Get weights of all targets
255                MIntArray indexList;
256                m_pBlendShapeFn->weightIndexList(indexList);
257                for (i=0; i<indexList.length(); i++)
258                {
259                        // Create a pose reference
260                        // Index of pose is relative to current blend shape
261                        vertexPoseRef poseref;
262                        poseref.poseIndex = startPoseId + i;
263                        poseref.poseWeight = envelope * m_pBlendShapeFn->weight(indexList[i]);
264                        key.poserefs.push_back(poseref);
265                }
266                return key;
267        }
268
269        // Get blend shape deformer name
270        MString BlendShape::getName()
271        {
272                return m_pBlendShapeFn->name();
273        }
274
275        // Get blend shape poses
276        std::vector<pose>& BlendShape::getPoses()
277        {
278                return m_poses;
279        }
280
281        // Set maya blend shape deformer envelope
282        void BlendShape::setEnvelope(float envelope)
283        {
284                m_pBlendShapeFn->setEnvelope(envelope);
285        }
286        // Restore maya blend shape deformer original envelope
287        void BlendShape::restoreEnvelope()
288        {
289                m_pBlendShapeFn->setEnvelope(m_origEnvelope);
290        }
291} // end namespace
Note: See TracBrowser for help on using the repository browser.