1 /*
2  * Sample BMF file reader (from view3ds by David Farrell)
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <ctype.h>
7 #ifdef WIN32
8 #include <windows.h>
9 #endif
10 #include "GL/glut.h"
11 #include "bmf.h"
12 #include "ou.h"
13 
14 GLubyte *read_JPEG_file(char *, int *, int *, int *);
15 
16 char modelspath[100] = MODEL_DIR;
17 
LoadBMF(char * filename,double radius)18 BMFObject *LoadBMF(char *filename, double radius)
19 {
20 	uword MeshType;
21 	SparseMesh *MaterialList;
22 	StripMesh *StripMaterialList;
23 	BMFObject *obj;
24 	FILE *in;
25 	int i, j;
26 	int width, height, components;
27 	GLubyte *image;
28 	char s[120];				/* openuniverse */
29 	double max = 0.0, d;		/* openuniverse */
30 
31 	/* Create the new BMF object */
32 	if (!(obj = (BMFObject *) malloc(sizeof(BMFObject)))) {
33 		error("Can't allocate memory for BMFObject\n");
34 		shutdown(1);
35 	}
36 
37 	sprintf(s, "%s/%s", modelspath, filename);
38 
39 	if (!(in = fopen(s, "rb"))) {
40 		sprintf(s, "Can't open file %s", filename);
41 		error("Can't open file\n");
42 		shutdown(1);
43 	}
44 	obj->texsize = 0;
45 
46 	/* Get number of materials */
47 	fread(&obj->NumMaterials, sizeof(uword), 1, in);
48 
49 	/* Get mesh type */
50 	fread(&MeshType, sizeof(uword), 1, in);
51 
52 	if (MeshType == 0) {
53 		/* Sparse Triangles */
54 
55 		/* Allocate space for the materials */
56 		if (!
57 			(MaterialList =
58 			 (SparseMesh *) malloc(sizeof(SparseMesh) *
59 								   obj->NumMaterials))) {
60 			error("Can't allocate memory for materials\n");
61 			shutdown(1);
62 		}
63 		obj->sparse = MaterialList;
64 		obj->strip = 0;
65 
66 		/* Read in each material */
67 		for (i = 0; i < obj->NumMaterials; i++) {
68 			/* Get the texture's name length */
69 			fread(&MaterialList[i].texture_name_length, sizeof(uword), 1,
70 				  in);
71 
72 			if (MaterialList[i].texture_name_length == 0) {
73 				error("Invalid texture name length\n");
74 				shutdown(1);
75 			}
76 
77 			/* Get the texture's name */
78 			MaterialList[i].texture_name =
79 				(char *) malloc(MaterialList[i].texture_name_length);
80 			fread(MaterialList[i].texture_name,
81 				  MaterialList[i].texture_name_length, 1, in);
82 
83 			if (MaterialList[i].texture_name_length > 1) {
84 
85 				for (j = 0; j < MaterialList[i].texture_name_length; j++)
86 					MaterialList[i].texture_name[j] =
87 						(char) tolower(MaterialList[i].texture_name[j]);
88 
89 				image =
90 					read_JPEG_file(MaterialList[i].texture_name, &width,
91 								   &height, &components);
92 
93 				if (image == NULL) {
94 					sprintf(s, "reading image %s",
95 							MaterialList[i].texture_name);
96 					error(s);
97 					shutdown(1);
98 				}
99 				image = texture_LOD(image, &width, &height, components);
100 				if (components == 1)
101 					j = 1;
102 				else
103 					j = color_depth / 8;
104 				obj->texsize += (width * height * j);
105 
106 				glGenTextures(1, &MaterialList[i].texbind);
107 				glBindTexture(GL_TEXTURE_2D, MaterialList[i].texbind);
108 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
109 								GL_LINEAR);
110 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
111 								GL_LINEAR);
112 				glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
113 						  GL_MODULATE);
114 
115 				glTexImage2D(GL_TEXTURE_2D,
116 							 0,
117 							 components == 3 ? cd_rgb : cd_lum,
118 							 width, height,
119 							 0,
120 							 components == 3 ? GL_RGB : GL_LUMINANCE,
121 							 GL_UNSIGNED_BYTE, image);
122 				free(image);
123 			}
124 
125 
126 			/* Read in RGB colors */
127 			fread(&MaterialList[i].ambient, sizeof(BMF_RGBCOLOR), 1, in);
128 
129 			fread(&MaterialList[i].diffuse, sizeof(BMF_RGBCOLOR), 1, in);
130 
131 			fread(&MaterialList[i].specular, sizeof(BMF_RGBCOLOR), 1, in);
132 
133 			/* Get the number of vertices */
134 			fread(&MaterialList[i].number_of_vertices, sizeof(uword), 1,
135 				  in);
136 
137 			/* Allocate space for the vertex list */
138 			MaterialList[i].vertexlist =
139 				(BMF_UNVERTEX *) malloc(sizeof(BMF_UNVERTEX) *
140 										MaterialList
141 										[i].number_of_vertices);
142 
143 			if (MaterialList[i].vertexlist == 0) {
144 				error("Error allocating memory for vertexlist\n");
145 				shutdown(1);
146 			}
147 
148 			/* Read in the vertex list */
149 			fread(MaterialList[i].vertexlist,
150 				  sizeof(BMF_UNVERTEX),
151 				  MaterialList[i].number_of_vertices, in);
152 
153 			for (j = 0; j < MaterialList[i].number_of_vertices; j++) {
154 				d = DISTANCE(MaterialList[i].vertexlist[j].x,
155 							 MaterialList[i].vertexlist[j].y,
156 							 MaterialList[i].vertexlist[j].z);
157 				if (d > max)
158 					max = d;
159 			}
160 
161 
162 			/* Read in the number of polygons */
163 			fread(&MaterialList[i].number_of_triangles, sizeof(uword), 1,
164 				  in);
165 
166 			/* Allocate space for the index list */
167 			MaterialList[i].indexlist =
168 				(BMF_SURFACE *) malloc(sizeof(BMF_SURFACE) *
169 									   MaterialList
170 									   [i].number_of_triangles);
171 
172 			/* Read in the triangle indices */
173 			fread(MaterialList[i].indexlist,
174 				  sizeof(BMF_SURFACE),
175 				  MaterialList[i].number_of_triangles, in);
176 		}
177 
178 		/* Sorta vertex normalization */
179 		for (i = 0; i < obj->NumMaterials; i++) {
180 			for (j = 0; j < MaterialList[i].number_of_vertices; j++) {
181 				MaterialList[i].vertexlist[j].x /= max / radius;
182 				MaterialList[i].vertexlist[j].y /= max / radius;
183 				MaterialList[i].vertexlist[j].z /= max / radius;
184 			}
185 		}
186 	} else {
187 		/* Triangle Strips */
188 
189 		/* Allocate space for the materials */
190 		if (!
191 			(StripMaterialList =
192 			 (StripMesh *) malloc(sizeof(StripMesh) *
193 								  obj->NumMaterials))) {
194 			error("Can't allocate memory for materials\n");
195 			shutdown(1);
196 		}
197 		obj->sparse = 0;
198 		obj->strip = StripMaterialList;
199 
200 		/* Read in each material */
201 		for (i = 0; i < obj->NumMaterials; i++) {
202 			/* Get the texture's name length */
203 			fread(&StripMaterialList[i].texture_name_length,
204 				  sizeof(uword), 1, in);
205 
206 			if (StripMaterialList[i].texture_name_length == 0) {
207 				error("Invalid texture name length\n");
208 				shutdown(1);
209 			}
210 
211 			/* Get the texture's name */
212 			StripMaterialList[i].texture_name =
213 				(char *) malloc(StripMaterialList[i].texture_name_length);
214 			fread(StripMaterialList[i].texture_name,
215 				  StripMaterialList[i].texture_name_length, 1, in);
216 
217 			if (StripMaterialList[i].texture_name_length > 1) {
218 
219 				for (j = 0; j < StripMaterialList[i].texture_name_length;
220 					 j++)
221 					StripMaterialList[i].texture_name[j] = (char)
222 						tolower(StripMaterialList[i].texture_name[j]);
223 
224 				image =
225 					read_JPEG_file(StripMaterialList[i].texture_name,
226 								   &width, &height, &components);
227 				if (image == NULL) {
228 					sprintf(s, "error reading image %s",
229 							StripMaterialList[i].texture_name);
230 					error(s);
231 					shutdown(1);
232 				}
233 				image = texture_LOD(image, &width, &height, components);
234 				if (components == 1)
235 					j = 1;
236 				else
237 					j = color_depth / 8;
238 				obj->texsize += (width * height * j);
239 
240 				glGenTextures(1, &StripMaterialList[i].texbind);
241 				glBindTexture(GL_TEXTURE_2D, StripMaterialList[i].texbind);
242 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
243 								GL_LINEAR);
244 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
245 								GL_LINEAR);
246 				glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
247 						  GL_MODULATE);
248 				glTexImage2D(GL_TEXTURE_2D, 0,
249 							 components == 3 ? cd_rgb : cd_lum,
250 							 width, height, 0,
251 							 components == 3 ? GL_RGB : GL_LUMINANCE,
252 							 GL_UNSIGNED_BYTE, image);
253 				free(image);
254 			}
255 
256 			/* Read in RGB colors */
257 			fread(&StripMaterialList[i].ambient, sizeof(BMF_RGBCOLOR), 1,
258 				  in);
259 
260 			fread(&StripMaterialList[i].diffuse, sizeof(BMF_RGBCOLOR), 1,
261 				  in);
262 
263 			fread(&StripMaterialList[i].specular,
264 				  sizeof(BMF_RGBCOLOR), 1, in);
265 
266 			/* Get the number of vertices */
267 			fread(&StripMaterialList[i].number_of_vertices,
268 				  sizeof(uword), 1, in);
269 
270 			/* Allocate space for the vertex list */
271 			StripMaterialList[i].vertexlist =
272 				(BMF_UNVERTEX *) malloc(sizeof(BMF_UNVERTEX) *
273 										StripMaterialList
274 										[i].number_of_vertices);
275 
276 			if (StripMaterialList[i].vertexlist == 0) {
277 				error("Error allocating memory for vertexlist\n");
278 				shutdown(1);
279 			}
280 
281 			/* Read in the vertex list */
282 			fread(StripMaterialList[i].vertexlist,
283 				  sizeof(BMF_UNVERTEX),
284 				  StripMaterialList[i].number_of_vertices, in);
285 
286 			for (j = 0; j < StripMaterialList[i].number_of_vertices; j++) {
287 				d = DISTANCE(StripMaterialList[i].vertexlist[j].x,
288 							 StripMaterialList[i].vertexlist[j].y,
289 							 StripMaterialList[i].vertexlist[j].z);
290 				if (d > max)
291 					max = d;
292 			}
293 
294 
295 			/* Read in the number of strips */
296 			fread(&StripMaterialList[i].number_of_strips,
297 				  sizeof(uword), 1, in);
298 
299 			/* Allocate space for the strip length list */
300 			StripMaterialList[i].length_of_strip =
301 				(uword *) malloc(sizeof(uword) *
302 								 StripMaterialList[i].number_of_strips);
303 
304 			/* Read in the triangle strip lengths */
305 			fread(StripMaterialList[i].length_of_strip,
306 				  sizeof(uword), StripMaterialList[i].number_of_strips,
307 				  in);
308 
309 			/* Read in the number of strip points */
310 			fread(&StripMaterialList[i].number_of_strip_indices,
311 				  sizeof(uword), 1, in);
312 
313 			/* Allocate space for the strip length list */
314 			StripMaterialList[i].stripindex =
315 				(uword *) malloc(sizeof(uword) *
316 								 StripMaterialList
317 								 [i].number_of_strip_indices);
318 
319 			/* Read in the triangle strip lengths */
320 			fread(StripMaterialList[i].stripindex,
321 				  sizeof(uword),
322 				  StripMaterialList[i].number_of_strip_indices, in);
323 		}
324 
325 		/* Sorta vertex normalization */
326 		for (i = 0; i < obj->NumMaterials; i++) {
327 			for (j = 0; j < StripMaterialList[i].number_of_vertices; j++) {
328 				StripMaterialList[i].vertexlist[j].x /= max / radius;
329 				StripMaterialList[i].vertexlist[j].y /= max / radius;
330 				StripMaterialList[i].vertexlist[j].z /= max / radius;
331 			}
332 		}
333 	}
334 
335 	fclose(in);
336 	obj->radius = radius;
337 	return obj;
338 }
339