1 /***************************************************************************
2 
3 	file                 : elevation.cpp
4 	created              : Mon May 20 22:31:09 CEST 2002
5 	copyright            : (C) 2001 by Eric Espie
6 	email                : eric.espie@torcs.org
7 	version              : $Id: elevation.cpp,v 1.9.2.4 2012/02/09 22:36:25 berniw Exp $
8 
9 ***************************************************************************/
10 
11 /***************************************************************************
12 *                                                                         *
13 *   This program is free software; you can redistribute it and/or modify  *
14 *   it under the terms of the GNU General Public License as published by  *
15 *   the Free Software Foundation; either version 2 of the License, or     *
16 *   (at your option) any later version.                                   *
17 *                                                                         *
18 ***************************************************************************/
19 
20 /** @file
21 
22 	@author	<a href=mailto:eric.espie@torcs.org>Eric Espie</a>
23 	@version	$Id: elevation.cpp,v 1.9.2.4 2012/02/09 22:36:25 berniw Exp $
24  */
25 
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <stdlib.h>
31 #ifndef WIN32
32 #include <unistd.h>
33 #endif
34 #include <math.h>
35 
36 #include <tgfclient.h>
37 #include <track.h>
38 #include <portability.h>
39 
40 #include "trackgen.h"
41 #include "util.h"
42 #include "elevation.h"
43 
44 static unsigned char	*ElvImage;
45 static int	ElvOk = 0;
46 static tdble 	Margin;
47 
48 static tdble	kX, kY, dX, dY;
49 static tdble	kZ, dZ;
50 static int	width, height;
51 
52 #define MAX_CLR	255.0
53 
LoadElevation(tTrack * track,void * TrackHandle,char * imgFile)54 void LoadElevation(tTrack *track, void *TrackHandle, char *imgFile)
55 {
56 	tdble zmin, zmax;
57 	tdble xmin, xmax, ymin, ymax;
58 
59 	ElvImage = GfImgReadPng(imgFile, &width, &height, 2.0);
60 	if (!ElvImage) {
61 		return;
62 	}
63 
64 	printf("Loading Elevation Map %s\n", imgFile);
65 
66 	Margin = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_BMARGIN, NULL, Margin);
67 
68 	xmin = track->min.x - Margin;
69 	xmax = track->max.x + Margin;
70 	ymin = track->min.y - Margin;
71 	ymax = track->max.y + Margin;
72 
73 	kX = (tdble)(width - 1) / (xmax - xmin);
74 	dX = -xmin * kX;
75 	kY = (tdble)(height - 1) / (ymax - ymin);
76 	dY = -ymin * kY;
77 	ElvOk = 1;
78 
79 	zmin = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_ALT_MIN, NULL, track->min.z);
80 	zmax = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_ALT_MAX, NULL, track->max.z);
81 
82 	dZ = zmin;
83 	kZ = (zmax - dZ) / MAX_CLR;
84 }
85 
86 
GetElevation(tdble x,tdble y,tdble z)87 tdble GetElevation(tdble x, tdble y, tdble z)
88 {
89 	int iX, iY;
90 	int clr;
91 
92 	if (ElvOk) {
93 		iX = (int)(x * kX + dX);
94 		iY = (int)(y * kY + dY);
95 		/* RGBA */
96 		clr = ElvImage[4 * (iY * width + iX)];
97 		return (tdble)clr * kZ + dZ;
98 	}
99 
100 	return z;
101 }
102 
103 
SaveElevation(tTrack * track,void * TrackHandle,char * imgFile,char * meshFile,int dispf)104 void SaveElevation(tTrack *track, void *TrackHandle, char *imgFile, char *meshFile, int dispf)
105 {
106 	ssgLoaderOptionsEx options;
107 	float zmin, zmax;
108 	float xmin, xmax, ymin, ymax;
109 	float x, y, z;
110 	int clr;
111 	int i, j, k, l;
112 	ssgRoot	*root;
113 	int columns;
114 	const int BUFSIZE = 1024;
115 	static char	buf[BUFSIZE];
116 	char *s;
117 	float heightStep;
118 
119 	s = getenv("COLUMNS");
120 	if (s) {
121 		columns = strtol(getenv("COLUMNS"), NULL, 0);
122 	} else {
123 		columns = 80;
124 	}
125 
126 	Margin = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_BMARGIN, NULL, Margin);
127 
128 	xmin = track->min.x - Margin;
129 	xmax = track->max.x + Margin;
130 	ymin = track->min.y - Margin;
131 	ymax = track->max.y + Margin;
132 
133 	width = 1024;
134 	height = (int)((ymax - ymin) * width / (xmax - xmin));
135 
136 	printf("Generating Elevation Map %s (%d, %d)\n", imgFile, width, height);
137 	kX = (xmax - xmin) / width;
138 	dX = xmin;
139 	kY = (ymax - ymin) / height;
140 	dY = ymin;
141 
142 	zmin = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_ALT_MIN, NULL, track->min.z);
143 	zmax = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_ALT_MAX, NULL, track->max.z);
144 
145 	heightStep = (float)(zmax - zmin) / (float)HeightSteps;
146 	if (dispf == 2) {
147 		printf("Height of steps = %f\n", heightStep);
148 	}
149 
150 	kZ = MAX_CLR / (zmax - zmin);
151 	dZ = - zmin * MAX_CLR / (zmax - zmin);
152 
153 	ElvImage = (unsigned char*)calloc(width * height, 3);
154 	if (!ElvImage) {
155 		return;
156 	}
157 
158 	ssgSetCurrentOptions(&options);
159 	snprintf(buf, BUFSIZE, "tracks/%s/%s;data/textures;data/img;.", track->category, track->internalname);
160 	ssgTexturePath(buf);
161 	snprintf(buf, BUFSIZE, ".;tracks/%s/%s", track->category, track->internalname);
162 	ssgModelPath(buf);
163 	root = (ssgRoot*)ssgLoadAC(meshFile);
164 
165 	if (root == NULL) {
166 		printf("Could not load %s, ", meshFile);
167 		printf("please generate it with \"trackgen -c %s -n %s -a\"\n", track->category, track->internalname);
168 		return;
169 	}
170 
171 	l = columns - 18;
172 	for (j = 0; j < height; j++) {
173 		s = buf;
174 		s += snprintf(buf, BUFSIZE, "%4d%% |", (j+1) * 100 / height);
175 		for (k = s - buf; k < s - buf + l; k++) {
176 			if ((k - (s - buf)) > (l * (j+1) / height)) {
177 				buf[k] = ' ';
178 			} else {
179 				buf[k] = '*';
180 			}
181 		}
182 		s += l;
183 		sprintf(s, "| row %4d", j+1);
184 		printf("\r%s", buf);
185 		fflush(stdout);
186 		for (i = 0; i < width; i++) {
187 			x = i * kX + dX;
188 			y = j * kY + dY;
189 			z = getHOT(root, x, y);
190 			if (z != -1000000.0f) {
191 				switch (dispf) {
192 					case 0:
193 						clr = 0;
194 						break;
195 					case 1:
196 						clr = (int)(z * kZ + dZ);
197 						break;
198 					case 2:
199 						clr = (int)(floor((z + heightStep / 2.0) / heightStep) * heightStep * kZ + dZ);
200 						break;
201 					default:
202 						clr = 0;
203 						break;
204 				}
205 			} else {
206 				clr = (int)MAX_CLR;
207 			}
208 
209 			ElvImage[3 * (i + width * j)]     = (unsigned char)clr;
210 			ElvImage[3 * (i + width * j) + 1] = (unsigned char)clr;
211 			ElvImage[3 * (i + width * j) + 2] = (unsigned char)clr;
212 		}
213 	}
214 
215 	printf("\n");
216 	GfImgWritePng(ElvImage, imgFile, width, height);
217 }
218