';
90 |
91 | $('#log tbody').append(html);
92 |
93 | console.log("LOG: " + message);
94 | }
95 |
96 | /**
97 | * Checks the support of necessary APIs.
98 | */
99 | function checkRequiredAPI()
100 | {
101 | if (window.File && window.FileReader && window.FileList)
102 | log('FileReader API is supported', LogType.SUCCESS);
103 | else
104 | {
105 | log('FileReader API is not supported. No BSP files can be loaded!', LogType.ERROR);
106 | return false;
107 | }
108 |
109 | if (window.ArrayBuffer)
110 | log('ArrayBuffer API is supported', LogType.SUCCESS);
111 | else
112 | {
113 | log('ArrayBuffer API is not supported. No BSP files can be loaded!', LogType.ERROR);
114 | return false;
115 | }
116 |
117 | // This is VERY new
118 | // Khronos Editor's Draft 08 December 2011
119 | // http://www.khronos.org/registry/typedarray/specs/latest/#8
120 | if (window.DataView)
121 | log('DataView API is supported', LogType.SUCCESS);
122 | else
123 | log('DataView API is not supported. Parsing files may take longer!', LogType.WARNING);
124 |
125 | return true;
126 | }
127 |
128 | /**
129 | * Actives the WebGL context on the canvas. Sets var gl to the context handle.
130 | */
131 | function initWebGL()
132 | {
133 | var context;
134 |
135 | canvas = $('canvas')[0];
136 |
137 | try
138 | {
139 | // Try to grab the standard context
140 | log('Trying to get webgl context');
141 | context = 'webgl';
142 | gl = canvas.getContext(context);
143 | }
144 | catch(e)
145 | {
146 | log('Failed to grab webgl context: ' + e, LogType.ERROR);
147 | }
148 |
149 | if(!gl)
150 | {
151 | try
152 | {
153 | // Try to grab the experimental context
154 | log('Trying to get experimental-webgl context');
155 | context = 'experimental-webgl';
156 | gl = canvas.getContext(context);
157 | }
158 | catch(e)
159 | {
160 | log('Failed to grab experimental-webgl context: ' + e, LogType.ERROR);
161 | }
162 | }
163 |
164 | // If we don't have a GL context, give up now
165 | if (gl)
166 | {
167 | log('Initialized ' + context + ' context', LogType.SUCCESS);
168 | return true;
169 | }
170 | else
171 | {
172 | log('Sorry: Your browser does not support WebGL!', LogType.ERROR);
173 | return false;
174 | }
175 | }
176 |
177 | /**
178 | * Reads a shader from the given DOM element's id.
179 | *
180 | * @param gl Handle to the OpenGL context.
181 | * @param id DOM id of element where the shader's source is stored.
182 | * @return Returns the OpenGL identifier of the shader obtained by calling createShader().
183 | */
184 | function getShader(gl, id)
185 | {
186 | var shaderScript, theSource, currentChild, shader;
187 |
188 | var shaderScript = document.getElementById(id);
189 |
190 | if (!shaderScript) {
191 | return null;
192 | }
193 |
194 | theSource = "";
195 | currentChild = shaderScript.firstChild;
196 |
197 | while(currentChild) {
198 | if (currentChild.nodeType == currentChild.TEXT_NODE) {
199 | theSource += currentChild.textContent;
200 | }
201 |
202 | currentChild = currentChild.nextSibling;
203 | }
204 | if (shaderScript.type == "x-shader/x-fragment")
205 | shader = gl.createShader(gl.FRAGMENT_SHADER);
206 | else if (shaderScript.type == "x-shader/x-vertex")
207 | shader = gl.createShader(gl.VERTEX_SHADER);
208 | else
209 | return null;
210 |
211 | gl.shaderSource(shader, theSource);
212 |
213 | gl.compileShader(shader);
214 |
215 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
216 | {
217 | log('Error compiling shader ' + id + ': ' + gl.getShaderInfoLog(shader), LogType.ERROR);
218 | return null;
219 | }
220 | else
221 | {
222 | log('Successfully compiled shader ' + id, LogType.SUCCESS);
223 | return shader;
224 | }
225 | }
226 |
227 | var projectionMatrixLocation;
228 | var modelviewMatrixLocation;
229 |
230 | var positionLocation;
231 | var texCoordLocation;
232 | var lightmapCoordLocation;
233 | var normalLocation;
234 | var colorLocation;
235 |
236 | var samplerTextureLocation;
237 | var samplerLightmapLocation;
238 |
239 | var texturesEnabledLocation;
240 | var lightmapsEnabledLocation;
241 |
242 | var useColorLocation;
243 |
244 | var alphaTestLocation;
245 |
246 | var alphaLocation;
247 |
248 | function initShaders()
249 | {
250 | var vertexShader = getShader(gl, "shader-vs");
251 | var fragmentShader = getShader(gl, "shader-fs");
252 |
253 | // Create the shader program
254 |
255 | var shaderProgram = gl.createProgram();
256 | gl.attachShader(shaderProgram, vertexShader);
257 | gl.attachShader(shaderProgram, fragmentShader);
258 | gl.linkProgram(shaderProgram);
259 |
260 | // If creating the shader program failed, alert
261 |
262 | if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS))
263 | {
264 | log('Linking the shader program failed', LogType.ERROR);
265 | return false;
266 | }
267 |
268 | gl.useProgram(shaderProgram);
269 | log('Successfully linked shader program', LogType.SUCCESS);
270 |
271 | // Get variable locations
272 | projectionMatrixLocation = gl.getUniformLocation(shaderProgram, 'pMatrix');
273 | modelviewMatrixLocation = gl.getUniformLocation(shaderProgram, 'mvMatrix');
274 |
275 |
276 | positionLocation = gl.getAttribLocation(shaderProgram, "attribPosition");
277 | texCoordLocation = gl.getAttribLocation(shaderProgram, "attribTexCoord");
278 | lightmapCoordLocation = gl.getAttribLocation(shaderProgram, "attribLightmapCoord");
279 | normalLocation = gl.getAttribLocation(shaderProgram, "attribNormal");
280 | colorLocation = gl.getAttribLocation(shaderProgram, "attribColor");
281 |
282 | samplerTextureLocation = gl.getUniformLocation(shaderProgram, "uniSamplerTexture");
283 | gl.uniform1i(samplerTextureLocation, 0);
284 | samplerLightmapLocation = gl.getUniformLocation(shaderProgram, "uniSamplerLightmap");
285 | gl.uniform1i(samplerLightmapLocation, 1);
286 |
287 | texturesEnabledLocation = gl.getUniformLocation(shaderProgram, "texturesEnabled");
288 | gl.uniform1i(texturesEnabledLocation, 1);
289 | lightmapsEnabledLocation = gl.getUniformLocation(shaderProgram, "lightmapsEnabled");
290 | gl.uniform1i(lightmapsEnabledLocation, 1);
291 |
292 | useColorLocation = gl.getUniformLocation(shaderProgram, "useColor");
293 |
294 | alphaTestLocation = gl.getUniformLocation(shaderProgram, "alphaTest");
295 |
296 | alphaLocation = gl.getUniformLocation(shaderProgram, "alpha");
297 |
298 | //
299 | // Init some of them
300 | //
301 |
302 | gl.enableVertexAttribArray(positionLocation); // We will always need vertices
303 |
304 | gl.uniform1f(alphaLocation, 1.0);
305 |
306 | return true;
307 | }
308 |
309 | var coordSystem =
310 | {
311 | vertexBuffer : undefined,
312 | colorBuffer : undefined
313 | };
314 |
315 | function initBuffers()
316 | {
317 | /**
318 | * Coord system
319 | */
320 | coordSystem.vertexBuffer = gl.createBuffer();
321 | gl.bindBuffer(gl.ARRAY_BUFFER, coordSystem.vertexBuffer);
322 |
323 | var coordVertices =
324 | [
325 | 0.0, 0.0, 0.0,
326 | 4000.0, 0.0, 0.0,
327 | 0.0, 0.0, 0.0,
328 | 0.0, 4000.0, 0.0,
329 | 0.0, 0.0, 0.0,
330 | 0.0, 0.0, 4000.0,
331 |
332 | 0.0, 0.0, 0.0,
333 | -4000.0, 0.0, 0.0,
334 | 0.0, 0.0, 0.0,
335 | 0.0, -4000.0, 0.0,
336 | 0.0, 0.0, 0.0,
337 | 0.0, 0.0, -4000.0,
338 | ];
339 |
340 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coordVertices), gl.STATIC_DRAW);
341 |
342 | coordSystem.colorBuffer = gl.createBuffer();
343 | gl.bindBuffer(gl.ARRAY_BUFFER, coordSystem.colorBuffer);
344 |
345 | var coordColors =
346 | [
347 | 1.0, 0.0, 0.0, 1.0,
348 | 1.0, 0.0, 0.0, 1.0,
349 | 0.0, 1.0, 0.0, 1.0,
350 | 0.0, 1.0, 0.0, 1.0,
351 | 0.0, 0.0, 1.0, 1.0,
352 | 0.0, 0.0, 1.0, 1.0,
353 |
354 | 0.3, 0.0, 0.0, 1.0,
355 | 0.3, 0.0, 0.0, 1.0,
356 | 0.0, 0.3, 0.0, 1.0,
357 | 0.0, 0.3, 0.0, 1.0,
358 | 0.0, 0.0, 0.3, 1.0,
359 | 0.0, 0.0, 0.3, 1.0,
360 | ];
361 |
362 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coordColors), gl.STATIC_DRAW);
363 |
364 | return true;
365 | }
366 |
367 | function setStates()
368 | {
369 | log('Setting states ...');
370 |
371 | gl.clearColor(0, 0, 0, 1);
372 | gl.enable(gl.DEPTH_TEST);
373 |
374 | gl.cullFace(gl.FRONT);
375 | gl.enable(gl.CULL_FACE);
376 | }
377 |
378 | function resize()
379 | {
380 | var width = canvas.clientWidth;
381 | var height = canvas.clientHeight;
382 |
383 | log('Resizing to ' + width + ' x ' + height);
384 |
385 | projectionMatrix.perspective(60.0, width / height, 8.0, 6000.0);
386 | gl.viewport(0, 0, width, height);
387 |
388 | projectionMatrix.setUniform(gl, projectionMatrixLocation, false);
389 | }
390 |
391 | /**
392 | * Updates the scene.
393 | *
394 | * @param interval Number seconds passed since the last frame.
395 | */
396 | function update(interval)
397 | {
398 | camera.update(interval);
399 | }
400 |
401 | function render()
402 | {
403 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
404 |
405 | modelviewMatrix.makeIdentity();
406 | camera.look();
407 | //modelviewMatrix.translate(0,0,-10);
408 | //modelviewMatrix.setUniform(gl, modelviewMatrixLocation, false);
409 |
410 | if(bsp.loaded)
411 | bsp.render(camera.pos);
412 |
413 | gl.uniform1i(useColorLocation, 1); // use colors for rendering
414 |
415 | // enable/disable the required attribute arrays
416 | gl.disableVertexAttribArray(texCoordLocation);
417 | gl.disableVertexAttribArray(lightmapCoordLocation);
418 | gl.disableVertexAttribArray(normalLocation);
419 | gl.enableVertexAttribArray(colorLocation);
420 |
421 | if(showCoordSystem)
422 | {
423 | gl.bindBuffer(gl.ARRAY_BUFFER, coordSystem.vertexBuffer);
424 | gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
425 | gl.bindBuffer(gl.ARRAY_BUFFER, coordSystem.colorBuffer);
426 | gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
427 |
428 | gl.drawArrays(gl.LINES, 0, 12);
429 | }
430 |
431 | gl.uniform1i(useColorLocation, 0);
432 | }
433 |
434 | var lastTime = new Date().getTime();
435 | var fps;
436 | var fpsCounter = 0;
437 | var lastFpsUpdate = 0;
438 |
439 | function mainloop()
440 | {
441 | // Calculate time since the last frame
442 | var time = new Date().getTime();
443 | var interval = time - lastTime;
444 |
445 | // Update FPS
446 | fpsCounter++;
447 | if(time - lastFpsUpdate >= 1000)
448 | {
449 | // Update of fps is longer than a second ago
450 | fps = fpsCounter;
451 | fpsCounter = 0;
452 | lastFpsUpdate = time;
453 | $('#info p:first-child').html('Rendering at ' + fps + ' FPS');
454 | }
455 |
456 | lastTime = time;
457 |
458 | // Update the scene based on the passed time
459 | update(interval / 1000.0);
460 |
461 | // Send all geometry to the renderer
462 | render();
463 |
464 | // Start next frame
465 | setTimeout(mainloop, 0);
466 | }
467 |
468 | function main()
469 | {
470 | startTime = new Date();
471 | log('<< STARTUP >>');
472 |
473 | if(!initWebGL())
474 | return;
475 |
476 | // Show WebGL information
477 | $('#info img')
478 | .after('
Vendor: ' + gl.getParameter(gl.VENDOR) + '
')
479 | .after('
Renderer: ' + gl.getParameter(gl.RENDERER) + '
')
480 | .after('
Version: ' + gl.getParameter(gl.VERSION) + '
');
481 |
482 | if(!checkRequiredAPI())
483 | return;
484 | if(!initShaders())
485 | return;
486 | if(!initBuffers())
487 | return;
488 |
489 | setStates();
490 |
491 | resize();
492 |
493 | camera.z = 0;
494 |
495 | log('Starting mainloop');
496 | mainloop();
497 | }
498 |
499 | // GET THE BALL ROLLING
500 | window.addEventListener('load', main, false);
501 |
--------------------------------------------------------------------------------
/js/mathlib.js:
--------------------------------------------------------------------------------
1 | /*
2 | * mathlib.js
3 | *
4 | * Copyright (c) 2012, Bernhard Manfred Gruber. All rights reserved.
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 3 of the License, or any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 | * MA 02110-1301 USA
20 | */
21 |
22 | 'use strict';
23 |
24 | //
25 | // Provides basic mathematical routines for vector processing.
26 | //
27 |
28 | /** Defines the epsilon used for collision detection */
29 | var EPSILON = 0.03125 // 1/32
30 |
31 | /**
32 | * Structure for representing a point (or vector) in 3D space.
33 | *
34 | * @param v Optional. An instance of Vector3D to copy.
35 | */
36 | function Vector3D(v)
37 | {
38 | var x;
39 | var y;
40 | var z;
41 |
42 | if(v != undefined)
43 | {
44 | this.x = v.x;
45 | this.y = v.y;
46 | this.z = v.z;
47 | }
48 | }
49 |
50 | /**
51 | * Vector addition.
52 | */
53 | function vectorAdd(a, b)
54 | {
55 | var result = new Vector3D();
56 | result.x = a.x + b.x;
57 | result.y = a.y + b.y;
58 | result.z = a.z + b.z;
59 | return result;
60 | }
61 |
62 | /**
63 | * Vector subtraction.
64 | */
65 | function vectorSub(a, b)
66 | {
67 | var result = new Vector3D();
68 | result.x = a.x - b.x;
69 | result.y = a.y - b.y;
70 | result.z = a.z - b.z;
71 | return result;
72 | }
73 |
74 | /**
75 | * Multiplies a vector with a scalar.
76 | */
77 | function vectorMul(v, s)
78 | {
79 | var result = new Vector3D(v);
80 | result.x *= s;
81 | result.y *= s;
82 | result.z *= s;
83 | return result;
84 | }
85 |
86 | /**
87 | * Checks whether or not two vectors are equal.
88 | */
89 | function vectorEquals(a, b)
90 | {
91 | return (a.x == b.x) && (a.y == b.y) && (a.z == b.z);
92 | }
93 |
94 | /**
95 | * Returns the dot product of two vectors.
96 | */
97 | function dotProduct(a, b)
98 | {
99 | return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
100 | }
101 |
102 | /**
103 | * Converts an angle in degrees to radians.
104 | *
105 | * @param degree An angle in degrees.
106 | */
107 | function degToRad(degree)
108 | {
109 | return degree / 180.0 * Math.PI;
110 | }
111 |
112 | /**
113 | * Tests whether or not the given point is in the axis aligned bounding box spaned by mins and maxs.
114 | *
115 | * @return Returns true when the point is inside or directly on the box surface.
116 | */
117 | function pointInBox(point, mins, maxs)
118 | {
119 | if((mins[0] <= point.x && point.x <= maxs[0] &&
120 | mins[1] <= point.y && point.y <= maxs[1] &&
121 | mins[2] <= point.z && point.z <= maxs[2]) ||
122 | (mins[0] >= point.x && point.x >= maxs[0] &&
123 | mins[1] >= point.y && point.y >= maxs[1] &&
124 | mins[2] >= point.z && point.z >= maxs[2]))
125 | return true;
126 | else
127 | return false;
128 | }
129 |
--------------------------------------------------------------------------------
/js/movement.js:
--------------------------------------------------------------------------------
1 | /*
2 | * movement.js
3 | *
4 | * Copyright (c) 2012, Bernhard Manfred Gruber. All rights reserved.
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 3 of the License, or any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 | * MA 02110-1301 USA
20 | */
21 |
22 | 'use strict';
23 |
24 | var hull;
25 |
26 | /**
27 | * Calculates a complete move through the bsp tree from start to end.
28 | *
29 | * @param start The start position of the movement. An object having at least an x, y, and z component.
30 | * @param end The end position of the movement. An object having at least an x, y, and z component.
31 | * @param collisionHull The hull of the bsp tree to use for collision detecting.
32 | * @return Returns the final position of the movement as Vector3D. @see Vector3D
33 | */
34 | function playerMove(start, end, collisionHull)
35 | {
36 | if(collisionHull == undefined)
37 | collisionHull = 0;
38 | hull = collisionHull;
39 |
40 | return traceLine(start, end);
41 | }
42 |
43 | //
44 | // The following code has been taken from mainly from the Quake 1 source code.
45 | //
46 |
47 | /**
48 | * Structure containing trace related information used during the tracing process.
49 | */
50 | function Trace()
51 | {
52 | /** */
53 | var allsolid;
54 |
55 | /** The BspPlane the trace has collided with */
56 | var plane;
57 |
58 | /** The ratio between 0.0 and 1.0 how far the trace from start to end was successful */
59 | var ratio;
60 | }
61 |
62 | /**
63 | * Traces a line inside the current clipping hull.
64 | * @param start The start position of the movement. An object having at least an x, y, and z component.
65 | * @param end The end position of the movement. An object having at least an x, y, and z component.
66 | * @return Returns the final position of the movement as Vector3D. @see Vector3D
67 | */
68 | function traceLine(start, end)
69 | {
70 | if(vectorEquals(start, end))
71 | return end; // no move
72 |
73 | // create a default trace
74 | var trace = new Trace();
75 | trace.allsolid = true;
76 | trace.plane = null;
77 | trace.ratio = 1.0;
78 |
79 | // We start with the first node (0), setting our start and end ratio to 0 and 1.
80 | // We will recursively go through all of the clipnodes and try to find collisions with their planes.
81 | recursiveHullCheck(bsp.models[0].headNodes[hull], 0.0, 1.0, start, end, trace);
82 |
83 | // If the trace ratio is STILL 1.0, then we never collided and just return our end position
84 | if(trace.ratio == 1.0)
85 | return end;
86 | else // else COLLISION!!!!
87 | {
88 | // Set our new position to a position that is right up to the plane we collided with
89 | var newPosition = vectorAdd(start, vectorMul(vectorSub(end, start), trace.ratio));
90 |
91 | // Get the distance vector from the wanted end point to the actual new position
92 | // The distance we have to travel backward from the original end position to the collision point)
93 | var missingMove = vectorSub(end, newPosition);
94 |
95 | // Get the distance we need to travel backwards from the end position to the new slide position.
96 | // (The position we arrive when we collide with a plane and slide along it with the remaining momentum)
97 | // This is a distance along the normal of the plane we collided with.
98 | var distance = dotProduct(missingMove, trace.plane.normal);
99 |
100 | // Get the final end position that we will end up (after collision and sliding along the plane).
101 | var endPosition = vectorSub(end, vectorMul(trace.plane.normal, distance));
102 |
103 | // Since we got a new position after sliding, we need to make sure
104 | // that the new sliding position doesn't collide with anything else.
105 | newPosition = traceLine(newPosition, endPosition);
106 |
107 | // Return the new position
108 | return newPosition;
109 | }
110 | }
111 |
112 | /**
113 | * Traverses the clipping hull down to the content (see defines in bspdef).
114 | * @param The clipnodes index to get the content at a position.
115 | * @param The point to get the content for.
116 | * @return Returns the content at the given point. (see defines in bspdef)
117 | */
118 | function hullPointContents(nodeIndex, point)
119 | {
120 | while (nodeIndex >= 0)
121 | {
122 | var node = bsp.clipNodes[nodeIndex];
123 | var plane = bsp.planes[node.plane];
124 |
125 | var d = dotProduct(plane.normal, point) - plane.dist;
126 |
127 | if (d < 0)
128 | nodeIndex = node.children[1];
129 | else
130 | nodeIndex = node.children[0];
131 | }
132 |
133 | return nodeIndex;
134 | }
135 |
136 | /**
137 | * Recursively checks a part of the traced line against the collision hull.
138 | *
139 | * @param nodeIndex The index of the clipnode currently checked.
140 | * @param startFraction The start fraction for this node between 0.0 and 1.0 on the currently traced line.
141 | * @param endFraction The end fraction for this node between 0.0 and 1.0 on the currently traced line.
142 | * @param startPoint The start point for this node on the currently traced line.
143 | * @param endPoint The end point for this node on the currently traced line.
144 | * @param trace Reference to the current trace data.
145 | * @return Returns true, if the current node index is not a clipnode but a content identifier (see defines in bspdef),
146 | * meaning a leaf of the clipnode tree has been reached.
147 | */
148 | function recursiveHullCheck(nodeIndex, startFraction, endFraction, startPoint, endPoint, trace)
149 | {
150 | // check for empty
151 | if (nodeIndex < 0)
152 | {
153 | if (nodeIndex != CONTENTS_SOLID)
154 | trace.allsolid = false;
155 |
156 | return true; // empty
157 | }
158 |
159 | // find the point distances
160 | var node = bsp.clipNodes[nodeIndex];
161 | var plane = bsp.planes[node.plane];
162 |
163 | var t1, t2;
164 |
165 | t1 = dotProduct(plane.normal, startPoint) - plane.dist;
166 | t2 = dotProduct(plane.normal, endPoint) - plane.dist;
167 |
168 | if (t1 >= 0.0 && t2 >= 0.0)
169 | return recursiveHullCheck(node.children[0], startFraction, endFraction, startPoint, endPoint, trace);
170 | if (t1 < 0.0 && t2 < 0.0)
171 | return recursiveHullCheck(node.children[1], startFraction, endFraction, startPoint, endPoint, trace);
172 |
173 | // put the crosspoint EPSILON pixels on the near side
174 | var frac;
175 |
176 | if (t1 < 0.0)
177 | frac = (t1 + EPSILON) / (t1 - t2);
178 | else
179 | frac = (t1 - EPSILON) / (t1 - t2);
180 | if (frac < 0.0)
181 | frac = 0.0;
182 | if (frac > 1.0)
183 | frac = 1.0;
184 |
185 | var midf = startFraction + (endFraction - startFraction) * frac;
186 | var midPoint = vectorAdd(startPoint, vectorMul(vectorSub(endPoint, startPoint), frac));
187 |
188 | var side = (t1 < 0) ? 1 : 0;
189 |
190 | // move up to the node
191 | if (!recursiveHullCheck(node.children[side], startFraction, midf, startPoint, midPoint, trace))
192 | return false;
193 |
194 | if (hullPointContents(node.children[side ^ 1], midPoint) != CONTENTS_SOLID)
195 | // go past the node
196 | return recursiveHullCheck (node.children[side ^ 1], midf, endFraction, midPoint, endPoint, trace);
197 |
198 | if (trace.allsolid)
199 | return false; // never got out of the solid area
200 |
201 | // the other side of the node is solid, this is the impact point
202 | if (!side)
203 | trace.plane = plane;
204 | else
205 | {
206 | trace.plane = new BspPlane();
207 | trace.plane.normal = vectorMul(plane.normal, -1);
208 | trace.plane.dist = -plane.dist;
209 | }
210 |
211 | while(hullPointContents(bsp.models[0].headNodes[hull], midPoint) == CONTENTS_SOLID)
212 | {
213 | // shouldn't really happen, but does occasionally
214 | frac -= 0.1;
215 | if (frac < 0)
216 | {
217 | trace.ratio = midf;
218 | return false;
219 | }
220 | midf = startFraction + (endFraction - startFraction) * frac;
221 | midPoint = vectorAdd(startPoint, vectorMul(vectorSub(endPoint, startPoint), frac));
222 | }
223 |
224 | trace.ratio = midf;
225 |
226 | return false;
227 | }
228 |
--------------------------------------------------------------------------------
/js/texutils.js:
--------------------------------------------------------------------------------
1 | /*
2 | * texutils.js
3 | *
4 | * Copyright (c) 2012, Bernhard Manfred Gruber. All rights reserved.
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 3 of the License, or any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 | * MA 02110-1301 USA
20 | */
21 |
22 | 'use strict';
23 |
24 | /**
25 | * Returns true, if the given value is a power of two.
26 | */
27 | function isPowerOfTwo(x)
28 | {
29 | return (x & (x - 1)) == 0;
30 | }
31 |
32 | /**
33 | * Gets the next highest power of two for a given integer.
34 | */
35 | function nextHighestPowerOfTwo(x)
36 | {
37 | --x;
38 | for (var i = 1; i < 32; i <<= 1)
39 | x = x | x >> i;
40 | return x + 1;
41 | }
42 |
43 | /** Canvas used for the image conversion and scaling in pixelsToImage() */
44 | var conversionCanvas = document.createElement("canvas");
45 |
46 | /** Context to conversionCanvas */
47 | var conversionCtx = conversionCanvas.getContext("2d");
48 |
49 | /**
50 | * Converts a raw pixel array into an Image object whose dimensions are powers of two.
51 | *
52 | * @param pixelArray An array (or equivalent, must support operator[]) of bytes (e.g. RGBRGBRGB ...)
53 | * @param width The with of the image.
54 | * @param height The height of the image.
55 | * @param channels The number of channels. Must be 3 (RGB) or 4 (RGBA).
56 | * @return Returns a new Image object containing the given data.
57 | */
58 | function pixelsToTexture(pixelArray, width, height, channels, callback)
59 | {
60 | conversionCanvas.width = width;
61 | conversionCanvas.height = height;
62 | //var ctx = conversionCanvas.getContext("2d");
63 |
64 | var texture = gl.createTexture();
65 |
66 | //
67 | // Convert
68 | //
69 |
70 | var imgData = conversionCtx.createImageData(width, height);
71 | for (var x = 0; x < width; x++)
72 | {
73 | for (var y = 0; y < height; y++)
74 | {
75 | var dataIndex = (x + y * width) * 4;
76 | var pixelIndex = (x + y * width) * channels;
77 | imgData.data[dataIndex + 0] = pixelArray[pixelIndex + 0];
78 | imgData.data[dataIndex + 1] = pixelArray[pixelIndex + 1];
79 | imgData.data[dataIndex + 2] = pixelArray[pixelIndex + 2];
80 | if(channels == 4)
81 | imgData.data[dataIndex + 3] = pixelArray[pixelIndex + 3];
82 | else
83 | imgData.data[dataIndex + 3] = 255;
84 | }
85 | }
86 | conversionCtx.putImageData(imgData, 0, 0);
87 |
88 | var img = new Image();
89 | img.width = width;
90 | img.height = height;
91 |
92 | img.onload = function(img)
93 | {
94 | return function()
95 | {
96 | //
97 | // Scale
98 | //
99 |
100 | if (!isPowerOfTwo(img.width) || !isPowerOfTwo(img.height))
101 | {
102 | // Scale up the texture to the next highest power of two dimensions.
103 | conversionCanvas.width = nextHighestPowerOfTwo(img.width);
104 | conversionCanvas.height = nextHighestPowerOfTwo(img.height);
105 | //var ctx = conversionCanvas.getContext("2d");
106 | conversionCtx.drawImage(img, 0, 0, conversionCanvas.width, conversionCanvas.height);
107 |
108 | img = new Image();
109 | img.width = conversionCanvas.width;
110 | img.height = conversionCanvas.height;
111 |
112 | img.onload = function(img)
113 | {
114 | return function()
115 | {
116 | callback(texture, img);
117 | };
118 | }(img);
119 |
120 | img.src = conversionCanvas.toDataURL();
121 | }
122 | else
123 | callback(texture, img);
124 | };
125 | }(img);
126 |
127 | img.src = conversionCanvas.toDataURL();
128 | //$('body').append('Texture (' + img.width + 'x' + img.height + ')').append(img);
129 |
130 |
131 | //$('body').append('Texture (' + img.width + 'x' + img.height + ')').append(img);
132 |
133 | return texture;
134 | }
--------------------------------------------------------------------------------
/js/wad.js:
--------------------------------------------------------------------------------
1 | /*
2 | * wad.js
3 | *
4 | * Copyright (c) 2012, Bernhard Manfred Gruber. All rights reserved.
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 3 of the License, or any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 | * MA 02110-1301 USA
20 | */
21 |
22 | 'use strict';
23 |
24 | /*
25 | typedef struct
26 | {
27 | char szMagic[4];
28 | int32_t nDir;
29 | int32_t nDirOffset;
30 | } WADHEADER;
31 | */
32 | function WadHeader()
33 | {
34 | var magic; // should be WAD2/WAD3
35 | var dirs; // number of directory entries
36 | var dirOffset; // offset into directory
37 | }
38 | var SIZE_OF_WADHEADER = 12;
39 |
40 | // Directory entry structure
41 | /*
42 | typedef struct _WADDIRENTRY
43 | {
44 | int32_t nFilePos;
45 | int32_t nDiskSize;
46 | int32_t nSize;
47 | int8_t nType;
48 | bool bCompression;
49 | int16_t nDummy;
50 | char szName[MAXTEXTURENAME];
51 | } WADDIRENTRY;
52 | */
53 |
54 | function WadDirEntry()
55 | {
56 | var offset; // offset in WAD
57 | var compressedSize; // size in file
58 | var size; // uncompressed size
59 | var type; // type of entry
60 | var compressed; // 0 if none
61 | var name; // must be null terminated
62 | }
63 |
64 | /**
65 | * Wad class.
66 | * Represents a wad archiev and offers methods for extracting textures from it.
67 | */
68 | function Wad()
69 | {
70 | /** Identifies the wad */
71 | var name;
72 |
73 | var src;
74 |
75 | /** Wad file header */
76 | var header;
77 |
78 | /** Array of directory entries */
79 | var entries;
80 | };
81 |
82 | /**
83 | * Opens the wad file and loads it's directory for texture searching.
84 | */
85 | Wad.prototype.open = function(buffer)
86 | {
87 | console.log('Begin loading wad');
88 |
89 | this.src = new BinaryFile(buffer);
90 |
91 | var src = this.src;
92 |
93 | var header = new WadHeader();
94 | header.magic = src.readString(4);
95 | header.dirs = src.readLong();
96 | header.dirOffset = src.readLong();
97 |
98 | console.log('Header: ' + header.magic + ' (' + header.dirs + ' contained objects)');
99 |
100 | if(header.magic != 'WAD2' && header.magic != 'WAD3')
101 | return false;
102 |
103 | this.header = header;
104 | this.entries = new Array();
105 |
106 | src.seek(header.dirOffset);
107 |
108 | for(var i = 0; i < header.dirs; i++)
109 | {
110 | var entry = new WadDirEntry();
111 |
112 | entry.offset = src.readLong();
113 | entry.compressedSize = src.readLong();
114 | entry.size = src.readLong();
115 | entry.type = src.readByte();
116 | entry.compressed = (src.readUByte() ? true : false);
117 | src.readUShort();
118 | entry.name = src.readString(MAXTEXTURENAME);
119 |
120 | console.log('Texture #' + i + ' name: ' + entry.name);
121 |
122 | this.entries.push(entry);
123 | }
124 |
125 | console.log('Finished loading wad');
126 |
127 | return true;
128 | }
129 |
130 | /**
131 | * Finds and loads a texture from the wad file.
132 | *
133 | * @param texName The name of the texture to find.
134 | * @return Returns the OpenGL identifier for the loaded textrue obtained by calling gl.createTexture()
135 | * or null if the texture could not be found.
136 | */
137 | Wad.prototype.loadTexture = function(texName)
138 | {
139 | // Find cooresponding directory entry
140 | for(var i = 0; i < this.entries.length; i++)
141 | {
142 | var entry = this.entries[i];
143 | if(entry.name.toLowerCase() == texName.toLowerCase())
144 | return this.fetchTextureAtOffset(this.src, entry.offset);
145 | }
146 |
147 | return null;
148 | }
149 |
150 | /**
151 | * Static method for fetching a texture at a given offset from a byte buffer.
152 | * Reads the texture header and decodes the indexed image into a rgba image.
153 | * Finally creates a OpenGL texture.
154 | *
155 | * @param src A BinaryFile object used to read data from.
156 | * @param offset The offset in the binary file to start reading.
157 | * @return Returns a WebGLTexture obtained by calling createTexture().
158 | */
159 | Wad.prototype.fetchTextureAtOffset = function(src, offset)
160 | {
161 | // Seek to the texture beginning
162 | src.seek(offset);
163 |
164 | // Load texture header
165 | var mipTex = new BspMipTexture();
166 | mipTex.name = src.readString(MAXTEXTURENAME);
167 | mipTex.width = src.readULong();
168 | mipTex.height = src.readULong();
169 | mipTex.offsets = new Array();
170 | for(var i = 0; i < MIPLEVELS; i++)
171 | mipTex.offsets.push(src.readULong());
172 |
173 | // Fetch color palette
174 | var paletteOffset = mipTex.offsets[MIPLEVELS - 1] + ((mipTex.width / 8) * (mipTex.height / 8)) + 2;
175 |
176 | var palette = new Uint8Array(src.buffer, offset + paletteOffset, 256 * 3);
177 |
178 | // Generate texture
179 | //var texture = gl.createTexture();
180 | //gl.bindTexture(gl.TEXTURE_2D, texture);
181 |
182 | //for (var i = 0; i < MIPLEVELS; i++) // ONLY LOAD FIRST MIPLEVEL !!!
183 | {
184 | // Width and height shrink to half for every level
185 | var width = mipTex.width; //>> i;
186 | var height = mipTex.height; // >> i;
187 |
188 | // Fetch the indexed texture
189 | var textureIndexes = new Uint8Array(src.buffer, offset + mipTex.offsets[0 /*i*/], width * height);
190 |
191 | // Allocate storage for the rgba texture
192 | var textureData = new Array(width * height * 4);
193 |
194 | // Translate the texture from indexes to rgba
195 | for (var j = 0; j < width * height; j++)
196 | {
197 | var paletteIndex = textureIndexes[j] * 3;
198 |
199 | textureData[j * 4] = palette[paletteIndex];
200 | textureData[j * 4 + 1] = palette[paletteIndex + 1];
201 | textureData[j * 4 + 2] = palette[paletteIndex + 2];
202 | textureData[j * 4 + 3] = 255; //every pixel is totally opaque
203 | }
204 |
205 | if(mipTex.name.substring(0, 1) == "{") // this is an alpha texture
206 | {
207 | console.log(mipTex.name + " is an alpha texture");
208 | // Transfere alpha key color to actual alpha values
209 | this.applyAlphaSections(textureData, width, height, palette[255 * 3 + 0], palette[255 * 3 + 1], palette[255 * 3 + 2]);
210 | }
211 |
212 | // Upload the data to OpenGL
213 | //var img = pixelsToImage(textureData, width, height, 4);
214 |
215 | //$('body').append('Texture (' + img.width + 'x' + img.height + ')').append(img);
216 |
217 | //gl.texImage2D(gl.TEXTURE_2D, 0 /*i*/, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
218 | }
219 |
220 | var texture = pixelsToTexture(textureData, width, height, 4, function(texture, image)
221 | {
222 | gl.bindTexture(gl.TEXTURE_2D, texture);
223 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
224 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR_MIPMAP_LINEAR);
225 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
226 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
227 | gl.texImage2D(gl.TEXTURE_2D, 0 , gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
228 | gl.generateMipmap(gl.TEXTURE_2D);
229 | gl.bindTexture(gl.TEXTURE_2D, null);
230 | });
231 |
232 |
233 |
234 | return texture;
235 | }
236 |
237 | /**
238 | * Translates the transparent regions of an image given by a selected "transparency color"
239 | * into actual alpha values.
240 | * Also performs color interpolation at the edges of transparent regions to prevent that the
241 | * "transparency color" can be seen on the final texture.
242 | *
243 | * @param pixels An array of pixels (rgba) which will be altered.
244 | * @param width The width of the image hold by pixels.
245 | * @param height The height of the image hold by pixels.
246 | * @param key* The "transparency color".
247 | */
248 | Wad.prototype.applyAlphaSections = function(pixels, width, height, keyR, keyG, keyB)
249 | {
250 | // Create an equally sized pixel buffer initialized to the key color
251 | var rgbBuffer = new Array(width * height * 3);
252 |
253 | for(var y = 0; y < height; y++)
254 | {
255 | for(var x = 0; x < width; x++)
256 | {
257 | var bufIndex = (y * width + x) * 3;
258 | rgbBuffer[bufIndex + 0] = keyR;
259 | rgbBuffer[bufIndex + 1] = keyG;
260 | rgbBuffer[bufIndex + 2] = keyB;
261 | }
262 | }
263 |
264 | // The key color signifies a transparent portion of the texture. Zero alpha for blending and
265 | // to get rid of key colored edges choose the average color of the nearest non key pixels.
266 |
267 | // Interpolate colors for transparent pixels
268 | for(var y = 0; y < height; y++)
269 | {
270 | for(var x = 0; x < width; x++)
271 | {
272 | var index = (y * width + x) * 4;
273 |
274 | if ((pixels[index + 0] == keyR) &&
275 | (pixels[index + 1] == keyG) &&
276 | (pixels[index + 2] == keyB))
277 | {
278 | // This is a pixel which should be transparent
279 |
280 | pixels[index + 3] = 0;
281 |
282 | var count = 0;
283 | var colorSum = new Array(3);
284 | colorSum[0] = 0;
285 | colorSum[1] = 0;
286 | colorSum[2] = 0;
287 |
288 | // left above pixel
289 | if((x > 0) && (y > 0))
290 | {
291 | var pixelIndex = ((y - 1) * width + (x - 1)) * 4;
292 | if (pixels[pixelIndex + 0] != keyR ||
293 | pixels[pixelIndex + 1] != keyG ||
294 | pixels[pixelIndex + 2] != keyB)
295 | {
296 | colorSum[0] += pixels[pixelIndex + 0] * Math.SQRT2;
297 | colorSum[1] += pixels[pixelIndex + 1] * Math.SQRT2;
298 | colorSum[2] += pixels[pixelIndex + 2] * Math.SQRT2;
299 | count++;
300 | }
301 | }
302 |
303 | // above pixel
304 | if((x >= 0) && (y > 0))
305 | {
306 | var pixelIndex = ((y - 1) * width + x) * 4;
307 | if (pixels[pixelIndex + 0] != keyR ||
308 | pixels[pixelIndex + 1] != keyG ||
309 | pixels[pixelIndex + 2] != keyB)
310 | {
311 | colorSum[0] += pixels[pixelIndex + 0];
312 | colorSum[1] += pixels[pixelIndex + 1];
313 | colorSum[2] += pixels[pixelIndex + 2];
314 | count++;
315 | }
316 | }
317 |
318 | // right above pixel
319 | if((x < width - 1) && (y > 0))
320 | {
321 | var pixelIndex = ((y - 1) * width + (x + 1)) * 4;
322 | if (pixels[pixelIndex + 0] != keyR ||
323 | pixels[pixelIndex + 1] != keyG ||
324 | pixels[pixelIndex + 2] != keyB)
325 | {
326 | colorSum[0] += pixels[pixelIndex + 0] * Math.SQRT2;
327 | colorSum[1] += pixels[pixelIndex + 1] * Math.SQRT2;
328 | colorSum[2] += pixels[pixelIndex + 2] * Math.SQRT2;
329 | count++;
330 | }
331 | }
332 |
333 | // left pixel
334 | if(x > 0)
335 | {
336 | var pixelIndex = (y * width + (x - 1)) * 4;
337 | if (pixels[pixelIndex + 0] != keyR ||
338 | pixels[pixelIndex + 1] != keyG ||
339 | pixels[pixelIndex + 2] != keyB)
340 | {
341 | colorSum[0] += pixels[pixelIndex + 0];
342 | colorSum[1] += pixels[pixelIndex + 1];
343 | colorSum[2] += pixels[pixelIndex + 2];
344 | count++;
345 | }
346 | }
347 |
348 | // right pixel
349 | if(x < width - 1)
350 | {
351 | var pixelIndex = (y * width + (x + 1)) * 4;
352 | if (pixels[pixelIndex + 0] != keyR ||
353 | pixels[pixelIndex + 1] != keyG ||
354 | pixels[pixelIndex + 2] != keyB)
355 | {
356 | colorSum[0] += pixels[pixelIndex + 0];
357 | colorSum[1] += pixels[pixelIndex + 1];
358 | colorSum[2] += pixels[pixelIndex + 2];
359 | count++;
360 | }
361 | }
362 |
363 | // left underneath pixel
364 | if((x > 0) && (y < height - 1))
365 | {
366 | var pixelIndex = ((y + 1) * width + (x - 1)) * 4;
367 | if (pixels[pixelIndex + 0] != keyR ||
368 | pixels[pixelIndex + 1] != keyG ||
369 | pixels[pixelIndex + 2] != keyB)
370 | {
371 | colorSum[0] += pixels[pixelIndex + 0] * Math.SQRT2;
372 | colorSum[1] += pixels[pixelIndex + 1] * Math.SQRT2;
373 | colorSum[2] += pixels[pixelIndex + 2] * Math.SQRT2;
374 | count++;
375 | }
376 | }
377 |
378 | // underneath pixel
379 | if((x >= 0) && (y < height - 1))
380 | {
381 | var pixelIndex = ((y + 1) * width + x) * 4;
382 | if (pixels[pixelIndex + 0] != keyR ||
383 | pixels[pixelIndex + 1] != keyG ||
384 | pixels[pixelIndex + 2] != keyB)
385 | {
386 | colorSum[0] += pixels[pixelIndex + 0];
387 | colorSum[1] += pixels[pixelIndex + 1];
388 | colorSum[2] += pixels[pixelIndex + 2];
389 | count++;
390 | }
391 | }
392 |
393 | // right underneath pixel
394 | if((x < width - 1) && (y < height - 1))
395 | {
396 | var pixelIndex = ((y + 1) * width + (x + 1)) * 4;
397 | if (pixels[pixelIndex + 0] != keyR ||
398 | pixels[pixelIndex + 1] != keyG ||
399 | pixels[pixelIndex + 2] != keyB)
400 | {
401 | colorSum[0] += pixels[pixelIndex + 0] * Math.SQRT2;
402 | colorSum[1] += pixels[pixelIndex + 1] * Math.SQRT2;
403 | colorSum[2] += pixels[pixelIndex + 2] * Math.SQRT2;
404 | count++;
405 | }
406 | }
407 |
408 | if (count > 0)
409 | {
410 | colorSum[0] /= count;
411 | colorSum[1] /= count;
412 | colorSum[2] /= count;
413 |
414 | var bufIndex = (y * width + x) * 3;
415 | rgbBuffer[bufIndex + 0] = Math.round(colorSum[0]);
416 | rgbBuffer[bufIndex + 1] = Math.round(colorSum[1]);
417 | rgbBuffer[bufIndex + 2] = Math.round(colorSum[2]);
418 | }
419 | }
420 | }
421 | }
422 |
423 | // Transfer interpolated colors to the texture
424 | for(var y = 0; y < height; y++)
425 | {
426 | for(var x = 0; x < width; x++)
427 | {
428 | var index = (y * width + x) * 4;
429 | var bufindex = (y * width + x) * 3;
430 |
431 | if ((rgbBuffer[bufindex + 0] != keyR) ||
432 | (rgbBuffer[bufindex + 1] != keyG) ||
433 | (rgbBuffer[bufindex + 2] != keyB))
434 | {
435 | pixels[index + 0] = rgbBuffer[bufindex + 0];
436 | pixels[index + 1] = rgbBuffer[bufindex + 1];
437 | pixels[index + 2] = rgbBuffer[bufindex + 2];
438 | }
439 | }
440 | }
441 | }
442 |
443 | /** Stores all loaded wads */
444 | var loadedWads = new Array();
--------------------------------------------------------------------------------
/license:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
--------------------------------------------------------------------------------
/readme:
--------------------------------------------------------------------------------
1 | === hlbsp viewer ===
2 |
3 | Last edited: January 11th 2010
4 |
5 |
6 | = Author =
7 | The author of this project is Bernhard Manfred Gruber,
8 | a 20 year old student at the
9 | Upper Austrian University of Applied Science in Hagenberg (Austria).
10 | Feel free to send me a mail at: dixxi1@gmx.net
11 |
12 |
13 | = About =
14 | The hlbsp viewer is a client side html 5 application using JavaScript and
15 | WebGL to render bsp files.
16 |
17 |
18 | = Reasons =
19 | This project mainly targets the need of a free implementation of the .bsp
20 | (short for binary space partitioning) file format version 30 (used by the
21 | well-known HalfLife/GoldSrc engine), which has already been done by my old
22 | hlbsp project written in C/C++.
23 | You can find it here: http://sourceforge.net/projects/hlbsp/
24 | During the work on this "reimplementation" I could refactor and improve some
25 | parts of the code as well as port the existing OpenGL implementation using
26 | mostly OpenGL 1.1 features (glBegin etc.) to meet the WebGL standard (which
27 | is basically OpenGL ES 2.0) by using advanced features like Buffer Objects.
28 |
29 | The second aspect of this code is to show an examplary WebGL implementation
30 | rendering something "more advanced" than cubes (as mostly used in WebGL
31 | tutorials) or anything similar. Additionally, it shows how to deal with binary
32 | data. Currently only in a very bleeding edge way (the working draft from
33 | Khronos specifying the DataView class has been released some weeks ago), but it
34 | should give developers an idea how to treat this issue.
35 |
36 | Finally I had to do some sort of project over the christmas holidays for my
37 | eb Design course at university, so this topic came in handy.
38 |
39 |
40 | = Usage =
41 | When the page has been opened in a supported web browser, you should see a
42 | black region in the middle. This is the