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