1 /*
2     OpenUniverse 1.0
3     Copyright (C) 2000  Raul Alonso <amil@las.es>
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 Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 
20 /*
21   Initialization routines:
22 
23   	- Read texture images
24   	- Initialize planets' data
25   	- Create display lists
26   	- Other initialization routines
27 */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33 #include <time.h>
34 extern "C" {
35 #include "jpeglib.h"
36 }
37 #include <setjmp.h>
38 #include "ou.h"
39 #include "texture.h"
40 #include "bmf.h"
41 #include "glext.h"
42 
43 GLfloat LightPos[4] = { 0.0, 0.0, 0.0, 1.0 };
44 GLfloat ambient[4] = { 0.2, 0.2, 0.2, 0.0 };
45 GLfloat White[4] = { 1.0, 1.0, 1.0, 1.0 };
46 GLfloat Black[4] = { 0.0, 0.0, 0.0, 1.0 };
47 GLfloat Fog[4] = { 1.0, 0.9, 0.8, 1.0 };
48 float fogdensity = 0.1;
49 int texture = 1, lighting = 1, drawstars = 1, gravity = 1, logo = 1;
50 GLenum smodel = GL_SMOOTH;
51 GLuint StarsDL, MessierDL, MilkyWayDL;
52 int ImgWidth, ImgHeight, components, red, polaris;
53 int width = 640, height = 480;	/* default WIDTH and HEIGHT */
54 planetdata planets[MAXBODIES];
55 stardata stars[NUMSTARS];
56 messierdata messierobjs[MAXMESSIER];
57 double days;
58 int timefactor = 1;				/* iterarion = 1 second */
59 int slices = 16, stacks = 16, NUMBODIES, num_messier, border = 0, filter =
60 	GL_LINEAR;
61 int mipmap = 1, mipmap_filter = GL_LINEAR_MIPMAP_LINEAR;
62 char texturepath[100] = TEXTURE_DIR;
63 char confpath[100] = CONF_DIR;
64 unsigned char tmpimg[258 * 258 * 4], *splash_image;
65 int splashwidth = 0, splashheight = 0, splashbitmap = 1, LOD = HIGH, tex_compr;
66 int color_depth = 24;
67 GLenum cd_rgb, cd_lum, cd_rgba, cd_luma;
68 GLuint splashtex[4], logotex;
69 extern float star_mag;
70 
71 static void SetUpTrails(void);
72 static void Spheroid(double, float, float, float, float, int, int,
73 					 planetdata *, int);
74 void Print(char *), InitLogo(void);
75 GLubyte *read_JPEG_file(char *, int *, int *, int *);
76 
77 
Init(void)78 void Init(void)
79 {
80 	time_t t;
81 
82 
83 	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
84 
85 	t = time(NULL);
86 	srand(t);
87 	days = t / 3600.0 / 24.0 - 10092.0;
88 	initfontengine();
89 	hasPointEXT = glutExtensionSupported("GL_EXT_point_parameters");
90 	tex_compr = glutExtensionSupported("GL_EXT_texture_compression_s3tc");
91 	tex_compr *= glutExtensionSupported("GL_ARB_texture_compression");
92 #ifdef WIN32
93 	InitPointEXT();
94 #endif
95 	ReadConfigFile();
96 	SetUpTrails();
97 	Print("Setting up Stars");
98 	InitStars(star_mag, 1);
99 	Print("Setting up Messier Objects");
100 	InitMessier();
101 	Print("Setting up Milky Way");
102 	InitMilkyWay();
103 	InitLogo();
104 	InitFlares();
105 	glShadeModel(smodel);
106 	glEnable(GL_LIGHTING);
107 	glEnable(GL_LIGHT0);
108 	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
109 	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
110 	glHint((GLenum) GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST);
111 	glEnable(GL_TEXTURE_2D);
112 	glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
113 	glEnable(GL_CULL_FACE);
114 	glEnable(GL_DEPTH_TEST);
115 }
116 
117 
InitLogo(void)118 void InitLogo(void)
119 {
120 	static int i, width, height, components;
121 	static double j;
122 	static unsigned char *image, *localimage;
123 	char sbuf[80];
124 
125 	image = read_JPEG_file("cyclo.jpg", &width, &height, &components);
126 	if (!image) {
127 		sprintf(sbuf, "Couldn't read image %s/cyclo.jpg\n", texturepath);
128 		error(sbuf);
129 		shutdown(1);
130 	}
131 
132 	localimage = (unsigned char *) malloc(width * height * 4);
133 	if (localimage == NULL) {
134 		error("Couldn't allocate memory");
135 		shutdown(1);
136 	}
137 
138 	for (i = 0; i < (width * height); i++) {
139 		localimage[i * 4] = image[i * 3];
140 		localimage[i * 4 + 1] = image[i * 3 + 1];
141 		localimage[i * 4 + 2] = image[i * 3 + 2];
142 		j = (image[i * 3] + image[i * 3 + 1] + image[i * 3 + 2]) / 3.0;
143 		if (j < (double) 100.0)
144 			j = 0.0;
145 		localimage[i * 4 + 3] = j > 255.0 ? 255 : (int) j;
146 	}
147 
148 	glGenTextures(1, &logotex);
149 	glBindTexture(GL_TEXTURE_2D, logotex);
150 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
151 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
152 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
153 	glTexImage2D(GL_TEXTURE_2D,
154 				 0,
155 				 components == 3 ? cd_rgba : cd_luma,
156 				 width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, localimage);
157 	free(image);
158 	free(localimage);
159 }
160 
161 /*
162     A quick and dirty Print function for the opening screen
163 
164     I know it's not the best way to do this but it will only have impact in the
165     loading time ;-)
166 */
Print(char * s)167 void Print(char *s)
168 {
169 	glViewport(0, 0, width, height);
170 	glMatrixMode(GL_PROJECTION);
171 	glLoadIdentity();
172 	gluOrtho2D(0, width, 0, height);
173 	glMatrixMode(GL_MODELVIEW);
174 	glLoadIdentity();
175 
176 	if (splashbitmap) {
177 		if (!splashwidth) {
178 			char *files[4]={"splash1.jpg", "splash2.jpg", "splash3.jpg", "splash4.jpg"};
179 			int i;
180 
181 			splash_image =
182 				read_JPEG_file(files[rand() % 4], &splashwidth, &splashheight,
183 							   &components);
184 
185 			if ((splashwidth != 512) || (splashheight != 512)
186 				|| (components != 3)) {
187 				error("splash.jpg must be 512x512 24bits");
188 				shutdown(1);
189 			}
190 			glGenTextures(4, splashtex);
191 
192 			for (i = 0; i < 256; i++)
193 				memcpy(tmpimg + i * 256 * 3,
194 					   splash_image + i * splashwidth * components,
195 					   256 * components);
196 
197 			glEnable(GL_TEXTURE_2D);
198 			glBindTexture(GL_TEXTURE_2D, splashtex[0]);
199 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
200 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
201 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
202 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
203 			glTexImage2D(GL_TEXTURE_2D,
204 						 0,
205 						 components == 3 ? cd_rgb : cd_lum,
206 						 256, 256,
207 						 0,
208 						 components == 3 ? GL_RGB : GL_LUMINANCE,
209 						 GL_UNSIGNED_BYTE, tmpimg);
210 
211 			for (i = 0; i < 256; i++)
212 				memcpy(tmpimg + i * 256 * 3,
213 					   splash_image + i * splashwidth * components +
214 					   256 * components, 256 * components);
215 
216 			glBindTexture(GL_TEXTURE_2D, splashtex[1]);
217 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
218 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
219 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
220 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
221 			glTexImage2D(GL_TEXTURE_2D,
222 						 0,
223 						 components == 3 ? cd_rgb : cd_lum,
224 						 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, tmpimg);
225 
226 
227 			for (i = 0; i < 256; i++)
228 				memcpy(tmpimg + i * 256 * 3,
229 					   splash_image + (i + 256) * splashwidth * components,
230 					   256 * components);
231 
232 			glBindTexture(GL_TEXTURE_2D, splashtex[2]);
233 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
234 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
235 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
236 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
237 			glTexImage2D(GL_TEXTURE_2D,
238 						 0,
239 						 components == 3 ? cd_rgb : cd_lum,
240 						 256, 256,
241 						 0,
242 						 components == 3 ? GL_RGB : GL_LUMINANCE,
243 						 GL_UNSIGNED_BYTE, tmpimg);
244 
245 			for (i = 0; i < 256; i++)
246 				memcpy(tmpimg + i * 256 * 3,
247 					   splash_image + (i +
248 									   256) * splashwidth * components +
249 					   256 * components, 256 * components);
250 
251 			glBindTexture(GL_TEXTURE_2D, splashtex[3]);
252 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
253 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
254 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
255 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
256 			glTexImage2D(GL_TEXTURE_2D,
257 						 0,
258 						 components == 3 ? cd_rgb : cd_lum,
259 						 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, tmpimg);
260 			free(splash_image);
261 		}
262 
263 		glDisable(GL_LIGHTING);
264 		glDisable(GL_DEPTH_TEST);
265 		glEnable(GL_TEXTURE_2D);
266 		glColor3f(1.0, 1.0, 1.0);
267 
268 		glBindTexture(GL_TEXTURE_2D, splashtex[0]);
269 		glBegin(GL_QUADS);
270 		glTexCoord2f(0.0, 0.0);
271 		glVertex2i(0, 0);
272 		glTexCoord2f(1.0, 0.0);
273 		glVertex2i(width / 2, 0);
274 		glTexCoord2f(1.0, 1.0);
275 		glVertex2i(width / 2, height / 2);
276 		glTexCoord2f(0.0, 1.0);
277 		glVertex2i(0, height / 2);
278 		glEnd();
279 
280 		glBindTexture(GL_TEXTURE_2D, splashtex[1]);
281 		glBegin(GL_QUADS);
282 		glTexCoord2f(0.0, 0.0);
283 		glVertex2i(width / 2, 0);
284 		glTexCoord2f(1.0, 0.0);
285 		glVertex2i(width, 0);
286 		glTexCoord2f(1.0, 1.0);
287 		glVertex2i(width, height / 2);
288 		glTexCoord2f(0.0, 1.0);
289 		glVertex2i(width / 2, height / 2);
290 		glEnd();
291 
292 		glBindTexture(GL_TEXTURE_2D, splashtex[2]);
293 		glBegin(GL_QUADS);
294 		glTexCoord2f(0.0, 0.0);
295 		glVertex2i(0, height / 2);
296 		glTexCoord2f(1.0, 0.0);
297 		glVertex2i(width / 2, height / 2);
298 		glTexCoord2f(1.0, 1.0);
299 		glVertex2i(width / 2, height);
300 		glTexCoord2f(0.0, 1.0);
301 		glVertex2i(0, height);
302 		glEnd();
303 
304 		glBindTexture(GL_TEXTURE_2D, splashtex[3]);
305 		glBegin(GL_QUADS);
306 		glTexCoord2f(0.0, 0.0);
307 		glVertex2i(width / 2, height / 2);
308 		glTexCoord2f(1.0, 0.0);
309 		glVertex2i(width, height / 2);
310 		glTexCoord2f(1.0, 1.0);
311 		glVertex2i(width, height);
312 		glTexCoord2f(0.0, 1.0);
313 		glVertex2i(width / 2, height);
314 		glEnd();
315 
316 	} else
317 		glClear(GL_COLOR_BUFFER_BIT);
318 
319 
320 	switch (fonttype) {
321 	case TEXFONT:
322 		txfBindFontTexture(txf);
323 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
324 		break;
325 	case BMAPFONT:
326 		glDisable(GL_TEXTURE_2D);
327 		glDisable(GL_LIGHTING);
328 		glDisable(GL_DEPTH_TEST);
329 		glColor3f(1.0, 1.0, 1.0);
330 	}
331 	printstring(width / 2 - strlen(s) * glyphwidth / 2, height / 2, 0, s);
332 	glutSwapBuffers();
333 }
334 
335 /*
336     Spheroid drawing routine based on gluSphere Mesa function (src-glu/quadric.c)
337     patched to allow multiple texture objects and flattening.
338 */
Spheroid(double radius,float xflat,float yflat,float zflat,float randomness,int slices,int stacks,planetdata * pdata,int textured)339 static void Spheroid(double radius, float xflat, float yflat, float zflat,
340 					 float randomness, int slices, int stacks,
341 					 planetdata * pdata, int textured)
342 {
343 	static GLfloat rho, drho, theta, dtheta;
344 	GLfloat x, y, z;
345 	GLfloat s, t, ds, dt;
346 	int i, j, k, imin, imax, tex;
347 	double *rarray1, *rarray2, *tmp;
348 
349 
350 	drho = M_PI / (GLfloat) stacks;
351 	dtheta = 2.0 * M_PI / (GLfloat) slices;
352 
353 /* Allocate memory for surface randomness arrays */
354 	rarray1 = (double *) malloc((slices + 1) * 3 * sizeof(double));
355 	rarray2 = (double *) malloc((slices + 1) * 3 * sizeof(double));
356 
357 	if (textured) {
358 
359 		if (stacks % pdata->texheight) {
360 			error("Incorrect STACKS value, edit configuration file\n");
361 			shutdown(1);
362 		}
363 
364 		if (slices % pdata->texwidth) {
365 			error("Incorrect SLICES value, edit configuration file\n");
366 			shutdown(1);
367 		}
368 
369 		ds = 1.0 / slices * pdata->texwidth;
370 		dt = 1.0 / stacks * pdata->texheight;
371 		t = 1.0;
372 		imin = 0;
373 		imax = stacks;
374 
375 
376 		/* Initialize surface randomness arrays */
377 		for (i = 0; i < (slices + 1) * 3; i++) {
378 			rarray1[i] =
379 				(1.0 - randomness) +
380 				(randomness * 2.0 * rand()) / RAND_MAX;
381 			rarray2[i] =
382 				(1.0 - randomness) +
383 				(randomness * 2.0 * rand()) / RAND_MAX;
384 		}
385 
386 		for (i = imin; i < imax; i++) {
387 			rho = i * drho;
388 			if (!(i % (imax / pdata->texheight)))
389 				t = 1.0;
390 			tmp = rarray1;
391 			rarray1 = rarray2;
392 			rarray2 = tmp;
393 			for (k = 0; k < (slices + 1) * 3; k++)
394 				rarray2[k] =
395 					(1.0 - randomness) +
396 					(randomness * 2.0 * rand()) / RAND_MAX;
397 
398 			for (k = 0; k < pdata->texwidth; k++) {
399 				/* Find the texture map we should apply in this iteration */
400 				tex = imax / pdata->texheight;
401 				tex =
402 					(pdata->texwidth * (pdata->texheight - 1) -
403 					 i / tex * pdata->texwidth) + k;
404 				glBindTexture(GL_TEXTURE_2D, pdata->textures[tex]);
405 				glBegin(GL_QUAD_STRIP);
406 				s = 0.0;
407 				/* overwrite last element with first element data */
408 				rarray1[(k + 1) * slices / pdata->texwidth * 3] =
409 					rarray1[k * slices / pdata->texwidth * 3];
410 				rarray1[(k + 1) * slices / pdata->texwidth * 3 + 1] =
411 					rarray1[k * slices / pdata->texwidth * 3 + 1];
412 				rarray1[(k + 1) * slices / pdata->texwidth * 3 + 2] =
413 					rarray1[k * slices / pdata->texwidth * 3 + 2];
414 				rarray2[(k + 1) * slices / pdata->texwidth * 3] =
415 					rarray2[k * slices / pdata->texwidth * 3];
416 				rarray2[(k + 1) * slices / pdata->texwidth * 3 + 1] =
417 					rarray2[k * slices / pdata->texwidth * 3 + 1];
418 				rarray2[(k + 1) * slices / pdata->texwidth * 3 + 2] =
419 					rarray2[k * slices / pdata->texwidth * 3 + 2];
420 				for (j = (k * slices / pdata->texwidth);
421 					 j <= ((k + 1) * slices / pdata->texwidth); j++) {
422 					theta = (j == slices) ? 0.0 : j * dtheta;
423 					x = -sin(theta) * sin(rho) * rarray1[j * 3];
424 					y = cos(theta) * sin(rho) * rarray1[j * 3 + 1];
425 					z = cos(rho) * rarray1[j * 3 + 2];
426 					glNormal3f(x, y, z);
427 					glTexCoord2f(s, t);
428 					glVertex3f(x * radius * (1.0 - xflat),
429 							   y * radius * (1.0 - yflat),
430 							   z * radius * (1.0 - zflat));
431 					x = -sin(theta) * sin(rho + drho) * rarray2[j * 3];
432 					y = cos(theta) * sin(rho + drho) * rarray2[j * 3 + 1];
433 					z = cos(rho + drho) * rarray2[j * 3 + 2];
434 					glNormal3f(x, y, z);
435 					glTexCoord2f(s, t - dt);
436 					s += ds;
437 					glVertex3f(x * radius * (1.0 - xflat),
438 							   y * radius * (1.0 - yflat),
439 							   z * radius * (1.0 - zflat));
440 				}
441 				glEnd();
442 			}
443 			t -= dt;
444 		}
445 	} else {
446 		ds = 1.0 / slices;
447 		dt = 1.0 / stacks;
448 		imin = 0;
449 		imax = stacks;
450 		for (i = imin; i < imax; i++) {
451 			rho = i * drho;
452 			glBegin(GL_QUAD_STRIP);
453 			for (j = 0; j <= slices; j++) {
454 				theta = (j == slices) ? 0.0 : j * dtheta;
455 				x = -sin(theta) * sin(rho);
456 				y = cos(theta) * sin(rho);
457 				z = cos(rho);
458 				glNormal3f(x, y, z);
459 				glVertex3f(x * radius, y * radius, z * radius);
460 				x = -sin(theta) * sin(rho + drho);
461 				y = cos(theta) * sin(rho + drho);
462 				z = cos(rho + drho);
463 				glNormal3f(x, y, z);
464 				glVertex3f(x * radius, y * radius, z * radius);
465 			}
466 			glEnd();
467 		}
468 	}
469 	free(rarray1);
470 	free(rarray2);
471 }
472 
473 
474 
475 /*
476     Read texture, split large textures into 256x256 pieces and set up
477     display lists
478 */
SetUpBody(int body,char * texfile,int compress_texture)479 void SetUpBody(int body, char *texfile, int compress_texture)
480 {
481 	int width = 256, height =
482 		256, x1, x2, x3, y, i, j, k, current;
483 	GLenum gluerr;
484 	BMFObject *obj;
485 	char sbuf[80];
486 	GLenum intformat, format;
487 
488 	sprintf(sbuf, "Setting up body: %s", planets[body].Name);
489 	Print(sbuf);
490 
491 	switch (texfile[strlen(texfile) - 1]) {
492 	case 'f':					/* BMF file */
493 		obj = LoadBMF(texfile, RADIUSSCALE(planets[body].Radius));
494 		planets[body].HighDetail = glGenLists(1);
495 		glNewList(planets[body].HighDetail, GL_COMPILE);
496 		glMaterialf(GL_FRONT, GL_SHININESS, 1.0);
497 		if (obj->sparse) {
498 			for (i = 0; i < obj->NumMaterials; i++) {
499 				glInterleavedArrays(GL_T2F_N3F_V3F, 0,
500 									obj->sparse[i].vertexlist);
501 				glMaterialfv(GL_FRONT, GL_AMBIENT,
502 							 (GLfloat *) & obj->sparse[i].ambient);
503 				glMaterialfv(GL_FRONT, GL_DIFFUSE,
504 							 (GLfloat *) & obj->sparse[i].diffuse);
505 				glMaterialfv(GL_FRONT, GL_SPECULAR,
506 							 (GLfloat *) & obj->sparse[i].specular);
507 
508 				if (obj->sparse[i].texture_name_length > 1) {
509 					glEnable(GL_TEXTURE_2D);
510 					glBindTexture(GL_TEXTURE_2D, obj->sparse[i].texbind);
511 				} else
512 					glDisable(GL_TEXTURE_2D);
513 				glDrawElements(GL_TRIANGLES,
514 							   obj->sparse[i].number_of_triangles * 3,
515 							   GL_UNSIGNED_SHORT,
516 							   obj->sparse[i].indexlist);
517 			}
518 		} else {
519 			for (i = 0; i < obj->NumMaterials; i++) {
520 				glInterleavedArrays(GL_T2F_N3F_V3F, 0,
521 									obj->strip[i].vertexlist);
522 				glMaterialfv(GL_FRONT, GL_AMBIENT,
523 							 (GLfloat *) & obj->strip[i].ambient);
524 				glMaterialfv(GL_FRONT, GL_DIFFUSE,
525 							 (GLfloat *) & obj->strip[i].diffuse);
526 				glMaterialfv(GL_FRONT, GL_SPECULAR,
527 							 (GLfloat *) & obj->strip[i].specular);
528 
529 				if (obj->strip[i].texture_name_length > 1) {
530 					glEnable(GL_TEXTURE_2D);
531 					glBindTexture(GL_TEXTURE_2D, obj->strip[i].texbind);
532 				} else
533 					glDisable(GL_TEXTURE_2D);
534 
535 				current = 0;
536 				for (j = 0; j < obj->strip[i].number_of_strips; j++) {
537 					glDrawElements(GL_TRIANGLE_STRIP,
538 								   obj->strip[i].length_of_strip[j],
539 								   GL_UNSIGNED_SHORT,
540 								   &obj->strip[i].stripindex[current]);
541 					current += obj->strip[i].length_of_strip[j];
542 				}
543 			}
544 		}
545 		glMaterialfv(GL_FRONT, GL_SPECULAR, Black);
546 		glEndList();
547 		planets[body].LowDetail = planets[body].MidDetail =
548 			planets[body].HighDetail;
549 		planets[body].texsize = obj->texsize;
550 		break;
551 
552 	case 'g':					/* Spherical body, JPEG texture */
553 		planets[body].Image =
554 			read_JPEG_file(texfile, &ImgWidth, &ImgHeight, &components);
555 
556 		if (!planets[body].Image) {
557 			sprintf(sbuf, "Couldn't read image %s/%s\n", texturepath,
558 					texfile);
559 			error(sbuf);
560 			shutdown(1);
561 		}
562 
563 		planets[body].Image =
564 			texture_LOD(planets[body].Image, &ImgWidth, &ImgHeight,
565 						components);
566 		if (components == 1)
567 			j = 1;
568 		else
569 			j = color_depth / 8;
570 		planets[body].texsize = (ImgWidth * ImgHeight * j);
571 
572 		if (ImgWidth < width) {
573 			planets[body].texwidth = 1;
574 			width = ImgWidth;
575 		} else
576 			planets[body].texwidth = ImgWidth / width;
577 		if (ImgHeight < height) {
578 			planets[body].texheight = 1;
579 			height = ImgHeight;
580 		} else
581 			planets[body].texheight = ImgHeight / height;
582 		planets[body].texnum =
583 			planets[body].texwidth * planets[body].texheight;
584 		planets[body].textures =
585 			(GLuint *) malloc(planets[body].texnum * sizeof(GLuint));
586 		if (planets[body].textures == NULL) {
587 			error("Couldn't allocate memory");
588 			shutdown(1);
589 		}
590 
591 		intformat = components == 3 ? cd_rgb : cd_lum;
592 		format = components == 3 ? (GLenum) GL_RGB : (GLenum) GL_LUMINANCE;
593 		if ((format == GL_RGB) && tex_compr && compress_texture)
594 			intformat = (GLenum) GL_COMPRESSED_RGB_ARB;
595 
596 
597 		glGenTextures(planets[body].texnum, planets[body].textures);
598 
599 		for (j = 0; j < planets[body].texheight; j++)
600 			for (i = 0; i < planets[body].texwidth; i++) {
601 				glBindTexture(GL_TEXTURE_2D,
602 							  planets[body].textures[planets[body].
603 													 texwidth * j + i]);
604 				if (border) {
605 					/* Copy pixel data to texture buffer and set up borders */
606 					x1 = i * width;
607 					x2 = (i * width + ImgWidth - 1) % ImgWidth;
608 					x3 = ((i + 1) * width) % ImgWidth;
609 					for (k = 0; k < (height + 2); k++) {
610 						y = (j * height + k + ImgHeight - 1) % ImgHeight;
611 						memcpy(tmpimg + k * (width + 2) * components +
612 							   components,
613 							   planets[body].Image +
614 							   y * ImgWidth * components + x1 * components,
615 							   width * components);
616 						memcpy(tmpimg + k * (width + 2) * components,
617 							   planets[body].Image +
618 							   y * ImgWidth * components + x2 * components,
619 							   components);
620 						memcpy(tmpimg + k * (width + 2) * components +
621 							   (width + 1) * components,
622 							   planets[body].Image +
623 							   y * ImgWidth * components + x3 * components,
624 							   components);
625 					}
626 					glTexImage2D(GL_TEXTURE_2D,
627 								 0,
628 								 intformat,
629 								 width + 2, height + 2,
630 								 1,
631 								 format,
632 								 GL_UNSIGNED_BYTE, tmpimg);
633 				} else {
634 					for (k = 0; k < height; k++)
635 						memcpy(tmpimg + k * width * components,
636 							   planets[body].Image +
637 							   ImgWidth * width * components * j +
638 							   width * components * i +
639 							   ImgWidth * components * k,
640 							   width * components);
641 					if (mipmap) {
642 						if (
643 							(gluerr =
644 							 (GLenum) gluBuild2DMipmaps(GL_TEXTURE_2D,
645 														intformat,
646 														width,
647 														height,
648 														format,
649 														GL_UNSIGNED_BYTE,
650 														tmpimg))) {
651 							error((char *) gluErrorString(gluerr));
652 							shutdown(1);
653 						}
654 					} else {
655 						glTexImage2D(GL_TEXTURE_2D,
656 									 0,
657 									 intformat,
658 									 width, height,
659 									 0,
660 									 format,
661 									 GL_UNSIGNED_BYTE, tmpimg);
662 					}
663 				}
664 
665 				if (mipmap) {
666 					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
667 									mipmap_filter);
668 					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
669 									mipmap_filter);
670 				} else {
671 					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
672 									filter);
673 					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
674 									filter);
675 				}
676 				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
677 								GL_CLAMP);
678 				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
679 								GL_CLAMP);
680 			}
681 		free(planets[body].Image);
682 		planets[body].HighDetail = glGenLists(1);
683 		glNewList(planets[body].HighDetail, GL_COMPILE);
684 		Spheroid(RADIUSSCALE(planets[body].Radius), planets[body].xflat,
685 				 planets[body].yflat, planets[body].zflat, 0.0,
686 				 slices, stacks, &planets[body], 1);
687 		glEndList();
688 		planets[body].MidDetail = glGenLists(1);
689 		glNewList(planets[body].MidDetail, GL_COMPILE);
690 		Spheroid(RADIUSSCALE(planets[body].Radius), planets[body].xflat,
691 				 planets[body].yflat, planets[body].zflat, 0.0,
692 				 slices / 2, stacks / 2, &planets[body], 1);
693 		glEndList();
694 		planets[body].LowDetail = glGenLists(1);
695 		glNewList(planets[body].LowDetail, GL_COMPILE);
696 		Spheroid(RADIUSSCALE(planets[body].Radius), planets[body].xflat,
697 				 planets[body].yflat, planets[body].zflat, 0.0,
698 				 slices / 4, stacks / 4, &planets[body], 1);
699 		glEndList();
700 		break;
701 	}
702 }
703 
704 
SetUpAsteroid(int body,char * model)705 void SetUpAsteroid(int body, char *model)
706 {
707 	int i, j, current;
708 	BMFObject *obj;
709 	char sbuf[80];
710 
711 	sprintf(sbuf, "Setting up Asteroid: %s", planets[body].Name);
712 	Print(sbuf);
713 	planets[body].Radius /= RADIUSSCALE(1.0);
714 	obj = LoadBMF(model, RADIUSSCALE(planets[body].Radius));
715 
716 	planets[body].HighDetail = glGenLists(1);
717 	glNewList(planets[body].HighDetail, GL_COMPILE);
718 	glMaterialf(GL_FRONT, GL_SHININESS, 1.0);
719 	if (obj->sparse) {
720 		for (i = 0; i < obj->NumMaterials; i++) {
721 			glInterleavedArrays(GL_T2F_N3F_V3F, 0,
722 								obj->sparse[i].vertexlist);
723 			glMaterialfv(GL_FRONT, GL_AMBIENT,
724 						 (GLfloat *) & obj->sparse[i].ambient);
725 			glMaterialfv(GL_FRONT, GL_DIFFUSE,
726 						 (GLfloat *) & obj->sparse[i].diffuse);
727 			glMaterialfv(GL_FRONT, GL_SPECULAR,
728 						 (GLfloat *) & obj->sparse[i].specular);
729 
730 			if (obj->sparse[i].texture_name_length > 1) {
731 				glEnable(GL_TEXTURE_2D);
732 				glBindTexture(GL_TEXTURE_2D, obj->sparse[i].texbind);
733 			} else
734 				glDisable(GL_TEXTURE_2D);
735 			glDrawElements(GL_TRIANGLES,
736 						   obj->sparse[i].number_of_triangles * 3,
737 						   GL_UNSIGNED_SHORT, obj->sparse[i].indexlist);
738 		}
739 	} else {
740 		for (i = 0; i < obj->NumMaterials; i++) {
741 			glInterleavedArrays(GL_T2F_N3F_V3F, 0,
742 								obj->strip[i].vertexlist);
743 			glMaterialfv(GL_FRONT, GL_AMBIENT,
744 						 (GLfloat *) & obj->strip[i].ambient);
745 			glMaterialfv(GL_FRONT, GL_DIFFUSE,
746 						 (GLfloat *) & obj->strip[i].diffuse);
747 			glMaterialfv(GL_FRONT, GL_SPECULAR,
748 						 (GLfloat *) & obj->strip[i].specular);
749 
750 			if (obj->strip[i].texture_name_length > 1) {
751 				glEnable(GL_TEXTURE_2D);
752 				glBindTexture(GL_TEXTURE_2D, obj->strip[i].texbind);
753 			} else
754 				glDisable(GL_TEXTURE_2D);
755 
756 			current = 0;
757 			for (j = 0; j < obj->strip[i].number_of_strips; j++) {
758 				glDrawElements(GL_TRIANGLE_STRIP,
759 							   obj->strip[i].length_of_strip[j],
760 							   GL_UNSIGNED_SHORT,
761 							   &obj->strip[i].stripindex[current]);
762 				current += obj->strip[i].length_of_strip[j];
763 			}
764 		}
765 	}
766 	glMaterialfv(GL_FRONT, GL_SPECULAR, Black);
767 	glEndList();
768 	planets[body].texsize = obj->texsize;
769 }
770 
771 
772 
SetUpComet(int body,char * texfile,float randomness,float lenght,int num_part)773 void SetUpComet(int body, char *texfile, float randomness, float lenght,
774 				int num_part)
775 {
776 	int i;
777 	float a, b, c, xo, yo, zo, xd, yd, zd;
778 	char sbuf[80];
779 
780 	sprintf(sbuf, "Setting up body: %s", planets[body].Name);
781 	Print(sbuf);
782 
783 	planets[body].tail = (particle *) malloc(sizeof(particle) * num_part);
784 	planets[body].tail_lenght = lenght;
785 	planets[body].num_particles = num_part;
786 	for (i = 0; i < num_part; i++) {
787 		a = (rand() % 360) * M_PI / 180.0;
788 		b = (float) rand() / RAND_MAX;
789 		b *= RADIUSSCALE(planets[body].Radius);
790 		c = (float) i / (float) num_part *lenght;
791 		xo = yo = zo = 0.0;
792 		xd = 0.1 * b / RADIUSSCALE(planets[body].Radius) * sin(a);
793 		yd = RADIUSSCALE(planets[body].Radius);
794 		zd = 0.1 * b / RADIUSSCALE(planets[body].Radius) * cos(a);
795 		planets[body].tail[i].dist = c;
796 		c = DISTANCE(xd, yd, zd);
797 		planets[body].tail[i].origin[0] = xo;
798 		planets[body].tail[i].origin[1] = yo;
799 		planets[body].tail[i].origin[2] = zo;
800 		planets[body].tail[i].dir[0] = xd / c;
801 		planets[body].tail[i].dir[1] = zd / c;
802 		planets[body].tail[i].dir[2] = yd / c;
803 	}
804 }
805 
806 
SetUpOrbiter(int body,char * model)807 void SetUpOrbiter(int body, char *model)
808 {
809 	int i, j, current;
810 	BMFObject *obj;
811 	char sbuf[80];
812 
813 	sprintf(sbuf, "Setting up orbiter: %s", planets[body].Name);
814 	Print(sbuf);
815 	planets[body].Radius /= RADIUSSCALE(1.0);
816 	obj = LoadBMF(model, RADIUSSCALE(planets[body].Radius));
817 	planets[body].HighDetail = glGenLists(1);
818 	glNewList(planets[body].HighDetail, GL_COMPILE);
819 	glMaterialf(GL_FRONT, GL_SHININESS, 1.0);
820 	if (obj->sparse) {
821 		for (i = 0; i < obj->NumMaterials; i++) {
822 			glInterleavedArrays(GL_T2F_N3F_V3F, 0,
823 								obj->sparse[i].vertexlist);
824 			glMaterialfv(GL_FRONT, GL_AMBIENT,
825 						 (GLfloat *) & obj->sparse[i].ambient);
826 			glMaterialfv(GL_FRONT, GL_DIFFUSE,
827 						 (GLfloat *) & obj->sparse[i].diffuse);
828 			glMaterialfv(GL_FRONT, GL_SPECULAR,
829 						 (GLfloat *) & obj->sparse[i].specular);
830 
831 			if (obj->sparse[i].texture_name_length > 1) {
832 				glEnable(GL_TEXTURE_2D);
833 				glBindTexture(GL_TEXTURE_2D, obj->sparse[i].texbind);
834 			} else
835 				glDisable(GL_TEXTURE_2D);
836 			glDrawElements(GL_TRIANGLES,
837 						   obj->sparse[i].number_of_triangles * 3,
838 						   GL_UNSIGNED_SHORT, obj->sparse[i].indexlist);
839 		}
840 	} else {
841 		for (i = 0; i < obj->NumMaterials; i++) {
842 			glInterleavedArrays(GL_T2F_N3F_V3F, 0,
843 								obj->strip[i].vertexlist);
844 			glMaterialfv(GL_FRONT, GL_AMBIENT,
845 						 (GLfloat *) & obj->strip[i].ambient);
846 			glMaterialfv(GL_FRONT, GL_DIFFUSE,
847 						 (GLfloat *) & obj->strip[i].diffuse);
848 			glMaterialfv(GL_FRONT, GL_SPECULAR,
849 						 (GLfloat *) & obj->strip[i].specular);
850 
851 			if (obj->strip[i].texture_name_length > 1) {
852 				glEnable(GL_TEXTURE_2D);
853 				glBindTexture(GL_TEXTURE_2D, obj->strip[i].texbind);
854 			} else
855 				glDisable(GL_TEXTURE_2D);
856 
857 			current = 0;
858 			for (j = 0; j < obj->strip[i].number_of_strips; j++) {
859 				glDrawElements(GL_TRIANGLE_STRIP,
860 							   obj->strip[i].length_of_strip[j],
861 							   GL_UNSIGNED_SHORT,
862 							   &obj->strip[i].stripindex[current]);
863 				current += obj->strip[i].length_of_strip[j];
864 			}
865 		}
866 	}
867 	glMaterialfv(GL_FRONT, GL_SPECULAR, Black);
868 	glEndList();
869 	planets[body].texsize = obj->texsize;
870 }
871 
872 
SetUpSpaceShip(int body,char * model)873 void SetUpSpaceShip(int body, char *model)
874 {
875 	int i, j, current;
876 	BMFObject *obj;
877 	char sbuf[80];
878 
879 	sprintf(sbuf, "Setting up SpaceShip: %s", planets[body].Name);
880 	Print(sbuf);
881 	planets[body].Radius /= RADIUSSCALE(1.0);
882 	obj = LoadBMF(model, RADIUSSCALE(planets[body].Radius));
883 	planets[body].HighDetail = glGenLists(1);
884 	glNewList(planets[body].HighDetail, GL_COMPILE);
885 	glMaterialf(GL_FRONT, GL_SHININESS, 1.0);
886 	if (obj->sparse) {
887 		for (i = 0; i < obj->NumMaterials; i++) {
888 			glInterleavedArrays(GL_T2F_N3F_V3F, 0,
889 								obj->sparse[i].vertexlist);
890 			glMaterialfv(GL_FRONT, GL_AMBIENT,
891 						 (GLfloat *) & obj->sparse[i].ambient);
892 			glMaterialfv(GL_FRONT, GL_DIFFUSE,
893 						 (GLfloat *) & obj->sparse[i].diffuse);
894 			glMaterialfv(GL_FRONT, GL_SPECULAR,
895 						 (GLfloat *) & obj->sparse[i].specular);
896 
897 			if (obj->sparse[i].texture_name_length > 1) {
898 				glEnable(GL_TEXTURE_2D);
899 				glBindTexture(GL_TEXTURE_2D, obj->sparse[i].texbind);
900 			} else
901 				glDisable(GL_TEXTURE_2D);
902 
903 			glDrawElements(GL_TRIANGLES,
904 						   obj->sparse[i].number_of_triangles * 3,
905 						   GL_UNSIGNED_SHORT, obj->sparse[i].indexlist);
906 
907 			if (obj->sparse[i].texture_name_length <= 1)
908 				glEnable(GL_TEXTURE_2D);
909 
910 		}
911 	} else {
912 		for (i = 0; i < obj->NumMaterials; i++) {
913 			glInterleavedArrays(GL_T2F_N3F_V3F, 0,
914 								obj->strip[i].vertexlist);
915 			glMaterialfv(GL_FRONT, GL_AMBIENT,
916 						 (GLfloat *) & obj->strip[i].ambient);
917 			glMaterialfv(GL_FRONT, GL_DIFFUSE,
918 						 (GLfloat *) & obj->strip[i].diffuse);
919 			glMaterialfv(GL_FRONT, GL_SPECULAR,
920 						 (GLfloat *) & obj->strip[i].specular);
921 
922 			if (obj->strip[i].texture_name_length > 1) {
923 				glEnable(GL_TEXTURE_2D);
924 				glBindTexture(GL_TEXTURE_2D, obj->strip[i].texbind);
925 			} else
926 				glDisable(GL_TEXTURE_2D);
927 
928 			current = 0;
929 			for (j = 0; j < obj->strip[i].number_of_strips; j++) {
930 				glDrawElements(GL_TRIANGLE_STRIP,
931 							   obj->strip[i].length_of_strip[j],
932 							   GL_UNSIGNED_SHORT,
933 							   &obj->strip[i].stripindex[current]);
934 				current += obj->strip[i].length_of_strip[j];
935 			}
936 
937 			if (obj->strip[i].texture_name_length <= 1)
938 				glEnable(GL_TEXTURE_2D);
939 
940 		}
941 	}
942 	glMaterialfv(GL_FRONT, GL_SPECULAR, Black);
943 	glEndList();
944 	planets[body].texsize = obj->texsize;
945 }
946 
947 
948 
949 
SetUpRings(int body,char * texfile,float inner_radius,float outter_radius,float tlevel)950 void SetUpRings(int body, char *texfile, float inner_radius,
951 				float outter_radius, float tlevel)
952 {
953 	unsigned char *localimage;
954 	int i;
955 	char sbuf[80];
956 
957 	sprintf(sbuf, "Setting up rings: %s", planets[planets[body].Sat].Name);
958 	Print(sbuf);
959 
960 	planets[body].Image =
961 		read_JPEG_file(texfile, &ImgWidth, &ImgHeight, &components);
962 	if (!planets[body].Image) {
963 		sprintf(sbuf, "Couldn't read image %s/%s\n", texturepath, texfile);
964 		error(sbuf);
965 		shutdown(1);
966 	}
967 
968 	localimage =
969 		(unsigned char *) malloc(ImgHeight * ImgWidth * (components + 1));
970 	if (localimage == NULL) {
971 		error("Couldn't allocate memory");
972 		shutdown(1);
973 	}
974 
975 
976 	switch (components) {
977 	case 1:
978 		for (i = 0; i < (ImgHeight * ImgWidth); i++) {
979 			localimage[i * 2] = planets[body].Image[i];
980 			localimage[i * 2 + 1] =
981 				(unsigned char) (planets[body].Image[i] / tlevel);
982 		}
983 		break;
984 	case 3:
985 		for (i = 0; i < (ImgHeight * ImgWidth); i++) {
986 			localimage[i * 4] = planets[body].Image[i * 3];
987 			localimage[i * 4 + 1] = planets[body].Image[i * 3 + 1];
988 			localimage[i * 4 + 2] = planets[body].Image[i * 3 + 2];
989 			localimage[i * 4 + 3] =
990 				(unsigned
991 				 char) ((planets[body].Image[i * 3] +
992 						 planets[body].Image[i * 3 + 1] +
993 						 planets[body].Image[i * 3 + 2]) / 3 / tlevel);
994 		}
995 		break;
996 	}
997 
998 	planets[body].texnum = 1;
999 	planets[body].textures =
1000 		(GLuint *) malloc(planets[body].texnum * sizeof(GLuint));
1001 	if (planets[body].textures == NULL) {
1002 		error("Couldn't allocate memory");
1003 		shutdown(1);
1004 	}
1005 	glGenTextures(planets[body].texnum, planets[body].textures);
1006 	glBindTexture(GL_TEXTURE_2D, planets[body].textures[0]);
1007 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
1008 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
1009 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1010 	glTexImage2D(GL_TEXTURE_2D,
1011 				 0,
1012 				 components == 3 ? cd_rgba : cd_luma,
1013 				 ImgWidth, ImgHeight,
1014 				 0,
1015 				 components == 3 ? GL_RGBA : GL_LUMINANCE_ALPHA,
1016 				 GL_UNSIGNED_BYTE, localimage);
1017 
1018 	free(planets[body].Image);
1019 	free(localimage);
1020 
1021 
1022 }
1023 
1024 
SetUpAtmosphere(int body,char * texfile,float level,int cut)1025 void SetUpAtmosphere(int body, char *texfile, float level, int cut)
1026 {
1027 	int width = 256, height = 256, x1, x2, x3, y, i, j, k;
1028 	unsigned char localimage[258 * 258 * 4];
1029 	GLenum gluerr;
1030 	char sbuf[80];
1031 
1032 	sprintf(sbuf, "Setting up atmosphere: %s",
1033 			planets[planets[body].Sat].Name);
1034 	Print(sbuf);
1035 
1036 	planets[body].Image =
1037 		read_JPEG_file(texfile, &ImgWidth, &ImgHeight, &components);
1038 	if (!planets[body].Image) {
1039 		sprintf(sbuf, "Couldn't read image %s/%s\n", texturepath, texfile);
1040 		error(sbuf);
1041 		shutdown(1);
1042 	}
1043 
1044 	planets[body].Image =
1045 		texture_LOD(planets[body].Image, &ImgWidth, &ImgHeight,
1046 					components);
1047 	if (components == 1)
1048 		j = 1;
1049 	else
1050 		j = color_depth / 8;
1051 	planets[body].texsize = (ImgWidth * ImgHeight * j);
1052 
1053 	if (ImgWidth < width) {
1054 		planets[body].texwidth = 1;
1055 		width = ImgWidth;
1056 	} else
1057 		planets[body].texwidth = ImgWidth / width;
1058 	if (ImgHeight < height) {
1059 		planets[body].texheight = 1;
1060 		height = ImgHeight;
1061 	} else
1062 		planets[body].texheight = ImgHeight / height;
1063 	planets[body].texnum =
1064 		planets[body].texwidth * planets[body].texheight;
1065 	planets[body].textures =
1066 		(GLuint *) malloc(planets[body].texnum * sizeof(GLuint));
1067 	if (planets[body].textures == NULL) {
1068 		error("Couldn't allocate memory");
1069 		shutdown(1);
1070 	}
1071 	glGenTextures(planets[body].texnum, planets[body].textures);
1072 
1073 	for (j = 0; j < planets[body].texheight; j++)
1074 		for (i = 0; i < planets[body].texwidth; i++) {
1075 
1076 			glBindTexture(GL_TEXTURE_2D,
1077 						  planets[body].textures[planets[body].texwidth *
1078 												 j + i]);
1079 
1080 			if (border) {
1081 				/* Copy pixel data to texture buffer and set up borders */
1082 				x1 = i * width;
1083 				x2 = (i * width + ImgWidth - 1) % ImgWidth;
1084 				x3 = ((i + 1) * width) % ImgWidth;
1085 				for (k = 0; k < (height + 2); k++) {
1086 					y = (j * height + k + ImgHeight - 1) % ImgHeight;
1087 					memcpy(tmpimg + k * (width + 2) * components +
1088 						   components,
1089 						   planets[body].Image +
1090 						   y * ImgWidth * components + x1 * components,
1091 						   width * components);
1092 					memcpy(tmpimg + k * (width + 2) * components,
1093 						   planets[body].Image +
1094 						   y * ImgWidth * components + x2 * components,
1095 						   components);
1096 					memcpy(tmpimg + k * (width + 2) * components +
1097 						   (width + 1) * components,
1098 						   planets[body].Image +
1099 						   y * ImgWidth * components + x3 * components,
1100 						   components);
1101 				}
1102 
1103 				for (k = 0; k < (258 * 258); k++) {
1104 					localimage[k * (components + 1)] =
1105 						tmpimg[k * components];
1106 					localimage[k * (components + 1) + 1] =
1107 						tmpimg[k * components + 1];
1108 					localimage[k * (components + 1) + 2] =
1109 						tmpimg[k * components + 2];
1110 					if (components == 3)
1111 						y =
1112 							(tmpimg[k * 3] + tmpimg[k * 3 + 1] +
1113 							 tmpimg[k * 3 + 2]) / 3;
1114 					else
1115 						y = tmpimg[k];
1116 					if (y < cut)
1117 						y = 0;
1118 					localimage[k * (components + 1) + components] =
1119 						(unsigned char) ((float) y / level);
1120 				}
1121 
1122 				glTexImage2D(GL_TEXTURE_2D,
1123 							 0,
1124 							 components == 3 ? cd_rgba : cd_luma,
1125 							 width + 2, height + 2,
1126 							 1,
1127 							 components ==
1128 							 3 ? GL_RGBA : GL_LUMINANCE_ALPHA,
1129 							 GL_UNSIGNED_BYTE, localimage);
1130 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1131 								filter);
1132 			} else {
1133 				for (k = 0; k < height; k++)
1134 					memcpy(tmpimg + k * width * components,
1135 						   planets[body].Image +
1136 						   ImgWidth * width * components * j +
1137 						   width * components * i +
1138 						   ImgWidth * components * k, width * components);
1139 
1140 				for (k = 0; k < (256 * 256); k++) {
1141 					localimage[k * (components + 1)] =
1142 						tmpimg[k * components];
1143 					localimage[k * (components + 1) + 1] =
1144 						tmpimg[k * components + 1];
1145 					localimage[k * (components + 1) + 2] =
1146 						tmpimg[k * components + 2];
1147 					if (components == 3)
1148 						y =
1149 							(tmpimg[k * 3] + tmpimg[k * 3 + 1] +
1150 							 tmpimg[k * 3 + 2]) / 3;
1151 					else
1152 						y = tmpimg[k];
1153 					if (y < cut)
1154 						y = 0;
1155 					localimage[k * (components + 1) + components] =
1156 						(unsigned char) ((float) y / level);
1157 				}
1158 
1159 				if (mipmap) {
1160 					if (
1161 						(gluerr =
1162 						 (GLenum) gluBuild2DMipmaps(GL_TEXTURE_2D,
1163 													components ==
1164 													3 ? cd_rgba : cd_luma,
1165 													width, height,
1166 													components ==
1167 													3 ? GL_RGBA :
1168 													GL_LUMINANCE_ALPHA,
1169 													GL_UNSIGNED_BYTE,
1170 													localimage))) {
1171 						error((char *) gluErrorString(gluerr));
1172 						shutdown(1);
1173 					}
1174 					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1175 									mipmap_filter);
1176 				} else {
1177 					glTexImage2D(GL_TEXTURE_2D,
1178 								 0,
1179 								 components == 3 ? cd_rgba : cd_luma,
1180 								 width, height,
1181 								 0,
1182 								 components ==
1183 								 3 ? GL_RGBA : GL_LUMINANCE_ALPHA,
1184 								 GL_UNSIGNED_BYTE, localimage);
1185 					glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1186 									filter);
1187 				}
1188 
1189 			}
1190 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1191 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1192 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
1193 		}
1194 	free(planets[body].Image);
1195 	planets[body].HighDetail = glGenLists(1);
1196 	glNewList(planets[body].HighDetail, GL_COMPILE);
1197 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1198 	glEnable(GL_BLEND);
1199 	Spheroid(RADIUSSCALE(planets[body].Radius),
1200 			 planets[planets[body].Sat].xflat,
1201 			 planets[planets[body].Sat].yflat,
1202 			 planets[planets[body].Sat].zflat, 0.0, slices, stacks,
1203 			 &planets[body], 1);
1204 	glDisable(GL_BLEND);
1205 	glEndList();
1206 	planets[body].MidDetail = glGenLists(1);
1207 	glNewList(planets[body].MidDetail, GL_COMPILE);
1208 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1209 	glEnable(GL_BLEND);
1210 	Spheroid(RADIUSSCALE(planets[body].Radius),
1211 			 planets[planets[body].Sat].xflat,
1212 			 planets[planets[body].Sat].yflat,
1213 			 planets[planets[body].Sat].zflat, 0.0, slices / 2, stacks / 2,
1214 			 &planets[body], 1);
1215 	glDisable(GL_BLEND);
1216 	glEndList();
1217 	planets[body].LowDetail = glGenLists(1);
1218 	glNewList(planets[body].LowDetail, GL_COMPILE);
1219 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1220 	glEnable(GL_BLEND);
1221 	Spheroid(RADIUSSCALE(planets[body].Radius),
1222 			 planets[planets[body].Sat].xflat,
1223 			 planets[planets[body].Sat].yflat,
1224 			 planets[planets[body].Sat].zflat, 0.0, slices / 4, stacks / 4,
1225 			 &planets[body], 1);
1226 	glDisable(GL_BLEND);
1227 	glEndList();
1228 }
1229 
1230 
1231 
SetUpTrails(void)1232 static void SetUpTrails(void)
1233 {
1234 	int i, j;
1235 	double d;
1236 
1237 	Print("Setting up Trails");
1238 	for (i = 1; i < NUMBODIES; i++) {
1239 		if ((planets[i].Type != PLANET) &&
1240 			(planets[i].Type != ASTEROID) && (planets[i].Type != COMET))
1241 			continue;
1242 		planets[i].Trail = glGenLists(1);
1243 		glNewList(planets[i].Trail, GL_COMPILE);
1244 		glColor3f(planets[i].Color[0], planets[i].Color[1],
1245 				  planets[i].Color[2]);
1246 		glBegin(GL_LINE_LOOP);
1247 		d = 0.0;
1248 		for (j = 0; j < 360; j++) {
1249 			UpdatePositions(d, i);
1250 			glVertex3dv(planets[i].pos);
1251 			d += planets[i].OrbitalPeriod / 360.0;
1252 		}
1253 		glEnd();
1254 		glEndList();
1255 	}
1256 }
1257 
1258 
1259 
InitSun(char * filename,double blend,int cutlevel)1260 void InitSun(char *filename, double blend, int cutlevel)
1261 {
1262 	static int i;
1263 	char sbuf[80];
1264 
1265 	Print("Setting up The Sun");
1266 
1267 	planets[0].Radius = 2.0;	/*Real Radius is 109.6 */
1268 	planets[0].Degrees = 0.0;
1269 	planets[0].DeltaRotation = 0.0;
1270 	planets[0].Rotation = 360.0 / 28.0;
1271 	planets[0].Inclination = 0.0;
1272 	planets[0].Sat = 0;
1273 	INITVECTOR(planets[0].pos, 0.0, 0.0, 0.0);
1274 	INITVECTOR(planets[0].vel, 0.0, 0.0, 0.0);
1275 	sprintf(planets[0].Name, "Sun");
1276 
1277 	planets[0].Image =
1278 		read_JPEG_file(filename, &ImgWidth, &ImgHeight, &components);
1279 	if (!planets[0].Image) {
1280 		sprintf(sbuf, "Couldn't read image %s/sun.jpg\n", texturepath);
1281 		error(sbuf);
1282 		shutdown(1);
1283 	}
1284 	if (components == 1)
1285 		i = 1;
1286 	else
1287 		i = color_depth / 8;
1288 	planets[0].texsize = (ImgWidth * ImgHeight * i);
1289 
1290 	planets[0].texnum = 7;
1291 	planets[0].textures = (GLuint *) malloc(sizeof(GLuint) * 7);
1292 	if (planets[0].textures == NULL) {
1293 		error("Couldn't allocate memory");
1294 		shutdown(1);
1295 	}
1296 
1297 	glGenTextures(7, planets[0].textures);
1298 	glBindTexture(GL_TEXTURE_2D, planets[0].textures[0]);
1299 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
1300 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
1301 	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1302 	glTexImage2D(GL_TEXTURE_2D,
1303 				 0,
1304 				 components == 3 ? cd_rgb : cd_lum,
1305 				 ImgWidth, ImgHeight,
1306 				 0, GL_RGB, GL_UNSIGNED_BYTE, planets[0].Image);
1307 
1308 	free(planets[0].Image);
1309 }
1310