Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/Tools/MayaExport/src/particles.cpp @ 6

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

=…

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