1 /***************************************************************************
2 * Copyright (C) 2004 by Murray Evans *
3 * m.evans@rdg.ac.uk *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program 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 *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #include "ModelManager.h"
21 #include "DynArray.h"
22 #include <iostream>
23 using namespace std;
24
25 // Loads an Alias|Wavefront .obj file
LoadOBJ(string in_Filename_s)26 int CModelManager::LoadOBJ(string in_Filename_s)
27 {
28 // Wavefront .obj file is a text file.
29 // This loader will load a simple version of it
30 // It can cope with the v, vt, vn and g(?) instructions
31 // and of course, the f one.
32 // v: x z y vertex data
33 // vt: x y texture vertex
34 // vn: x z y vertex normal
35 // f: v/vt/vn v/vt/vn v/vt/vn ...
36
37 ifstream in;
38 in.open(in_Filename_s.c_str()); // open the file
39 if(!in.is_open())
40 {
41 cout << "Error loading file: " << in_Filename_s << endl;
42 exit(1);
43 }
44
45 // parse the file for the appropriate information
46 char ch;
47 CDynArray<CVec4f> points;
48 CDynArray<CVec4f> normals;
49 CDynArray<CVec4f> fnormals;
50 CDynArray<CVec2f> uvpoints;
51 CDynArray<CFace*> faces;
52 // .obj does not have vertex colours
53
54 // vector<CMesh> meshes;
55 string ones, twos, threes, digger;
56 float onef, twof, threef;
57 while(in)
58 {
59 in.get(ch);
60
61 switch(ch)
62 {
63 case 'v': // read v, vt, or vn /////////////////////////
64 { //
65 bool istext, isnormal; //
66 CVec4f tpoint; //
67 istext = false; //
68 isnormal=false; //
69 ones=""; //
70 twos=""; //
71 threes=""; //
72 in.get(ch); //
73 if(ch == 't') istext = true; //
74 if(ch == 'n') isnormal = true; //
75 in.get(ch); //
76 //
77 // skip any spaces //
78 while(ch==' ') //
79 { //
80 in.get(ch); //
81 } //
82 // read in first value (x or u) //
83 do //
84 { //
85 ones = ones+ch; //
86 in.get(ch); //
87 }while(ch!=' '); //
88 //
89 // skip any spaces //
90 while(ch==' ') //
91 { //
92 in.get(ch); //
93 } //
94 // read in second value (z or u) //
95 do //
96 { //
97 twos = twos+ch; //
98 in.get(ch); //
99 }while((ch!=' ') && (ch!='\n')); //
100 //
101 // only two values for texture coordinate //
102 if(!istext) //
103 { //
104 // skip any spaces //
105 while(ch==' ') //
106 { //
107 in.get(ch); //
108 } //
109 // read in third value (y coordinate) //
110 do //
111 { //
112 threes = threes+ch; //
113 in.get(ch); //
114 }while((ch!=' ') && (ch != '\n')); //
115 } //
116 //
117 //put info into relevant structure //
118 onef = Cast<float> (ones); //
119 twof = Cast<float> (twos); //
120 threef = Cast<float> (threes); //
121 //tpoint.xyz[0] = onef; //
122 //tpoint.xyz[2] = twof; //
123 //tpoint.xyz[1] = threef; //
124 tpoint.SetXYZW(onef, threef, -twof, 1); //
125 if(istext) //
126 { //
127 CVec2f tpoint2; //
128 // tpoint2.xy[0] = onef; //
129 // tpoint2.xy[1] = twof; //
130 tpoint2.SetXY(onef, twof); //
131 uvpoints.AddToEnd(tpoint2); //
132 } //
133 else if(isnormal) normals.AddToEnd(tpoint); //
134 else points.AddToEnd(tpoint); //
135 }break; //
136 ////////////////////////////////////////////////////
137
138 case 'f': // read face v/vt/vn v/vt/vn ... **************
139 {
140 CFace *tface;
141 tface = new(CFace);
142 do
143 {
144 // skip any spaces
145 in.get(ch);
146 while(ch==' ')
147 {
148 in.get(ch);
149 }
150 ones = "";
151 twos = "";
152 threes="";
153
154 // read to first / to get point
155 do
156 {
157 ones = ones + ch;
158 in.get(ch);
159
160 }while((ch!=' ') && (ch!='/') && (ch!='\n'));
161
162 // read until second / to get uvpoint
163 if(ch=='/')
164 {
165 in.get(ch);
166 do
167 {
168 if(ch!='/') twos = twos+ ch;
169 in.get(ch);
170 }while((ch!=' ') && (ch!='/') && (ch!='\n'));
171
172 }
173 // read until ' ' or '\n' for normal
174 if(ch=='/')
175 {
176 in.get(ch);
177 do
178 {
179 threes = threes + ch;
180 in.get(ch);
181 }while((ch!=' ') && (ch!='\n'));
182 }
183
184
185 // and add to the face
186
187 bool hasp = false;
188 bool hast = false;
189 bool hasn = false;
190
191 if(ones != "") hasp = true;
192 if(twos != "") hast = true;
193 if(threes!="") hasn = true;
194
195 if(hasp)onef = Cast<float> (ones)-1;
196 if(hast)twof = Cast<float> (twos)-1;
197 if(hasn)threef=Cast<float> (threes)-1;
198
199 if(hasp) tface->p.AddToEnd((int)onef);
200 if(hast) tface->uv.AddToEnd((int)twof);
201 if(hasn) tface->n.AddToEnd((int)threef);
202
203 }while(in && (ch!='\n'));
204 // add new face to list of faces
205 faces.AddToEnd(tface);
206 }break;
207 /******************************************************/
208
209 default : // comments or unknowns
210 while(ch != '\n')
211 {
212 in.get(ch);
213 }
214 break;
215 }// switch(ch)
216 } // while(in)
217
218 // and now, create the mesh.
219 CMesh *tmesh;
220 tmesh = new(CMesh);
221
222 tmesh->points = points;
223 tmesh->uvpoints = uvpoints;
224 tmesh->fnormals = fnormals;
225 tmesh->normals = normals;
226 tmesh->faces = faces;
227 tmesh->has_faces = true;
228 tmesh->has_points = true;
229 tmesh->has_uvpoints = false;
230 if(normals.Size() > 0) tmesh->has_normals = true;
231 else tmesh->has_normals = false;
232 tmesh->has_fnormals = false; //OBJ file doesn't use
233 if(tmesh->uvpoints.Size() > 0) tmesh->has_uvpoints = true;
234 tmesh->has_colors = false;
235 // add the mesh to the Model Manager's list of meshes
236 meshes.AddToEnd(tmesh);
237 return true;
238 return 0;
239 }
240