1 /* system headers */
2 #include <fstream>
3 #include <iostream>
4 #include <string>
5 #include <sstream>
6 #include <stack>
7 #include <vector>
8 #include <math.h>
9 #include <string.h>
10 
11 typedef int foo;
12 
13 #ifndef PI
14 #  define PI (3.1415926535897932384626433832795f)
15 #endif
16 #ifndef TWO_PI
17 #  define TWO_PI (2.0f*PI)
18 #endif
19 
20 
21 class Matrix3D
22 {
23 public:
Matrix3D()24     Matrix3D()
25     {
26         makeIdentity();
27     }
28 
operator [](int index)29     float *operator[]( int index )
30     {
31         if ((index < 0) || (index >= 4))
32             throw std::exception();
33 
34         return matrix[index];
35     }
36 
makeIdentity()37     void makeIdentity()
38     {
39         memset( matrix, 0, sizeof( float ) * 4 * 4 );
40         for (int i = 0; i < 4; i++)
41             matrix[i][i] = 1.0f;
42     }
43 
makeScale(float scaleX,float scaleY,float scaleZ)44     void makeScale( float scaleX, float scaleY, float scaleZ )
45     {
46         makeIdentity();
47         matrix[0][0] = scaleX;
48         matrix[1][1] = scaleY;
49         matrix[2][2] = scaleZ;
50 
51     }
52 
makeRotationZ(float angle)53     void makeRotationZ( float angle )
54     {
55         makeIdentity();
56         matrix[0][0] = (float)cos(angle);
57         matrix[0][1] = (float)-sin(angle);
58         matrix[1][0] = (float)sin(angle);
59         matrix[1][1] = (float)cos(angle);
60     }
61 
makeTranslation(float xPos,float yPos,float zPos)62     void makeTranslation( float xPos, float yPos, float zPos )
63     {
64         makeIdentity();
65         matrix[0][3] = (float)xPos;
66         matrix[1][3] = (float)yPos;
67         matrix[2][3] = (float)zPos;
68     }
69 
postMultiply(Matrix3D & inMatrix)70     void postMultiply( Matrix3D &inMatrix )
71     {
72         // this = this * matrix
73 
74         float src[4][4];
75         memcpy( src, matrix, sizeof(float)*4*4 );
76 
77         for (int y = 0; y < 4; y++)
78         {
79             for (int x = 0; x < 4; x++)
80             {
81                 matrix[x][y] =  src[0][y]*inMatrix.matrix[x][0] +
82                                 src[1][y]*inMatrix.matrix[x][1] +
83                                 src[2][y]*inMatrix.matrix[x][2] +
84                                 src[3][y]*inMatrix.matrix[x][3];
85             }
86         }
87 
88     }
89 
preMultiply(Matrix3D & inMatrix)90     void preMultiply( Matrix3D &inMatrix )
91     {
92         // this = matrix * this
93 
94         float src[4][4];
95         memcpy( src, matrix, sizeof(float)*4*4 );
96 
97         for (int y = 0; y < 4; y++)
98         {
99             for (int x = 0; x < 4; x++)
100             {
101                 matrix[x][y] =  inMatrix.matrix[0][y]*src[x][0] +
102                                 inMatrix.matrix[1][y]*src[x][1] +
103                                 inMatrix.matrix[2][y]*src[x][2] +
104                                 inMatrix.matrix[3][y]*src[x][3];
105             }
106         }
107     }
108 private:
109     float matrix[4][4];
110     friend class Point3D;
111 };
112 
113 class Point3D
114 {
115 public:
Point3D()116     Point3D()
117     {
118         memset( points, 0, sizeof(float)*4 );
119         points[3] = 1.0f;
120     }
121 
Point3D(float x,float y,float z)122     Point3D( float x, float y, float z )
123     {
124         setValue( x, y, z );
125     }
126 
setValue(float x,float y,float z)127     void setValue( float x, float y, float z )
128     {
129         points[0] = x;
130         points[1] = y;
131         points[2] = z;
132         points[3] = 1.0f;
133     }
134 
operator [](int index) const135     float operator[]( int index ) const
136     {
137         if ((index < 0) || (index >= 4))
138             throw std::exception();
139 
140         return points[index];
141     }
142 
transform(Matrix3D & matrix)143     void transform( Matrix3D &matrix )
144     {
145         float src[4];
146         memcpy( src, points, sizeof(float)*4 );
147 
148         for (int x = 0; x < 4; x++)
149         {
150             points[x] = 0.0;
151             for (int y = 0; y < 4; y++)
152                 points[x] += src[y] * matrix.matrix[x][y];
153         }
154 
155     }
156 
157 private:
158     float points[4];
159 };
160 
161 class BZObject
162 {
163 public:
BZObject(std::string _type,float * _position,float * _size,float _rotation)164     BZObject( std::string _type, float *_position, float *_size, float _rotation )
165     {
166         this->type = _type;
167         this->position.setValue( _position[0], _position[1], _position[2] );
168         this->size.setValue( _size[0], _size[1], _size[2] );
169         this->rotation = _rotation;
170     }
171 
isBox()172     bool isBox()
173     {
174         return type == "box";
175     }
176 public:
177 
178     std::string   type;
179     Point3D position;
180     Point3D size;
181     float   rotation;
182 };
183 
184 
box(std::ofstream & bzw,Point3D & position,Point3D & size,float rotation,char * comment=NULL)185 void box( std::ofstream &bzw, Point3D &position, Point3D &size, float rotation, char *comment = NULL )
186 {
187     if (comment != NULL)
188         bzw << "#" << comment << std::endl;
189     bzw << "box" << std::endl;
190     bzw << "position " << position[0] << " " << position[1] << " " << position[2] << std::endl;
191     bzw << "size " << size[0] << " " << size[1] << " " << size[2] << std::endl;
192     bzw << "rotation " << rotation << std::endl;
193     bzw << "end" << std::endl;
194     bzw << std::endl;
195 }
196 
pyramid(std::ofstream & bzw,Point3D & position,Point3D & size,float rotation,char * comment=NULL)197 void pyramid( std::ofstream &bzw, Point3D &position, Point3D &size, float rotation, char *comment = NULL )
198 {
199     if (comment != NULL)
200         bzw << "#" << comment << std::endl;
201     bzw << "pyramid" << std::endl;
202     bzw << "position " << position[0] << " " << position[1] << " " << position[2] << std::endl;
203     bzw << "size " << size[0] << " " << size[1] << " " << size[2] << std::endl;
204     bzw << "rotation " << rotation << std::endl;
205     bzw << "end" << std::endl;
206     bzw << std::endl;
207 }
208 
generateObjects(std::ofstream & bzw,std::vector<BZObject * > objects,Matrix3D & posMatrix,Matrix3D & sizeMatrix,float rotation,int count)209 void generateObjects( std::ofstream &bzw, std::vector<BZObject *> objects, Matrix3D &posMatrix, Matrix3D &sizeMatrix,
210                       float rotation, int count )
211 {
212     for (int cur = 0; cur < count; cur++)
213     {
214         for (std::vector<BZObject*>::iterator it = objects.begin(); it != objects.end(); it++)
215         {
216             BZObject *object = *it;
217             if (object->isBox())
218                 box( bzw, object->position, object->size, object->rotation );
219             else
220                 pyramid( bzw, object->position, object->size, object->rotation );
221 
222             object->position.transform( posMatrix );
223             object->size.transform( sizeMatrix );
224             object->rotation += rotation;
225         }
226     }
227 }
228 
229 
230 
parsebzwt(std::ifstream & bzwt,std::ofstream & bzw)231 void parsebzwt( std::ifstream &bzwt, std::ofstream &bzw )
232 {
233     enum { FREE, IN_TRANSFORM, IN_BOX, IN_PYRAMID, IN_MATRIX, IN_POSITION0, IN_POSITION1, IN_POSITION2, IN_SIZE0, IN_SIZE1, IN_SIZE2, IN_ROTATION,
234            IN_MATRIX_POSITION, IN_MATRIX_SIZE, IN_MATRIX_ROTATION, IN_ANGLE, IN_SCALE0, IN_SCALE1, IN_SCALE2, IN_TRANSLATE0, IN_TRANSLATE1, IN_TRANSLATE2, IN_COUNT
235          };
236     std::stack<int> stateStack;
237     std::string line, token;
238     int lineNo = 0;
239     int state = FREE;
240     float position[4];
241     float size[4];
242     float scale[4] = {0,0,0,0};
243     float translate[4] = {0,0,0,0};
244     float angle;
245 
246     std::vector<BZObject *> objects;
247     Matrix3D posMatrix, sizeMatrix, tempMatrix;
248     float rotation = 0.0f;
249     int   count = 0;
250 
251     try
252     {
253         while (!bzwt.eof())
254         {
255             getline( bzwt, line );
256             lineNo++;
257 
258             if (line.length() == 0) continue;
259             std::string::size_type start = line.find_first_not_of( " \t\n\r" );
260             if (start == std::string::npos) continue;
261             if (line.at(start) == '#') continue;
262 
263             std::istringstream lineStream( line.c_str() );
264 
265             while (!lineStream.eof())
266             {
267                 lineStream >> token;
268                 if (token.length() == 0)
269                     break;
270 
271                 switch (state)
272                 {
273                 case FREE:
274                     if (token == "transform")
275                     {
276                         state = IN_TRANSFORM;
277                         posMatrix.makeIdentity();
278                         sizeMatrix.makeIdentity();
279                         count = 1;
280                         rotation = 0.0f;
281                         for (unsigned int i = 0; i < objects.size(); i++)
282                             delete objects[i];
283                         objects.clear();
284                     }
285                     else
286                         throw "expecting transform";
287                     break;
288 
289                 case IN_TRANSFORM:
290                     memset( position, 0, sizeof(float)*4 );
291                     memset( size, 0, sizeof(float)*4 );
292 
293                     if (token == "box")
294                         state = IN_BOX;
295                     else if (token == "pyramid")
296                         state = IN_PYRAMID;
297                     else if (token == "matrix")
298                         state = IN_MATRIX;
299                     else if (token == "count")
300                         state = IN_COUNT;
301                     else if (token == "end")
302                     {
303                         generateObjects( bzw, objects, posMatrix, sizeMatrix, rotation, count );
304                         state = FREE;
305                     }
306                     else
307                         throw "expecting transform subitem, or end";
308                     break;
309 
310                 case IN_BOX:
311                     if (token == "position")
312                     {
313                         state = IN_POSITION0;
314                         stateStack.push( IN_BOX );
315                     }
316                     else if (token == "size")
317                     {
318                         state = IN_SIZE0;
319                         stateStack.push( IN_BOX );
320                     }
321                     else if (token == "rotation")
322                     {
323                         state = IN_ROTATION;
324                         stateStack.push( IN_BOX );
325                     }
326                     else if (token == "end")
327                     {
328                         BZObject *obj = new BZObject( std::string("box"), position, size, rotation );
329                         objects.push_back( obj );
330                         state = IN_TRANSFORM;
331                         memset( position, 0, sizeof(float)*4 );
332                         memset( size, 0, sizeof(float)*4 );
333                         rotation = 0.0f;
334                     }
335                     else
336                         throw "expecting transform subitem, or end";
337                     break;
338 
339                 case IN_PYRAMID:
340                     if (token == "position")
341                     {
342                         state = IN_POSITION0;
343                         stateStack.push( IN_PYRAMID );
344                     }
345                     else if (token == "size")
346                     {
347                         state = IN_SIZE0;
348                         stateStack.push( IN_PYRAMID );
349                     }
350                     else if (token == "rotation")
351                     {
352                         state = IN_ROTATION;
353                         stateStack.push( IN_PYRAMID );
354                     }
355                     else if (token == "end")
356                     {
357                         state = IN_TRANSFORM;
358                         BZObject *obj = new BZObject( std::string("pyramid"), position, size, rotation );
359                         objects.push_back( obj );
360                         state = IN_TRANSFORM;
361                         memset( position, 0, sizeof(float)*4 );
362                         memset( size, 0, sizeof(float)*4 );
363                         rotation = 0.0f;
364                     }
365                     else
366                         throw "expecting transform subitem, or end";
367                     break;
368 
369                 case IN_MATRIX:
370                     if (token == "position")
371                         state = IN_MATRIX_POSITION;
372                     else if (token == "size")
373                         state = IN_MATRIX_SIZE;
374                     else if (token == "rotation")
375                         state = IN_MATRIX_ROTATION;
376                     else if (token == "end")
377                         state = IN_TRANSFORM;
378                     else
379                         throw "expecting transform matrix subitem, or end";
380                     break;
381 
382                 case IN_COUNT:
383                     count = atoi( token.c_str( ));
384                     state = IN_TRANSFORM;
385                     break;
386 
387 
388                 case IN_POSITION0:
389                     position[0] = (float)atof(token.c_str());
390                     state = IN_POSITION1;
391                     break;
392 
393                 case IN_POSITION1:
394                     position[1] = (float)atof(token.c_str());
395                     state = IN_POSITION2;
396                     break;
397 
398                 case IN_POSITION2:
399                     position[2] = (float)atof(token.c_str());
400                     state = stateStack.top();
401                     stateStack.pop();
402                     break;
403 
404 
405                 case IN_SIZE0:
406                     size[0] = (float)atof(token.c_str());
407                     state = IN_SIZE1;
408                     break;
409 
410                 case IN_SIZE1:
411                     size[1] = (float)atof(token.c_str());
412                     state = IN_SIZE2;
413                     break;
414 
415                 case IN_SIZE2:
416                     size[2] = (float)atof(token.c_str());
417                     state = stateStack.top();
418                     stateStack.pop();
419                     break;
420 
421                 case IN_ROTATION:
422                     rotation = (float)atof(token.c_str());
423                     state = stateStack.top();
424                     stateStack.pop();
425                     break;
426 
427                 case IN_MATRIX_POSITION:
428                     if (token == "rotate")
429                     {
430                         stateStack.push( IN_MATRIX_POSITION );
431                         state = IN_ANGLE;
432                     }
433                     else if (token == "scale")
434                     {
435                         stateStack.push( IN_MATRIX_POSITION );
436                         state = IN_SCALE0;
437                     }
438                     else if (token == "translate")
439                     {
440                         stateStack.push( IN_MATRIX_POSITION );
441                         state = IN_TRANSLATE0;
442                     }
443                     else if (token == "end")
444                         state = IN_MATRIX;
445                     else
446                         throw "expecting a matrix operation, or end";
447                     break;
448 
449                 case IN_MATRIX_SIZE:
450                     if (token == "rotate")
451                     {
452                         stateStack.push( IN_MATRIX_SIZE );
453                         state = IN_ANGLE;
454                     }
455                     else if (token == "scale")
456                     {
457                         stateStack.push( IN_MATRIX_SIZE );
458                         state = IN_SCALE0;
459                     }
460                     else if (token == "translate")
461                     {
462                         stateStack.push( IN_MATRIX_SIZE );
463                         state = IN_TRANSLATE0;
464                     }
465                     else if (token == "end")
466                         state = IN_MATRIX;
467                     else
468                         throw "expecting a matrix operation, or end";
469                     break;
470 
471                 case IN_MATRIX_ROTATION:
472                     rotation = (float)atof( token.c_str( ));
473                     state = IN_MATRIX;
474                     break;
475 
476                 case IN_ANGLE:
477                     angle = (float)atof( token.c_str( ));
478                     state = stateStack.top();
479                     stateStack.pop();
480                     tempMatrix.makeRotationZ( (float)((angle * TWO_PI) / 360.0f) );
481                     if (state == IN_MATRIX_POSITION)
482                         posMatrix.postMultiply( tempMatrix );
483                     else if (state == IN_MATRIX_SIZE)
484                         sizeMatrix.postMultiply( tempMatrix );
485                     break;
486 
487                 case IN_SCALE0:
488                     scale[0] = (float)atof( token.c_str( ));
489                     state = IN_SCALE1;
490                     break;
491 
492                 case IN_SCALE1:
493                     scale[1] = (float)atof( token.c_str( ));
494                     state = IN_SCALE2;
495                     break;
496 
497                 case IN_SCALE2:
498                     scale[2] = (float)atof( token.c_str( ));
499                     state = stateStack.top();
500                     stateStack.pop();
501                     tempMatrix.makeScale( scale[0], scale[1], scale[2] );
502                     if (state == IN_MATRIX_POSITION)
503                         posMatrix.postMultiply( tempMatrix );
504                     else if (state == IN_MATRIX_SIZE)
505                         sizeMatrix.postMultiply( tempMatrix );
506                     break;
507 
508                 case IN_TRANSLATE0:
509                     translate[0] = (float)atof( token.c_str( ));
510                     state = IN_TRANSLATE1;
511                     break;
512 
513                 case IN_TRANSLATE1:
514                     translate[1] = (float)atof( token.c_str( ));
515                     state = IN_TRANSLATE2;
516                     break;
517 
518                 case IN_TRANSLATE2:
519                     translate[2] = (float)atof( token.c_str( ));
520                     state = stateStack.top();
521                     stateStack.pop();
522                     tempMatrix.makeTranslation( translate[0], translate[1], translate[2] );
523                     if (state == IN_MATRIX_POSITION)
524                         posMatrix.postMultiply( tempMatrix );
525                     else if (state == IN_MATRIX_SIZE)
526                         sizeMatrix.postMultiply( tempMatrix );
527                     break;
528 
529 
530                 default:
531                     throw "UnHandled state";
532                     break;
533 
534                 }
535             }
536         }
537     }
538     catch (std::exception &e)
539     {
540         std::cerr << "Parse error: line: " << lineNo << " " << e.what() << std::endl;
541         std::cerr << line << std::endl;
542     }
543 
544 }
545 
main(int argc,char ** argv)546 int main( int argc, char **argv )
547 {
548     if (argc != 3)
549     {
550         std::cout << "error invalid arguments" << std::endl;
551         std::cout << "\tbzwTransform inputName outputName" << std::endl;
552         return -1;
553     }
554 
555     std::ifstream bzwt( argv[1] );
556 
557     if (bzwt.is_open())
558     {
559         std::ofstream bzw( argv[2] );
560         if (bzw.is_open())
561             parsebzwt( bzwt, bzw );
562 
563         bzwt.close();
564     }
565 
566 
567     return 0;
568 }
569 
570 
571 // Local Variables: ***
572 // mode: C++ ***
573 // tab-width: 4 ***
574 // c-basic-offset: 4 ***
575 // indent-tabs-mode: nil ***
576 // End: ***
577 // ex: shiftwidth=4 tabstop=4
578