~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/bullet/Extras/ConvexDecomposition/cd_wavefront.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
#include <stdlib.h>
 
3
#include <string.h>
 
4
#include <assert.h>
 
5
#include <ctype.h>
 
6
 
 
7
/*----------------------------------------------------------------------
 
8
                Copyright (c) 2004 Open Dynamics Framework Group
 
9
                                        www.physicstools.org
 
10
                All rights reserved.
 
11
 
 
12
                Redistribution and use in source and binary forms, with or without modification, are permitted provided
 
13
                that the following conditions are met:
 
14
 
 
15
                Redistributions of source code must retain the above copyright notice, this list of conditions
 
16
                and the following disclaimer.
 
17
 
 
18
                Redistributions in binary form must reproduce the above copyright notice,
 
19
                this list of conditions and the following disclaimer in the documentation
 
20
                and/or other materials provided with the distribution.
 
21
 
 
22
                Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
 
23
                be used to endorse or promote products derived from this software without specific prior written permission.
 
24
 
 
25
                THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 
26
                INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
27
                DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
28
                EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
29
                LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 
30
                IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
31
                THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
32
-----------------------------------------------------------------------*/
 
33
 
 
34
// http://codesuppository.blogspot.com
 
35
//
 
36
// mailto: jratcliff@infiniplex.net
 
37
//
 
38
// http://www.amillionpixels.us
 
39
//
 
40
#include "float_math.h"
 
41
 
 
42
#include "cd_wavefront.h"
 
43
 
 
44
 
 
45
using namespace ConvexDecomposition;
 
46
 
 
47
/*----------------------------------------------------------------------
 
48
                Copyright (c) 2004 Open Dynamics Framework Group
 
49
                                        www.physicstools.org
 
50
                All rights reserved.
 
51
 
 
52
                Redistribution and use in source and binary forms, with or without modification, are permitted provided
 
53
                that the following conditions are met:
 
54
 
 
55
                Redistributions of source code must retain the above copyright notice, this list of conditions
 
56
                and the following disclaimer.
 
57
 
 
58
                Redistributions in binary form must reproduce the above copyright notice,
 
59
                this list of conditions and the following disclaimer in the documentation
 
60
                and/or other materials provided with the distribution.
 
61
 
 
62
                Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
 
63
                be used to endorse or promote products derived from this software without specific prior written permission.
 
64
 
 
65
                THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 
66
                INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
67
                DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
68
                EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
69
                LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 
70
                IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
71
                THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
72
-----------------------------------------------------------------------*/
 
73
 
 
74
#include <vector>
 
75
 
 
76
namespace ConvexDecomposition
 
