source: OGRE/trunk/ogrenew/Tools/MayaExport/src/particles.cpp @ 692

Revision 692, 13.2 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

Line 
1#include "particles.h"
2
3////////////////////////////////////////////////////////////////////////////////////////////////////
4namespace OgreMayaExporter
5{
6////////////////////////////////////////////////////////////////////////////////////////////////////
7const float FP_2PI = 6.28318531f;
8static float FP_MINDELTA = 0.005f;
9////////////////////////////////////////////////////////////////////////////////////////////////////
10inline float ToRadians( float fD ) { return fD * ( FP_2PI / 360.f ); }
11inline float ToDegrees( float fR ) { return fR * ( 360.f / FP_2PI ); }
12template<class T> void DropSame( const std::vector<T> &values, int nBeginTime, TKeyTrack<T> *pRes );
13template<class T> void MakeLinearSpline( const std::vector<T> &values, int nBeginTime, float fEpsilon, TKeyTrack<T> *pRes );
14template<class T> void writeTrackToXML( std::ofstream &outStream, const TKeyTrack<T> &dataTrack, const std::string &name );
15////////////////////////////////////////////////////////////////////////////////////////////////////
16// Particles
17////////////////////////////////////////////////////////////////////////////////////////////////////
18Particles::Particles():
19        nFrames(0)
20{
21}
22////////////////////////////////////////////////////////////////////////////////////////////////////
23Particles::~Particles()
24{
25        clear();
26}
27////////////////////////////////////////////////////////////////////////////////////////////////////
28MStatus Particles::load( MDagPath& dagPath, ParamList& params )
29{
30        int nMaxFrame, nMinFrame;
31        MGlobal::executeCommand( "playbackOptions -q -max", nMaxFrame );
32        MGlobal::executeCommand( "playbackOptions -q -min", nMinFrame );
33        if ( nMinFrame > 0 )
34                nMinFrame = 0;
35
36        for ( int nFrame = nMinFrame; nFrame <= nMaxFrame; ++nFrame )
37                ExportFrame( dagPath, nFrame );
38
39        FinalizeData( nMinFrame, nMaxFrame );
40        return MS::kSuccess;
41}
42////////////////////////////////////////////////////////////////////////////////////////////////////
43MStatus Particles::writeToXML( ParamList& params )
44{
45        params.outParticles << "<particles frames=\"" << nFrames << "\" tracks=\"" << particleTracks.size() << "\" >\n";
46        for ( uint nTemp = 0; nTemp < particleTracks.size(); ++nTemp )
47        {
48                const SParticle &particle = particleTracks[nTemp];
49                params.outParticles << "\t<particle startFrame=\"" << particle.nStartTime << "\" endFrame=\"" << particle.nEndTime << "\" >\n";
50                writeTrackToXML( params.outParticles, particle.pos, "position" );
51                writeTrackToXML( params.outParticles, particle.rotation, "rotation" );
52                writeTrackToXML( params.outParticles, particle.scale, "scale" );
53                writeTrackToXML( params.outParticles, particle.color, "color" );
54                writeTrackToXML( params.outParticles, particle.sprite, "sprite" );
55                params.outParticles << "\t</particle>\n";
56        }
57        params.outParticles << "</particles>\n";
58        return MS::kSuccess;
59}
60////////////////////////////////////////////////////////////////////////////////////////////////////
61void Particles::clear()
62{
63}
64////////////////////////////////////////////////////////////////////////////////////////////////////
65MStatus Particles::ExportFrame( MDagPath &dagPath, int nFrame )
66{
67        MGlobal::viewFrame( nFrame );
68
69        MStatus retStatus;
70        MFnDagNode dagNode( dagPath );
71        ////
72        int nParticles = 0;
73        MPlug countPlug = dagNode.findPlug( MString( "count" ), &retStatus );
74        retStatus = countPlug.getValue( nParticles );
75        if ( nParticles <= 0 )
76                return MS::kFailure;
77        ////
78        std::vector<int> idIndex( nParticles );
79        std::vector<int> sortedId( nParticles );
80        std::vector<SParticleData> particlesFrame( nParticles );
81        ////
82        MObject tempObj;
83        MPlug mappingPlug = dagNode.findPlug( MString( "idMapping" ), &retStatus );
84        ////
85        MPlug idPlug = mappingPlug.child( 0 );
86        retStatus = idPlug.getValue( tempObj );
87        MFnIntArrayData sSortedIDArray( tempObj, &retStatus );
88        for ( int nTemp = 0; nTemp < nParticles; ++nTemp )
89                sortedId[nTemp] = sSortedIDArray[nTemp];
90        ////
91        MPlug indexPlug = mappingPlug.child( 1 );
92        retStatus = indexPlug.getValue( tempObj );
93        MFnIntArrayData idIndexArray( tempObj, &retStatus );
94        for ( int nTemp = 0; nTemp < nParticles; ++nTemp )
95                idIndex[nTemp] = idIndexArray[nTemp];
96        //// Position
97        MPlug posPlug = dagNode.findPlug( MString( "worldPosition" ), &retStatus );
98        retStatus = posPlug.getValue( tempObj );
99        MFnVectorArrayData posData( tempObj, &retStatus );
100        for ( int nTemp = 0; nTemp < nParticles; ++nTemp )
101        {
102                SParticleData &particle = particlesFrame[nTemp];
103                particle.nFrame = nFrame;
104                particle.pos.x = (float)posData[idIndex[nTemp]].x;
105                particle.pos.y = (float)posData[idIndex[nTemp]].y;
106                particle.pos.z = (float)posData[idIndex[nTemp]].z;
107        }
108        //// Rotation
109        MPlug rotPlug = dagNode.findPlug( MString( "spriteTwistPP" ), &retStatus );
110        if ( retStatus == MS::kSuccess )
111        {
112                retStatus = rotPlug.getValue( tempObj );
113                MFnDoubleArrayData rotPlug( tempObj, &retStatus );
114                for ( int nTemp = 0; nTemp < nParticles; ++nTemp )
115                        particlesFrame[nTemp].fRotation = ToRadians( (float)rotPlug[idIndex[nTemp]] );
116        }
117        //// ScaleX
118        MPlug scaleXPlug = dagNode.findPlug( MString( "spriteScaleXPP" ), &retStatus );
119        if ( retStatus == MS::kSuccess )
120        {
121                retStatus = scaleXPlug.getValue( tempObj );
122                MFnDoubleArrayData scaleX( tempObj, &retStatus );
123                for ( int nTemp = 0; nTemp < nParticles; ++nTemp )
124                        particlesFrame[nTemp].scale.x = float( scaleX[idIndex[nTemp]] );
125        }
126        //// ScaleY
127        MPlug scaleYPlug = dagNode.findPlug( MString( "spriteScaleYPP" ), &retStatus );
128        if ( retStatus == MS::kSuccess )
129        {
130                retStatus = scaleYPlug.getValue( tempObj );
131                MFnDoubleArrayData scaleY( tempObj, &retStatus );
132                for ( int nTemp = 0; nTemp < nParticles; ++nTemp )
133                        particlesFrame[nTemp].scale.y = float( scaleY[idIndex[nTemp]] );
134        }
135        //// Sprite
136        MPlug spritePlug = dagNode.findPlug( MString( "spriteNumPP" ), &retStatus );
137        if ( retStatus == MS::kSuccess )
138        {
139                retStatus = spritePlug.getValue( tempObj );
140                MFnDoubleArrayData sprite( tempObj, &retStatus );
141                for ( int nTemp = 0; nTemp < nParticles; ++nTemp )
142                        particlesFrame[nTemp].nSprite = int( sprite[idIndex[nTemp]] - 1 );
143        }
144        //// Color
145        MPlug colorPlug = dagNode.findPlug( MString( "rgbPP" ), &retStatus );
146        if ( retStatus == MS::kSuccess )
147        {
148                retStatus = colorPlug.getValue( tempObj );
149                MFnVectorArrayData rgbData( tempObj, &retStatus );
150                for ( int nTemp = 0; nTemp < nParticles; ++nTemp )
151                {
152                        particlesFrame[nTemp].color.r = float( rgbData[idIndex[nTemp]].x );
153                        particlesFrame[nTemp].color.g = float( rgbData[idIndex[nTemp]].y );
154                        particlesFrame[nTemp].color.b = float( rgbData[idIndex[nTemp]].z );
155                }
156        }
157        //// Opacity
158        MPlug alphaPlug = dagNode.findPlug( MString( "opacityPP" ), &retStatus );
159        if ( retStatus == MS::kSuccess )
160        {
161                retStatus = alphaPlug.getValue( tempObj );
162                MFnDoubleArrayData alphaData( tempObj, &retStatus );
163                for ( int nTemp = 0; nTemp < nParticles; ++nTemp )
164                        particlesFrame[nTemp].color.a = float( alphaData[idIndex[nTemp]] );
165        }
166
167        for ( int nTemp = 0; nTemp < nParticles; ++nTemp )
168                data[sortedId[nTemp]].push_back( particlesFrame[nTemp] );
169
170        return MS::kSuccess;
171}
172////////////////////////////////////////////////////////////////////////////////////////////////////
173MStatus Particles::FinalizeData( int nMinFrame, int nMaxFrame )
174{
175        nFrames = nMaxFrame - nMinFrame + 1;
176        particleTracks.resize( data.size() );
177
178        int nTemp = 0;
179        for ( CParticlesData::const_iterator iTemp = data.begin(); iTemp != data.end(); ++iTemp, ++nTemp )
180        {
181                SParticle &particle = particleTracks[nTemp];
182                ////
183                const CParticlesTrack &particlesTrack = iTemp->second;
184                int nEndFrame = particlesTrack.back().nFrame;
185                int nStartFrame = particlesTrack.front().nFrame;
186                int nFrames = nEndFrame - nStartFrame + 1;
187                ////
188                if ( nFrames != particlesTrack.size() )
189                {
190                        std::cout << "ERROR: particle dosn't exist in some frames (unsupported)!\n";
191                        return MS::kFailure;
192                }
193                ////
194                int nBeginTime = nStartFrame;
195                particle.nEndTime = nEndFrame;
196                particle.nStartTime = nStartFrame;
197                ////
198                std::vector<SPos> tmpPos( nFrames );
199                for ( int nTemp = 0; nTemp < nFrames; ++nTemp )
200                        tmpPos[nTemp] = particlesTrack[nTemp].pos;
201                MakeLinearSpline( tmpPos, nBeginTime, FP_MINDELTA, &particle.pos );
202                ////
203                std::vector<float> tmpRot( nFrames );
204                for ( int nTemp = 0; nTemp < nFrames; ++nTemp )
205                        tmpRot[nTemp] = particlesTrack[nTemp].fRotation;
206                MakeLinearSpline( tmpRot, nBeginTime, FP_MINDELTA, &particle.rotation );
207                ////
208                std::vector<SScale> tmpScale( nFrames );
209                for ( int nTemp = 0; nTemp < nFrames; ++nTemp )
210                        tmpScale[nTemp] = particlesTrack[nTemp].scale;
211                MakeLinearSpline( tmpScale, nBeginTime, FP_MINDELTA, &particle.scale );
212                ////
213                std::vector<SColor> tmpColor( nFrames );
214                for ( int nTemp = 0; nTemp < nFrames; ++nTemp )
215                        tmpColor[nTemp] = particlesTrack[nTemp].color;
216                MakeLinearSpline( tmpColor, nBeginTime, FP_MINDELTA, &particle.color );
217                ////
218                std::vector<int> tmpSprite( nFrames );
219                for ( int nTemp = 0; nTemp < nFrames; ++nTemp )
220                        tmpSprite[nTemp] = particlesTrack[nTemp].nSprite;
221                DropSame( tmpSprite, nBeginTime, &particle.sprite );
222        }
223
224        return MS::kSuccess;
225}
226////////////////////////////////////////////////////////////////////////////////////////////////////
227template<class T>
228bool CanDropValue( const T &value, const T &prevVal, const T &nextVal, int nDelta, int nRange, float fEpsilon )
229{
230        T resVal;
231        float fCoeff = float( nDelta ) / nRange;
232        Interpolate( prevVal, nextVal, fCoeff, &resVal );
233        if ( fabs( resVal - value ) < fEpsilon )
234                return true;
235        ////
236        return false;
237}
238////////////////////////////////////////////////////////////////////////////////////////////////////
239template<class T>
240void MakeLinearSpline( const std::vector<T> &values, int nBeginTime, float fEpsilon, TKeyTrack<T> *pRes )
241{
242        if ( values.size() == 0 )
243                return;
244        ////
245        TKey<T> startKey;
246        startKey.nTime = nBeginTime;
247        startKey.value = values.front();
248        pRes->keys.push_back( startKey );
249        if ( values.size() == 1 )
250                return;
251        ////
252        uint nIndex = 0;
253        uint nPrevIndex = 0;
254        while( nIndex < values.size() - 1 )
255        {
256                if ( !CanDropValue<T>( values[nIndex], values[nPrevIndex], values[nIndex + 1], nIndex - nPrevIndex, nIndex - nPrevIndex + 1, fEpsilon ) )
257                {
258                        nPrevIndex = nIndex;
259                        TKey<T> resKey;
260                        resKey.nTime = nBeginTime + nIndex;
261                        resKey.value = values[nIndex];
262                        pRes->keys.push_back( resKey );
263                }
264                ////
265                nIndex++;
266        }
267        ////
268        TKey<T> endKey;
269        endKey.nTime = nBeginTime + values.size() - 1;
270        endKey.value = values.back();
271        pRes->keys.push_back( endKey );
272}
273////////////////////////////////////////////////////////////////////////////////////////////////////
274template<class T>
275void DropSame( const std::vector<T> &values, int nBeginTime, TKeyTrack<T> *pRes )
276{
277        if ( values.size() == 0 )
278                return;
279        ////
280        TKey<T> startKey;
281        startKey.nTime = nBeginTime;
282        startKey.value = values.front();
283        pRes->keys.push_back( startKey );
284        if ( values.size() == 1 )
285                return;
286        ////
287        T nCurrent = values.front();
288        TKey<T> curKey;
289        for ( uint nTemp = 1; nTemp < values.size() - 1; ++nTemp )
290        {
291                if ( values[nTemp] != nCurrent )
292                {
293                        curKey.nTime = nBeginTime + nTemp;
294                        curKey.value = values[nTemp];
295                        pRes->keys.push_back( curKey );
296                        ////
297                        nCurrent = values[nTemp];
298                }
299        }
300        ////
301        TKey<T> endKey;
302        endKey.nTime = nBeginTime + values.size() - 1;
303        endKey.value = values.back();
304        pRes->keys.push_back( endKey );
305}
306////////////////////////////////////////////////////////////////////////////////////////////////////
307template<class T>
308void writeKeyToXML( std::ofstream &outStream, const TKey<T> &data )
309{
310        outStream << "\t\t\t<key time=\"" << data.nTime << "\" value=\"" << data.value << "\"/>\n";
311}
312////////////////////////////////////////////////////////////////////////////////////////////////////
313void writeKeyToXML( std::ofstream &outStream, const TKey<SPos> &data )
314{
315        outStream << "\t\t\t<key time=\"" << data.nTime << "\" x=\"" << data.value.x << "\" y=\"" << data.value.y << "\" z=\"" << data.value.z << "\"/>\n";
316}
317////////////////////////////////////////////////////////////////////////////////////////////////////
318void writeKeyToXML( std::ofstream &outStream, const TKey<SColor> &data )
319{
320        outStream << "\t\t\t<key time=\"" << data.nTime << "\" r=\"" << data.value.x << "\" g=\"" << data.value.y << "\" b=\"" << data.value.z << "\" a=\"" << data.value.a << "\"/>\n";
321}
322////////////////////////////////////////////////////////////////////////////////////////////////////
323void writeKeyToXML( std::ofstream &outStream, const TKey<SScale> &data )
324{
325        outStream << "\t\t\t<key time=\"" << data.nTime << "\" x=\"" << data.value.x << "\" y=\"" << data.value.y << "\"/>\n";
326}
327////////////////////////////////////////////////////////////////////////////////////////////////////
328template<class T>
329void writeTrackToXML( std::ofstream &outStream, const TKeyTrack<T> &dataTrack, const std::string &name )
330{
331        outStream << "\t\t<" << name.c_str() << " keys=\"" << dataTrack.keys.size() << "\" >\n";
332        for ( uint nTemp = 0; nTemp < dataTrack.keys.size(); ++nTemp )
333                writeKeyToXML( outStream, dataTrack.keys[nTemp] );
334        outStream << "\t\t</" << name.c_str() << ">\n";
335}
336////////////////////////////////////////////////////////////////////////////////////////////////////
337} // NAMESPACE
338////////////////////////////////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.