Skip to content
Browse files

fuck it, ship it.

  • Loading branch information...
1 parent c4bc80d commit 5c38070862b9915fa0d80095a31ef0f3a8bb975e @jwagner committed Dec 9, 2012
Showing with 286 additions and 150 deletions.
  1. +1 −0 Makefile
  2. +11 −75 README.md
  3. +1 −0 build/public/.htaccess
  4. +87 −7 build/public/index.html
  5. +1 −0 build/public/style.css
  6. +24 −24 lib/game-shim.js
  7. +38 −15 public/index.html
  8. +33 −2 public/style.css
  9. +0 −1 src/cameracontroller.js
  10. +18 −6 src/gl/utils.js
  11. +2 −2 src/input.js
  12. +70 −18 src/main.js
View
1 Makefile
@@ -5,6 +5,7 @@ init:
npm install --dev
min:
+ sed '/require\.js/d' public/index.html > build/public/index.html
cd build;../node_modules/.bin/r.js -o build.js;
echo "(function(){" > build/min/main.js
cat lib/almond.min.js build/min/src/main.js >> build/min/main.js
View
86 README.md
@@ -1,82 +1,18 @@
-# simplex-noise.js
+# WebGL Voxel Worlds
-simplex-noise.js is a fast simplex noise implementation in Javascript. It works in the browser and on nodejs.
+A little demo showing how to generate and render voxel worlds using simplex-noise.js and WebGL.
-## Requirements
-
-It requires typed arrays, if you want to use it in browsers without support
-you will need to use a polyfill like [typedarray.js](http://www.calormen.com/polyfill/typedarray.js).
+## Warning
+This is *really hacky prototype code*. Feel free to learn from it (and my mistakes), **don't use it in production**.
## Demo
-Simple 2D plasma demo on [jsfiddle.net](http://jsfiddle.net/UL69K/5/).
-
-## Usage
-
-```javascript
-// initializing a simplex instance
-// do this only once it's relatively expensive
-var simplex = new SimplexNoise(),
- value2d = simplex.noise2D(x, y),
- value3d = simplex.noise3D(x, y, z),
- value4d = simplex.noise2D(x, y, z, w);
-```
-
-You can also pass an alternative random function to the constructor that is
-used to build the permutation table:
-
-```javascript
-var simplex = new SimplexNoise(Math.random),
- value2d = simplex.noise2D(x, y);
-```
-
-## node.js
-
-Node.js is also supported, you can install the package using [npm](https://npmjs.org/package/simplex-noise).
-
-```javascript
-var SimplexNoise = require('simplex-noise'),
- simplex = new SimplexNoise(Math.random),
- value2d = simplex.noise2D(x, y);
-```
-
-## Benchmarks
-
-- [Comparison between 2D and 3D noise](http://jsperf.com/simplex-noise/2)
-- [Comparison with simplex implementation in three.js](http://jsperf.com/simplex-noise-comparison)
-
-For development you can open `perf/index.html` and watch the console or run `node perf/benchmark.js` in a shell.
-There is also a rake task for comparing your current changes can also run `make compare`.
-The command works using git stash.
-
-## Tests
-
-There are some simple buster.js tests for this library to run them first install buster.js and jshint:
-```shell
-npm install buster.js
-# if you haven't done so already
-npm install -g jshint
-make tests
-```
-
-## Changelog
-
-### master
-- Small performance improvement for 2D noise
-
-### 2.1.1
-- Increased entropy by fixing a little initialization issue.
-
-### 2.1.0
-- AMD support
-
-### 2.0.0
-- Changed node.js api, SimplexNoise is now exported directly.
-- Added unit tests
+[Play the demo](http://29a.ch/sandbox/2012/voxelworld/)
-### 1.0.0
-- Initial Release
+## Blog Post
+[Read the blog post](http://29a.ch/2012/12/9/webgl-voxel-worlds)
-## Credits
+## Talk
+[Watch the talk](http://vimeo.com/53698797)
-This is mostly a direct javascript port of the [Java implementation](http://webstaff.itn.liu.se/~stegu/simplexnoise/SimplexNoise.java)
-by Stefan Gustavson and Peter Eastman.
+## License
+Everything is, unless stated otherwise, copyright 2012 by Jonas Wagner
View
1 build/public/.htaccess
View
94 build/public/index.html
@@ -1,11 +1,91 @@
-<!DOCTYPE HTML>
+<!DOCTYPE html>
<html>
<head>
- <title>Voxel</title>
+ <title>Voxel World WebGL</title>
+ <link href='http://fonts.googleapis.com/css?family=Michroma'
+ rel='stylesheet' type='text/css'>
+ <link rel="stylesheet" href="style.css" />
</head>
- <body>
- <h1>Voxel</h1>
- <canvas width=1200 height=720 id=c></canvas>
+ <body style="height: 100%; width: 100%">
+ <div id="header">
+ <h1><a href="http://29a.ch/">29a.ch</a></h1>
+ <p><a href="http://29a.ch/2012/12/9/webgl-voxel-worlds">More about this experiment</a></p>&nbsp;&nbsp;&nbsp;
+ <p><a href="http://29a.ch/experiments/">More Experiments &amp; Toys</a></p>
+ <div id="social">
+ <a href="http://twitter.com/share" class="twitter-share-button"
+ data-url="http://29a.ch/sandbox/2012/voxelworld/"
+ data-text="WebGL Voxel Worlds experiment"
+ data-count="horizontal" data-via="29a_ch">Tweet</a>
+ <iframe
+ src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2F29a.ch%2Fsandbox%2F2012%2Fvoxelworld%2F&amp;layout=button_count&amp;show_faces=true&amp;width=450&amp;action=like&amp;font&amp;colorscheme=light&amp;height=21"
+ scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:90px;height:20px;" allowTransparency="true"></iframe>
+ <div class="g-plusone" data-size="medium"
+ data-href="http://29a.ch/sandbox/2012/voxelworld/" data-count="true"></div>
+ </div>
+ </div>
+ <div id="menu">
+ <span class=fullscreen>Fullscreen</span>
+ <span class=generate-world data-prefix=0>Generate Smooth World</span>
+ <span class=generate-world data-prefix=1>Generate Rocky World</span>
+ <span class=generate-world data-prefix=6>Generate Spikey World</span>
+ <span class=show-controls>Show Controls</span>
+ </div>
+ <div id="loading">
+ <p class="status">loading ...</p>
+ </div>
+ <div id="debug"></div>
+ <div id=controls style=display:none>
+ <h1>Controls</h1>
+ <p>Look:<br>
+ Click and Drag
+ </p>
+ <p>Movement:<br>
+ <span class=key>W</span>
+ <span class=key>A</span>
+ <span class=key>S</span>
+ <span class=key>D</span> or
+ <span class=key>&#9664;</span>
+ <span class=key>&#9650;</span>
+ <span class=key>&#9660;</span>
+ <span class=key>&#9654;</span>
+ </p>
+ <p>
+ Remove Voxel:</br>
+ <span class=key>Q</span>
+ </p>
+ <p>
+ Add Voxel:</br>
+ <span class=key>E</span>, Right Click
+ </p>
+ <p>
+ Jet Pack:</br>
+ <span class=key>Space</span>
+ </div>
+ <div id="cc">
+ <canvas id=c width=1280 height=720></canvas>
+ </div>
+ <div id="video">
+ <iframe width="1280" height="720" data-src="http://www.youtube-nocookie.com/embed/W99QeBI_QBo" frameborder="0" allowfullscreen></iframe>
+ </div>
+ <div id="footer">
+ An experiment by <a href="https://plus.google.com/107896782168573495211?rel=author" rel="author">Jonas Wagner</a></p>
+ </div>
<script src=main.js></script>
- </body>
-</html>
+
+ <script type="text/javascript" src="http://platform.twitter.com/widgets.js" async defer></script>
+ <script type="text/javascript" src="https://apis.google.com/js/plusone.js" async defer></script>
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-5205069-2']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
+ </body>
+ </html>
View
1 build/public/style.css
View
48 lib/game-shim.js
@@ -1,33 +1,33 @@
/**
* @fileoverview game-shim - Shims to normalize gaming-related APIs to their respective specs
* @author Brandon Jones
- * @version 0.9
+ * @version 1.0
*/
-/*
- * Copyright (c) 2012 Brandon Jones
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source
- * distribution.
- */
+/* Copyright (c) 2012, Brandon Jones. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
(function(global) {
+ "use strict";
var elementPrototype = (global.HTMLElement || global.Element)["prototype"];
var getter;
@@ -107,7 +107,7 @@
getter = (function() {
// These are the functions that match the spec, and should be preferred
if("webkitIsFullScreen" in document) {
- return function() { return webkitRequestFullScreen in document; };
+ return function() { return document.webkitFullscreenEnabled; };
}
if("mozFullScreenEnabled" in document) {
return function() { return document.mozFullScreenEnabled; };
View
53 public/index.html
@@ -9,44 +9,67 @@
<body style="height: 100%; width: 100%">
<div id="header">
<h1><a href="http://29a.ch/">29a.ch</a></h1>
- <p><a href="http://29a.ch/2012/7/19/webgl-terrain-rendering-water-fog">More about this experiment</a></p>&nbsp;&nbsp;&nbsp;
+ <p><a href="http://29a.ch/2012/12/9/webgl-voxel-worlds">More about this experiment</a></p>&nbsp;&nbsp;&nbsp;
<p><a href="http://29a.ch/experiments/">More Experiments &amp; Toys</a></p>
<div id="social">
<a href="http://twitter.com/share" class="twitter-share-button"
- data-url="http://29a.ch/sandbox/2012/terrain/"
- data-text="WebGL terrain rendering experiment showing the island of maui."
+ data-url="http://29a.ch/sandbox/2012/voxelworld/"
+ data-text="WebGL Voxel Worlds experiment"
data-count="horizontal" data-via="29a_ch">Tweet</a>
<iframe
- src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2F29a.ch%2Fsandbox%2F2012%2Fterrain%2F&amp;layout=button_count&amp;show_faces=true&amp;width=450&amp;action=like&amp;font&amp;colorscheme=light&amp;height=21"
+ src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2F29a.ch%2Fsandbox%2F2012%2Fvoxelworld%2F&amp;layout=button_count&amp;show_faces=true&amp;width=450&amp;action=like&amp;font&amp;colorscheme=light&amp;height=21"
scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:90px;height:20px;" allowTransparency="true"></iframe>
<div class="g-plusone" data-size="medium"
- data-href="http://29a.ch/sandbox/2012/terrain/" data-count="true"></div>
+ data-href="http://29a.ch/sandbox/2012/voxelworld/" data-count="true"></div>
</div>
</div>
<div id="menu">
- <!--<span class=fullscreen>Fullscreen</span>-->
- <!--<span class=wireframe>Toggle Wireframe</span>-->
- <!--<span class=ghost>Toggle Ghost Mode</span>-->
- <!--<span>-->
- <!--<span class="hq">High LOD</span>-->
- <!--|-->
- <!--<span class="lq active">Low LOD</span>-->
- <!--</span>-->
+ <span class=fullscreen>Fullscreen</span>
+ <span class=generate-world data-prefix=0>Generate Smooth World</span>
+ <span class=generate-world data-prefix=1>Generate Rocky World</span>
+ <span class=generate-world data-prefix=6>Generate Spikey World</span>
+ <span class=show-controls>Show Controls</span>
</div>
<div id="loading">
<p class="status">loading ...</p>
</div>
<div id="debug"></div>
+ <div id=controls style=display:none>
+ <h1>Controls</h1>
+ <p>Look:<br>
+ Click and Drag
+ </p>
+ <p>Movement:<br>
+ <span class=key>W</span>
+ <span class=key>A</span>
+ <span class=key>S</span>
+ <span class=key>D</span> or
+ <span class=key>&#9664;</span>
+ <span class=key>&#9650;</span>
+ <span class=key>&#9660;</span>
+ <span class=key>&#9654;</span>
+ </p>
+ <p>
+ Remove Voxel:</br>
+ <span class=key>Q</span>
+ </p>
+ <p>
+ Add Voxel:</br>
+ <span class=key>E</span>, Right Click
+ </p>
+ <p>
+ Jet Pack:</br>
+ <span class=key>Space</span>
+ </div>
<div id="cc">
<canvas id=c width=1280 height=720></canvas>
</div>
<div id="video">
- <iframe data-src="http://player.vimeo.com/video/46319690" width="1280" height="720" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
+ <iframe width="1280" height="720" data-src="http://www.youtube-nocookie.com/embed/W99QeBI_QBo" frameborder="0" allowfullscreen></iframe>
</div>
<div id="footer">
An experiment by <a href="https://plus.google.com/107896782168573495211?rel=author" rel="author">Jonas Wagner</a></p>
</div>
- <script src=../lib/game-shim.js></script>
<script src=../node_modules/requirejs/require.js></script>
<script src=main.js></script>
View
35 public/style.css
@@ -74,9 +74,8 @@ html, body{
padding: 0 8px;
}
-.ghost, .fullscreen, .wireframe, .hq.active, .lq.active {
+.fullscreen, .generate-world, .show-controls {
cursor: pointer;
- text-decoration: underline;
}
#footer {
@@ -128,3 +127,35 @@ html, body{
right: 0px;
background-color: black;
}
+
+canvas:-webkit-full-screen {
+ width: 100% !important;
+ height: 100% !important;
+}
+canvas:-moz-full-screen {
+ width: 100% !important;
+ height: 100% !important;
+}
+
+#controls {
+ position: absolute;
+ left: 50%;
+ padding: 8px;
+ margin-left: -256px;
+ width: 512px;
+ z-index:2;
+ background-color: rgba(0, 0, 0, 0.5);
+ border-radius: 8px;
+ box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.2);
+ border: 2px solid rgba(0, 0, 0, 0.6);
+ font-size: 14px;
+}
+.key {
+ border-radius: 4px;
+ min-width: 24px;
+ display: inline-block;
+ text-align: center;
+ padding: 2px;
+ color: #333;
+ background-color: #fff;
+}
View
1 src/cameracontroller.js
@@ -4,7 +4,6 @@ var cameracontroller = exports,
clamp = require('utils').clamp;
-
cameracontroller.MouseController = function MouseController(input, camera) {
this.input = input;
this.camera = camera;
View
24 src/gl/utils.js
@@ -172,20 +172,32 @@ glUtils.getContext = function (canvas, context_options, options) {
return window.gl;
};
-glUtils.fullscreen = function (canvas, scene, parent) {
- function onresize() {
- var height = $(parent || canvas).height(),
- width = $(parent || canvas).width();
+glUtils.fullscreen = function (canvas, scene, parent, onresize) {
+ function resize() {
+ var $element = $(document.fullscreenElement == canvas && canvas || parent || canvas),
+ height = $element.height(),
+ width = $element.width(),
+ update = false;
if(canvas.width != width){
canvas.width = scene.viewportWidth = width;
+ update = true;
}
if(canvas.height != height){
canvas.height = scene.viewportHeight = height;
+ update = true;
}
+ if(!update) return;
+ if(onresize) onresize(width, height);
scene.draw();
}
- window.addEventListener('resize', onresize, false);
- onresize();
+ var t;
+ function throttledResize(){
+ window.clearTimeout(t);
+ t = window.setTimeout(resize, 500);
+ }
+ window.addEventListener('resize', throttledResize, false);
+ canvas.ownerDocument.addEventListener('fullscreenchange', throttledResize, false);
+ resize();
};
glUtils.onerror = function(){
View
4 src/input.js
@@ -69,7 +69,7 @@ input.Handler.prototype = {
});
*/
document.onmousemove = function(e) {
- self.mouseMove(e.pageX, e.pageY);
+ self.mouseMove(e.pageX, e.pageY, e.movementX, e.movementY);
};
$(element).mousedown(function(e){
self.mouseDown();
@@ -126,7 +126,7 @@ input.Handler.prototype = {
this.onClick(this.mouse.x, this.mouse.y);
}
},
- mouseMove: function(x, y){
+ mouseMove: function(x, y, movementX, movementY){
this.mouse.x = clamp(x-this.offset.x, 0, this.width);
this.mouse.y = clamp(y-this.offset.y, 0, this.height);
},
View
88 src/main.js
@@ -1,6 +1,7 @@
define(function(require, exports){
require('jquery');
+require('game-shim');
var Loader = require('loader').Loader,
Clock = require('clock').Clock,
@@ -48,19 +49,30 @@ var loader = new Loader(),
debug_element = $('#debug'),
camera, player;
-var cube, cube2;
+var cube, cube2, resizeVBO;
function prepareScene(){
+ canvas.style.display = 'block';
+
window.world = new voxel.World({width: 8, height: 4, depth: 8, chunk_size: 32, scale: 0.5});
voxel.random_world(window.world, seed);
//voxel.flat_world(window.world, 10);
window.renderer = new glvoxel.Renderer(window.world);
var albedoFBO = new FBO(canvas.width, canvas.height, gl.FLOAT),
- blurFBO0 = new FBO(canvas.width, canvas.height, gl.FLOAT),
- blurFBO1 = new FBO(canvas.width, canvas.height, gl.FLOAT),
+ blurFBO0 = new FBO(canvas.width>>1, canvas.height>>1, gl.FLOAT),
+ blurFBO1 = new FBO(canvas.width>>1, canvas.height>>1, gl.FLOAT),
blurFBO2 = new FBO(canvas.width>>2, canvas.height>>2, gl.FLOAT),
blurFBO3 = new FBO(canvas.width>>2, canvas.height>>2, gl.FLOAT);
+ resizeVBO = function() {
+ // hoping the GC will clean up...
+ FBO.call(albedoFBO, canvas.width, canvas.height, gl.FLOAT);
+ FBO.call(blurFBO0, canvas.width>>1, canvas.height>>1, gl.FLOAT);
+ FBO.call(blurFBO1, canvas.width>>1, canvas.height>>1, gl.FLOAT);
+ FBO.call(blurFBO2, canvas.width>>2, canvas.height>>2, gl.FLOAT);
+ FBO.call(blurFBO3, canvas.width>>2, canvas.height>>2, gl.FLOAT);
+ };
+
cube = new scene.Transform([
new scene.Material(shaders.get('solid'), {color: vec4.create([0.5, 0.0, 0.0, 0.5])}, [
new scene.SimpleMesh(new glUtils.VBO(mesh.cube(-0.5)))])
@@ -85,7 +97,7 @@ function prepareScene(){
new scene.Postprocess(shaders.get('blur.vertex', 'blur.frag'), {
texture: albedoFBO,
direction: vec2.create([1, 0]),
- size: vec2.create([albedoFBO.width, albedoFBO.height])
+ size: vec2.create([blurFBO0.width, blurFBO0.height])
})
]),
new scene.RenderTarget(blurFBO1, [
@@ -124,7 +136,7 @@ function prepareScene(){
window.camera = camera;
camera.position[0] = 4*32*0.5;
camera.position[1] = 5*32*0.5;
- camera.position[2] = 8*32*0.5;
+ camera.position[2] = 5*32*0.5;
player = new Player(window.world);
player.setPosition(camera.position);
camera.pitch = Math.PI*0.25;
@@ -160,10 +172,10 @@ function integrate(dt, t) {
player.acceleration = vec3.scale(vec3.subtract(camera.position, player.position, vec3.create()), 1.0/dt);
if(input.keys.SPACE){
- player.acceleration[1] = 5;
+ player.acceleration[1] = 15;
}
else {
- player.acceleration[1] = -10;
+ player.acceleration[1] = 0;
}
if(!nogravity)
player.acceleration[1] -= 10;
@@ -172,14 +184,6 @@ function integrate(dt, t) {
player.tick(dt);
vec3.set(player.position, camera.position);
-
- //debug_element.html('<h4>ray</h4>' +
- //(hit ? 'hit' : 'miss') +
- //'<br>' + Array.prototype.slice.call(ray).join(',') +
- //'<br>' + Array.prototype.slice.call(window.cposition).join(',') +
- //'<br>' + Array.prototype.slice.call(window.clposition).join(',') +
- //'<br>' + voxel
- //);
}
function render(dt, t){
var ray = window.camera.getRay(),
@@ -208,22 +212,70 @@ function render(dt, t){
window.URL = window.URL || window.webkitURL;
-if(glUtils.getContext(canvas, {}, {debug: debug, texture_float: true}) == null){
+glUtils.onerror = function(el, msg, id){
+ alert(msg);
$('#loading').hide();
+ var f = $('#video iframe');
+ f.attr('src', f.data('src'));
$('#video').show('slow');
-}
+};
+
+glUtils.getContext(canvas, {}, {debug: debug, texture_float: true});
loader.onready = function() {
$('#loading .status').text('generating world');
window.setTimeout(function () {
prepareScene();
$(canvas).show('slow', function(){
+ showControls();
clock.start(canvas);
- glUtils.fullscreen(canvas, graph, $('#cc')[0]);
+ glUtils.fullscreen(canvas, graph, $('#cc')[0], function(){
+ resizeVBO();
+ });
});
}, 1);
};
+function showControls(){
+ $('#controls').fadeIn('slow');
+ $(document).one('mousedown', function() {
+ $('#controls').fadeOut(500);
+ });
+}
+$('.show-controls').click(showControls);
+
+$('.generate-world').click(function() {
+ var seed = $(this).data('prefix') + 'x' + ~~(Math.random()*10000000);
+ location.hash = 'seed=' + seed;
+ voxel.random_world(window.world, seed);
+ camera.position[0] = 4*32*0.5;
+ camera.position[1] = 5*32*0.5;
+ camera.position[2] = 5*32*0.5;
+ camera.pitch = Math.PI*0.25;
+ camera.yaw = 0.0;
+ player.setPosition(camera.position);
+ vec3.scale(player.velocity, 0.0);
+});
+$('.fullscreen').click(function() {
+ canvas.requestFullscreen();
+});
+$(canvas).mousedown(function(e){
+ if(e.which === 3) {
+ add_block = true;
+ e.preventDefault();
+ }
+});
+$(canvas).on('contextmenu', function(e){
+ return false;
+});
+
+if(!document.fullscreenEnabled){
+ $('.fullscreen').hide();
+}
+$(canvas).on('fullscreenerror', function () {
+ alert('failed to enable fullscreen');
+});
+
loader.load(RESOURCES);
});

0 comments on commit 5c38070

Please sign in to comment.
Something went wrong with that request. Please try again.