77
{
 
78
 
 
79
typedef std::vector< int > IntVector;
 
80
typedef std::vector< float > FloatVector;
 
81
 
 
82
#if defined(__APPLE__) || defined(__CELLOS_LV2__)
 
83
#define stricmp(a, b) strcasecmp((a), (b))
 
84
#endif
 
85
 
 
86
/*******************************************************************/
 
87
/******************** InParser.h  ********************************/
 
88
/*******************************************************************/
 
89
class InPlaceParserInterface
 
90
{
 
91
public:
 
92
  virtual ~InPlaceParserInterface () {} ;
 
93
 
 
94
  virtual int ParseLine(int lineno,int argc,const char **argv) =0;  // return TRUE to continue parsing, return FALSE to abort parsing process
 
95
};
 
96
 
 
97
enum SeparatorType
 
98
{
 
99
        ST_DATA,        // is data
 
100
        ST_HARD,        // is a hard separator
 
101
        ST_SOFT,        // is a soft separator
 
102
        ST_EOS          // is a comment symbol, and everything past this character should be ignored
 
103
};
 
104
 
 
105
class InPlaceParser
 
106
{
 
107
public:
 
108
        InPlaceParser(void)
 
109
        {
 
110
                Init();
 
111
        }
 
112
 
 
113
        InPlaceParser(char *data,int len)
 
114
        {
 
115
                Init();
 
116
                SetSourceData(data,len);
 
117
        }
 
118
 
 
119
        InPlaceParser(const char *fname)
 
120
        {
 
121
                Init();
 
122
                SetFile(fname);
 
123
        }
 
124
 
 
125
        ~InPlaceParser(void);
 
126
 
 
127
        void Init(void)
 
128
        {
 
129
                mQuoteChar = 34;
 
130
                mData = 0;
 
131
                mLen  = 0;
 
132
                mMyAlloc = false;
 
133
                for (int i=0; i<256; i++)
 
134
                {
 
135
                        mHard[i] = ST_DATA;
 
136
                        mHardString[i*2] = i;
 
137
                        mHardString[i*2+1] = 0;
 
138
                }
 
139
                mHard[0]  = ST_EOS;
 
140
                mHard[32] = ST_SOFT;
 
141
                mHard[9]  = ST_SOFT;
 
142
                mHard[13] = ST_SOFT;
 
143
                mHard[10] = ST_SOFT;
 
144
        }
 
145
 
 
146
        void SetFile(const char *fname); // use this file as source data to parse.
 
147
 
 
148
        void SetSourceData(char *data,int len)
 
149
        {
 
150
                mData = data;
 
151
                mLen  = len;
 
152
                mMyAlloc = false;
 
153
        };
 
154
 
 
155
        int  Parse(InPlaceParserInterface *callback); // returns true if entire file was parsed, false if it aborted for some reason
 
156
 
 
157
        int ProcessLine(int lineno,char *line,InPlaceParserInterface *callback);
 
158
 
 
159
        const char ** GetArglist(char *source,int &count); // convert source string into an arg list, this is a destructive parse.
 
160
 
 
161
        void SetHardSeparator(char c) // add a hard separator
 
162
        {
 
163
                mHard[(int)c] = ST_HARD;
 
164
        }
 
165
 
 
166
        void SetHard(char c) // add a hard separator
 
167
        {
 
168
                mHard[(int)c] = ST_HARD;
 
169
        }
 
170
 
 
171
 
 
172
        void SetCommentSymbol(char c) // comment character, treated as 'end of string'
 
173
        {
 
174
                mHard[(int)c] = ST_EOS;
 
175
        }
 
176
 
 
177
        void ClearHardSeparator(char c)
 
178
        {
 
179
                mHard[(int)c] = ST_DATA;
 
180
        }
 
181
 
 
182
 
 
183
        void DefaultSymbols(void); // set up default symbols for hard seperator and comment symbol of the '#' character.
 
184
 
 
185
        bool EOS(char c)
 
186
        {
 
187
                if ( mHard[(int)c] == ST_EOS )
 
188
                {
 
189
                        return true;
 
190
                }
 
191
                return false;
 
192
        }
 
193
 
 
194
        void SetQuoteChar(char c)
 
195
        {
 
196
                mQuoteChar = c;
 
197
        }
 
198
 
 
199
private:
 
200
 
 
201
 
 
202
        inline char * AddHard(int &argc,const char **argv,char *foo);
 
203
        inline bool   IsHard(char c);
 
204
        inline char * SkipSpaces(char *foo);
 
205
        inline bool   IsWhiteSpace(char c);
 
206
        inline bool   IsNonSeparator(char c); // non seperator,neither hard nor soft
 
207
 
 
208
        bool   mMyAlloc; // whether or not *I* allocated the buffer and am responsible for deleting it.
 
209
        char  *mData;  // ascii data to parse.
 
210
        int    mLen;   // length of data
 
211
        SeparatorType  mHard[256];
 
212
        char   mHardString[256*2];
 
213
        char           mQuoteChar;
 
214
};
 
215
 
 
216
/*******************************************************************/
 
217
/******************** InParser.cpp  ********************************/
 
218
/*******************************************************************/
 
219
void InPlaceParser::SetFile(const char *fname)
 
220
{
 
221
        if ( mMyAlloc )
 
222
        {
 
223
                free(mData);
 
224
        }
 
225
        mData = 0;
 
226
        mLen  = 0;
 
227
        mMyAlloc = false;
 
228
 
 
229
 
 
230
        FILE *fph = fopen(fname,"rb");
 
231
        if ( fph )
 
232
        {
 
233
                fseek(fph,0L,SEEK_END);
 
234
                mLen = ftell(fph);
 
235
                fseek(fph,0L,SEEK_SET);
 
236
                if ( mLen )
 
237
                {
 
238
                        mData = (char *) malloc(sizeof(char)*(mLen+1));
 
239
                        int ok = fread(mData, mLen, 1, fph);
 
240
                        if ( !ok )
 
241
                        {
 
242
                                free(mData);
 
243
                                mData = 0;
 
244
                        }
 
245
                        else
 
246
                        {
 
247
                                mData[mLen] = 0; // zero byte terminate end of file marker.
 
248
                                mMyAlloc = true;
 
249
                        }
 
250
                }
 
251
                fclose(fph);
 
252
        }
 
253
}
 
254
 
 
255
InPlaceParser::~InPlaceParser(void)
 
256
{
 
257
        if ( mMyAlloc )
 
258
        {
 
259
                free(mData);
 
260
        }
 
261
}
 
262
 
 
263
#define MAXARGS 512
 
264
 
 
265
bool InPlaceParser::IsHard(char c)
 
266
{
 
267
        return mHard[(int)c] == ST_HARD;
 
268
}
 
269
 
 
270
char * InPlaceParser::AddHard(int &argc,const char **argv,char *foo)
 
271
{
 
272
        while ( IsHard(*foo) )
 
273
        {
 
274
                const char *hard = &mHardString[*foo*2];
 
275
                if ( argc < MAXARGS )
 
276
                {
 
277
                        argv[argc++] = hard;
 
278
                }
 
279
                foo++;
 
280
        }
 
281
        return foo;
 
282
}
 
283
 
 
284
bool   InPlaceParser::IsWhiteSpace(char c)
 
285
{
 
286
        return mHard[(int)c] == ST_SOFT;
 
287
}
 
288
 
 
289
char * InPlaceParser::SkipSpaces(char *foo)
 
290
{
 
291
        while ( !EOS(*foo) && IsWhiteSpace(*foo) ) foo++;
 
292
        return foo;
 
293
}
 
294
 
 
295
bool InPlaceParser::IsNonSeparator(char c)
 
296
{
 
297
        if ( !IsHard(c) && !IsWhiteSpace(c) && c != 0 ) return true;
 
298
        return false;
 
299
}
 
300
 
 
301
 
 
302
int InPlaceParser::ProcessLine(int lineno,char *line,InPlaceParserInterface *callback)
 
303
{
 
304
        int ret = 0;
 
305
 
 
306
        const char *argv[MAXARGS];
 
307
        int argc = 0;
 
308
 
 
309
        char *foo = line;
 
310
 
 
311
        while ( !EOS(*foo) && argc < MAXARGS )
 
312
        {
 
313
 
 
314
                foo = SkipSpaces(foo); // skip any leading spaces
 
315
 
 
316
                if ( EOS(*foo) ) break;
 
317
 
 
318
                if ( *foo == mQuoteChar ) // if it is an open quote
 
319
                {
 
320
                        foo++;
 
321
                        if ( argc < MAXARGS )
 
322
                        {
 
323
                                argv[argc++] = foo;
 
324
                        }
 
325
                        while ( !EOS(*foo) && *foo != mQuoteChar ) foo++;
 
326
                        if ( !EOS(*foo) )
 
327
                        {
 
328
                                *foo = 0; // replace close quote with zero byte EOS
 
329
                                foo++;
 
330
                        }
 
331
                }
 
332
                else
 
333
                {
 
334
 
 
335
                        foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces
 
336
 
 
337
                        if ( IsNonSeparator(*foo) )  // add non-hard argument.
 
338
                        {
 
339
                                bool quote  = false;
 
340
                                if ( *foo == mQuoteChar )
 
341
                                {
 
342
                                        foo++;
 
343
                                        quote = true;
 
344
                                }
 
345
 
 
346
                                if ( argc < MAXARGS )
 
347
                                {
 
348
                                        argv[argc++] = foo;
 
349
                                }
 
350
 
 
351
                                if ( quote )
 
352
                                {
 
353
                                        while (*foo && *foo != mQuoteChar ) foo++;
 
354
                                        if ( *foo ) *foo = 32;
 
355
                                }
 
356
 
 
357
                                // continue..until we hit an eos ..
 
358
                                while ( !EOS(*foo) ) // until we hit EOS
 
359
                                {
 
360
                                        if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit
 
361
                                        {
 
362
                                                *foo = 0;
 
363
                                                foo++;
 
364
                                                break;
 
365
                                        }
 
366
                                        else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
 
367
                                        {
 
368
                                                const char *hard = &mHardString[*foo*2];
 
369
                                                *foo = 0;
 
370
                                                if ( argc < MAXARGS )
 
371
                                                {
 
372
                                                        argv[argc++] = hard;
 
373
                                                }
 
374
                                                foo++;
 
375
                                                break;
 
376
                                        }
 
377
                                        foo++;
 
378
                                } // end of while loop...
 
379
                        }
 
380
                }
 
381
        }
 
382
 
 
383
        if ( argc )
 
384
        {
 
385
                ret = callback->ParseLine(lineno, argc, argv );
 
386
        }
 
387
 
 
388
        return ret;
 
389
}
 
390
 
 
391
int  InPlaceParser::Parse(InPlaceParserInterface *callback) // returns true if entire file was parsed, false if it aborted for some reason
 
392
{
 
393
        assert( callback );
 
394
        if ( !mData ) return 0;
 
395
 
 
396
        int ret = 0;
 
397
 
 
398
        int lineno = 0;
 
399
 
 
400
        char *foo   = mData;
 
401
        char *begin = foo;
 
402
 
 
403
 
 
404
        while ( *foo )
 
405
        {
 
406
                if ( *foo == 10 || *foo == 13 )
 
407
                {
 
408
                        lineno++;
 
409
                        *foo = 0;
 
410
 
 
411
                        if ( *begin ) // if there is any data to parse at all...
 
412
                        {
 
413
                                int v = ProcessLine(lineno,begin,callback);
 
414
                                if ( v ) ret = v;
 
415
                        }
 
416
 
 
417
                        foo++;
 
418
                        if ( *foo == 10 ) foo++; // skip line feed, if it is in the carraige-return line-feed format...
 
419
                        begin = foo;
 
420
                }
 
421
                else
 
422
                {
 
423
                        foo++;
 
424
                }
 
425
        }
 
426
 
 
427
        lineno++; // lasst line.
 
428
 
 
429
        int v = ProcessLine(lineno,begin,callback);
 
430
        if ( v ) ret = v;
 
431
        return ret;
 
432
}
 
433
 
 
434
 
 
435
void InPlaceParser::DefaultSymbols(void)
 
436
{
 
437
        SetHardSeparator(',');
 
438
        SetHardSeparator('(');
 
439
        SetHardSeparator(')');
 
440
        SetHardSeparator('=');
 
441
        SetHardSeparator('[');
 
442
        SetHardSeparator(']');
 
443
        SetHardSeparator('{');
 
444
        SetHardSeparator('}');
 
445
        SetCommentSymbol('#');
 
446
}
 
447
 
 
448
 
 
449
const char ** InPlaceParser::GetArglist(char *line,int &count) // convert source string into an arg list, this is a destructive parse.
 
450
{
 
451
        const char **ret = 0;
 
452
 
 
453
        const char *argv[MAXARGS];
 
454
        int argc = 0;
 
455
 
 
456
        char *foo = line;
 
457
 
 
458
        while ( !EOS(*foo) && argc < MAXARGS )
 
459
        {
 
460
 
 
461
                foo = SkipSpaces(foo); // skip any leading spaces
 
462
 
 
463
                if ( EOS(*foo) ) break;
 
464
 
 
465
                if ( *foo == mQuoteChar ) // if it is an open quote
 
466
                {
 
467
                        foo++;
 
468
                        if ( argc < MAXARGS )
 
469
                        {
 
470
                                argv[argc++] = foo;
 
471
                        }
 
472
                        while ( !EOS(*foo) && *foo != mQuoteChar ) foo++;
 
473
                        if ( !EOS(*foo) )
 
474
                        {
 
475
                                *foo = 0; // replace close quote with zero byte EOS
 
476
                                foo++;
 
477
                        }
 
478
                }
 
479
                else
 
480
                {
 
481
 
 
482
                        foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces
 
483
 
 
484
                        if ( IsNonSeparator(*foo) )  // add non-hard argument.
 
485
                        {
 
486
                                bool quote  = false;
 
487
                                if ( *foo == mQuoteChar )
 
488
                                {
 
489
                                        foo++;
 
490
                                        quote = true;
 
491
                                }
 
492
 
 
493
                                if ( argc < MAXARGS )
 
494
                                {
 
495
                                        argv[argc++] = foo;
 
496
                                }
 
497
 
 
498
                                if ( quote )
 
499
                                {
 
500
                                        while (*foo && *foo != mQuoteChar ) foo++;
 
501
                                        if ( *foo ) *foo = 32;
 
502
                                }
 
503
 
 
504
                                // continue..until we hit an eos ..
 
505
                                while ( !EOS(*foo) ) // until we hit EOS
 
506
                                {
 
507
                                        if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit
 
508
                                        {
 
509
                                                *foo = 0;
 
510
                                                foo++;
 
511
                                                break;
 
512
                                        }
 
513
                                        else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
 
514
                                        {
 
515
                                                const char *hard = &mHardString[*foo*2];
 
516
                                                *foo = 0;
 
517
                                                if ( argc < MAXARGS )
 
518
                                                {
 
519
                                                        argv[argc++] = hard;
 
520
                                                }
 
521
                                                foo++;
 
522
                                                break;
 
523
                                        }
 
524
                                        foo++;
 
525
                                } // end of while loop...
 
526
                        }
 
527
                }
 
528
        }
 
529
 
 
530
        count = argc;
 
531
        if ( argc )
 
532
        {
 
533
                ret = argv;
 
534
        }
 
535
 
 
536
        return ret;
 
537
}
 
538
 
 
539
/*******************************************************************/
 
540
/******************** Geometry.h  ********************************/
 
541
/*******************************************************************/
 
542
 
 
543
class GeometryVertex
 
544
{
 
545
public:
 
546
        float        mPos[3];
 
547
        float        mNormal[3];
 
548
        float        mTexel[2];
 
549
};
 
550
 
 
551
 
 
552
class GeometryInterface
 
553
{
 
554
public:
 
555
 
 
556
  virtual void NodeTriangle(const GeometryVertex *v1,const GeometryVertex *v2,const GeometryVertex *v3) {}
 
557
 
 
558
  virtual ~GeometryInterface () {}
 
559
};
 
560
 
 
561
 
 
562
/*******************************************************************/
 
563
/******************** Obj.h  ********************************/
 
564
/*******************************************************************/
 
565
 
 
566
 
 
567
class OBJ : public InPlaceParserInterface
 
568
{
 
569
public:
 
570
  int          LoadMesh(const char *fname,GeometryInterface *callback);
 
571
  int ParseLine(int lineno,int argc,const char **argv);  // return TRUE to continue parsing, return FALSE to abort parsing process
 
572
private:
 
573
 
 
574
  void getVertex(GeometryVertex &v,const char *face) const;
 
575
 
 
576
  FloatVector     mVerts;
 
577
  FloatVector     mTexels;
 
578
  FloatVector     mNormals;
 
579
 
 
580
  GeometryInterface *mCallback;
 
581
};
 
582
 
 
583
 
 
584
/*******************************************************************/
 
585
/******************** Obj.cpp  ********************************/
 
586
/*******************************************************************/
 
587
 
 
588
int OBJ::LoadMesh(const char *fname,GeometryInterface *iface)
 
589
{
 
590
  int ret = 0;
 
591
 
 
592
  mVerts.clear();
 
593
  mTexels.clear();
 
594
  mNormals.clear();
 
595
 
 
596
  mCallback = iface;
 
597
 
 
598
  InPlaceParser ipp(fname);
 
599
 
 
600
  ipp.Parse(this);
 
601
 
 
602
 
 
603
  return ret;
 
604
}
 
605
 
 
606
//static const char * GetArg(const char **argv,int i,int argc)
 
607
//{
 
608
 // const char * ret = 0;
 
609
 // if ( i < argc ) ret = argv[i];
 
610
 // return ret;
 
611
//}
 
612
 
 
613
void OBJ::getVertex(GeometryVertex &v,const char *face) const
 
614
{
 
615
  v.mPos[0] = 0;
 
616
  v.mPos[1] = 0;
 
617
  v.mPos[2] = 0;
 
618
 
 
619
  v.mTexel[0] = 0;
 
620
  v.mTexel[1] = 0;
 
621
 
 
622
  v.mNormal[0] = 0;
 
623
  v.mNormal[1] = 1;
 
624
  v.mNormal[2] = 0;
 
625
 
 
626
  int index = atoi( face )-1;
 
627
 
 
628
  const char *texel = strstr(face,"/");
 
629
 
 
630
  if ( texel )
 
631
  {
 
632
    int tindex = atoi( texel+1) - 1;
 
633
 
 
634
    if ( tindex >=0 && tindex < (int)(mTexels.size()/2) )
 
635
    {
 
636
        const float *t = &mTexels[tindex*2];
 
637
 
 
638
      v.mTexel[0] = t[0];
 
639
      v.mTexel[1] = t[1];
 
640
 
 
641
    }
 
642
 
 
643
    const char *normal = strstr(texel+1,"/");
 
644
    if ( normal )
 
645
    {
 
646
      int nindex = atoi( normal+1 ) - 1;
 
647
 
 
648
      if (nindex >= 0 && nindex < (int)(mNormals.size()/3) )
 
649
      {
 
650
        const float *n = &mNormals[nindex*3];
 
651
 
 
652
        v.mNormal[0] = n[0];
 
653
        v.mNormal[1] = n[1];
 
654
        v.mNormal[2] = n[2];
 
655
      }
 
656
    }
 
657
  }
 
658
 
 
659
  if ( index >= 0 && index < (int)(mVerts.size()/3) )
 
660
  {
 
661
 
 
662
    const float *p = &mVerts[index*3];
 
663
 
 
664
    v.mPos[0] = p[0];
 
665
    v.mPos[1] = p[1];
 
666
    v.mPos[2] = p[2];
 
667
  }
 
668
 
 
669
}
 
670
 
 
671
int OBJ::ParseLine(int lineno,int argc,const char **argv)  // return TRUE to continue parsing, return FALSE to abort parsing process
 
672
{
 
673
  int ret = 0;
 
674
 
 
675
  if ( argc >= 1 )
 
676
  {
 
677
    const char *foo = argv[0];
 
678
    if ( *foo != '#' )
 
679
    {
 
680
  if ( strcmp(argv[0],"v") == 0 && argc == 4 )
 
681
 
 
682
      //if ( stricmp(argv[0],"v") == 0 && argc == 4 )
 
683
      {
 
684
        float vx = (float) atof( argv[1] );
 
685
        float vy = (float) atof( argv[2] );
 
686
        float vz = (float) atof( argv[3] );
 
687
        mVerts.push_back(vx);
 
688
        mVerts.push_back(vy);
 
689
        mVerts.push_back(vz);
 
690
      }
 
691
  else if ( strcmp(argv[0],"vt") == 0 && argc == 3 )
 
692
 
 
693
 //     else if ( stricmp(argv[0],"vt") == 0 && argc == 3 )
 
694
      {
 
695
        float tx = (float) atof( argv[1] );
 
696
        float ty = (float) atof( argv[2] );
 
697
        mTexels.push_back(tx);
 
698
        mTexels.push_back(ty);
 
699
      }
 
700
        //  else if ( stricmp(argv[0],"vn") == 0 && argc == 4 )
 
701
 
 
702
      else if ( strcmp(argv[0],"vn") == 0 && argc == 4 )
 
703
      {
 
704
        float normalx = (float) atof(argv[1]);
 
705
        float normaly = (float) atof(argv[2]);
 
706
        float normalz = (float) atof(argv[3]);
 
707
        mNormals.push_back(normalx);
 
708
        mNormals.push_back(normaly);
 
709
        mNormals.push_back(normalz);
 
710
      }
 
711
//  else if ( stricmp(argv[0],"f") == 0 && argc >= 4 )
 
712
 
 
713
      else if ( strcmp(argv[0],"f") == 0 && argc >= 4 )
 
714
      {
 
715
        GeometryVertex v[32];
 
716
 
 
717
        int vcount = argc-1;
 
718
 
 
719
        for (int i=1; i<argc; i++)
 
720
        {
 
721
          getVertex(v[i-1],argv[i] );
 
722
        }
 
723
 
 
724
        // need to generate a normal!
 
725
#if 0 // not currently implemented
 
726
        if ( mNormals.empty() )
 
727
        {
 
728
          Vector3d<float> p1( v[0].mPos );
 
729
          Vector3d<float> p2( v[1].mPos );
 
730
          Vector3d<float> p3( v[2].mPos );
 
731
 
 
732
          Vector3d<float> n;
 
733
          n.ComputeNormal(p3,p2,p1);
 
734
 
 
735
          for (int i=0; i<vcount; i++)
 
736
          {
 
737
            v[i].mNormal[0] = n.x;
 
738
            v[i].mNormal[1] = n.y;
 
739
            v[i].mNormal[2] = n.z;
 
740
          }
 
741
 
 
742
        }
 
743
#endif
 
744
 
 
745
        mCallback->NodeTriangle(&v[0],&v[1],&v[2]);
 
746
 
 
747
        if ( vcount >=3 ) // do the fan
 
748
        {
 
749
          for (int i=2; i<(vcount-1); i++)
 
750
          {
 
751
            mCallback->NodeTriangle(&v[0],&v[i],&v[i+1]);
 
752
          }
 
753
        }
 
754
 
 
755
      }
 
756
    }
 
757
  }
 
758
 
 
759
  return ret;
 
760
}
 
761
 
 
762
 
 
763
 
 
764
 
 
765
class BuildMesh : public GeometryInterface
 
766
{
 
767
public:
 
768
 
 
769
        int getIndex(const float *p)
 
770
        {
 
771
 
 
772
                int vcount = mVertices.size()/3;
 
773
 
 
774
                if(vcount>0)
 
775
                {
 
776
                        //New MS STL library checks indices in debug build, so zero causes an assert if it is empty.
 
777
                        const float *v = &mVertices[0];
 
778
 
 
779
                        for (int i=0; i<vcount; i++)
 
780
                        {
 
781
                                if ( v[0] == p[0] && v[1] == p[1] && v[2] == p[2] ) return i;
 
782
                                v+=3;
 
783
                        }
 
784
                }
 
785
 
 
786
                mVertices.push_back( p[0] );
 
787
                mVertices.push_back( p[1] );
 
788
                mVertices.push_back( p[2] );
 
789
 
 
790
                return vcount;
 
791
        }
 
792
 
 
793
        virtual void NodeTriangle(const GeometryVertex *v1,const GeometryVertex *v2,const GeometryVertex *v3)
 
794
        {
 
795
                mIndices.push_back( getIndex(v1->mPos) );
 
796
                mIndices.push_back( getIndex(v2->mPos) );
 
797
                mIndices.push_back( getIndex(v3->mPos) );
 
798
        }
 
799
 
 
800
  const FloatVector& GetVertices(void) const { return mVertices; };
 
801
  const IntVector& GetIndices(void) const { return mIndices; };
 
802
 
 
803
private:
 
804
  FloatVector     mVertices;
 
805
  IntVector                 mIndices;
 
806
};
 
807
 
 
808
 
 
809
WavefrontObj::WavefrontObj(void)
 
810
{
 
811
        mVertexCount = 0;
 
812
        mTriCount    = 0;
 
813
        mIndices     = 0;
 
814
        mVertices    = 0;
 
815
}
 
816
 
 
817
WavefrontObj::~WavefrontObj(void)
 
818
{
 
819
        delete [] mIndices;
 
820
        delete [] mVertices;
 
821
}
 
822
 
 
823
unsigned int WavefrontObj::loadObj(const char *fname) // load a wavefront obj returns number of triangles that were loaded.  Data is persists until the class is destructed.
 
824
{
 
825
 
 
826
        unsigned int ret = 0;
 
827
 
 
828
        delete [] mVertices;
 
829
        mVertices = 0;
 
830
        delete [] mIndices;
 
831
        mIndices = 0;
 
832
        mVertexCount = 0;
 
833
        mTriCount = 0;
 
834
 
 
835
 
 
836
  BuildMesh bm;
 
837
 
 
838
  OBJ obj;
 
839
 
 
840
  obj.LoadMesh(fname,&bm);
 
841
 
 
842
 
 
843
        const FloatVector &vlist = bm.GetVertices();
 
844
        const IntVector &indices = bm.GetIndices();
 
845
        if ( vlist.size() )
 
846
        {
 
847
                mVertexCount = vlist.size()/3;
 
848
                mVertices = new float[mVertexCount*3];
 
849
                memcpy( mVertices, &vlist[0], sizeof(float)*mVertexCount*3 );
 
850
                mTriCount = indices.size()/3;
 
851
                mIndices = new int[mTriCount*3*sizeof(int)];
 
852
                memcpy(mIndices, &indices[0], sizeof(int)*mTriCount*3);
 
853
                ret = mTriCount;
 
854
        }
 
855
 
 
856
 
 
857
        return ret;
 
858
}
 
859
 
 
860
}