1 /*
2      PLIB - A Suite of Portable Game Libraries
3      Copyright (C) 1998,2002  Steve Baker
4 
5      This library is free software; you can redistribute it and/or
6      modify it under the terms of the GNU Library General Public
7      License as published by the Free Software Foundation; either
8      version 2 of the License, or (at your option) any later version.
9 
10      This library is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Library General Public License for more details.
14 
15      You should have received a copy of the GNU Library General Public
16      License along with this library; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 
19      For further information visit http://plib.sourceforge.net
20 
21      $Id: ssgLoadM.cxx 1568 2002-09-02 06:05:49Z sjbaker $
22 */
23 
24 #include <stdio.h>
25 #include "ssgLocal.h"
26 
27 static ssgLoaderOptions* current_options;
28 
ssgLoadM(const char * fname,const ssgLoaderOptions * options)29 ssgEntity* ssgLoadM( const char* fname,
30                     const ssgLoaderOptions* options ) {
31   ssgSetCurrentOptions ( (ssgLoaderOptions*)options ) ;
32   current_options = ssgGetCurrentOptions () ;
33 
34   char filename [ 1024 ] ;
35   current_options -> makeModelPath ( filename, fname ) ;
36 
37   FILE* model_file = fopen(filename, "r");
38   if(!model_file) {
39     ulSetError(UL_WARNING, "ssgLoadM: Couldn't open file '%s'.",
40       filename);
41     return NULL;
42   }
43 
44   ssgVertexArray* vertices = new ssgVertexArray;
45   ssgNormalArray* normals  = new ssgNormalArray;
46   ssgIndexArray*  indices  = new ssgIndexArray;
47 
48   int i, index;
49   char line[256];
50   sgVec3 zero = {0.0f, 0.0f, 0.0f};
51 
52   fgets(line, 256, model_file);
53   while ( !feof(model_file) ) {
54     char* token;
55 
56     switch (line[0]) {
57     case '#':                    // comment, skip this line
58       break;
59     case 'V':
60       sgVec3 vtx;
61       token = strtok(line, " ");  // token should now be "Vertex"
62       token = strtok(NULL, " ");  // token is vertex index now
63 
64       index = atoi(token) - 1;
65 
66       // fill out non-declared vertices with zero vectors
67       while (index > vertices->getNum()) {
68         vertices->add(zero);
69         normals ->add(zero);
70       }
71 
72       // get vertex coordinate
73       for (i = 0; i < 3; i++) {
74         token = strtok(NULL, " ");
75         vtx[i] = (float) atof(token);
76       }
77 
78       vertices->add(vtx) ;
79       normals ->add(zero);
80 
81       break;
82 
83     case 'F':                   // face
84       token = strtok(line, " ");  // token should now be "Face"
85       token = strtok(NULL, " ");  // face index, ignored
86 
87       for (i = 0; i < 3; i++) {
88         token = strtok(NULL, " ");
89         indices->add( atoi(token)-1 );
90       }
91 
92       break;
93 
94     case 'E':                  // Edge, ignored
95       break;
96 
97     default:
98       ulSetError(UL_WARNING, "ssgLoadM: Syntax error on line \"%s\".", line);
99     }
100 
101     fgets(line, 256, model_file);
102   }
103 
104   ssgSimpleState* state = new ssgSimpleState();
105   state->setOpaque();
106   state->disable(GL_BLEND);
107   state->disable(GL_ALPHA_TEST);
108   state->disable(GL_TEXTURE_2D);
109   state->enable(GL_COLOR_MATERIAL);
110   state->enable(GL_LIGHTING);
111   state->setShadeModel(GL_SMOOTH);
112   state->setMaterial(GL_AMBIENT , 0.7f, 0.7f, 0.0f, 1.0f);
113   state->setMaterial(GL_DIFFUSE , 0.7f, 0.7f, 0.0f, 1.0f);
114   state->setMaterial(GL_SPECULAR, 1.0f, 1.0f, 1.0f, 1.0f);
115   state->setMaterial(GL_EMISSION, 0.0f, 0.0f, 0.0f, 1.0f);
116   state->setShininess(50);
117 
118   // now calculate smooth normals (this code belongs elsewhere)
119   for (i = 0; i < indices->getNum(); i += 3) {
120     short idx0 = *indices->get(i    );
121     short idx1 = *indices->get(i + 1);
122     short idx2 = *indices->get(i + 2);
123 
124     sgVec3 normal;
125     sgMakeNormal( normal,
126       vertices->get(idx0),
127       vertices->get(idx1),
128       vertices->get(idx2) );
129 
130     sgAddVec3( normals->get(idx0), normal );
131     sgAddVec3( normals->get(idx1), normal );
132     sgAddVec3( normals->get(idx2), normal );
133   }
134 
135   for (i = 0; i < vertices->getNum(); i++) {
136     sgNormaliseVec3( normals->get(i) );
137   }
138 
139   ssgVtxArray* leaf = new ssgVtxArray( GL_TRIANGLES,
140     vertices,
141     normals,
142     NULL,
143     NULL,
144     indices );
145 
146   leaf->setCullFace( TRUE );
147   leaf->setState( state );
148 
149   ssgLeaf* model = current_options -> createLeaf( leaf, NULL );
150 
151   return model;
152 }
153