f970f6ee5afea6c0151f16ad275e40d33668e056
[blender.git] / intern / elbeem / intern / attributes.cpp
1 /******************************************************************************
2  *
3  * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
4  * Copyright 2003,2004 Nils Thuerey
5  *
6  * configuration attribute storage class and attribute class
7  *
8  *****************************************************************************/
9
10 #include "attributes.h"
11 #include "ntl_matrices.h"
12 #include "elbeem.h"
13 #include <sstream>
14
15
16 //! output attribute values? on=1/off=0
17 #define DEBUG_ATTRIBUTES 0
18
19 //! output channel values? on=1/off=0
20 #define DEBUG_CHANNELS 0
21
22
23 /******************************************************************************
24  * attribute conversion functions
25  *****************************************************************************/
26
27 bool Attribute::initChannel(int elemSize) {
28         if(!mIsChannel) return true;
29         if(mChannelInited==elemSize) {
30                 // already inited... ok
31                 return true;
32         } else {
33                 // sanity check
34                 if(mChannelInited>0) {
35                         errMsg("Attribute::initChannel","Duplicate channel init!? ("<<mChannelInited<<" vs "<<elemSize<<")...");
36                         return false;
37                 }
38         }
39         
40         if((mValue.size() % (elemSize+1)) !=  0) {
41                 errMsg("Attribute::initChannel","Invalid # elements in Attribute...");
42                 return false;
43         }
44         
45         int numElems = mValue.size()/(elemSize+1);
46         vector<string> newvalue;
47         for(int i=0; i<numElems; i++) {
48         //errMsg("ATTR"," i"<<i<<" "<<mName); // debug
49
50                 vector<string> elem(elemSize);
51                 for(int j=0; j<elemSize; j++) {
52                 //errMsg("ATTR"," j"<<j<<" "<<mValue[i*(elemSize+1)+j]  ); // debug
53                         elem[j] = mValue[i*(elemSize+1)+j];
54                 }
55                 mChannel.push_back(elem);
56                 // use first value as default
57                 if(i==0) newvalue = elem;
58                 
59                 double t = 0.0; // similar to getAsFloat
60                 const char *str = mValue[i*(elemSize+1)+elemSize].c_str();
61                 char *endptr;
62                 t = strtod(str, &endptr);
63                 if((str!=endptr) && (*endptr != '\0')) return false;
64                 mTimes.push_back(t);
65                 //errMsg("ATTR"," t"<<t<<" "); // debug
66         }
67         for(int i=0; i<numElems-1; i++) {
68                 if(mTimes[i]>mTimes[i+1]) {
69                         errMsg("Attribute::initChannel","Invalid time at entry "<<i<<" setting to "<<mTimes[i]);
70                         mTimes[i+1] = mTimes[i];
71                 }
72         }
73
74         // dont change until done with parsing, and everythings ok
75         mValue = newvalue;
76
77         mChannelInited = elemSize;
78         if(DEBUG_CHANNELS) print();
79         return true;
80 }
81
82 // get value as string 
83 string Attribute::getAsString(bool debug)
84 {
85         if(mIsChannel && (!debug)) {
86                 errMsg("Attribute::getAsString", "Attribute \"" << mName << "\" used as string is a channel! Not allowed...");
87                 print();
88                 return string("");
89         }
90         if(mValue.size()!=1) {
91                 // for directories etc. , this might be valid! cutoff "..." first
92                 string comp = getCompleteString();
93                 if(comp.size()<2) return string("");
94                 return comp.substr(1, comp.size()-2);
95         }
96         return mValue[0];
97 }
98
99 // get value as integer value
100 int Attribute::getAsInt()
101 {
102         bool success = true;
103         int ret = 0;
104
105         if(!initChannel(1)) success=false; 
106         if(success) {
107                 if(mValue.size()!=1) success = false;
108                 else {
109                         const char *str = mValue[0].c_str();
110                         char *endptr;
111                         ret = strtol(str, &endptr, 10);
112                         if( (str==endptr) ||
113                                         ((str!=endptr) && (*endptr != '\0')) )success = false;
114                 }
115         }
116
117         if(!success) {
118                 errMsg("Attribute::getAsInt", "Attribute \"" << mName << "\" used as int has invalid value '"<< getCompleteString() <<"' ");
119                 errMsg("Attribute::getAsInt", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
120                 errMsg("Attribute::getAsInt", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
121 #if ELBEEM_PLUGIN!=1
122                 setElbeemState( -4 ); // parse error
123 #endif
124                 return 0;
125         }
126         return ret;
127 }
128
129
130 // get value as integer value
131 bool Attribute::getAsBool() 
132 {
133         int val = getAsInt();
134         if(val==0) return false;
135         else                     return true;
136 }
137
138
139 // get value as double value
140 double Attribute::getAsFloat()
141 {
142         bool success = true;
143         double ret = 0.0;
144
145         if(!initChannel(1)) success=false; 
146         if(success) {
147                 if(mValue.size()!=1) success = false;
148                 else {
149                         const char *str = mValue[0].c_str();
150                         char *endptr;
151                         ret = strtod(str, &endptr);
152                         if((str!=endptr) && (*endptr != '\0')) success = false;
153                 }
154         }
155
156         if(!success) {
157                 print();
158                 errMsg("Attribute::getAsFloat", "Attribute \"" << mName << "\" used as double has invalid value '"<< getCompleteString() <<"' ");
159                 errMsg("Attribute::getAsFloat", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
160                 errMsg("Attribute::getAsFloat", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
161 #if ELBEEM_PLUGIN!=1
162                 setElbeemState( -4 ); // parse error
163 #endif
164                 return 0.0;
165         }
166         return ret;
167 }
168
169 // get value as 3d vector 
170 ntlVec3d Attribute::getAsVec3d()
171 {
172         bool success = true;
173         ntlVec3d ret(0.0);
174
175         if(!initChannel(3)) success=false; 
176         if(success) {
177                 if(mValue.size()==1) {
178                         const char *str = mValue[0].c_str();
179                         char *endptr;
180                         double rval = strtod(str, &endptr);
181                         if( (str==endptr) ||
182                                         ((str!=endptr) && (*endptr != '\0')) )success = false;
183                         if(success) ret = ntlVec3d( rval );
184                 } else if(mValue.size()==3) {
185                         char *endptr;
186                         const char *str = NULL;
187
188                         str = mValue[0].c_str();
189                         double rval1 = strtod(str, &endptr);
190                         if( (str==endptr) ||
191                                         ((str!=endptr) && (*endptr != '\0')) )success = false;
192
193                         str = mValue[1].c_str();
194                         double rval2 = strtod(str, &endptr);
195                         if( (str==endptr) ||
196                                         ((str!=endptr) && (*endptr != '\0')) )success = false;
197
198                         str = mValue[2].c_str();
199                         double rval3 = strtod(str, &endptr);
200                         if( (str==endptr) ||
201                                         ((str!=endptr) && (*endptr != '\0')) )success = false;
202
203                         if(success) ret = ntlVec3d( rval1, rval2, rval3 );
204                 } else {
205                         success = false;
206                 }
207         }
208
209         if(!success) {
210                 errMsg("Attribute::getAsVec3d", "Attribute \"" << mName << "\" used as Vec3d has invalid value '"<< getCompleteString() <<"' ");
211                 errMsg("Attribute::getAsVec3d", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
212                 errMsg("Attribute::getAsVec3d", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
213 #if ELBEEM_PLUGIN!=1
214                 setElbeemState( -4 ); // parse error
215 #endif
216                 return ntlVec3d(0.0);
217         }
218         return ret;
219 }
220                 
221 // get value as 4x4 matrix 
222 void Attribute::getAsMat4Gfx(ntlMat4Gfx *mat)
223 {
224         bool success = true;
225         ntlMat4Gfx ret(0.0);
226         char *endptr;
227
228         if(mValue.size()==1) {
229                 const char *str = mValue[0].c_str();
230                 double rval = strtod(str, &endptr);
231                 if( (str==endptr) ||
232                                 ((str!=endptr) && (*endptr != '\0')) )success = false;
233                 if(success) {
234                         ret = ntlMat4Gfx( 0.0 );
235                         ret.value[0][0] = rval;
236                         ret.value[1][1] = rval;
237                         ret.value[2][2] = rval;
238                         ret.value[3][3] = 1.0;
239                 }
240         } else if(mValue.size()==9) {
241                 // 3x3
242                 for(int i=0; i<3;i++) {
243                         for(int j=0; j<3;j++) {
244                                 const char *str = mValue[i*3+j].c_str();
245                                 ret.value[i][j] = strtod(str, &endptr);
246                                 if( (str==endptr) ||
247                                                 ((str!=endptr) && (*endptr != '\0')) ) success = false;
248                         }
249                 }
250         } else if(mValue.size()==16) {
251                 // 4x4
252                 for(int i=0; i<4;i++) {
253                         for(int j=0; j<4;j++) {
254                                 const char *str = mValue[i*4+j].c_str();
255                                 ret.value[i][j] = strtod(str, &endptr);
256                                 if( (str==endptr) ||
257                                                 ((str!=endptr) && (*endptr != '\0')) ) success = false;
258                         }
259                 }
260
261         } else {
262                 success = false;
263         }
264
265         if(!success) {
266                 errMsg("Attribute::getAsMat4Gfx", "Attribute \"" << mName << "\" used as Mat4x4 has invalid value '"<< getCompleteString() <<"' ");
267                 errMsg("Attribute::getAsMat4Gfx", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
268                 errMsg("Attribute::getAsMat4Gfx", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
269 #if ELBEEM_PLUGIN!=1
270                 setElbeemState( -4 ); // parse error
271 #endif
272                 *mat = ntlMat4Gfx(0.0);
273                 return;
274         }
275         *mat = ret;
276 }
277                 
278
279 // get the concatenated string of all value string
280 string Attribute::getCompleteString()
281 {
282         string ret;
283         for(size_t i=0;i<mValue.size();i++) {
284                 ret += mValue[i];
285                 if(i<mValue.size()-1) ret += " ";
286         }
287         return ret;
288 }
289
290
291 /******************************************************************************
292  * channel returns
293  *****************************************************************************/
294
295 //! get channel as double value
296 AnimChannel<double> Attribute::getChannelFloat() {
297         vector<double> timeVec;
298         vector<double> valVec;
299         
300         if((!initChannel(1)) || (!mIsChannel)) {
301                 timeVec.push_back( 0.0 );
302                 valVec.push_back( getAsFloat() );
303         } else {
304         for(size_t i=0; i<mChannel.size(); i++) {
305                 mValue = mChannel[i];
306                 double val = getAsFloat();
307                 timeVec.push_back( mTimes[i] );
308                 valVec.push_back( val );
309         }}
310
311         return AnimChannel<double>(valVec,timeVec);
312 }
313
314 //! get channel as integer value
315 AnimChannel<int> Attribute::getChannelInt() { 
316         vector<double> timeVec;
317         vector<int> valVec;
318         
319         if((!initChannel(1)) || (!mIsChannel)) {
320                 timeVec.push_back( 0.0 );
321                 valVec.push_back( getAsInt() );
322         } else {
323         for(size_t i=0; i<mChannel.size(); i++) {
324                 mValue = mChannel[i];
325                 int val = getAsInt();
326                 timeVec.push_back( mTimes[i] );
327                 valVec.push_back( val );
328         }}
329
330         return AnimChannel<int>(valVec,timeVec);
331 }
332
333 //! get channel as integer value
334 AnimChannel<ntlVec3d> Attribute::getChannelVec3d() { 
335         vector<double> timeVec;
336         vector<ntlVec3d> valVec;
337         
338         if((!initChannel(3)) || (!mIsChannel)) {
339                 timeVec.push_back( 0.0 );
340                 valVec.push_back( getAsVec3d() );
341         } else {
342         for(size_t i=0; i<mChannel.size(); i++) {
343                 mValue = mChannel[i];
344                 ntlVec3d val = getAsVec3d();
345                 timeVec.push_back( mTimes[i] );
346                 valVec.push_back( val );
347         }}
348
349         return AnimChannel<ntlVec3d>(valVec,timeVec);
350 }
351
352 //! get channel as float vector set
353 AnimChannel<ntlSetVec3f> 
354 Attribute::getChannelSetVec3f() {
355         vector<double> timeVec;
356         ntlSetVec3f setv;
357         vector< ntlSetVec3f > valVec;
358         
359         if((!initChannel(3)) || (!mIsChannel)) {
360                 timeVec.push_back( 0.0 );
361                 setv.mVerts.push_back( vec2F( getAsVec3d() ) );
362                 valVec.push_back( setv );
363         } else {
364                 for(size_t i=0; i<mChannel.size(); i++) {
365                         mValue = mChannel[i];
366                         ntlVec3f val = vec2F( getAsVec3d() );
367                         timeVec.push_back( mTimes[i] );
368                         setv.mVerts.push_back( val );
369                 }
370                 valVec.push_back( setv );
371                 valVec.push_back( setv );
372         }
373
374         return AnimChannel<ntlSetVec3f>(valVec,timeVec);
375 }
376
377 /******************************************************************************
378  * check if there were unknown params
379  *****************************************************************************/
380 bool AttributeList::checkUnusedParams()
381 {
382         bool found = false;
383         for(map<string, Attribute*>::iterator i=mAttrs.begin();
384                         i != mAttrs.end(); i++) {
385                 if((*i).second) {
386                         if(!(*i).second->getUsed()) {
387                                 errMsg("AttributeList::checkUnusedParams", "List "<<mName<<" has unknown parameter '"<<(*i).first<<"' = '"<< mAttrs[(*i).first]->getAsString(true) <<"' ");
388                                 found = true;
389                         }
390                 }
391         }
392         return found;
393 }
394 //! set all params to used, for invisible objects
395 void AttributeList::setAllUsed() {
396         for(map<string, Attribute*>::iterator i=mAttrs.begin();
397                         i != mAttrs.end(); i++) {
398                 if((*i).second) {
399                         (*i).second->setUsed(true);
400                 }
401         }
402 }
403
404 /******************************************************************************
405  * Attribute list read functions
406  *****************************************************************************/
407 int AttributeList::readInt(string name, int defaultValue, string source,string target, bool needed) {
408         if(!exists(name)) {
409                 if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<"  not set! ", SIMWORLD_INITERROR); }
410                 return defaultValue;
411         } 
412         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
413         find(name)->setUsed(true);
414         return find(name)->getAsInt(); 
415 }
416 bool AttributeList::readBool(string name, bool defaultValue, string source,string target, bool needed) {
417         if(!exists(name)) {
418                 if(needed) { errFatal("AttributeList::readBool","Required attribute '"<<name<<"' for "<< source <<"  not set! ", SIMWORLD_INITERROR); }
419                 return defaultValue;
420         } 
421         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
422         find(name)->setUsed(true);
423         return find(name)->getAsBool(); 
424 }
425 double AttributeList::readFloat(string name, double defaultValue, string source,string target, bool needed) {
426         if(!exists(name)) {
427                 if(needed) { errFatal("AttributeList::readFloat","Required attribute '"<<name<<"' for "<< source <<"  not set! ", SIMWORLD_INITERROR); }
428                 return defaultValue;
429         } 
430         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
431         find(name)->setUsed(true);
432         return find(name)->getAsFloat(); 
433 }
434 string AttributeList::readString(string name, string defaultValue, string source,string target, bool needed) {
435         if(!exists(name)) {
436                 if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<"  not set! ", SIMWORLD_INITERROR); }
437                 return defaultValue;
438         } 
439         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
440         find(name)->setUsed(true);
441         return find(name)->getAsString(false); 
442 }
443 ntlVec3d AttributeList::readVec3d(string name, ntlVec3d defaultValue, string source,string target, bool needed) {
444         if(!exists(name)) {
445                 if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<"  not set! ", SIMWORLD_INITERROR); }
446                 return defaultValue;
447         } 
448         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
449         find(name)->setUsed(true);
450         return find(name)->getAsVec3d(); 
451 }
452
453 void AttributeList::readMat4Gfx(string name, ntlMat4Gfx defaultValue, string source,string target, bool needed, ntlMat4Gfx *mat) {
454         if(!exists(name)) {
455                 if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<"  not set! ", SIMWORLD_INITERROR); }
456                 *mat = defaultValue;
457                 return;
458         } 
459         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
460         find(name)->setUsed(true);
461         find(name)->getAsMat4Gfx( mat ); 
462         return;
463 }
464
465 // set that a parameter can be given, and will be ignored...
466 bool AttributeList::ignoreParameter(string name, string source) {
467         if(!exists(name)) return false;
468         find(name)->setUsed(true);
469         if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Param '"<< name <<"' set but ignored... " , 3); }
470         return true;
471 }
472                 
473 // read channels
474 AnimChannel<int> AttributeList::readChannelInt(string name, int defaultValue, string source, string target, bool needed) {
475         if(!exists(name)) { return AnimChannel<int>(defaultValue); } 
476         AnimChannel<int> ret = find(name)->getChannelInt(); 
477         find(name)->setUsed(true);
478         channelSimplifyi(ret);
479         return ret;
480 }
481 AnimChannel<double> AttributeList::readChannelFloat(string name, double defaultValue, string source, string target, bool needed ) {
482         if(!exists(name)) { return AnimChannel<double>(defaultValue); } 
483         AnimChannel<double> ret = find(name)->getChannelFloat(); 
484         find(name)->setUsed(true);
485         channelSimplifyd(ret);
486         return ret;
487 }
488 AnimChannel<ntlVec3d> AttributeList::readChannelVec3d(string name, ntlVec3d defaultValue, string source, string target, bool needed ) {
489         if(!exists(name)) { return AnimChannel<ntlVec3d>(defaultValue); } 
490         AnimChannel<ntlVec3d> ret = find(name)->getChannelVec3d(); 
491         find(name)->setUsed(true);
492         channelSimplifyVd(ret);
493         return ret;
494 }
495 AnimChannel<ntlSetVec3f> AttributeList::readChannelSetVec3f(string name, ntlSetVec3f defaultValue, string source, string target, bool needed) {
496         if(!exists(name)) { return AnimChannel<ntlSetVec3f>(defaultValue); } 
497         AnimChannel<ntlSetVec3f> ret = find(name)->getChannelSetVec3f(); 
498         find(name)->setUsed(true);
499         //channelSimplifyVf(ret);
500         return ret;
501 }
502 AnimChannel<float> AttributeList::readChannelSinglePrecFloat(string name, float defaultValue, string source, string target, bool needed ) {
503         if(!exists(name)) { return AnimChannel<float>(defaultValue); } 
504         AnimChannel<double> convert = find(name)->getChannelFloat(); 
505         find(name)->setUsed(true);
506         channelSimplifyd(convert);
507         // convert to float vals
508         vector<float> vals;
509         for(size_t i=0; i<convert.accessValues().size(); i++) {
510                 vals.push_back( (float)(convert.accessValues()[i]) );
511         }
512         vector<double> times = convert.accessTimes();
513         AnimChannel<float> ret(vals, times);
514         return ret;
515 }
516 AnimChannel<ntlVec3f> AttributeList::readChannelVec3f(string name, ntlVec3f defaultValue, string source, string target, bool needed) {
517         if(!exists(name)) { return AnimChannel<ntlVec3f>(defaultValue); } 
518
519         AnimChannel<ntlVec3d> convert = find(name)->getChannelVec3d(); 
520         // convert to float
521         vector<ntlVec3f> vals;
522         for(size_t i=0; i<convert.accessValues().size(); i++) {
523                 vals.push_back( vec2F(convert.accessValues()[i]) );
524         }
525         vector<double> times = convert.accessTimes();
526         AnimChannel<ntlVec3f> ret(vals, times);
527         find(name)->setUsed(true);
528         channelSimplifyVf(ret);
529         return ret;
530 }
531
532 /******************************************************************************
533  * destructor
534  *****************************************************************************/
535 AttributeList::~AttributeList() { 
536         for(map<string, Attribute*>::iterator i=mAttrs.begin();
537                         i != mAttrs.end(); i++) {
538                 if((*i).second) {
539                         delete (*i).second;
540                         (*i).second = NULL;
541                 }
542         }
543 };
544
545
546 /******************************************************************************
547  * debugging
548  *****************************************************************************/
549
550 //! debug function, prints value 
551 void Attribute::print()
552 {
553         std::ostringstream ostr;
554         ostr << "ATTR "<< mName <<"= ";
555         for(size_t i=0;i<mValue.size();i++) {
556                 ostr <<"'"<< mValue[i]<<"' ";
557         }
558         if(mIsChannel) {
559                 ostr << " CHANNEL: ";
560                 if(mChannelInited>0) {
561                 for(size_t i=0;i<mChannel.size();i++) {
562                         for(size_t j=0;j<mChannel[i].size();j++) {
563                                 ostr <<"'"<< mChannel[i][j]<<"' ";
564                         }
565                         ostr << "@"<<mTimes[i]<<"; ";
566                 }
567                 } else {
568                         ostr <<" -nyi- ";
569                 }                       
570         }
571         ostr <<" (at line "<<mLine<<") "; //<< std::endl;
572         debugOut( ostr.str(), 10);
573 }
574                 
575 //! debug function, prints all attribs 
576 void AttributeList::print()
577 {
578         debugOut("Attribute "<<mName<<" values:", 10);
579         for(map<string, Attribute*>::iterator i=mAttrs.begin();
580                         i != mAttrs.end(); i++) {
581                 if((*i).second) {
582                         (*i).second->print();
583                 }
584         }
585 }
586
587
588 /******************************************************************************
589  * import attributes from other attribute list
590  *****************************************************************************/
591 void AttributeList::import(AttributeList *oal)
592 {
593         for(map<string, Attribute*>::iterator i=oal->mAttrs.begin();
594                         i !=oal->mAttrs.end(); i++) {
595                 // FIXME - check freeing of copyied attributes
596                 if((*i).second) {
597                         Attribute *newAttr = new Attribute( *(*i).second );
598                         mAttrs[ (*i).first ] = newAttr;
599                 }
600         }
601 }
602
603
604 /******************************************************************************
605  * channel max finding
606  *****************************************************************************/
607 ntlVec3f channelFindMaxVf (AnimChannel<ntlVec3f> channel) {
608         ntlVec3f ret(0.0);
609         float maxLen = 0.0;
610         for(size_t i=0; i<channel.accessValues().size(); i++) {
611                 float nlen = normNoSqrt(channel.accessValues()[i]);
612                 if(nlen>maxLen) { ret=channel.accessValues()[i]; maxLen=nlen; }
613         }
614         return ret;
615 }
616 ntlVec3d channelFindMaxVd (AnimChannel<ntlVec3d> channel) {
617         ntlVec3d ret(0.0);
618         float maxLen = 0.0;
619         for(size_t i=0; i<channel.accessValues().size(); i++) {
620                 float nlen = normNoSqrt(channel.accessValues()[i]);
621                 if(nlen>maxLen) { ret=channel.accessValues()[i]; maxLen=nlen; }
622         }
623         return ret;
624 }
625 int      channelFindMaxi  (AnimChannel<float   > channel) {
626         int ret = 0;
627         float maxLen = 0.0;
628         for(size_t i=0; i<channel.accessValues().size(); i++) {
629                 float nlen = ABS(channel.accessValues()[i]);
630                 if(nlen>maxLen) { ret= (int)channel.accessValues()[i]; maxLen=nlen; }
631         }
632         return ret;
633 }
634 float    channelFindMaxf  (AnimChannel<float   > channel) {
635         float ret = 0.0;
636         float maxLen = 0.0;
637         for(size_t i=0; i<channel.accessValues().size(); i++) {
638                 float nlen = ABS(channel.accessValues()[i]);
639                 if(nlen>maxLen) { ret=channel.accessValues()[i]; maxLen=nlen; }
640         }
641         return ret;
642 }
643 double   channelFindMaxd  (AnimChannel<double  > channel) {
644         double ret = 0.0;
645         float maxLen = 0.0;
646         for(size_t i=0; i<channel.accessValues().size(); i++) {
647                 float nlen = ABS(channel.accessValues()[i]);
648                 if(nlen>maxLen) { ret=channel.accessValues()[i]; maxLen=nlen; }
649         }
650         return ret;
651 }
652
653 /******************************************************************************
654  // unoptimized channel simplification functions, use elbeem.cpp functions
655  // warning - currently only with single precision
656  *****************************************************************************/
657
658 template<class SCALAR>
659 static bool channelSimplifyScalarT(AnimChannel<SCALAR> &channel) {
660         int   size = channel.getSize();
661         if(size<=1) return false;
662         float *nchannel = new float[2*size];
663         if(DEBUG_CHANNELS) errMsg("channelSimplifyf","S" << channel.printChannel() );
664         // convert to array
665         for(size_t i=0; i<channel.accessValues().size(); i++) {
666                 nchannel[i*2 + 0] = (float)channel.accessValues()[i];
667                 nchannel[i*2 + 1] = (float)channel.accessTimes()[i];
668         }
669         bool ret = elbeemSimplifyChannelFloat(nchannel, &size);
670         if(ret) {
671                 vector<SCALAR> vals;
672                 vector<double> times;
673                 for(int i=0; i<size; i++) {
674                         vals.push_back(  (SCALAR)(nchannel[i*2 + 0]) );
675                         times.push_back( (double)(nchannel[i*2 + 1]) );
676                 }
677                 channel = AnimChannel<SCALAR>(vals, times);
678                 if(DEBUG_CHANNELS) errMsg("channelSimplifyf","C" << channel.printChannel() );
679         }
680         delete [] nchannel;
681         return ret;
682 }
683 bool channelSimplifyi  (AnimChannel<int   > &channel) { return channelSimplifyScalarT<int>(channel); }
684 bool channelSimplifyf  (AnimChannel<float> &channel) { return channelSimplifyScalarT<float>(channel); }
685 bool channelSimplifyd  (AnimChannel<double  > &channel) { return channelSimplifyScalarT<double>(channel); }
686 template<class VEC>
687 static bool channelSimplifyVecT(AnimChannel<VEC> &channel) {
688         int   size = channel.getSize();
689         if(size<=1) return false;
690         float *nchannel = new float[4*size];
691         if(DEBUG_CHANNELS) errMsg("channelSimplifyf","S" << channel.printChannel() );
692         // convert to array
693         for(size_t i=0; i<channel.accessValues().size(); i++) {
694                 nchannel[i*4 + 0] = (float)channel.accessValues()[i][0];
695                 nchannel[i*4 + 1] = (float)channel.accessValues()[i][1];
696                 nchannel[i*4 + 2] = (float)channel.accessValues()[i][2];
697                 nchannel[i*4 + 3] = (float)channel.accessTimes()[i];
698         }
699         bool ret = elbeemSimplifyChannelVec3(nchannel, &size);
700         if(ret) {
701                 vector<VEC> vals;
702                 vector<double> times;
703                 for(int i=0; i<size; i++) {
704                         vals.push_back(  VEC(nchannel[i*4 + 0], nchannel[i*4 + 1], nchannel[i*4 + 2] ) );
705                         times.push_back( (double)(nchannel[i*4 + 3]) );
706                 }
707                 channel = AnimChannel<VEC>(vals, times);
708                 if(DEBUG_CHANNELS) errMsg("channelSimplifyf","C" << channel.printChannel() );
709         }
710         delete [] nchannel;
711         return ret;
712 }
713 bool channelSimplifyVf (AnimChannel<ntlVec3f> &channel) {
714         return channelSimplifyVecT<ntlVec3f>(channel);
715 }
716 bool channelSimplifyVd (AnimChannel<ntlVec3d> &channel) {
717         return channelSimplifyVecT<ntlVec3d>(channel);
718 }
719
720 //! debug function, prints channel as string
721 template<class Scalar>
722 string AnimChannel<Scalar>::printChannel() {
723         std::ostringstream ostr;
724         ostr << " CHANNEL #"<<  mValue.size() <<" = { ";
725         for(size_t i=0;i<mValue.size();i++) {
726                 ostr <<"'"<< mValue[i]<<"' ";
727                 ostr << "@"<<mTimes[i]<<"; ";
728         }
729         ostr << " } ";
730         return ostr.str();
731 } // */
732
733 //! debug function, prints to stdout if DEBUG_CHANNELS flag is enabled, used in constructors
734 template<class Scalar>
735 void AnimChannel<Scalar>::debugPrintChannel() {
736         if(DEBUG_CHANNELS) { errMsg("channelCons"," : " << this->printChannel() ); }
737 }
738
739
740 ntlSetVec3f::ntlSetVec3f(double v ) {
741         mVerts.clear();
742         mVerts.push_back( ntlVec3f(v) );
743 }
744 const ntlSetVec3f& 
745 ntlSetVec3f::operator=(double v ) {
746         mVerts.clear();
747         mVerts.push_back( ntlVec3f(v) );
748         return *this;
749 }
750
751 std::ostream& operator<<( std::ostream& os, const ntlSetVec3f& vs ) {
752         os<< "{";
753         for(int j=0;j<(int)vs.mVerts.size();j++)  os<<vs.mVerts[j];
754         os<< "}";
755   return os;
756 }
757
758 ntlSetVec3f& 
759 ntlSetVec3f::operator+=( double v )
760 {
761         for(int j=0;j<(int)(mVerts.size()) ;j++) {
762                 mVerts[j] += v;
763         }
764         return *this;
765 }
766
767 ntlSetVec3f& 
768 ntlSetVec3f::operator+=( const ntlSetVec3f &v )
769 {
770         for(int j=0;j<(int)MIN(mVerts.size(),v.mVerts.size()) ;j++) {
771                 mVerts[j] += v.mVerts[j];
772         }
773         return *this;
774 }
775
776 ntlSetVec3f& 
777 ntlSetVec3f::operator*=( double v )
778 {
779         for(int j=0;j<(int)(mVerts.size()) ;j++) {
780                 mVerts[j] *= v;
781         }
782         return *this;
783 }
784
785 ntlSetVec3f& 
786 ntlSetVec3f::operator*=( const ntlSetVec3f &v )
787 {
788         for(int j=0;j<(int)MIN(mVerts.size(),v.mVerts.size()) ;j++) {
789                 mVerts[j] *= v.mVerts[j];
790         }
791         return *this;
792 }
793
794