5
private GLfloat min_height = float.MAX;
6
private GLfloat max_height = float.MIN;
7
private GLfloat[] vertices;
8
private GLushort[] triangles;
9
private GLfloat[] normals;
10
private GLfloat[] texture_coords;
12
public TDSModel (File file) throws Error
14
var stream = file.read ();
15
parse_block (stream, stream.query_info (FILE_ATTRIBUTE_STANDARD_SIZE).get_size ());
17
/* Calculate normals */
18
normals = new GLfloat[vertices.length];
19
for (int i = 0; i < normals.length; i++)
21
for (int i = 0; i < triangles.length; i += 3)
23
var v0 = triangles[i] * 3;
24
var v1 = triangles[i+1] * 3;
25
var v2 = triangles[i+2] * 3;
27
/* Do cross-product of face to get normal */
28
GLfloat a[3], b[3], normal[3];
29
a[0] = vertices[v1] - vertices[v0];
30
a[1] = vertices[v1+1] - vertices[v0+1];
31
a[2] = vertices[v1+2] - vertices[v0+2];
32
b[0] = vertices[v2] - vertices[v0];
33
b[1] = vertices[v2+1] - vertices[v0+1];
34
b[2] = vertices[v2+2] - vertices[v0+2];
35
normal[0] = a[1]*b[2] - a[2]*b[1];
36
normal[1] = a[2]*b[0] - a[0]*b[2];
37
normal[2] = a[0]*b[1] - a[1]*b[0];
39
/* Add this normal to the three vertices of this face */
40
normals[v0] += normal[0];
41
normals[v0+1] += normal[1];
42
normals[v0+2] += normal[2];
43
normals[v1] += normal[0];
44
normals[v1+1] += normal[1];
45
normals[v1+2] += normal[2];
46
normals[v2] += normal[0];
47
normals[v2+1] += normal[1];
48
normals[v2+2] += normal[2];
51
/* Normalize normals */
52
for (int i = 0; i < normals.length; i += 3)
54
GLfloat length = (GLfloat) Math.sqrt (normals[i]*normals[i] + normals[i+1]*normals[i+1] + normals[i+2]*normals[i+2]);
56
normals[i+1] /= length;
57
normals[i+2] /= length;
60
/* Set texture coordinates to a conical projection */
61
texture_coords = new GLfloat[(vertices.length / 3) * 2];
62
for (int i = 0, j = 0; i < vertices.length; i += 3, j += 2)
65
var v = vertices[i+2];
66
var r = (GLfloat) Math.sqrt (u*u + v*v);
73
/* Maximum height is in the middle of the texture, minimum on the boundary */
74
var h = 1.0f - (vertices[i+1] / max_height);
75
texture_coords[j] = 0.5f + 0.5f * h * u;
76
texture_coords[j+1] = 0.5f + 0.5f * h * v;
80
private void parse_block (FileInputStream stream, int64 length) throws Error
84
var id = read_uint16 (stream);
85
int64 block_length = read_uint32 (stream);
90
if (block_length > length)
93
stderr.printf("Overflow, need %lli octets for %04X, but only have %lli\n", block_length, (int) id, length);
101
//stdout.printf("<root>\n");
102
parse_block (stream, block_length - 6);
103
//stdout.printf("</root>\n");
108
var version = read_uint32 (stream);
109
//stdout.printf("<version>%u</version>\n", version);
114
//stdout.printf("<editor>\n");
115
parse_block (stream, block_length - 6);
116
//stdout.printf("</editor>\n");
121
var name = read_string (stream);
122
//stdout.printf("<object name=\"%s\">\n", name);
123
parse_block (stream, block_length - 6 - (name.length + 1));
124
//stdout.printf("</object>\n");
127
/* Triangular mesh */
129
//stdout.printf("<triangles>\n");
130
parse_block (stream, block_length - 6);
131
//stdout.printf("</triangles>\n");
136
//stdout.printf("<vertices>\n");
137
var n = read_uint16 (stream);
138
vertices = new GLfloat[n*3];
139
for (var i = 0; i < n; i++)
141
var x = read_float (stream);
142
var y = read_float (stream);
143
var z = read_float (stream);
144
var scale = 3.5f; // FIXME: Fix the model files
145
vertices[i*3] = scale*x;
146
vertices[i*3+1] = scale*z;
147
vertices[i*3+2] = scale*y;
155
//stdout.printf ("<vertex x=\"%f\" y=\"%f\" z=\"%f\"/>\n", x, y, z);
157
//stdout.printf("</vertices>\n");
162
//stdout.printf("<faces>\n");
163
if (block_length < 2)
165
var n = read_uint16 (stream);
166
triangles = new GLushort[n*3];
167
if (block_length < 2 + n * 8)
169
stderr.printf("Invalid face data, need %u, have %lli\n", 2+n*8, block_length);
172
for (var i = 0; i < n; i++)
174
var a = read_uint16 (stream);
175
var b = read_uint16 (stream);
176
var c = read_uint16 (stream);
177
/*var flags = */read_uint16 (stream);
178
triangles[i*3] = (GLushort) a;
179
triangles[i*3+1] = (GLushort) c;
180
triangles[i*3+2] = (GLushort) b;
181
//stdout.printf ("<face a=\"%u\" b=\"%u\" c=\"%u\"/ flags=\"%u\">\n", a, b, c, flags);
183
parse_block (stream, block_length - (2 + n*8));
184
//stdout.printf("</faces>\n");
189
//stdout.printf("<keyframe>\n");
190
parse_block (stream, block_length - 6);
191
//stdout.printf("</keyframe>\n");
195
//stdout.printf ("<%04X>", id);
196
for (var i = 0; i < block_length - 6; i++)
198
/*var c = */read_uint8 (stream);
199
//stdout.printf("%02X ", c);
201
//stdout.printf ("<\\%04X>\n", id);
205
length -= block_length;
206
//stream.seek (block_length - 6, SeekType.CUR);
211
return; // throw error
215
public void render ()
217
glEnable (GL_CULL_FACE);
219
glEnableClientState (GL_VERTEX_ARRAY);
220
glEnableClientState (GL_NORMAL_ARRAY);
221
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
223
glVertexPointer (3, GL_FLOAT, 0, vertices);
224
glNormalPointer (GL_FLOAT, 0, normals);
225
glTexCoordPointer (2, GL_FLOAT, 0, texture_coords);
226
glDrawElements (GL_TRIANGLES, (GLsizei) triangles.length, GL_UNSIGNED_SHORT, triangles);
228
glDisableClientState (GL_VERTEX_ARRAY);
229
glDisableClientState (GL_NORMAL_ARRAY);
230
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
233
private uint8 read_uint8 (InputStream stream) throws Error
236
stream.read_all (buffer, null, null);
240
private uint16 read_uint16 (InputStream stream) throws Error
243
stream.read_all (buffer, null, null);
244
return buffer[1] << 8 | buffer[0];
247
private uint32 read_uint32 (InputStream stream) throws Error
250
stream.read_all (buffer, null, null);
251
return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
254
private float read_float (InputStream stream) throws Error
257
stream.read_all (buffer, null, null);
258
float[] fbuffer = (float[]) buffer;
262
private string read_string (InputStream stream) throws Error
264
var value = new StringBuilder();
267
var c = read_uint8 (stream);
270
value.append_c ((char)c);
b'\\ No newline at end of file'