1 #include <iostream>
2 #include <fstream>
3 #include <cmath>
4 #include <cstdio>
5
6 #include <io.h>
7 #include <fcntl.h>
8
9 #include "../../celmath/vecmath.h"
10
11 using namespace std;
12
13
14 typedef unsigned int uint32;
15
16 // TODO: these shouldn't be hardcoded
17 static int latSamples = 1440;
18 static int longSamples = 2880;
19
20 const float pi = 3.14159265;
21
22 static float* samples = NULL;
23
24 // Read a big-endian 32-bit unsigned integer
readUint(istream & in)25 static uint32 readUint(istream& in)
26 {
27 uint32 ret;
28 in.read((char*) &ret, sizeof(uint32));
29 return (uint32) ret;
30 }
31
32
readFloat(istream & in)33 static float readFloat(istream& in)
34 {
35 uint32 i = readUint(in);
36 uint32 n = ((i & 0xff) << 24) | ((i & 0xff00) << 8) | ((i & 0xff0000) >> 8) | ((i & 0xff000000) >> 24);
37 return *((float*) &n);
38 }
39
40
readLongLatAscii(istream & in)41 bool readLongLatAscii(istream& in)
42 {
43 return false;
44 }
45
46
readBinary(istream & in,unsigned int latSampleCount,unsigned int longSampleCount)47 bool readBinary(istream& in,
48 unsigned int latSampleCount,
49 unsigned int longSampleCount)
50 {
51 for (unsigned int i = 0; i < latSampleCount; i++)
52 {
53 for (unsigned int j = 0; j < longSampleCount; j++)
54 {
55 float r = readFloat(in) / 1000.0f;
56 samples[i * longSampleCount + j] = r;
57 }
58 }
59
60 return true;
61 }
62
63
sample(float samples[],unsigned int width,unsigned int height,float s,float t)64 inline float sample(float samples[],
65 unsigned int width,
66 unsigned int height,
67 float s,
68 float t)
69 {
70 float ssamp = (float) (width - 1) + 0.99f;
71 float tsamp = (float) (height - 1) + 0.99f;
72
73 return samples[(unsigned int) (t * tsamp) * width +
74 (unsigned int) (s * ssamp)];
75 }
76
77
sampleBilinear(float samples[],unsigned int width,unsigned int height,float s,float t)78 inline float sampleBilinear(float samples[],
79 unsigned int width,
80 unsigned int height,
81 float s,
82 float t)
83 {
84 unsigned int x0 = (unsigned int) (s * width) % width;
85 unsigned int y0 = (unsigned int) (t * height) % height;
86 unsigned int x1 = (unsigned int) (x0 + 1) % width;
87 unsigned int y1 = (unsigned int) (y0 + 1) % height;
88
89 float tx = s * width - (float) (unsigned int) (s * width);
90 float ty = t * height - (float) (unsigned int) (t * height);
91
92 float s00 = samples[y0 * width + x0];
93 float s01 = samples[y0 * width + x1];
94 float s10 = samples[y1 * width + x0];
95 float s11 = samples[y1 * width + x1];
96
97 float s0 = (1.0f - tx) * s00 + tx * s01;
98 float s1 = (1.0f - tx) * s10 + tx * s11;
99
100 return (1.0f - ty) * s0 + ty * s1;
101 }
102
103
104 // subdiv is the number of rows in the triangle
triangleSection(unsigned int subdiv,Vec3f v0,Vec3f v1,Vec3f v2,Vec2f tex0,Vec2f tex1,Vec2f tex2)105 void triangleSection(unsigned int subdiv,
106 Vec3f v0, Vec3f v1, Vec3f v2,
107 Vec2f tex0, Vec2f tex1, Vec2f tex2)
108 {
109 float ssamp = (float) (longSamples - 1) + 0.99f;
110 float tsamp = (float) (latSamples - 1) + 0.99f;
111
112 for (unsigned int i = 0; i <= subdiv; i++)
113 {
114 for (unsigned int j = 0; j <= i; j++)
115 {
116 float u = (i == 0) ? 0.0f : (float) j / (float) i;
117 float v = (float) i / (float) subdiv;
118
119 Vec3f w0 = (1.0f - v) * v0 + v * v1;
120 Vec3f w1 = (1.0f - v) * v0 + v * v2;
121 Vec3f w = (1.0f - u) * w0 + u * w1;
122
123 Vec2f t((1.0f - u) * tex1.x + u * tex2.x,
124 (1.0f - v) * tex0.y + v * tex1.y);
125
126 w.normalize();
127
128 if (samples != NULL)
129 {
130 float theta = (float) acos(w.y);
131 float phi = (float) atan2(-w.z, w.x);
132 float s = phi / (2.0f * pi) + 0.5f;
133 float t = theta / pi;
134
135 float r = sampleBilinear(samples, longSamples, latSamples, s, t);
136
137 w = w * r;
138 }
139
140 cout << w.x << " " << w.y << " " << w.z << " "
141 << t.x << " " << t.y << "\n";
142 }
143 }
144 }
145
146
147 // return the nth triangular number
trinum(unsigned int n)148 inline unsigned int trinum(unsigned int n)
149 {
150 return (n * (n + 1)) / 2;
151 }
152
153
triangleMesh(unsigned int subdiv,unsigned int baseIndex)154 void triangleMesh(unsigned int subdiv,
155 unsigned int baseIndex)
156 {
157 for (unsigned int i = 0; i < subdiv; i++)
158 {
159 for (unsigned int j = 0; j <= i; j++)
160 {
161 unsigned int t0 = baseIndex + trinum(i) + j;
162 unsigned int t1 = baseIndex + trinum(i + 1) + j;
163
164 cout << t0 << " " << t1 << " " << t1 + 1 << "\n";
165 if (j != i)
166 cout << t0 << " " << t1 + 1 << " " << t0 + 1 << "\n";
167 }
168 }
169 }
170
171
main(int argc,char * argv[])172 int main(int argc, char* argv[])
173 {
174 // Get the command line arguments
175 if (argc != 4)
176 {
177 cerr << "Usage: cmodsphere <width> <height> <tessellation>\n";
178 return 1;
179 }
180
181 if (sscanf(argv[1], "%u", &longSamples) != 1)
182 {
183 cerr << "Invalid width\n";
184 return 1;
185 }
186
187 if (sscanf(argv[2], "%u", &latSamples) != 1)
188 {
189 cerr << "Invalid height\n";
190 return 1;
191 }
192
193 unsigned int subdiv = 0;
194 if (sscanf(argv[3], "%u", &subdiv) != 1)
195 {
196 cerr << "Invalid tessellation level\n";
197 return 1;
198 }
199
200 samples = new float[latSamples * longSamples];
201
202 #ifdef _WIN32
203 // Enable binary reads for stdin on Windows
204 _setmode(_fileno(stdin), _O_BINARY);
205 #endif
206
207 // Read the height map
208 readBinary(cin, latSamples, longSamples);
209
210 // Output the mesh header
211 cout << "#celmodel__ascii\n";
212 cout << "\n";
213
214 cout << "material\n";
215 cout << "diffuse 0.8 0.8 0.8\n";
216 cout << "end_material\n";
217 cout << "\n";
218
219 cout << "mesh\n";
220 cout << "vertexdesc\n";
221 cout << "position f3\n";
222 cout << "texcoord0 f2\n";
223 cout << "end_vertexdesc\n";
224 cout << "\n";
225
226 // Octahedral subdivision; the subdivison level for an a face
227 // is one fourth the overall tessellation level.
228 unsigned int primitiveFaces = 8;
229 subdiv = subdiv / 4;
230
231 unsigned int s1 = subdiv + 1;
232 unsigned int verticesPerPrimFace = (s1 * s1 + s1) / 2;
233 unsigned int vertexCount = primitiveFaces * verticesPerPrimFace;
234 unsigned int trianglesPerPrimFace = s1 * s1 - 2 * s1 + 1;
235 unsigned int triangleCount = primitiveFaces * trianglesPerPrimFace;
236
237 cout << "vertices " << vertexCount << "\n";
238
239 triangleSection(subdiv,
240 Vec3f(0.0f, 1.0f, 0.0f),
241 Vec3f(1.0f, 0.0f, 0.0f),
242 Vec3f(0.0f, 0.0f, -1.0f),
243 Vec2f(0.0f, 0.0f),
244 Vec2f(0.00f, 0.5f),
245 Vec2f(0.25f, 0.5f));
246 triangleSection(subdiv,
247 Vec3f(0.0f, 1.0f, 0.0f),
248 Vec3f(0.0f, 0.0f, 1.0f),
249 Vec3f(1.0f, 0.0f, 0.0f),
250 Vec2f(0.0f, 0.0f),
251 Vec2f(0.75f, 0.5f),
252 Vec2f(1.00f, 0.5f));;
253 triangleSection(subdiv,
254 Vec3f(0.0f, 1.0f, 0.0f),
255 Vec3f(-1.0f, 0.0f, 0.0f),
256 Vec3f(0.0f, 0.0f, 1.0f),
257 Vec2f(0.0f, 0.0f),
258 Vec2f(0.50f, 0.5f),
259 Vec2f(0.75f, 0.5f));
260 triangleSection(subdiv,
261 Vec3f(0.0f, 1.0f, 0.0f),
262 Vec3f(0.0f, 0.0f, -1.0f),
263 Vec3f(-1.0f, 0.0f, 0.0f),
264 Vec2f(0.0f, 0.0f),
265 Vec2f(0.25f, 0.5f),
266 Vec2f(0.50f, 0.5f));
267
268 triangleSection(subdiv,
269 Vec3f(0.0f, -1.0f, 0.0f),
270 Vec3f(0.0f, 0.0f, -1.0f),
271 Vec3f(1.0f, 0.0f, 0.0f),
272 Vec2f(0.0f, 1.0f),
273 Vec2f(0.25f, 0.5f),
274 Vec2f(0.00f, 0.5f));
275 triangleSection(subdiv,
276 Vec3f(0.0f, -1.0f, 0.0f),
277 Vec3f(1.0f, 0.0f, 0.0f),
278 Vec3f(0.0f, 0.0f, 1.0f),
279 Vec2f(0.0f, 1.0f),
280 Vec2f(1.00f, 0.5f),
281 Vec2f(0.75f, 0.5f));
282 triangleSection(subdiv,
283 Vec3f(0.0f, -1.0f, 0.0f),
284 Vec3f(0.0f, 0.0f, 1.0f),
285 Vec3f(-1.0f, 0.0f, 0.0f),
286 Vec2f(0.0f, 1.0f),
287 Vec2f(0.75f, 0.5f),
288 Vec2f(0.50f, 0.5f));
289 triangleSection(subdiv,
290 Vec3f(0.0f, -1.0f, 0.0f),
291 Vec3f(-1.0f, 0.0f, 0.0f),
292 Vec3f(0.0f, 0.0f, -1.0f),
293 Vec2f(0.0f, 1.0f),
294 Vec2f(0.50f, 0.5f),
295 Vec2f(0.25f, 0.5f));
296
297 cout << "trilist 0 " << triangleCount * 3 << "\n";
298
299 for (unsigned int f = 0; f < primitiveFaces; f++)
300 {
301 triangleMesh(subdiv, f * verticesPerPrimFace);
302 }
303
304 cout << "end_mesh\n";
305 }
306