...
 
Commits (13)
node_modules
/css/
/node_modules/
*.swp
# Install
npm install
npm install -g browserify
npm start
gulp
gulp watch
node parse.js >> rooms.json
# Parse rooms
node parse.js >> app/rooms.json
# TODO doesnt work
browserify -t brfs index.js -o bundle.js
open index.html
# TODO
# TODO / Plan
- [ ] Gulp fixes (move server.js to gulp watch task)
- [ ] replace libxml-to-js with dom
- [ ] Draw SVG shapes over PDF maps in Inscape and set id to roomnumber.
- [ ] Parse SVG into suitable json datastructur (room, coordinates, dimensions).
- [ ] Render with three.js like described below.
- Draw SVG-shapes over PDF maps in Inscape and set id to roomnumber.
- parse SVG into suitable json datastructur (room, coordinates, dimensions)
- render with three.js like described below
# TODO improvements
- [ ] SVG parser: Allow SVG paths (see utils.js), use custom attribute for room numbers, make more generic
# Design
Similar to [this three.js design](http://threejs.org/examples/#webgl_lines_colors)
- Black backgrund
- Wireframe of room per floor tagged with name of room
- Highlight room by drawing color semitransparent glowing cube on tob of room floor
- Controller by query param and browser controls
- Highlight room by drawing color semi-transparent glowing cube on tob of room floor
- Controlled by query param and browser controls
# References
- [Three.js](http://threejs.org/docs/)
- [PDF maps of Chateau Neuf](http://www.admin.uio.no/ta/PDF_fra_Pythagoras_bygningsvis_public/universitetet/blindern/bl38/bl38.htm)
<!doctype html>
<html>
<head>
<title>Indoor map of Chateau Neuf</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/main.css" type="text/css">
</head>
<body class="">
<script src="/js/jquery-1.11.0.min.js"></script>
<script src="/js/three.js"></script>
<script src="/js/helvetiker_regular.typeface.js"></script>
<script src="/js/shaders/ConvolutionShader.js"></script>
<script src="/js/shaders/CopyShader.js"></script>
<script src="/js/shaders/FXAAShader.js"></script>
<script src="/js/post/EffectComposer.js"></script>
<script src="/js/post/RenderPass.js"></script>
<script src="/js/post/ShaderPass.js"></script>
<script src="/js/post/BloomPass.js"></script>
<script src="/js/post/MaskPass.js"></script>
<script src="/js/index.js"></script>
<div id="map"></div>
</body>
</html>
This diff is collapsed.
/* global THREE, window, document, $ */
(function () {
'use strict';
$(document).ready(function() {
var cubes = [];
var floors = [];
var bboxes = [];
var scene = new THREE.Scene();
var sceneWidth = 1000;
var sceneHeight = 1000;
//var smallestSize = Math.min(window.innerWidth, window.innerHeight);
//var sceneWidth = smallestSize;
//var sceneHeight = smallestSize;
var effectFXAA;
var composer;
var camera = new THREE.PerspectiveCamera( 75, sceneHeight / sceneWidth, 0.1, 2500 );
var renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(sceneWidth, sceneHeight);
document.getElementById('map').appendChild( renderer.domElement );
// material
var green_color = 0x00ff00;
var red_color = 0xcb3626;
var orange_color = 0xf58220;
var material = new THREE.LineBasicMaterial( { color: green_color, opacity: 0.3, blending: THREE.AdditiveBlending, transparent: true } );
var red_material = new THREE.MeshBasicMaterial( { color: red_color, opacity: 1, blending: THREE.AdditiveBlending, transparent: true } );
// rooms
var floor_height = 100;
var axis = new THREE.Vector3(0, 0.5, 0);//tilted a bit on x and y - feel free to plug your different axis here
function render() {
var i = 0;
var rad = 0;
var radIncrement = 0.001;
window.requestAnimationFrame(render);
var brand = scene.getObjectByName('brand');
for(i=0; i<scene.children.length; i++) {
var f = scene.children[i];
//in your update/draw function
rad -= radIncrement;
brand.rotateOnAxis(axis,rad);
}
//for(i=0; i<bboxes.length; i++) {
// bboxes[i].update();
//}
renderer.render(scene, camera);
//renderer.clear();
//composer.render();
}
function add_rooms(rooms, floor) {
var i = 0;
var cube;
var floor_container = new THREE.Object3D();
for(i=0; i<rooms.length; i++) {
var room = rooms[i];
// geometry
var geometry = new THREE.BoxGeometry(room.dimensions.width, room.dimensions.height, floor_height);
// KAK ?
if(floor === 4 && typeof room.number === "object" && (room.number.indexOf("428") > -1 || room.number.indexOf("429") > -1) ) {
cube = new THREE.Mesh( geometry, red_material );
} else {
cube = new THREE.Mesh( geometry, material );
}
cube.position.x = room.position.x + room.dimensions.width / 2;
cube.position.y = room.position.y * -1 - room.dimensions.height / 2; // Why flipped?
cube.position.z = floor_height * floor;
cube.name = room.number;
cubes.push(cube);
floor_container.add( cube );
}
scene.add(floor_container);
floor_container.rotation.z = -90 * (Math.PI / 180);
// DEBUG rotation around center
var bbox = new THREE.BoundingBoxHelper( floor_container, red_color);
bboxes[floor] = bbox;
scene.add(bbox);
}
function drawText() {
var shape = new THREE.TextGeometry("Chateau Neuf", {font: 'helvetiker'});
var wrapper = new THREE.MeshBasicMaterial({color: orange_color});
var words = new THREE.Mesh(shape, wrapper);
words.position.set(-600, -200, 450);
words.rotation.x = 90 * (Math.PI / 180);
words.name = 'brand';
scene.add(words);
}
function onRoomData(data) {
drawText();
var rooms = data.rooms;
var floor = parseInt(rooms[0].number[0], 10);
add_rooms(rooms, floor);
add_rooms(rooms, floor -1); // FIXME: play
camera.position.z = 1100;
camera.position.x = -700;
camera.position.y = -1500;
camera.rotation.x = 55 * (Math.PI / 180);
//camera.lookAt(scene.position);
/* FX */
var renderModel = new THREE.RenderPass( scene, camera );
var effectBloom = new THREE.BloomPass( 1.1 );
var effectCopy = new THREE.ShaderPass( THREE.CopyShader );
effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
var width = window.innerWidth || 2;
var height = window.innerHeight || 2;
effectFXAA.uniforms.resolution.value.set( 1 / width, 1 / height );
effectCopy.renderToScreen = true;
composer = new THREE.EffectComposer( renderer );
composer.addPass( renderModel );
composer.addPass( effectFXAA );
composer.addPass( effectBloom );
composer.addPass( effectCopy );
render();
}
// load rooms
$.getJSON("/rooms.json", onRoomData);
});
}());
This diff is collapsed.
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.BloomPass = function ( strength, kernelSize, sigma, resolution ) {
strength = ( strength !== undefined ) ? strength : 1;
kernelSize = ( kernelSize !== undefined ) ? kernelSize : 25;
sigma = ( sigma !== undefined ) ? sigma : 4.0;
resolution = ( resolution !== undefined ) ? resolution : 256;
// render targets
var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat };
this.renderTargetX = new THREE.WebGLRenderTarget( resolution, resolution, pars );
this.renderTargetY = new THREE.WebGLRenderTarget( resolution, resolution, pars );
// copy material
if ( THREE.CopyShader === undefined )
console.error( "THREE.BloomPass relies on THREE.CopyShader" );
var copyShader = THREE.CopyShader;
this.copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
this.copyUniforms[ "opacity" ].value = strength;
this.materialCopy = new THREE.ShaderMaterial( {
uniforms: this.copyUniforms,
vertexShader: copyShader.vertexShader,
fragmentShader: copyShader.fragmentShader,
blending: THREE.AdditiveBlending,
transparent: true
} );
// convolution material
if ( THREE.ConvolutionShader === undefined )
console.error( "THREE.BloomPass relies on THREE.ConvolutionShader" );
var convolutionShader = THREE.ConvolutionShader;
this.convolutionUniforms = THREE.UniformsUtils.clone( convolutionShader.uniforms );
this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurx;
this.convolutionUniforms[ "cKernel" ].value = THREE.ConvolutionShader.buildKernel( sigma );
this.materialConvolution = new THREE.ShaderMaterial( {
uniforms: this.convolutionUniforms,
vertexShader: convolutionShader.vertexShader,
fragmentShader: convolutionShader.fragmentShader,
defines: {
"KERNEL_SIZE_FLOAT": kernelSize.toFixed( 1 ),
"KERNEL_SIZE_INT": kernelSize.toFixed( 0 )
}
} );
this.enabled = true;
this.needsSwap = false;
this.clear = false;
this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
this.scene = new THREE.Scene();
this.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
this.scene.add( this.quad );
};
THREE.BloomPass.prototype = {
render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
if ( maskActive ) renderer.context.disable( renderer.context.STENCIL_TEST );
// Render quad with blured scene into texture (convolution pass 1)
this.quad.material = this.materialConvolution;
this.convolutionUniforms[ "tDiffuse" ].value = readBuffer;
this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurX;
renderer.render( this.scene, this.camera, this.renderTargetX, true );
// Render quad with blured scene into texture (convolution pass 2)
this.convolutionUniforms[ "tDiffuse" ].value = this.renderTargetX;
this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurY;
renderer.render( this.scene, this.camera, this.renderTargetY, true );
// Render original scene with superimposed blur to texture
this.quad.material = this.materialCopy;
this.copyUniforms[ "tDiffuse" ].value = this.renderTargetY;
if ( maskActive ) renderer.context.enable( renderer.context.STENCIL_TEST );
renderer.render( this.scene, this.camera, readBuffer, this.clear );
}
};
THREE.BloomPass.blurX = new THREE.Vector2( 0.001953125, 0.0 );
THREE.BloomPass.blurY = new THREE.Vector2( 0.0, 0.001953125 );
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.EffectComposer = function ( renderer, renderTarget ) {
this.renderer = renderer;
if ( renderTarget === undefined ) {
var width = window.innerWidth || 1;
var height = window.innerHeight || 1;
var parameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
renderTarget = new THREE.WebGLRenderTarget( width, height, parameters );
}
this.renderTarget1 = renderTarget;
this.renderTarget2 = renderTarget.clone();
this.writeBuffer = this.renderTarget1;
this.readBuffer = this.renderTarget2;
this.passes = [];
if ( THREE.CopyShader === undefined )
console.error( "THREE.EffectComposer relies on THREE.CopyShader" );
this.copyPass = new THREE.ShaderPass( THREE.CopyShader );
};
THREE.EffectComposer.prototype = {
swapBuffers: function() {
var tmp = this.readBuffer;
this.readBuffer = this.writeBuffer;
this.writeBuffer = tmp;
},
addPass: function ( pass ) {
this.passes.push( pass );
},
insertPass: function ( pass, index ) {
this.passes.splice( index, 0, pass );
},
render: function ( delta ) {
this.writeBuffer = this.renderTarget1;
this.readBuffer = this.renderTarget2;
var maskActive = false;
var pass, i, il = this.passes.length;
for ( i = 0; i < il; i ++ ) {
pass = this.passes[ i ];
if ( !pass.enabled ) continue;
pass.render( this.renderer, this.writeBuffer, this.readBuffer, delta, maskActive );
if ( pass.needsSwap ) {
if ( maskActive ) {
var context = this.renderer.context;
context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, delta );
context.stencilFunc( context.EQUAL, 1, 0xffffffff );
}
this.swapBuffers();
}
if ( pass instanceof THREE.MaskPass ) {
maskActive = true;
} else if ( pass instanceof THREE.ClearMaskPass ) {
maskActive = false;
}
}
},
reset: function ( renderTarget ) {
if ( renderTarget === undefined ) {
renderTarget = this.renderTarget1.clone();
renderTarget.width = window.innerWidth;
renderTarget.height = window.innerHeight;
}
this.renderTarget1 = renderTarget;
this.renderTarget2 = renderTarget.clone();
this.writeBuffer = this.renderTarget1;
this.readBuffer = this.renderTarget2;
},
setSize: function ( width, height ) {
var renderTarget = this.renderTarget1.clone();
renderTarget.width = width;
renderTarget.height = height;
this.reset( renderTarget );
}
};
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.MaskPass = function ( scene, camera ) {
this.scene = scene;
this.camera = camera;
this.enabled = true;
this.clear = true;
this.needsSwap = false;
this.inverse = false;
};
THREE.MaskPass.prototype = {
render: function ( renderer, writeBuffer, readBuffer, delta ) {
var context = renderer.context;
// don't update color or depth
context.colorMask( false, false, false, false );
context.depthMask( false );
// set up stencil
var writeValue, clearValue;
if ( this.inverse ) {
writeValue = 0;
clearValue = 1;
} else {
writeValue = 1;
clearValue = 0;
}
context.enable( context.STENCIL_TEST );
context.stencilOp( context.REPLACE, context.REPLACE, context.REPLACE );
context.stencilFunc( context.ALWAYS, writeValue, 0xffffffff );
context.clearStencil( clearValue );
// draw into the stencil buffer
renderer.render( this.scene, this.camera, readBuffer, this.clear );
renderer.render( this.scene, this.camera, writeBuffer, this.clear );
// re-enable update of color and depth
context.colorMask( true, true, true, true );
context.depthMask( true );
// only render where stencil is set to 1
context.stencilFunc( context.EQUAL, 1, 0xffffffff ); // draw if == 1
context.stencilOp( context.KEEP, context.KEEP, context.KEEP );
}
};
THREE.ClearMaskPass = function () {
this.enabled = true;
};
THREE.ClearMaskPass.prototype = {
render: function ( renderer, writeBuffer, readBuffer, delta ) {
var context = renderer.context;
context.disable( context.STENCIL_TEST );
}
};
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.RenderPass = function ( scene, camera, overrideMaterial, clearColor, clearAlpha ) {
this.scene = scene;
this.camera = camera;
this.overrideMaterial = overrideMaterial;
this.clearColor = clearColor;
this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 1;
this.oldClearColor = new THREE.Color();
this.oldClearAlpha = 1;
this.enabled = true;
this.clear = true;
this.needsSwap = false;
};
THREE.RenderPass.prototype = {
render: function ( renderer, writeBuffer, readBuffer, delta ) {
this.scene.overrideMaterial = this.overrideMaterial;
if ( this.clearColor ) {
this.oldClearColor.copy( renderer.getClearColor() );
this.oldClearAlpha = renderer.getClearAlpha();
renderer.setClearColor( this.clearColor, this.clearAlpha );
}
renderer.render( this.scene, this.camera, readBuffer, this.clear );
if ( this.clearColor ) {
renderer.setClearColor( this.oldClearColor, this.oldClearAlpha );
}
this.scene.overrideMaterial = null;
}
};
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.ShaderPass = function ( shader, textureID ) {
this.textureID = ( textureID !== undefined ) ? textureID : "tDiffuse";
this.uniforms = THREE.UniformsUtils.clone( shader.uniforms );
this.material = new THREE.ShaderMaterial( {
uniforms: this.uniforms,
vertexShader: shader.vertexShader,
fragmentShader: shader.fragmentShader
} );
this.renderToScreen = false;
this.enabled = true;
this.needsSwap = true;
this.clear = false;
this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
this.scene = new THREE.Scene();
this.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
this.scene.add( this.quad );
};
THREE.ShaderPass.prototype = {
render: function ( renderer, writeBuffer, readBuffer, delta ) {
if ( this.uniforms[ this.textureID ] ) {
this.uniforms[ this.textureID ].value = readBuffer;
}
this.quad.material = this.material;
if ( this.renderToScreen ) {
renderer.render( this.scene, this.camera );
} else {
renderer.render( this.scene, this.camera, writeBuffer, this.clear );
}
}
};
/**
* @author alteredq / http://alteredqualia.com/
*
* Convolution shader
* ported from o3d sample to WebGL / GLSL
* http://o3d.googlecode.com/svn/trunk/samples/convolution.html
*/
THREE.ConvolutionShader = {
defines: {
"KERNEL_SIZE_FLOAT": "25.0",
"KERNEL_SIZE_INT": "25",
},
uniforms: {
"tDiffuse": { type: "t", value: null },
"uImageIncrement": { type: "v2", value: new THREE.Vector2( 0.001953125, 0.0 ) },
"cKernel": { type: "fv1", value: [] }
},
vertexShader: [
"uniform vec2 uImageIncrement;",
"varying vec2 vUv;",
"void main() {",
"vUv = uv - ( ( KERNEL_SIZE_FLOAT - 1.0 ) / 2.0 ) * uImageIncrement;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"uniform float cKernel[ KERNEL_SIZE_INT ];",
"uniform sampler2D tDiffuse;",
"uniform vec2 uImageIncrement;",
"varying vec2 vUv;",
"void main() {",
"vec2 imageCoord = vUv;",
"vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );",
"for( int i = 0; i < KERNEL_SIZE_INT; i ++ ) {",
"sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ];",
"imageCoord += uImageIncrement;",
"}",
"gl_FragColor = sum;",
"}"
].join("\n"),
buildKernel: function ( sigma ) {
// We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway.
function gauss( x, sigma ) {
return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) );
}
var i, values, sum, halfWidth, kMaxKernelSize = 25, kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1;
if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize;
halfWidth = ( kernelSize - 1 ) * 0.5;
values = new Array( kernelSize );
sum = 0.0;
for ( i = 0; i < kernelSize; ++i ) {
values[ i ] = gauss( i - halfWidth, sigma );
sum += values[ i ];
}
// normalize the kernel
for ( i = 0; i < kernelSize; ++i ) values[ i ] /= sum;
return values;
}
};
/**
* @author alteredq / http://alteredqualia.com/
*
* Full-screen textured quad shader
*/
THREE.CopyShader = {
uniforms: {
"tDiffuse": { type: "t", value: null },
"opacity": { type: "f", value: 1.0 }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"uniform float opacity;",
"uniform sampler2D tDiffuse;",
"varying vec2 vUv;",
"void main() {",
"vec4 texel = texture2D( tDiffuse, vUv );",
"gl_FragColor = opacity * texel;",
"}"
].join("\n")
};
/**
* @author alteredq / http://alteredqualia.com/
* @author davidedc / http://www.sketchpatch.net/
*
* NVIDIA FXAA by Timothy Lottes
* http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html
* - WebGL port by @supereggbert
* http://www.glge.org/demos/fxaa/
*/
THREE.FXAAShader = {
uniforms: {
"tDiffuse": { type: "t", value: null },
"resolution": { type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"uniform sampler2D tDiffuse;",
"uniform vec2 resolution;",
"varying vec2 vUv;",
"#define FXAA_REDUCE_MIN (1.0/128.0)",
"#define FXAA_REDUCE_MUL (1.0/8.0)",
"#define FXAA_SPAN_MAX 8.0",
"void main() {",
"vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;",
"vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;",
"vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;",
"vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;",
"vec4 rgbaM = texture2D( tDiffuse, gl_FragCoord.xy * resolution );",
"vec3 rgbM = rgbaM.xyz;",
"float opacity = rgbaM.w;",
"vec3 luma = vec3( 0.299, 0.587, 0.114 );",
"float lumaNW = dot( rgbNW, luma );",
"float lumaNE = dot( rgbNE, luma );",
"float lumaSW = dot( rgbSW, luma );",
"float lumaSE = dot( rgbSE, luma );",
"float lumaM = dot( rgbM, luma );",
"float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );",
"float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );",
"vec2 dir;",
"dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));",
"dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));",
"float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );",
"float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );",
"dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),",
"max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),",
"dir * rcpDirMin)) * resolution;",
"vec3 rgbA = texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ).xyz;",
"rgbA += texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ).xyz;",
"rgbA *= 0.5;",
"vec3 rgbB = texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * -0.5 ).xyz;",
"rgbB += texture2D( tDiffuse, gl_FragCoord.xy * resolution + dir * 0.5 ).xyz;",
"rgbB *= 0.25;",
"rgbB += rgbA * 0.5;",
"float lumaB = dot( rgbB, luma );",
"if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {",
"gl_FragColor = vec4( rgbA, opacity );",
"} else {",
"gl_FragColor = vec4( rgbB, opacity );",
"}",
"}"
].join("\n")
};
This diff is collapsed.
This diff is collapsed.
body,
html
{
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
body {
background-color: lighten(black, 8%);
background: radial-gradient(lighten(black, 10%), black);
text-align: center;
}
#svg {
display: none;
}
.debug #svg{
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 100%;
}
{
"name": "indoormap",
"version": "0.0.1",
"authors": [
"EDB-gjengen <kak-edb@studentersamfundet.no>"
],
"description": "Indoor map of Chateau Neuf",
"main": "index.js",
"license": "MIT",
"homepage": "https://edb.neuf.no",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}
This diff is collapsed.
{"rooms":[{"number":"447","pos":{"x":"53.564445","y":"-158.08394"},"size":{"height":"77.731247","width":"77.904381"}},{"number":"450","pos":{"x":"318.01108","y":"-185.0863"},"size":{"height":"69.93187","width":"36.000183"}},{"number":"448","pos":{"x":"354.71475","y":"-185.08415"},"size":{"height":"100.39677","width":"112.169"}},{"number":"423","pos":{"x":"466.89041","y":"-185.09079"},"size":{"height":"101.79505","width":"146.80646"}},{"number":"427","pos":{"x":"665.62469","y":"-230.11064"},"size":{"height":"45.028267","width":"76.190018"}},{"number":"437","pos":{"x":"756.34747","y":"-184.39943"},"size":{"height":"291.53769","width":"35.318886"}},{"number":["428","429"],"pos":{"x":"791.67664","y":"-184.38683"},"size":{"height":"146.09106","width":"117.69923"}},{"number":"430","pos":{"x":"793.05017","y":"-36.899376"},"size":{"height":"68.555847","width":"117.72215"}},{"number":"431","pos":{"x":"793.05017","y":"30.963974"},"size":{"height":"76.865646","width":"118.41465"}},{"number":"440","pos":{"x":"792.3576","y":"107.82961"},"size":{"height":"146.11398","width":"118.41465"}},{"number":"436","pos":{"x":"756.38678","y":"107.17565"},"size":{"height":"294.92099","width":"35.932209"}},{"number":"435","pos":{"x":"792.3576","y":"321.80695"},"size":{"height":"81.020546","width":"117.02967"}},{"number":"444","pos":{"x":"685.02264","y":"474.84579"},"size":{"height":"71.325775","width":"72.710747"}},{"number":"402","pos":{"x":"827.67426","y":"498.39026"},"size":{"height":"44.318932","width":"72.710747"}},{"number":"420","pos":{"x":"758.47394","y":"581.2832"},"size":{"height":"115.85214","width":"69.047668"}},{"number":"411","pos":{"x":"22.717258","y":"580.50562"},"size":{"height":"82.557472","width":"53.380753"}},{"number":"403","pos":{"x":"152.27817","y":"580.30676"},"size":{"height":"38.193451","width":"43.090046"}},{"number":"409","pos":{"x":"195.37247","y":"580.31085"},"size":{"height":"78.540001","width":"49.447254"}},{"number":"412","pos":{"x":"23.009211","y":"546.86469"},"size":{"height":"33.930614","width":"589.30219"}},{"number":"407","pos":{"x":"319.73325","y":"580.29822"},"size":{"height":"117.53546","width":"75.99839"}},{"number":"406","pos":{"x":"395.63904","y":"580.30676"},"size":{"height":"118.00798","width":"70.021324"}},{"number":"405","pos":{"x":"465.17068","y":"580.79633"},"size":{"height":"117.02865","width":"146.89789"}},{"number":"404","pos":{"x":"612.0686","y":"581.7757"},"size":{"height":"115.55968","width":"76.386887"}},{"number":"421","pos":{"x":"688.44983","y":"581.48309"},"size":{"height":"115.65492","width":"70.522224"}},{"number":"419","pos":{"x":"827.03021","y":"543.58331"},"size":{"height":"153.60759","width":"80.791679"}},{"number":"422","pos":{"x":"22.019121","y":"108.75488"},"size":{"height":"32.623585","width":"34.29538"}},{"number":"417","pos":{"x":"22.518375","y":"141.57167"},"size":{"height":"205.65706","width":"105.27682"}},{"number":"414","pos":{"x":"23.008051","y":"401.58087"},"size":{"height":"43.579708","width":"71.490303"}},{"number":"413","pos":{"x":"23.008051","y":"444.6709"},"size":{"height":"102.8285","width":"71.490265"}}]}
\ No newline at end of file
body,
html {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden; }
body {
background-color: #141414;
background: radial-gradient(#1a1a1a, black);
text-align: center; }
#svg {
display: none; }
.debug #svg {
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 100%; }
<!doctype html>
<html>
<head>
<title>Indoor map of Chateau Neuf</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/main.css" type="text/css">
</head>
<body class="">
<script src="/js/jquery-1.11.0.min.js"></script>
<script src="/js/three.js"></script>
<script src="/js/helvetiker_regular.typeface.js"></script>
<script src="/js/shaders/ConvolutionShader.js"></script>
<script src="/js/shaders/CopyShader.js"></script>
<script src="/js/shaders/FXAAShader.js"></script>
<script src="/js/post/EffectComposer.js"></script>
<script src="/js/post/RenderPass.js"></script>
<script src="/js/post/ShaderPass.js"></script>
<script src="/js/post/BloomPass.js"></script>
<script src="/js/post/MaskPass.js"></script>
<script src="/js/index.js"></script>
<div id="map"></div>
</body>
</html>
This diff is collapsed.
/* global THREE, window, document, $ */
(function () {
'use strict';
$(document).ready(function() {
var cubes = [];
var floors = [];
var bboxes = [];
var scene = new THREE.Scene();
var sceneWidth = 1000;
var sceneHeight = 1000;
//var smallestSize = Math.min(window.innerWidth, window.innerHeight);
//var sceneWidth = smallestSize;
//var sceneHeight = smallestSize;
var effectFXAA;
var composer;
var camera = new THREE.PerspectiveCamera( 75, sceneHeight / sceneWidth, 0.1, 2500 );
var renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(sceneWidth, sceneHeight);
document.getElementById('map').appendChild( renderer.domElement );
// material
var green_color = 0x00ff00;
var red_color = 0xcb3626;
var orange_color = 0xf58220;
var material = new THREE.LineBasicMaterial( { color: green_color, opacity: 0.3, blending: THREE.AdditiveBlending, transparent: true } );
var red_material = new THREE.MeshBasicMaterial( { color: red_color, opacity: 1, blending: THREE.AdditiveBlending, transparent: true } );
// rooms
var floor_height = 100;
var axis = new THREE.Vector3(0, 0.5, 0);//tilted a bit on x and y - feel free to plug your different axis here
function render() {
var i = 0;
var rad = 0;
var radIncrement = 0.001;
window.requestAnimationFrame(render);
var brand = scene.getObjectByName('brand');
for(i=0; i<scene.children.length; i++) {
var f = scene.children[i];
//in your update/draw function
rad -= radIncrement;
brand.rotateOnAxis(axis,rad);
}
//for(i=0; i<bboxes.length; i++) {
// bboxes[i].update();
//}
renderer.render(scene, camera);
//renderer.clear();
//composer.render();
}
function add_rooms(rooms, floor) {
var i = 0;
var cube;
var floor_container = new THREE.Object3D();
for(i=0; i<rooms.length; i++) {
var room = rooms[i];
// geometry
var geometry = new THREE.BoxGeometry(room.dimensions.width, room.dimensions.height, floor_height);
// KAK ?
if(floor === 4 && typeof room.number === "object" && (room.number.indexOf("428") > -1 || room.number.indexOf("429") > -1) ) {
cube = new THREE.Mesh( geometry, red_material );
} else {
cube = new THREE.Mesh( geometry, material );
}
cube.position.x = room.position.x + room.dimensions.width / 2;
cube.position.y = room.position.y * -1 - room.dimensions.height / 2; // Why flipped?
cube.position.z = floor_height * floor;
cube.name = room.number;
cubes.push(cube);
floor_container.add( cube );
}
scene.add(floor_container);
floor_container.rotation.z = -90 * (Math.PI / 180);
// DEBUG rotation around center
var bbox = new THREE.BoundingBoxHelper( floor_container, red_color);
bboxes[floor] = bbox;
scene.add(bbox);
}
function drawText() {
var shape = new THREE.TextGeometry("Chateau Neuf", {font: 'helvetiker'});
var wrapper = new THREE.MeshBasicMaterial({color: orange_color});
var words = new THREE.Mesh(shape, wrapper);
words.position.set(-600, -200, 450);
words.rotation.x = 90 * (Math.PI / 180);
words.name = 'brand';
scene.add(words);
}
function onRoomData(data) {
drawText();
var rooms = data.rooms;
var floor = parseInt(rooms[0].number[0], 10);
add_rooms(rooms, floor);
add_rooms(rooms, floor -1); // FIXME: play
camera.position.z = 1100;
camera.position.x = -700;
camera.position.y = -1500;
camera.rotation.x = 55 * (Math.PI / 180);
//camera.lookAt(scene.position);
/* FX */
var renderModel = new THREE.RenderPass( scene, camera );
var effectBloom = new THREE.BloomPass( 1.1 );
var effectCopy = new THREE.ShaderPass( THREE.CopyShader );
effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
var width = window.innerWidth || 2;
var height = window.innerHeight || 2;
effectFXAA.uniforms.resolution.value.set( 1 / width, 1 / height );
effectCopy.renderToScreen = true;
composer = new THREE.EffectComposer( renderer );
composer.addPass( renderModel );
composer.addPass( effectFXAA );
composer.addPass( effectBloom );
composer.addPass( effectCopy );
render();
}
// load rooms
$.getJSON("/rooms.json", onRoomData);
});
}());
This diff is collapsed.
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.BloomPass = function ( strength, kernelSize, sigma, resolution ) {
strength = ( strength !== undefined ) ? strength : 1;
kernelSize = ( kernelSize !== undefined ) ? kernelSize : 25;
sigma = ( sigma !== undefined ) ? sigma : 4.0;
resolution = ( resolution !== undefined ) ? resolution : 256;
// render targets
var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat };
this.renderTargetX = new THREE.WebGLRenderTarget( resolution, resolution, pars );
this.renderTargetY = new THREE.WebGLRenderTarget( resolution, resolution, pars );
// copy material
if ( THREE.CopyShader === undefined )
console.error( "THREE.BloomPass relies on THREE.CopyShader" );
var copyShader = THREE.CopyShader;
this.copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
this.copyUniforms[ "opacity" ].value = strength;
this.materialCopy = new THREE.ShaderMaterial( {
uniforms: this.copyUniforms,
vertexShader: copyShader.vertexShader,
fragmentShader: copyShader.fragmentShader,
blending: THREE.AdditiveBlending,
transparent: true
} );
// convolution material
if ( THREE.ConvolutionShader === undefined )
console.error( "THREE.BloomPass relies on THREE.ConvolutionShader" );
var convolutionShader = THREE.ConvolutionShader;
this.convolutionUniforms = THREE.UniformsUtils.clone( convolutionShader.uniforms );
this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurx;
this.convolutionUniforms[ "cKernel" ].value = THREE.ConvolutionShader.buildKernel( sigma );
this.materialConvolution = new THREE.ShaderMaterial( {
uniforms: this.convolutionUniforms,
vertexShader: convolutionShader.vertexShader,
fragmentShader: convolutionShader.fragmentShader,
defines: {
"KERNEL_SIZE_FLOAT": kernelSize.toFixed( 1 ),
"KERNEL_SIZE_INT": kernelSize.toFixed( 0 )
}
} );
this.enabled = true;
this.needsSwap = false;
this.clear = false;
this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
this.scene = new THREE.Scene();
this.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
this.scene.add( this.quad );
};
THREE.BloomPass.prototype = {
render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
if ( maskActive ) renderer.context.disable( renderer.context.STENCIL_TEST );
// Render quad with blured scene into texture (convolution pass 1)
this.quad.material = this.materialConvolution;
this.convolutionUniforms[ "tDiffuse" ].value = readBuffer;
this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurX;
renderer.render( this.scene, this.camera, this.renderTargetX, true );
// Render quad with blured scene into texture (convolution pass 2)
this.convolutionUniforms[ "tDiffuse" ].value = this.renderTargetX;
this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurY;
renderer.render( this.scene, this.camera, this.renderTargetY, true );
// Render original scene with superimposed blur to texture
this.quad.material = this.materialCopy;
this.copyUniforms[ "tDiffuse" ].value = this.renderTargetY;
if ( maskActive ) renderer.context.enable( renderer.context.STENCIL_TEST );
renderer.render( this.scene, this.camera, readBuffer, this.clear );
}
};
THREE.BloomPass.blurX = new THREE.Vector2( 0.001953125, 0.0 );
THREE.BloomPass.blurY = new THREE.Vector2( 0.0, 0.001953125 );
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.EffectComposer = function ( renderer, renderTarget ) {
this.renderer = renderer;
if ( renderTarget === undefined ) {
var width = window.innerWidth || 1;
var height = window.innerHeight || 1;
var parameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
renderTarget = new THREE.WebGLRenderTarget( width, height, parameters );
}
this.renderTarget1 = renderTarget;
this.renderTarget2 = renderTarget.clone();
this.writeBuffer = this.renderTarget1;
this.readBuffer = this.renderTarget2;
this.passes = [];
if ( THREE.CopyShader === undefined )
console.error( "THREE.EffectComposer relies on THREE.CopyShader" );
this.copyPass = new THREE.ShaderPass( THREE.CopyShader );
};
THREE.EffectComposer.prototype = {
swapBuffers: function() {
var tmp = this.readBuffer;
this.readBuffer = this.writeBuffer;
this.writeBuffer = tmp;
},
addPass: function ( pass ) {
this.passes.push( pass );
},
insertPass: function ( pass, index ) {
this.passes.splice( index, 0, pass );
},
render: function ( delta ) {
this.writeBuffer = this.renderTarget1;
this.readBuffer = this.renderTarget2;
var maskActive = false;
var pass, i, il = this.passes.length;
for ( i = 0; i < il; i ++ ) {
pass = this.passes[ i ];
if ( !pass.enabled ) continue;
pass.render( this.renderer, this.writeBuffer, this.readBuffer, delta, maskActive );
if ( pass.needsSwap ) {
if ( maskActive ) {
var context = this.renderer.context;
context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, delta );
context.stencilFunc( context.EQUAL, 1, 0xffffffff );
}
this.swapBuffers();
}
if ( pass instanceof THREE.MaskPass ) {
maskActive = true;
} else if ( pass instanceof THREE.ClearMaskPass ) {
maskActive = false;
}
}
},
reset: function ( renderTarget ) {
if ( renderTarget === undefined ) {
renderTarget = this.renderTarget1.clone();
renderTarget.width = window.innerWidth;
renderTarget.height = window.innerHeight;
}
this.renderTarget1 = renderTarget;
this.renderTarget2 = renderTarget.clone();
this.writeBuffer = this.renderTarget1;
this.readBuffer = this.renderTarget2;
},
setSize: function ( width, height ) {
var renderTarget = this.renderTarget1.clone();
renderTarget.width = width;
renderTarget.height = height;
this.reset( renderTarget );
}
};
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.MaskPass = function ( scene, camera ) {
this.scene = scene;
this.camera = camera;
this.enabled = true;
this.clear = true;
this.needsSwap = false;
this.inverse = false;
};