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