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