2017-03-11 15:22:17 +01:00
|
|
|
<!DOCTYPE html>
|
|
|
|
|
|
|
|
|
|
<html lang="en">
|
|
|
|
|
|
|
|
|
|
<head>
|
2017-03-18 15:59:26 +01:00
|
|
|
<title>Web VR - #2 JS Meetup Sarajevo</title>
|
2017-03-11 15:22:17 +01:00
|
|
|
<meta charset="utf-8">
|
|
|
|
|
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0, shrink-to-fit=no">
|
|
|
|
|
<meta name="mobile-web-app-capable" content="yes">
|
|
|
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
|
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
|
|
|
<style>
|
|
|
|
|
body {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
background-color: #000;
|
|
|
|
|
color: #fff;
|
|
|
|
|
margin: 0px;
|
|
|
|
|
padding: 0;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
/* Position the button on the bottom of the page. */
|
|
|
|
|
|
|
|
|
|
#ui {
|
|
|
|
|
position: absolute;
|
|
|
|
|
bottom: 10px;
|
|
|
|
|
left: 50%;
|
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
|
text-align: center;
|
|
|
|
|
font-family: 'Karla', sans-serif;
|
|
|
|
|
z-index: 1;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-11 19:26:53 +01:00
|
|
|
#magic-window {
|
2017-03-11 15:22:17 +01:00
|
|
|
display: block;
|
|
|
|
|
color: white;
|
|
|
|
|
margin-top: 1em;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
<body>
|
|
|
|
|
<div id="ui">
|
|
|
|
|
<div id="vr-button"></div>
|
2017-03-18 06:43:20 +01:00
|
|
|
<a id="magic-window">Try it without a headset</a>
|
2017-03-11 15:22:17 +01:00
|
|
|
</div>
|
|
|
|
|
</body>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
/*
|
|
|
|
|
* Debug parameters.
|
|
|
|
|
*/
|
|
|
|
|
WebVRConfig = {
|
|
|
|
|
/**
|
|
|
|
|
* webvr-polyfill configuration
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// Forces availability of VR mode.
|
|
|
|
|
//FORCE_ENABLE_VR: true, // Default: false.
|
|
|
|
|
// Complementary filter coefficient. 0 for accelerometer, 1 for gyro.
|
|
|
|
|
//K_FILTER: 0.98, // Default: 0.98.
|
|
|
|
|
// How far into the future to predict during fast motion.
|
|
|
|
|
//PREDICTION_TIME_S: 0.040, // Default: 0.040 (in seconds).
|
|
|
|
|
// Flag to disable touch panner. In case you have your own touch controls
|
|
|
|
|
//TOUCH_PANNER_DISABLED: true, // Default: false.
|
|
|
|
|
// Enable yaw panning only, disabling roll and pitch. This can be useful for
|
|
|
|
|
// panoramas with nothing interesting above or below.
|
|
|
|
|
//YAW_ONLY: true, // Default: false.
|
|
|
|
|
// Enable the deprecated version of the API (navigator.getVRDevices).
|
|
|
|
|
//ENABLE_DEPRECATED_API: true, // Default: false.
|
|
|
|
|
// Scales the recommended buffer size reported by WebVR, which can improve
|
|
|
|
|
// performance. Making this very small can lower the effective resolution of
|
|
|
|
|
// your scene.
|
|
|
|
|
BUFFER_SCALE: 0.5, // default: 1.0
|
|
|
|
|
// Allow VRDisplay.submitFrame to change gl bindings, which is more
|
|
|
|
|
// efficient if the application code will re-bind it's resources on the
|
|
|
|
|
// next frame anyway.
|
|
|
|
|
// Dirty bindings include: gl.FRAMEBUFFER_BINDING, gl.CURRENT_PROGRAM,
|
|
|
|
|
// gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING,
|
|
|
|
|
// and gl.TEXTURE_BINDING_2D for texture unit 0
|
|
|
|
|
// Warning: enabling this might lead to rendering issues.
|
|
|
|
|
//DIRTY_SUBMIT_FRAME_BINDINGS: true // default: false
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<!--
|
|
|
|
|
A polyfill for Promises. Needed for IE and Edge.
|
|
|
|
|
-->
|
|
|
|
|
<script src="node_modules/es6-promise/dist/es6-promise.min.js"></script>
|
|
|
|
|
|
|
|
|
|
<!--
|
|
|
|
|
three.js 3d library
|
|
|
|
|
-->
|
|
|
|
|
<script src="node_modules/three/build/three.min.js"></script>
|
|
|
|
|
|
|
|
|
|
<!--
|
|
|
|
|
VRControls.js acquires positional information from connected VR devices and applies the transformations to a three.js camera object.
|
|
|
|
|
-->
|
|
|
|
|
<script src="node_modules/three/examples/js/controls/VRControls.js"></script>
|
|
|
|
|
|
|
|
|
|
<!--
|
|
|
|
|
VREffect.js handles stereo camera setup and rendering.
|
|
|
|
|
-->
|
|
|
|
|
<script src="node_modules/three/examples/js/effects/VREffect.js"></script>
|
|
|
|
|
|
|
|
|
|
<!--
|
|
|
|
|
A polyfill for WebVR using the Device{Motion,Orientation}Event API.
|
|
|
|
|
-->
|
|
|
|
|
<script src="node_modules/webvr-polyfill/build/webvr-polyfill.min.js"></script>
|
|
|
|
|
|
|
|
|
|
<!--
|
|
|
|
|
A set of UI controls for entering VR mode.
|
|
|
|
|
-->
|
|
|
|
|
<script src="node_modules/webvr-ui/build/webvr-ui.min.js"></script>
|
|
|
|
|
|
2017-03-18 15:59:26 +01:00
|
|
|
|
2017-03-11 19:26:53 +01:00
|
|
|
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.5.0.js"></script>
|
|
|
|
|
|
2017-03-18 06:43:20 +01:00
|
|
|
<script src="./orbit-gamepad.js"></script>
|
|
|
|
|
|
2017-03-11 15:22:17 +01:00
|
|
|
|
|
|
|
|
<script>
|
2017-03-11 19:26:53 +01:00
|
|
|
var pubnub = new PubNub({
|
|
|
|
|
publishKey: 'pub-c-7f43492c-431c-4404-b7a7-96ee3f60086a',
|
|
|
|
|
subscribeKey: 'sub-c-1fd379da-067e-11e7-83b6-0619f8945a4f'
|
|
|
|
|
})
|
|
|
|
|
|
2017-03-18 15:59:26 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-03-18 06:43:20 +01:00
|
|
|
var heightOfUser = 1.6;
|
|
|
|
|
|
|
|
|
|
if (isClient()) {
|
2017-03-18 15:59:26 +01:00
|
|
|
|
2017-03-22 17:35:01 +01:00
|
|
|
// ablyChannel.subscribe('camsync', function(message) {
|
|
|
|
|
// if (vrButton.isPresenting()) {
|
|
|
|
|
// var newMatrix = message.data.camera;
|
|
|
|
|
// camera.matrix.fromArray(message.data.camera);
|
|
|
|
|
// camera.matrix.decompose(camera.position, camera.quaternion, camera.scale);
|
|
|
|
|
// dollyCam.matrix.fromArray(message.data.dollyCam);
|
|
|
|
|
// dollyCam.matrix.decompose(dollyCam.position, dollyCam.quaternion, dollyCam.scale);
|
|
|
|
|
// effect.render(scene, camera);
|
|
|
|
|
// controls.update();
|
|
|
|
|
// }
|
|
|
|
|
// });
|
2017-03-11 19:26:53 +01:00
|
|
|
// Subscribe to the demo_tutorial channel
|
|
|
|
|
pubnub.addListener({
|
|
|
|
|
message: function(message) {
|
2017-03-18 06:43:20 +01:00
|
|
|
if (vrButton.isPresenting()) {
|
2017-03-18 15:59:26 +01:00
|
|
|
var newMatrix = message.message.camera;
|
2017-03-18 06:43:20 +01:00
|
|
|
camera.matrix.fromArray(message.message.camera);
|
|
|
|
|
camera.matrix.decompose(camera.position, camera.quaternion, camera.scale);
|
|
|
|
|
dollyCam.matrix.fromArray(message.message.dollyCam);
|
|
|
|
|
dollyCam.matrix.decompose(dollyCam.position, dollyCam.quaternion, dollyCam.scale);
|
|
|
|
|
effect.render(scene, camera);
|
|
|
|
|
controls.update();
|
|
|
|
|
}
|
2017-03-11 19:26:53 +01:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2017-03-22 17:35:01 +01:00
|
|
|
pubnub.subscribe({
|
2017-03-11 19:26:53 +01:00
|
|
|
channels: ['cameramatrix']
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-18 06:43:20 +01:00
|
|
|
function isClient() {
|
2017-03-18 15:59:26 +01:00
|
|
|
return window.location.hash === '' || window.location.hash === '#client';
|
2017-03-18 06:43:20 +01:00
|
|
|
}
|
|
|
|
|
|
2017-03-11 19:26:53 +01:00
|
|
|
var oldCameraMatrix;
|
2017-03-18 15:59:26 +01:00
|
|
|
var oldDollyCamMatrix;
|
2017-03-11 19:26:53 +01:00
|
|
|
var CAM_DELTA = 0.02;
|
|
|
|
|
|
|
|
|
|
function matrixChanged(oldMatrix, newMatrix) {
|
|
|
|
|
if (!oldMatrix) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
var oldLength = oldMatrix.length;
|
|
|
|
|
var newLength = newMatrix.length;
|
|
|
|
|
if (oldLength != newLength) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < newLength; i++) {
|
2017-03-18 06:43:20 +01:00
|
|
|
if (Math.abs(oldMatrix[i] - newMatrix[i]) > CAM_DELTA) {
|
2017-03-11 19:26:53 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-22 17:35:01 +01:00
|
|
|
function publishCameraLocationMessage() {
|
2017-03-11 19:26:53 +01:00
|
|
|
|
|
|
|
|
if (window.location.hash !== '#presenter') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var newCameraMatrix = camera.matrix.toArray();
|
2017-03-18 06:43:20 +01:00
|
|
|
var newDollyCamMatrix = dollyCam.matrix.toArray();
|
2017-03-11 19:26:53 +01:00
|
|
|
var publishConfig = {
|
|
|
|
|
channel: "cameramatrix",
|
2017-03-18 06:43:20 +01:00
|
|
|
message: {
|
|
|
|
|
camera: newCameraMatrix,
|
|
|
|
|
dollyCam: newDollyCamMatrix
|
|
|
|
|
}
|
2017-03-11 19:26:53 +01:00
|
|
|
}
|
|
|
|
|
|
2017-03-18 15:59:26 +01:00
|
|
|
// ablyChannel.publish('camsync', {
|
|
|
|
|
// camera: newCameraMatrix,
|
|
|
|
|
// dollyCam: newDollyCamMatrix
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
if (matrixChanged(oldCameraMatrix, newCameraMatrix) || matrixChanged(oldDollyCamMatrix, newDollyCamMatrix)) {
|
2017-03-11 19:26:53 +01:00
|
|
|
pubnub.publish(publishConfig, function(status, response) {
|
|
|
|
|
//console.log(status, response);
|
|
|
|
|
})
|
|
|
|
|
oldCameraMatrix = newCameraMatrix;
|
2017-03-18 15:59:26 +01:00
|
|
|
oldDollyCamMatrix = newDollyCamMatrix;
|
2017-03-11 19:26:53 +01:00
|
|
|
}
|
|
|
|
|
}
|
2017-03-11 15:22:17 +01:00
|
|
|
// Last time the scene was rendered.
|
|
|
|
|
var lastRenderTime = 0;
|
|
|
|
|
// Currently active VRDisplay.
|
|
|
|
|
var vrDisplay;
|
|
|
|
|
// How big of a sphere to render.
|
2017-03-18 15:59:26 +01:00
|
|
|
var boxSize = 200;
|
2017-03-11 15:22:17 +01:00
|
|
|
// Various global THREE.Objects.
|
|
|
|
|
var scene;
|
|
|
|
|
var cube;
|
|
|
|
|
var controls;
|
2017-03-18 06:43:20 +01:00
|
|
|
var orbitControls;
|
2017-03-11 15:22:17 +01:00
|
|
|
var effect;
|
|
|
|
|
var camera;
|
2017-03-11 19:26:53 +01:00
|
|
|
var dollyCam;
|
2017-03-11 15:22:17 +01:00
|
|
|
// EnterVRButton for rendering enter/exit UI.
|
|
|
|
|
var vrButton;
|
|
|
|
|
|
2017-03-22 17:35:01 +01:00
|
|
|
var moved = false;
|
|
|
|
|
var pressing = false;
|
|
|
|
|
var positions = [{
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
z: -6
|
|
|
|
|
}, // closeup
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
x: 0,
|
|
|
|
|
y: heightOfUser,
|
|
|
|
|
z: 0
|
|
|
|
|
}, // intro
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
x: 25,
|
|
|
|
|
y: 25,
|
|
|
|
|
z: 25
|
|
|
|
|
}, // vr first
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 25,
|
|
|
|
|
z: 25
|
|
|
|
|
}, // vr second
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
x: 25,
|
|
|
|
|
y: 0,
|
|
|
|
|
z: 25
|
|
|
|
|
}, // Web VR
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
x: 50,
|
|
|
|
|
y: 50,
|
|
|
|
|
z: 50
|
|
|
|
|
}, // CODE
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
x: 50,
|
|
|
|
|
y: 50,
|
|
|
|
|
z: 0
|
|
|
|
|
}, // QA
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 50,
|
|
|
|
|
z: 0
|
|
|
|
|
}, // Thank You
|
|
|
|
|
|
|
|
|
|
]
|
|
|
|
|
var currentPositionIndex = 0;
|
|
|
|
|
|
|
|
|
|
function currentPosition() {
|
|
|
|
|
if (currentPositionIndex >= 0 && currentPositionIndex < positions.length) {
|
|
|
|
|
return positions[currentPositionIndex];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function goToNextPosition() {
|
|
|
|
|
if (currentPositionIndex >= 0 && currentPositionIndex < positions.length - 1) {
|
|
|
|
|
currentPositionIndex = currentPositionIndex + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function goToPreviousPosition() {
|
|
|
|
|
|
|
|
|
|
if (currentPositionIndex > 0 && currentPositionIndex <= positions.length - 1) {
|
|
|
|
|
currentPositionIndex = currentPositionIndex - 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-03-11 15:22:17 +01:00
|
|
|
|
|
|
|
|
function loadFont(afterFont) {
|
|
|
|
|
|
|
|
|
|
var loader = new THREE.FontLoader();
|
|
|
|
|
loader.load('fonts/helvetiker_regular.typeface.json', function(response) {
|
|
|
|
|
|
|
|
|
|
font = response;
|
|
|
|
|
if (afterFont) {
|
|
|
|
|
afterFont();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function degreesToRadians(degrees) {
|
2017-03-11 19:26:53 +01:00
|
|
|
return degrees * (Math.PI / 180.0);
|
2017-03-11 15:22:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onLoad() {
|
|
|
|
|
// Setup three.js WebGL renderer. Note: Antialiasing is a big performance hit.
|
|
|
|
|
// Only enable it if you actually need to.
|
|
|
|
|
var renderer = new THREE.WebGLRenderer({
|
|
|
|
|
antialias: true
|
|
|
|
|
});
|
|
|
|
|
renderer.setPixelRatio(window.devicePixelRatio);
|
|
|
|
|
|
|
|
|
|
// Append the canvas element created by the renderer to document body element.
|
|
|
|
|
document.body.appendChild(renderer.domElement);
|
|
|
|
|
|
2017-03-22 17:35:01 +01:00
|
|
|
document.body.addEventListener('keydown', function(e) {
|
|
|
|
|
e = e || window.event;
|
|
|
|
|
var charCode = e.charCode || e.keyCode,
|
|
|
|
|
character = String.fromCharCode(charCode);
|
|
|
|
|
switch (character) {
|
|
|
|
|
case 'p':
|
|
|
|
|
case 'P':
|
|
|
|
|
moveToNextPlace();
|
|
|
|
|
break;
|
|
|
|
|
case 'q':
|
|
|
|
|
case 'Q':
|
|
|
|
|
moveToPreviousPlace();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
console.log('pressed ', character);
|
|
|
|
|
});
|
|
|
|
|
|
2017-03-11 15:22:17 +01:00
|
|
|
// Create a three.js scene.
|
|
|
|
|
scene = new THREE.Scene();
|
|
|
|
|
|
|
|
|
|
// Create a three.js camera.
|
|
|
|
|
var aspect = window.innerWidth / window.innerHeight;
|
|
|
|
|
camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 10000);
|
|
|
|
|
|
2017-03-18 06:43:20 +01:00
|
|
|
var dummyControls = {
|
|
|
|
|
update: function() {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
controls = (!isClient()) ? new THREE.VRControls(camera) : dummyControls;
|
2017-03-11 15:22:17 +01:00
|
|
|
controls.standing = true;
|
2017-03-22 17:35:01 +01:00
|
|
|
var current = currentPosition();
|
|
|
|
|
|
2017-03-11 19:26:53 +01:00
|
|
|
var oldUpdate = controls.update;
|
|
|
|
|
controls.update = function() {
|
|
|
|
|
oldUpdate();
|
2017-03-22 17:35:01 +01:00
|
|
|
publishCameraLocationMessage();
|
2017-03-11 19:26:53 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// The dolly has to be a PerspectiveCamera, as opposed
|
|
|
|
|
// to a simple Object3D, since that's what
|
|
|
|
|
// OrbitControls expects.
|
2017-03-18 06:43:20 +01:00
|
|
|
dollyCam = new THREE.PerspectiveCamera(75, aspect, 0.1, 10000);
|
2017-03-11 19:26:53 +01:00
|
|
|
/*var orbitControls = new THREE.OrbitControls(dollyCam); */
|
2017-03-18 06:43:20 +01:00
|
|
|
|
2017-03-11 19:26:53 +01:00
|
|
|
dollyCam.add(camera);
|
2017-03-18 06:43:20 +01:00
|
|
|
//orbitControls = new OrbitControls(dollyCam);
|
2017-03-22 17:35:01 +01:00
|
|
|
dollyCam.position.set(current.x, current.y, current.z);
|
2017-03-11 19:26:53 +01:00
|
|
|
scene.add(dollyCam);
|
|
|
|
|
|
2017-03-11 15:22:17 +01:00
|
|
|
|
|
|
|
|
// Apply VR stereo rendering to renderer.
|
|
|
|
|
effect = new THREE.VREffect(renderer);
|
|
|
|
|
effect.setSize(window.innerWidth, window.innerHeight);
|
|
|
|
|
|
|
|
|
|
var loader = new THREE.TextureLoader();
|
|
|
|
|
loader.load('img/livada.jpg', onTextureLoaded);
|
|
|
|
|
|
2017-03-18 15:59:26 +01:00
|
|
|
// // Create 3D objects.
|
|
|
|
|
// var geometry = new THREE.SphereGeometry(0.5, 0.5, 0.5);
|
|
|
|
|
// var material = new THREE.MeshNormalMaterial();
|
|
|
|
|
// cube = new THREE.Mesh(geometry, material);
|
|
|
|
|
//
|
|
|
|
|
// // Position cube mesh to be right in front of you.
|
|
|
|
|
// cube.position.set(0, heightOfUser, -1);
|
2017-03-11 15:22:17 +01:00
|
|
|
|
|
|
|
|
// Add cube mesh to your three.js scene
|
|
|
|
|
//scene.add(cube);
|
|
|
|
|
|
|
|
|
|
window.addEventListener('resize', onResize, true);
|
|
|
|
|
window.addEventListener('vrdisplaypresentchange', onResize, true);
|
|
|
|
|
|
|
|
|
|
// Initialize the WebVR UI.
|
|
|
|
|
var uiOptions = {
|
|
|
|
|
color: 'black',
|
|
|
|
|
background: 'white',
|
|
|
|
|
corners: 'square'
|
|
|
|
|
};
|
2017-03-22 17:35:01 +01:00
|
|
|
|
2017-03-11 15:22:17 +01:00
|
|
|
vrButton = new webvrui.EnterVRButton(renderer.domElement, uiOptions);
|
|
|
|
|
vrButton.on('exit', function() {
|
|
|
|
|
camera.quaternion.set(0, 0, 0, 1);
|
2017-03-22 17:35:01 +01:00
|
|
|
camera.position.set(current.x, current.y, current.z);
|
2017-03-11 15:22:17 +01:00
|
|
|
});
|
|
|
|
|
vrButton.on('hide', function() {
|
|
|
|
|
document.getElementById('ui').style.display = 'none';
|
|
|
|
|
});
|
|
|
|
|
vrButton.on('show', function() {
|
|
|
|
|
document.getElementById('ui').style.display = 'inherit';
|
|
|
|
|
});
|
|
|
|
|
document.getElementById('vr-button').appendChild(vrButton.domElement);
|
|
|
|
|
document.getElementById('magic-window').addEventListener('click', function() {
|
|
|
|
|
vrButton.requestEnterFullscreen();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var light = new THREE.PointLight(0xffffff, 1, 300);
|
|
|
|
|
light.position.set(0, 4.9, 0);
|
|
|
|
|
scene.add(light);
|
|
|
|
|
|
|
|
|
|
loadFont(function() {
|
2017-03-22 17:35:01 +01:00
|
|
|
|
|
|
|
|
displayText("Intro", {
|
2017-03-11 15:22:17 +01:00
|
|
|
color: 0xffaa00,
|
2017-03-18 15:59:26 +01:00
|
|
|
size: 2,
|
2017-03-11 15:22:17 +01:00
|
|
|
height: 0.01,
|
|
|
|
|
specular: 0xaaaaaa
|
|
|
|
|
}, {
|
2017-03-22 17:35:01 +01:00
|
|
|
x: -2,
|
2017-03-18 15:59:26 +01:00
|
|
|
y: heightOfUser + 5,
|
|
|
|
|
z: -9
|
2017-03-11 15:22:17 +01:00
|
|
|
});
|
|
|
|
|
|
2017-03-22 17:35:01 +01:00
|
|
|
var pos2 = positions[2];
|
|
|
|
|
displayText("About VR", {
|
|
|
|
|
color: 0x00ff00,
|
|
|
|
|
size: 2,
|
|
|
|
|
height: 0.01,
|
|
|
|
|
specular: 0xaaaaaa
|
|
|
|
|
}, {
|
|
|
|
|
x: pos2.x - 5,
|
|
|
|
|
y: pos2.y + 5,
|
|
|
|
|
z: pos2.z - 9
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var pos3 = positions[3];
|
|
|
|
|
displayText("Cardboard", {
|
|
|
|
|
color: 0x00ff00,
|
|
|
|
|
size: 2,
|
|
|
|
|
height: 0.01,
|
|
|
|
|
specular: 0xaaaaaa
|
|
|
|
|
}, {
|
|
|
|
|
x: pos3.x - 5,
|
|
|
|
|
y: pos3.y + 5,
|
|
|
|
|
z: pos3.z - 9
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var pos4 = positions[4];
|
|
|
|
|
displayText("Web VR & Three.js", {
|
|
|
|
|
color: 0x00ff00,
|
|
|
|
|
size: 2,
|
|
|
|
|
height: 0.01,
|
|
|
|
|
specular: 0xaaaaaa
|
|
|
|
|
}, {
|
|
|
|
|
x: pos4.x - 10,
|
|
|
|
|
y: pos4.y + 5,
|
|
|
|
|
z: pos4.z - 9
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var pos5 = positions[5];
|
|
|
|
|
displayText("Code", {
|
|
|
|
|
color: 0x00ff00,
|
|
|
|
|
size: 2,
|
|
|
|
|
height: 0.01,
|
|
|
|
|
specular: 0xaaaaaa
|
|
|
|
|
}, {
|
|
|
|
|
x: pos5.x - 2,
|
|
|
|
|
y: pos5.y + 5,
|
|
|
|
|
z: pos5.z - 9
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var pos6 = positions[6];
|
|
|
|
|
displayText("Q and A", {
|
|
|
|
|
color: 0x00ff00,
|
|
|
|
|
size: 2,
|
|
|
|
|
height: 0.04,
|
|
|
|
|
specular: 0xaaaaaa
|
|
|
|
|
}, {
|
|
|
|
|
x: pos6.x - 4,
|
|
|
|
|
y: pos6.y,
|
|
|
|
|
z: pos6.z - 5
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var pos7 = positions[7];
|
|
|
|
|
displayText("verygoodpoint.net", {
|
|
|
|
|
color: 0x00ff00,
|
|
|
|
|
size: 2,
|
|
|
|
|
height: 0.04,
|
|
|
|
|
specular: 0xaaaaaa
|
|
|
|
|
}, {
|
|
|
|
|
x: pos7.x - 10,
|
|
|
|
|
y: pos7.y,
|
|
|
|
|
z: pos7.z - 9
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//displayText("Senad Uka", {
|
|
|
|
|
// color: 0x00ff00,
|
|
|
|
|
// size: 0.3,
|
|
|
|
|
// height: 0.01,
|
|
|
|
|
// specular: 0xaaaaaa
|
|
|
|
|
// }, {
|
|
|
|
|
// x: 2,
|
|
|
|
|
// y: heightOfUser + 2,
|
|
|
|
|
// z: -2
|
|
|
|
|
// }, {
|
|
|
|
|
// x: 0.1,
|
|
|
|
|
// y: degreesToRadians(-35),
|
|
|
|
|
// z: 0
|
|
|
|
|
// });
|
2017-03-11 15:22:17 +01:00
|
|
|
|
2017-03-18 15:59:26 +01:00
|
|
|
// displayText("JS Meetup Sarajevo", {
|
|
|
|
|
// color: 0xaaff12,
|
|
|
|
|
// size: 0.3,
|
|
|
|
|
// height: 0.02,
|
|
|
|
|
// specular: 0x11aaaa
|
|
|
|
|
// }, {
|
|
|
|
|
// x: 2,
|
|
|
|
|
// y: heightOfUser - 1,
|
|
|
|
|
// z: -2
|
|
|
|
|
// }, {
|
|
|
|
|
// x: degreesToRadians(-40),
|
|
|
|
|
// y: degreesToRadians(0),
|
|
|
|
|
// z: 0
|
|
|
|
|
// });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
2017-03-22 17:35:01 +01:00
|
|
|
// 1 pravo
|
|
|
|
|
displayPicture('./img/slide1.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: 0,
|
|
|
|
|
x: 0,
|
|
|
|
|
z: -9
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
z: 0
|
2017-03-18 15:59:26 +01:00
|
|
|
|
2017-03-22 17:35:01 +01:00
|
|
|
});
|
2017-03-18 15:59:26 +01:00
|
|
|
|
2017-03-22 17:35:01 +01:00
|
|
|
// // 1 dole
|
|
|
|
|
// displayPicture('./img/slide2.jpeg', {
|
|
|
|
|
// width: 5,
|
|
|
|
|
// height: 2.5,
|
|
|
|
|
// depth: 0.1,
|
|
|
|
|
// }, {
|
|
|
|
|
// y: 0.01,
|
|
|
|
|
// x: 0,
|
|
|
|
|
// z: 0
|
|
|
|
|
// }, {
|
|
|
|
|
// x: degreesToRadians(-90),
|
|
|
|
|
// y: 0,
|
|
|
|
|
// z: 0
|
|
|
|
|
//
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// 1 desno
|
|
|
|
|
displayPicture('./img/slide3.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: 0,
|
|
|
|
|
x: 10,
|
|
|
|
|
z: -5
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 5,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 1 lijevo
|
|
|
|
|
displayPicture('./img/slide2.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: 0,
|
|
|
|
|
x: -10,
|
|
|
|
|
z: -5
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: -5,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var pos2 = positions[2];
|
|
|
|
|
|
|
|
|
|
displayPicture('./img/slide4.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
2017-03-22 17:40:08 +01:00
|
|
|
y: pos2.y,
|
2017-03-22 17:35:01 +01:00
|
|
|
x: pos2.x,
|
|
|
|
|
z: pos2.z -9
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 1 lijevo
|
|
|
|
|
displayPicture('./img/slide5.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos2.y ,
|
|
|
|
|
x: pos2.x -10,
|
|
|
|
|
z: pos2.z -5
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: -5,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1 desno
|
|
|
|
|
displayPicture('./img/slide6.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos2.y ,
|
|
|
|
|
x: pos2.x + 10,
|
|
|
|
|
z: pos2.z -5
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 5,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var pos3 = positions[3];
|
|
|
|
|
|
|
|
|
|
displayPicture('./img/slide8.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos3.y ,
|
|
|
|
|
x: pos3.x,
|
|
|
|
|
z: pos3.z -9
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 1 lijevo
|
|
|
|
|
displayPicture('./img/slide9.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos3.y ,
|
|
|
|
|
x: pos3.x -10,
|
|
|
|
|
z: pos3.z -5
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: -5,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1 desno
|
|
|
|
|
displayPicture('./img/slide7.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos3.y ,
|
|
|
|
|
x: pos3.x + 10,
|
|
|
|
|
z: pos3.z -5
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 5,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var pos4 = positions[4];
|
|
|
|
|
|
|
|
|
|
displayPicture('./img/slide10.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos4.y ,
|
|
|
|
|
x: pos4.x,
|
|
|
|
|
z: pos4.z -9
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 1 lijevo
|
|
|
|
|
displayPicture('./img/slide11.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos4.y ,
|
|
|
|
|
x: pos4.x -10,
|
|
|
|
|
z: pos4.z -5
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: -5,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1 desno
|
|
|
|
|
displayPicture('./img/slide12.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos4.y ,
|
|
|
|
|
x: pos4.x + 10,
|
|
|
|
|
z: pos4.z -5
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 5,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var pos5 = positions[5];
|
|
|
|
|
|
|
|
|
|
displayPicture('./img/slide13.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos5.y ,
|
|
|
|
|
x: pos5.x,
|
|
|
|
|
z: pos5.z -9
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 1 lijevo
|
|
|
|
|
displayPicture('./img/slide14.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos5.y ,
|
|
|
|
|
x: pos5.x -10,
|
|
|
|
|
z: pos5.z -5
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: -5,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1 desno
|
|
|
|
|
displayPicture('./img/slide15.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos5.y ,
|
|
|
|
|
x: pos5.x + 10,
|
|
|
|
|
z: pos5.z -5
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 5,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// nazad desno
|
|
|
|
|
|
|
|
|
|
// 1 lijevo
|
|
|
|
|
displayPicture('./img/slide16.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos5.y ,
|
|
|
|
|
x: pos5.x -10,
|
|
|
|
|
z: pos5.z + 5
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 5,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// nazad lijevo
|
|
|
|
|
// 1 desno
|
|
|
|
|
displayPicture('./img/slide17.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos5.y ,
|
|
|
|
|
x: pos5.x + 10,
|
|
|
|
|
z: pos5.z + 5
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: -5,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// nazad pravo
|
|
|
|
|
// 1 desno
|
|
|
|
|
displayPicture('./img/slide18.jpeg', {
|
|
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
|
|
|
|
depth: 0.1,
|
|
|
|
|
}, {
|
|
|
|
|
y: pos5.y ,
|
|
|
|
|
x: pos5.x,
|
|
|
|
|
z: pos5.z + 9
|
|
|
|
|
}, {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: degreesToRadians(180),
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
});
|
2017-03-18 15:59:26 +01:00
|
|
|
|
2017-03-11 15:22:17 +01:00
|
|
|
|
2017-03-18 15:59:26 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-03-11 15:22:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onTextureLoaded(texture) {
|
|
|
|
|
texture.wrapS = THREE.RepeatWrapping;
|
|
|
|
|
texture.wrapT = THREE.RepeatWrapping;
|
|
|
|
|
//texture.repeat.set(boxSize, boxSize);
|
|
|
|
|
|
|
|
|
|
var geometry = new THREE.SphereGeometry(boxSize, boxSize, boxSize);
|
|
|
|
|
var material = new THREE.MeshBasicMaterial({
|
|
|
|
|
map: texture,
|
|
|
|
|
/* color: 0x01BE00,
|
|
|
|
|
side: THREE.BackSide */
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Align the skybox to the floor (which is at y=0).
|
|
|
|
|
skybox = new THREE.Mesh(geometry, material);
|
|
|
|
|
skybox.position.y = boxSize / 3;
|
|
|
|
|
skybox.scale.x = -1;
|
|
|
|
|
scene.add(skybox);
|
|
|
|
|
|
|
|
|
|
// For high end VR devices like Vive and Oculus, take into account the stage
|
|
|
|
|
// parameters provided.
|
|
|
|
|
setupStage();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Request animation frame loop function
|
|
|
|
|
function animate(timestamp) {
|
|
|
|
|
var delta = Math.min(timestamp - lastRenderTime, 500);
|
|
|
|
|
lastRenderTime = timestamp;
|
|
|
|
|
|
|
|
|
|
// Apply rotation to cube mesh
|
2017-03-18 15:59:26 +01:00
|
|
|
//cube.rotation.y += delta * 0.0006;
|
2017-03-11 15:22:17 +01:00
|
|
|
|
|
|
|
|
// Only update controls if we're presenting.
|
|
|
|
|
if (vrButton.isPresenting()) {
|
|
|
|
|
controls.update();
|
|
|
|
|
}
|
|
|
|
|
// Render the scene.
|
|
|
|
|
effect.render(scene, camera);
|
|
|
|
|
|
|
|
|
|
vrDisplay.requestAnimationFrame(animate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onResize(e) {
|
|
|
|
|
effect.setSize(window.innerWidth, window.innerHeight);
|
|
|
|
|
camera.aspect = window.innerWidth / window.innerHeight;
|
|
|
|
|
camera.updateProjectionMatrix();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the HMD, and if we're dealing with something that specifies
|
|
|
|
|
// stageParameters, rearrange the scene.
|
|
|
|
|
function setupStage() {
|
|
|
|
|
navigator.getVRDisplays().then(function(displays) {
|
|
|
|
|
if (displays.length > 0) {
|
|
|
|
|
vrDisplay = displays[0];
|
|
|
|
|
if (vrDisplay.stageParameters) {
|
|
|
|
|
setStageDimensions(vrDisplay.stageParameters);
|
|
|
|
|
}
|
|
|
|
|
vrDisplay.requestAnimationFrame(animate);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setStageDimensions(stage) {
|
|
|
|
|
// Make the skybox fit the stage.
|
|
|
|
|
var material = skybox.material;
|
|
|
|
|
scene.remove(skybox);
|
|
|
|
|
|
|
|
|
|
// Size the skybox according to the size of the actual stage.
|
|
|
|
|
var geometry = new THREE.BoxGeometry(stage.sizeX, boxSize, stage.sizeZ);
|
|
|
|
|
skybox = new THREE.Mesh(geometry, material);
|
|
|
|
|
|
|
|
|
|
// Place it on the floor.
|
|
|
|
|
skybox.position.y = boxSize / 2;
|
|
|
|
|
//scene.add(skybox);
|
|
|
|
|
|
|
|
|
|
// Place the cube in the middle of the scene, at user height.
|
2017-03-18 06:43:20 +01:00
|
|
|
cube.position.set(0, heightOfUser, 0);
|
2017-03-11 15:22:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var currentCityTextMesh;
|
|
|
|
|
|
|
|
|
|
function displayText(text,
|
|
|
|
|
format = {
|
|
|
|
|
color: 0xffaa00,
|
|
|
|
|
specular: 0xaaaaaa,
|
|
|
|
|
size: 0.5,
|
|
|
|
|
height: 0.01,
|
|
|
|
|
},
|
|
|
|
|
position = {
|
2017-03-18 06:43:20 +01:00
|
|
|
y: heightOfUser,
|
2017-03-11 15:22:17 +01:00
|
|
|
x: 0,
|
|
|
|
|
z: -1
|
|
|
|
|
}, rotation = {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
}) {
|
|
|
|
|
currentCityText = new THREE.TextGeometry(text, {
|
|
|
|
|
size: format.size,
|
|
|
|
|
height: format.height,
|
|
|
|
|
font: font,
|
|
|
|
|
curveSegments: 12,
|
|
|
|
|
bevelThickness: 0.01,
|
|
|
|
|
bevelSize: 0.01,
|
|
|
|
|
bevelEnabled: false
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
currentCityTextMesh = new THREE.Mesh(currentCityText, new THREE.MeshPhongMaterial({
|
|
|
|
|
color: format.color,
|
|
|
|
|
specular: format.specular
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
currentCityTextMesh.position.y = position.y;
|
|
|
|
|
currentCityTextMesh.position.z = position.z;
|
|
|
|
|
currentCityTextMesh.position.x = position.x;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
currentCityTextMesh.rotateX(rotation.x);
|
|
|
|
|
currentCityTextMesh.rotateY(rotation.y);
|
|
|
|
|
currentCityTextMesh.rotateZ(rotation.z);
|
|
|
|
|
|
|
|
|
|
scene.add(currentCityTextMesh);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-11 19:26:53 +01:00
|
|
|
function displayPicture(picture,
|
|
|
|
|
format = {
|
2017-03-18 15:59:26 +01:00
|
|
|
width: 10,
|
|
|
|
|
height: 5,
|
2017-03-11 19:26:53 +01:00
|
|
|
depth: 0.1,
|
|
|
|
|
},
|
|
|
|
|
position = {
|
2017-03-18 06:43:20 +01:00
|
|
|
y: heightOfUser,
|
2017-03-11 19:26:53 +01:00
|
|
|
x: 0,
|
|
|
|
|
z: -9
|
|
|
|
|
}, rotation = {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
z: 0
|
|
|
|
|
|
|
|
|
|
}) {
|
|
|
|
|
|
|
|
|
|
var loader = new THREE.TextureLoader();
|
|
|
|
|
loader.load(picture, function(texture) {
|
|
|
|
|
|
|
|
|
|
var geometry = new THREE.BoxGeometry(format.width, format.height, format.depth);
|
|
|
|
|
var material = new THREE.MeshBasicMaterial({
|
|
|
|
|
map: texture,
|
|
|
|
|
});
|
|
|
|
|
var display = new THREE.Mesh(geometry, material);
|
|
|
|
|
|
|
|
|
|
display.position.y = position.y;
|
|
|
|
|
display.position.z = position.z;
|
|
|
|
|
display.position.x = position.x;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
display.rotateX(rotation.x);
|
|
|
|
|
display.rotateY(rotation.y);
|
|
|
|
|
display.rotateZ(rotation.z);
|
|
|
|
|
|
|
|
|
|
scene.add(display);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-22 17:35:01 +01:00
|
|
|
function moveToNextPlace() {
|
|
|
|
|
if (!pressing) {
|
|
|
|
|
goToNextPosition();
|
|
|
|
|
// U - naprijed
|
|
|
|
|
var current = currentPosition();
|
|
|
|
|
dollyCam.position.x = current.x;
|
|
|
|
|
dollyCam.position.y = current.y;
|
|
|
|
|
dollyCam.position.z = current.z;
|
|
|
|
|
controls.update();
|
|
|
|
|
moved = false;
|
|
|
|
|
pressing = true;
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
pressing = false;
|
|
|
|
|
}, 500);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function moveToPreviousPlace() {
|
|
|
|
|
|
|
|
|
|
if (!pressing) {
|
|
|
|
|
// O - nazad
|
|
|
|
|
if (!moved) {
|
|
|
|
|
goToPreviousPosition();
|
|
|
|
|
}
|
|
|
|
|
var current = currentPosition();
|
|
|
|
|
dollyCam.position.x = current.x;
|
|
|
|
|
dollyCam.position.y = current.y;
|
|
|
|
|
dollyCam.position.z = current.z;
|
|
|
|
|
controls.update();
|
|
|
|
|
moved = false;
|
|
|
|
|
pressing = true;
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
pressing = false;
|
|
|
|
|
}, 500);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-18 06:43:20 +01:00
|
|
|
|
|
|
|
|
function buttonPressed(buttonNumber) {
|
|
|
|
|
var keyPanSpeed = 1;
|
|
|
|
|
var direction = camera.getWorldDirection();
|
|
|
|
|
var vectorUp = new THREE.Vector3(0, 1, 0);
|
|
|
|
|
var strafeVector = new THREE.Vector3().crossVectors(vectorUp, direction).normalize();
|
|
|
|
|
|
|
|
|
|
switch (buttonNumber) {
|
|
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
|
|
|
|
|
|
dollyCam.position.add(direction.multiplyScalar(keyPanSpeed));
|
|
|
|
|
controls.update();
|
2017-03-22 17:35:01 +01:00
|
|
|
moved = true;
|
2017-03-18 06:43:20 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 7:
|
|
|
|
|
dollyCam.position.add(direction.multiplyScalar(-keyPanSpeed));
|
|
|
|
|
controls.update();
|
2017-03-22 17:35:01 +01:00
|
|
|
moved = true;
|
2017-03-18 06:43:20 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
|
dollyCam.position.add(strafeVector.multiplyScalar(keyPanSpeed))
|
|
|
|
|
controls.update();
|
2017-03-22 17:35:01 +01:00
|
|
|
moved = true;
|
2017-03-18 06:43:20 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 9:
|
|
|
|
|
dollyCam.position.add(strafeVector.multiplyScalar(-keyPanSpeed))
|
|
|
|
|
controls.update();
|
2017-03-22 17:35:01 +01:00
|
|
|
moved = true;
|
2017-03-18 06:43:20 +01:00
|
|
|
break;
|
|
|
|
|
case 0:
|
2017-03-22 17:35:01 +01:00
|
|
|
moveToPreviousPlace();
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
moveToNextPlace();
|
2017-03-18 06:43:20 +01:00
|
|
|
break;
|
|
|
|
|
|
2017-03-22 17:35:01 +01:00
|
|
|
|
2017-03-18 06:43:20 +01:00
|
|
|
}
|
|
|
|
|
//alert(buttonNumber);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-22 17:35:01 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-03-11 15:22:17 +01:00
|
|
|
window.addEventListener('load', onLoad);
|
|
|
|
|
</script>
|
|
|
|
|
|
2017-03-18 06:43:20 +01:00
|
|
|
<script src="./gamepad.js"></script>
|
|
|
|
|
|
2017-03-11 15:22:17 +01:00
|
|
|
</html>
|