/** * @preserve @license Copyright 2014-Forever Secret Robot LLC. All rights reserved. */ /** @define {boolean} */ var DEBUG = false; // jQuery-like helper. /* function $(id) { return document.getElementById( id ); } */ function rgb(r, g, b) { r = Math.floor(r); g = Math.floor(g); b = Math.floor(b); return ["rgb(",r,",",g,",",b,")"].join(""); } function rgba(r, g, b, a) { r = Math.floor(r); g = Math.floor(g); b = Math.floor(b); return ["rgba(",r,",",g,",",b,",",a,")"].join(""); } function UpdateSceneViz() { if (DEBUG) { var cubeFaceMeshIndex = 0; cubeFaceMeshes.map(function(cubeFaceMesh) { var id = 'sceneRect' + cubeFaceMeshIndex.toString() // var colorString = rgb(color.r * 255.0, color.g * 255.0, color.b * 255.0) var element = $(id) var sceneIndex = cubeScenes.indexOf(cubeFaceMesh.scene) element.innerHTML = sceneIndex var color = cubeFaceMesh.children[1].material.color id = 'rect' + cubeFaceMeshIndex.toString() var colorString = rgba(color.r * 255.0, color.g * 255.0, color.b * 255.0, cubeFaceMesh.isVisible ? 1.0 : 0.03) element = $(id) var before = element.style.backgroundColor element.style.backgroundColor = colorString; element.style.border = cubeFaceMesh.isVisible ? "1px solid black" : "1px dashed #dddddd"; element.style.color = cubeFaceMesh.isVisible ? "black" : "#bbbbbb"; cubeFaceMeshIndex += 1 }); } } /* var mouseX = 0, mouseY = 0; var windowHalfX = window.innerWidth / 2; var windowHalfY = window.innerHeight / 2; */ var container; //
created in JS to hold the WebGL canvas. var camera, scene, renderer; var orbitControls; var controlSchemes = [] var controls; var vrmgr, effect; var clock = new THREE.Clock(); // Used to advance animation. var cubeScenes = [] var cubeFaceMeshes = [] var mainCubeFaceMesh var sceneFilenameToCubeSceneMap = {} var windowsObject var moonCubeScene var moonNormalMap var faceMesh // Jumbled up vertices /* var initialized = []; */ var ambientLight; // Workaround: ??? what does this do ??? var pendingObjects = []; var pendingCubeFaces = []; var moonHouseFilename = 'Assets3D/Box - Moon House 010' //var faceFilename = 'Assets3D/Box - Suzanne 002' var caveFilename = 'Assets3D/EXPERIMENT - cave 005 - DELETE_ME_MANGLED_FOR_EXPORT 013' var filenames = [ 'Assets3D/Box - QR universe 006', 'Assets3D/Box - Test sphere 009', moonHouseFilename, 'Assets3D/Box - Moon 001', 'Assets3D/Box - Cornell Cube 008', caveFilename, // faceFilename, // 'Assets3D/Box - Rooms 001', // 'Assets3D/Box - screens 001', ] var sceneFilenames = filenames.map(function(filename) { return filename + '.obj'; }) var sceneMtlFilenames = filenames.map(function(filename) { return filename + '.mtl'; }) VR_INSTRUCTION_DEFAULT = 0 VR_INSTRUCTION_WAITING_FOR_LANDSCAPE = 1 VR_INSTRUCTION_COUNTING_DOWN = 2 VR_INSTRUCTION_IN_VR = 3 var vrInstructionState = VR_INSTRUCTION_DEFAULT function log() { /* var _console = document.getElementById('_console') // console.log.apply(console, arguments); // _console.innerHTML += arguments.join(",") + '\n' //'\nwindow.orientation: ' + window.orientation _console.innerHTML += arguments[0] + '\n' //'\nwindow.orientation: ' + window.orientation // if(console){ // console.log.apply(console, arguments); // } */ } $(function() { var result = init(); if (result !== false) { animate(); // Jumpstart the first of an "infinite" series of calls to animate(). } }) /* function WORKAROUND_FixEmptyHierarchyEntries(animation) { animation.hierarchy.splice(1,1) } */ function ToggleWebVRInLandscape() { // var _console = document.getElementById('_console') // _console.innerHTML += '\nwindow.orientation: ' + window.orientation if (window.orientation == -90 || window.orientation == 90) { // Landscape orientation, hide divs - logo, blurb, etc. $('.HideInVR').hide() vrmgr.setVisibility(true) // _console.innerHTML += '\nDivs: HIDDEN' if (vrInstructionState == VR_INSTRUCTION_WAITING_FOR_LANDSCAPE) { // Start countdown! $('#vrInstructionText1').hide() $('#vrInstructionButtons').hide() $('#vrInstructionText2').show() $('#vrInstructionCountdown').show() vrInstructionState = VR_INSTRUCTION_COUNTING_DOWN // TODO Update countdown timer every second or so. // Start timer to hide instructions & enter VR mode after 5 seconds var startTime = new Date().getTime(); var startSeconds = new Date().getSeconds(); $('#countdownSpan').html('5') var interval = setInterval(function() { if(new Date().getTime() - startTime > 5000) { clearInterval(interval); return false; } var countDownValue = 5 - (new Date().getSeconds() - startSeconds) $('#countdownSpan').html(countDownValue + '') log(countDownValue) //do whatever here.. }, 500); setTimeout(function() { $('#vrInstructions1').hide() }, 4500) setTimeout(function() { $('#vrInstructionText1').show() $('#vrInstructionButtons').show() $('#vrInstructionText2').hide() $('#vrInstructionCountdown').hide() vrmgr.enterVR() }, 5000) } } else { // Exit VR when go back to portrait. if (vrmgr.isVRMode()) vrmgr.exitVR() // Portrait orientation, show divs - logo, blurb, etc. $('.HideInVR').show() vrmgr.setVisibility(false) // _console.innerHTML += '\nDivs: SHOWN' } } function IsWebGLSupported() { var canvas; var ctx; var exts; try { canvas = document.createElement('canvas'); ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); exts = ctx.getSupportedExtensions(); } catch (e) { return false; } if (ctx !== undefined) { return true // Modernizr.webglextensions = new Boolean(true); } for (var i = -1, len = exts.length; ++i < len; ) { // Modernizr.webglextensions[exts[i]] = true; } canvas = undefined; return false } function init() { container = document.createElement( 'div' ); document.body.appendChild( container ); if (!IsWebGLSupported()) { console.log('Error initializing WebGL') var error = $('#error').get(0) error.removeAttribute( 'data-status' ) error.setAttribute( 'data-status', 'shown' ); var progress = $('#progress').get(0) progress.removeAttribute( 'data-status' ) progress.setAttribute( 'data-status', 'removed' ); return false } try { renderer = new THREE.WebGLRenderer({ antialias: true, stencil: true }); } catch (error) { } camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 100 ); // camera.position.x = 2; camera.position.z = 2.5; // Touch-based orbit controls, non-VR mode. orbitControls = new THREE.OrbitControls(camera) // orbitControls.damping = 0.2 orbitControls.momentumOn = true orbitControls.momentumDampingFactor = 0.9 // How much we reduce momentum in every time step. orbitControls.momentumScalingFactor = 0.005 // // orbitControls.momentumScalingFactor = 0.05 // orbitControls.addEventListener('change', render); // NOTE: Don't need to trigger render when controls change, b/c we're already rendering every frame. // orbitControls.userZoom = false // orbitControls.userPan = false orbitControls.noPan = true orbitControls.noZoom = true orbitControls.autoRotate = true // Applies VR headset positional data to camera. var vrControls = new THREE.VRControls(camera) // We switch between 2 controls schemes: touch orbit & VR IMU controls. Touch orbit controls are the default. controlSchemes = [orbitControls, vrControls] controls = orbitControls // var controls = new THREE.VRControls(camera); // Apply VR stereo rendering to renderer effect = new THREE.VREffect(renderer); effect.setSize(window.innerWidth, window.innerHeight); var _console = document.getElementById('_console') // Create a VR manager helper to enter and exit VR mode. vrmgr = new WebVRManager(effect); // TODO Wait for WebVR manager to be initialized, log("before setup ready callback") /* // $(window).load(function() $(function() { */ log("\nsetup event handlers") // TODO Enable VR on desktop, for Oculus. // Only enable VR when we're ready !!! if (vrmgr.os == 'iOS' || vrmgr.os == 'Android') { $('#enterVRButton').show() $('#enterVRButton').click(function(e) { e.preventDefault(); if (vrmgr.os == 'iOS' || vrmgr.os == 'Android') { $('#vrInstructions1').show(); // TODO Animate / fade in background vrInstructionState = VR_INSTRUCTION_WAITING_FOR_LANDSCAPE return false } else { vrmgr.enterVR() } }) } $('#noVRPleaseButton').click(function(e) { e.preventDefault(); $('#vrInstructions1').hide(); // TODO Animate / fade in background return false }) /* $('#dontHaveVRHeadsetButton').click(function(e) { e.preventDefault(); $('#vrInstructions1').hide(); // TODO Animate / fade in background $('#whereToBuyVRHeadset').show(); // TODO Animate / fade in background return false }) */ $('#dismissBuyVRHeadset').click(function(e) { e.preventDefault(); $('#whereToBuyVRHeadset').hide(); // TODO Animate / fade in background return false }) ToggleWebVRInLandscape() log("DONE setup event handlers") /* }) */ log("after setup ready callback") ToggleWebVRInLandscape() window.addEventListener("orientationchange", function() { ToggleWebVRInLandscape() }, false); /* vrmgr.isHMDAvailable().then(function(isCompatible) { if (isCompatible) { // When enter landscape, just turn on VR mode by default. if (window.orientation == -90 || window.orientation == 90) { // TODO Don't enter VR by default. vrmgr.enterVR() log("entered VR!") log("" + vrmgr.isVRMode()) // Hide divs - logo, blurb, etc. $('.HideInVR').hide() } } else { // this.setMode(Modes.INCOMPATIBLE); } }.bind(this)); */ // scene scene = new THREE.Scene(); // var ambientLight = new THREE.AmbientLight( 0x101030 ); // var ambientLight = new THREE.AmbientLight( 0xffffff ); ambientLight = new THREE.AmbientLight( 0xffffff ); scene.add( ambientLight ); /* var directionalLight = new THREE.DirectionalLight( 0xffeedd ); directionalLight.position.set( 0, 0, 1 ); scene.add( directionalLight ); */ // texture var manager = THREE.DefaultLoadingManager; /* var manager = new THREE.LoadingManager(); manager.onProgress = function ( item, loaded, total ) { console.log('LoadingManager - LOADED PROGRESS CALLBACK:', item, loaded, total ); var bar = 250; var total = progress.totalModels + progress.totalTextures; var loaded = progress.loadedModels + progress.loadedTextures; if (total) bar = Math.floor(bar * loaded / total); $("bar").style.width = bar + "px"; // TODO Trigger the app to start when all are loaded. }; */ log("InitScenes()") InitScenes(manager); log("DONE InitScenes()") // renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); renderer.setClearColor( 0xffffff, 1); // renderer.setClearColor( 0x000000, 1); // renderer.setClearColor( 0x333333, 1); document.addEventListener( 'mousemove', onDocumentMouseMove, false ); document.addEventListener( 'mousedown', onDocumentMouseDown, false ); document.addEventListener( 'mouseup', onDocumentMouseUp, false ); // window.addEventListener( 'resize', onWindowResize, false ); log("DONE init()") } function Finalize() { console.log('%c Finalize -- DONE LOADING, STARTING 3D', 'background: magenta;') log("BEGIN finalize()") var maxAnisotropy = renderer.getMaxAnisotropy(); if (pendingObjects.length <= 0) { console.log('%cERROR','background: red', 'only', pendingObjects.length, 'pendingObjects') } pendingObjects.map(function(pendingObject) { var object = pendingObject[0]; var index = pendingObject[1]; var filename = pendingObject[2]; object.traverse( function ( child ) { // if (child instanceof THREE.Mesh) if (child instanceof THREE.Mesh && child.material.name.indexOf('__DONT_FIX_MATERIAL__') < 0) { // TODO Need to do this *after* texture has loaded, so setup asset setup in that order !!! var map = child.material.map; // child.material = new THREE.MeshBasicMaterial( { color: 0xffffff } ); child.material = new THREE.MeshBasicMaterial( { color: child.material.color, name: child.material.name } ); child.material.map = map; // TODO ??? if (child.material.map != undefined) { // if (child.material.name.indexOf('__NO_ANISOTROPY__') < 0) // { child.material.map.anisotropy = maxAnisotropy; // console.log('%cmaterial','background:cyan',child.material.name) // } // else // { if (child.material.name.indexOf('__CLAMP_TEXTURE_TO_EDGE__') >= 0) { child.material.map.wrapS = child.material.map.wrapT = THREE.ClampToEdgeWrapping; } } } } ); object.visible = false; // This look super cool ! The interior box scenes get a really weird orientation relative to each other. // object.rotation.y = Math.PI / 2.0 * index * Math.PI / 2.0; // object.rotation.y = Math.PI / 2.0 * index - 3.0 * Math.PI / 2.0; if (filename != 'Assets3D/Box - Moon 001.obj') { cubeScenes[index] = object; // Initialize(index); } sceneFilenameToCubeSceneMap[filename] = object; scene.add( object ); console.log('Loaded .OBJ file and added to scene:',filename,index); }); // Pre-upload all textures. // OPTIMIZATION: Do this *during load* so there's no "pop" when calling texImage2D() at "runtime". // OPTIMIZATION: Fixes the issue where the scene pauses just as a new cube face becomes visible - due to blocking call uploading its textures. scene.traverse(function(object) { // if (child instanceof THREE.Mesh) if (object instanceof THREE.Mesh && object.material != undefined && object.material != null) { var map = object.material.map; if (map != undefined && map != null) { renderer.uploadTexture(map) } } }); if (cubeScenes.length != filenames.length) { console.log('%cERROR','background: red', cubeScenes.length, 'cubeScenes, but ', filenames.length, 'filenames!') } // Post-process scenes. // var moonScene = sceneFilenameToCubeSceneMap['Assets3D/Box - Moon 001.obj'] var moonObject = scene.getObjectByName('__THE_MOON___Icosphere.001') moonObject.traverse(function(child) { if (child.material != undefined && child.material.map != undefined) { // THREE.MeshPhongMaterial( { ambient: 0x000000, color: 0xff66aa, specular: 0x555555, shininess: 20 } ) ); // child.material = new THREE.MeshLambertMaterial( { color: child.material.color, map: child.material.map, normalMap: moonNormalMap } ); child.material = new THREE.MeshLambertMaterial( { color: child.material.color, map: child.material.map } ); } }); // var faceScene = sceneFilenameToCubeSceneMap[faceFilename + '.obj'] // faceScene.add(faceMesh) var faceNames = [ 'Cube.002_Face2', // Cube face that's coincident with the "open face" of the cube. 'Cube_Face1', 'Cube.003_Face3', 'Cube.004_Face4', 'Cube.001_Face5', // Top 'Cube.005_Face6', // Bottom ]; if (pendingCubeFaces.length <= 0) console.log('%cERROR','background: red', 'only', pendingObjects.length, 'pendingObjects'); pendingCubeFaces.map(function(object) { object.traverse( function ( child ) { if (child.name != '' && faceNames.indexOf(child.name) >= 0) { // var index = faceNames.indexOf(child.name); child.material = new THREE.MeshBasicMaterial( { color: 0xffffff } ); // child.material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); // child.material.color = 0xff0000; // child.material.wireframe = true; // TODO Does order matter here? // cubeFaceMeshes[index] = child; cubeFaceMeshes.push(child); } }); scene.add( object ); console.log('Loaded box faces and added to scene:'); }); // Initialize each cube face: // * assign its initial scene (duplicate are OK). var i = 0; cubeFaceMeshes.map(function(cubeFaceMesh) { cubeFaceMesh.isVisible = false cubeFaceMesh.wasVisible = false cubeFaceMesh.scene = cubeScenes[i] i = (i + 1) % cubeScenes.length if (cubeFaceMesh.scene == undefined) console.log('%cERROR','background: red', 'cubeFaceMesh.scene is null!'); }); UpdateSceneViz(); var mainCubeFaceMesh = scene.getObjectByName('Cube.002_Face2', true) // Hide all the special objects that we should hide... var objectsToDelete = [] scene.traverse(function(child) { if (child.name.indexOf('__HIDE_ME__') > -1) { objectsToDelete.push(child) /* console.log('%cHID AN OBJECT','background:magenta',child) child.visible = false; child.traverse(function(subChild) { console.log('%cHID AN OBJECT','background:magenta',subChild) subChild.visible = false; }); */ } }); objectsToDelete.map(function(object) { THREE.SceneUtils.detach(object, object.parent, scene); }); // Hide loading bar. var progress = $('#progress').get(0) progress.removeAttribute( 'data-status' ) progress.setAttribute( 'data-status', 'hidden' ); setTimeout( function() { progress.removeAttribute( 'data-status' ); progress.setAttribute( 'data-status', 'removed' ); // state = $('progress').getAttribute( 'data-status' ); }, 1000 ); // $("progress").style.display = 'none'; log("DONE finalize()") } /* function LoadVerticesAndColors(string) { var currentBuffer, vertices=[], colors=[] var entries = string.split(',') entries.forEach(function(string) { if (string.indexOf('vert-xyz') > -1) { currentBuffer = vertices } else if (string.indexOf('col-rgba') > -1) { currentBuffer = colors } else { currentBuffer.push( parseFloat(string) ) } }) if (vertices.length/3 != colors.length/4) { console.log('%cERROR','vertex and color array lengths are not expected lengths! Should be multiple of 3 and 4, resp.',vertices,colors) } // // this is all pretty ad-hoc but it will work well enough for a demo // if (vertices.length/3 === colors.length/4) // { // polys.setArrays(vertices, colors) // vertBuffer.update( polys.vertArr ) // colBuffer.update( polys.colArr ) // } return [vertices, colors] } function LoadVertexJumbleObject(url) { // TODO Use Three.JS XHR loader, so this is included in loading progress... var loader = new THREE.XHRLoader(); // loader.setCrossOrigin( this.crossOrigin ); loader.load( url, function ( text ) { Setup(text) // onLoad( scope.parse( JSON.parse( text ) ) ); }); // var client = new XMLHttpRequest() // client.open('GET', url); // client.onreadystatechange = function() // { // // TODO Handle error ! // var verticesAndColorsString = client.responseText // Setup(verticesAndColorsString) // } // client.send(); } function SetupMaterial() { var attributes = { // customColor: { type: 'v4v', value: [] } customColor: { type: 'v4', value: null } }; // uniforms = { }; var shaderMaterial = new THREE.ShaderMaterial({ // var shaderMaterial = new THREE.RawShaderMaterial({ // uniforms: uniforms, attributes: attributes, vertexShader: document.getElementById( 'vertexshader' ).textContent, fragmentShader: document.getElementById( 'fragmentshader' ).textContent, // NOTE: AndyHall's projectron uses default GL blending, no depth test, transparency (blending), and double-sided triangles // blending: THREE.AdditiveBlending, depthTest: false, transparent: true, side: THREE.DoubleSide, name: '__DONT_FIX_MATERIAL__' }); return shaderMaterial } function Setup(verticesAndColorsString) { var shaderMaterial = SetupMaterial() var verticesAndColors = LoadVerticesAndColors(verticesAndColorsString) var vertices = verticesAndColors[0] // Unpack multiple return values. var vertexColors = verticesAndColors[1] console.log('%cVERTICES','background:pink',vertices.length) console.log('%cVERTEX COLORS','background:pink',vertexColors.length) console.log('%cTRIS','background:pink',vertices.length / 9) console.log('%cTRIS','background:pink',vertexColors.length / 12) // Populate attribute buffer w/ RGBA vertex colors. // var vertices = mesh.geometry.vertices; // var bufferGeometry = new THREE.BufferGeometry() // var verticesArray = new Float32Array(vertices.length); verticesArray.set(vertices) // bufferGeometry.addAttribute('position', new THREE.BufferAttribute(verticesArray, 3)) // var vertexColorsArray = new Float32Array(vertexColors.length); vertexColorsArray.set(vertexColors) // bufferGeometry.addAttribute('customColor', new THREE.BufferAttribute(vertexColorsArray, 4)) // var bufferGeometry = new THREE.BufferGeometry() // var verticesArray = new Float32Array(vertices.length); verticesArray.set(vertices) // bufferGeometry.addAttribute('position', new THREE.BufferAttribute(verticesArray, 3)) // var vertexColorsArray = new Float32Array(vertexColors.length); vertexColorsArray.set(vertexColors) // var vertexColorsBufferAttribute = new THREE.BufferAttribute(vertexColorsArray, 4) // bufferGeometry.addAttribute('customColor', vertexColorsBufferAttribute) // var mesh = new THREE.Mesh(bufferGeometry, shaderMaterial) // console.log('%cVERTICES','background:pink',verticesArray.length) // console.log('%cVERTEX COLORS','background:pink',vertexColorsArray.length) // var values_color = shaderMaterial.attributes.customColor.value; // for (var vertexColorIndex = 0; vertexColorIndex < vertexColors.length / 4; vertexColorIndex ++) // { // // values_color[vertexColorIndex] = new THREE.Vector4(vertexColors[vertexColorIndex*4+0], vertexColors[vertexColorIndex*4+1], vertexColors[vertexColorIndex*4+2], vertexColors[vertexColorIndex*4+3]); // var vertexColor = new THREE.Vector4(vertexColors[vertexColorIndex*4+0], vertexColors[vertexColorIndex*4+1], vertexColors[vertexColorIndex*4+2], vertexColors[vertexColorIndex*4+3]) // values_color.push(vertexColor) // } // var geometry = new THREE.Geometry(); // for (var triangleIndex = 0; triangleIndex < vertices.length / 9; triangleIndex++) // { // // geometry.vertices.push( // // new THREE.Vector3( vertices[triangleIndex*3+0], vertices[triangleIndex*3+1], vertices[triangleIndex*3+2]), // // new THREE.Vector3( vertices[triangleIndex*3+3], vertices[triangleIndex*3+4], vertices[triangleIndex*3+5]), // // new THREE.Vector3( vertices[triangleIndex*3+6], vertices[triangleIndex*3+7], vertices[triangleIndex*3+8]) // // ); // geometry.vertices.push(new THREE.Vector3( vertices[triangleIndex*3+0], vertices[triangleIndex*3+1], vertices[triangleIndex*3+2])) // geometry.vertices.push(new THREE.Vector3( vertices[triangleIndex*3+3], vertices[triangleIndex*3+4], vertices[triangleIndex*3+5])) // geometry.vertices.push(new THREE.Vector3( vertices[triangleIndex*3+6], vertices[triangleIndex*3+7], vertices[triangleIndex*3+8])) // var face = new THREE.Face3(triangleIndex*3 + 0, triangleIndex*3 + 1, triangleIndex*3 + 2) // // var vertexColorArray = [ ??? ] // // var face = new THREE.Face3(vertexIndex + 0, vertexIndex + 1, vertexIndex + 2, undefined, vertexColorArray) // // var face = new THREE.Face3(vertexIndex + 0, vertexIndex + 1, vertexIndex + 2, undefined, vertexColorArray, materialIndex) // // var face = new THREE.Face3(vertexIndex + 0, vertexIndex + 1, vertexIndex + 2, normal, color, materialIndex) // // var face = new THREE.Face3(vertexIndex + 0, vertexIndex + 1, vertexIndex + 2) // geometry.faces.push(face) // } // geometry.dynamic = true; // // geometry.computeBoundingSphere() // TODO ??? // shaderMaterial.attributes.customColor.needsUpdate = true; // var mesh = new THREE.Mesh(geometry, shaderMaterial) // // mesh.position.set(-1,-1,-1) // // mesh.scale.set(2,2,2) // mesh.rotation.y = Math.PI / 2.0 // // mesh.position.set(-.5,-.5,-.5) // // mesh.scale.set(1,1,-1) // var scale = 2 // mesh.scale.set(2,2,-2) // mesh.position.set(0,-scale/2.0,scale/2.0) // var scale = 4 // mesh.scale.set(scale,scale,-1) // mesh.position.set(1,-scale/2.0,scale/2.0) // scene.add(mesh) faceMesh = mesh // cubeScenes.push(mesh) // TODO ??? // sceneFilenameToCubeSceneMap['Plato'] = mesh // TODO ??? // TODO "Taper-scale" vertices either (a) beforehand, or (b) in vertex shader } */ function InitScenes(manager) { THREE.DefaultLoadingManager.onProgress = function(event, loaded, total) { console.log('%c THREE.DefaultLoadingManager.onProgress', 'background: green;', event) console.log('\t', loaded, total) /* var bar = 250; var total = progress.totalModels + progress.totalTextures; var loaded = progress.loadedModels + progress.loadedTextures; if (total) bar = Math.floor(bar * loaded / total); $("bar").style.width = bar + "px"; */ // When both are true, then everything is loaded and we can proceed: // (a) loaded === total // (b) AND we submitted calls to load every scene /* if (loaded === total) { console.log('FINALIZING...') Finalize(); } else { console.log('*NOT* FINALIZING...', loaded, total) } */ } THREE.DefaultLoadingManager.onLoad = function() { /* $("progress").style.display = 'none'; */ console.log('FINALIZING...') Finalize(); } /* var originalItemStart = THREE.DefaultLoadingManager.itemStart; THREE.DefaultLoadingManager.itemStart = function(url) { originalItemStart(url); } var originalItemEnd = THREE.DefaultLoadingManager.itemEnd; THREE.DefaultLoadingManager.itemEnd = function(url) { originalItemEnd(url); } */ // var texture = new THREE.Texture(); var onProgress = function ( xhr ) { // console.log('%c onProgress', 'background: yellow;', xhr) console.log('%c onProgress', 'background: yellow;', xhr.target.responseURL) if ( xhr.lengthComputable ) { var percentComplete = xhr.loaded / xhr.total * 100; console.log( Math.round(percentComplete, 2) + '% downloaded' ); /* var bar = 250; var total = progress.totalModels + progress.totalTextures; var loaded = progress.loadedModels + progress.loadedTextures; if (total) bar = Math.floor(bar * loaded / total); $("bar").style.width = bar + "px"; */ // var bar = 250; // bar = Math.floor(bar * percentComplete / 100.0); // $("bar").style.width = bar + "px"; } }; var onError = function ( xhr ) { }; /* // textureFilenames = ['Assets/QRTexture001.png', 'Assets/BakeCornellBox001.png', undefined] sceneFilenames = ['Assets/Box - QR Universe 003.obj', 'Assets/Box 002.obj', 'Assets/Box - flat earth - 003.obj', 'Assets/Box - test sphere - 003.obj']; sceneMtlFilenames = ['Assets/Box - QR Universe 003.mtl', 'Assets/Box 002.mtl', 'Assets/Box - flat earth - 003.mtl', 'Assets/Box - test sphere - 003.mtl']; */ /* sceneFilenames.map(function(filename) { initialized.push(false); }); // initialized = [false, false]; */ // Load all the OBJ files. function ProcessAndAddObject(object, index, filename) { // console.log(object) pendingObjects.push([object, index, filename]) } /* // var imageLoader = new THREE.ImageLoader(manager) THREE.ImageUtils.loadTexture ('Assets/moon_normal.png', undefined, function(texture) { moonNormalMap = texture }) */ // var objLoader = new THREE.OBJLoader( manager ); var objLoader = new THREE.OBJMTLLoader(manager); sceneFilenames.map(function(filename) { var index = sceneFilenames.indexOf(filename) var mtlFilename = sceneMtlFilenames[index] // Ugh ugly workaround to make a 'curried' function with extra scope variables. function MakeClosure() { return function (object) { return ProcessAndAddObject(object, index, filename) } } objLoader.load( filename, mtlFilename, MakeClosure(), onProgress, onError ); }) //new TWEEN.Tween( cube.rotation ).to( { y:Math.random()}, 1000 ).easing( TWEEN.Easing.Quadratic.EaseOut).start();) function ProcessAndAddObject2(object) { pendingCubeFaces.push(object) } objLoader.load('Assets3D/Box -- META - box face meshes 005.obj', 'Assets3D/Box -- META - box face meshes 005.mtl', ProcessAndAddObject2, onProgress, onError); // objLoader.load('Assets/BoxFaces001.obj', 'Assets/BoxFaces001.mtl', ProcessAndAddObject2, onProgress, onError); // objLoader.load( 'EXPERIMENT_AUTO_EXPORT_ASSETS/BoxFaces001.obj', 'EXPERIMENT_AUTO_EXPORT_ASSETS/BoxFaces001.mtl', function ( object ) // LoadVertexJumbleObject('Assets/Plato_VerticesAndColors002.txt') } // ____ _ _ _ _ // / ___|__ _| | | |__ __ _ ___| | _____ // | | / _` | | | '_ \ / _` |/ __| |/ / __| // | |__| (_| | | | |_) | (_| | (__| <\__ \ // \____\__,_|_|_|_.__/ \__,_|\___|_|\_\___/ function onWindowResize() { /* windowHalfX = window.innerWidth / 2; windowHalfY = window.innerHeight / 2; */ camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); } var damper = new Damper(2.0, 2000.0); function onDocumentMouseDown( event ) { damper.dampen(); damper.pause(); } function onDocumentMouseUp( event ) { damper.dampen(); damper.resume(); } function onDocumentMouseMove( event ) { } /* function onKeyDown(event) { switch (event.keyCode) { case 37: // Left log('left') break; case 38: // Up log('up') break; case 39: // Right log('right') break case 40: // Down log('down') break } } window.addEventListener('keydown', onKeyDown, false) */ function PositionCameraOrbitVR() { if (!vrmgr.isVRMode()) return; // 1) Find the camera vector var cameraVector = new THREE.Vector3( 0, 0, -1 ); // Camera points down -Z by default. cameraVector.applyQuaternion(camera.quaternion); // 2) Position the camera along that vector, at fixed distance from the origin camera.position.copy(cameraVector); // camera.position.multiplyScalar(-2.5) // TODO Use a constant, this is the same value used below. camera.position.multiplyScalar(-3) // TODO Use a constant, this is the same value used below. } function animate() { ToggleWebVRInLandscape() // log("vrmgr.isVRMode(): " + vrmgr.isVRMode()) // log("vrmgr.mode: " + vrmgr.mode) requestAnimationFrame( animate ); if (vrmgr.isVRMode()) { // TODO } controls = vrmgr.isVRMode() ? controlSchemes[1] : controlSchemes[0]; controls.update(); if (!vrmgr.isVRMode()) { damper.update(); console.log(damper); orbitControls.autoRotateSpeed = damper.getValue(); } PositionCameraOrbitVR() // ??? If we invert the "Z" (3rd) vector of the matrix, then the camera is pointed in the opposition direction ??? // To do this, negate 3rd entry in identity matrix. /* var m = new THREE.Matrix4(); m = m.makeBasis(new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, -1 )) camera.matrixWorld.applyMatrix4(m) */ /* // var worldNormal = normal.applyMatrix3(normalMatrix).normalize(); var cameraVector = new THREE.Vector3( 0, 0, -1 ); // Camera points down -Z by default. cameraVector.applyQuaternion(camera.quaternion); // var ray = new THREE.Raycaster(camera.position, cube.position.clone().sub(camera.position).normalize() ); // NOTE: THIS IS NEEDED FOR VISIBILITY TESTING camera.updateMatrixWorld() */ THREE.AnimationHandler.update( clock.getDelta() ); render(); } // ___ _ _ _ __ ___ _ _ _ _ _ _ _ _ _ // / _ \| |__ (_) ___ ___| |_ \ \ / (_)___(_) |__ (_) (_) |_ _ _ | | | | ___| |_ __ ___ _ __ ___ // | | | | '_ \| |/ _ \/ __| __| \ \ / /| / __| | '_ \| | | | __| | | | | |_| |/ _ \ | '_ \ / _ \ '__/ __| // | |_| | |_) | | __/ (__| |_ \ V / | \__ \ | |_) | | | | |_| |_| | | _ | __/ | |_) | __/ | \__ \ // \___/|_.__// |\___|\___|\__| \_/ |_|___/_|_.__/|_|_|_|\__|\__, | |_| |_|\___|_| .__/ \___|_| |___/ // |__/ |___/ |_| function ShowAll() { scene.traverse(function(child) { child.visible = true; }); if (cubeFaceMeshes.length > 0) { cubeFaceMeshes[0].parent.visible = false; cubeFaceMeshes[0].visible = false; cubeFaceMeshes[1].visible = false; cubeFaceMeshes[2].visible = false; cubeFaceMeshes[3].visible = false; } } function HideAllBut(object) { scene.traverse(function(child) { if ( !(child instanceof THREE.Scene) && !(child instanceof THREE.Light) && !(child instanceof THREE.AmbientLight)) { child.visible = false; } }); object.visible = true; // TODO Walk up hierarchy. var current = object.parent; while (current != undefined && current != current.parent) { current.visible = true; current = current.parent; } /* if (object.parent != undefined) { object.parent.visible = true; } */ object.traverse(function(child) { child.visible = true; // TODO Fix this workaround!!! }); // console.log(object); } function HideAllButCubeFace(index) { if (cubeFaceMeshes.length > 0) { HideAllBut(cubeFaceMeshes[index]) } else { // console.error('Cube face not yet defined', index); } /* scene.traverse(function(child) { if ( !(child instanceof THREE.Scene) && !(child instanceof THREE.Light)) { child.visible = false; } }); if (cubeFaceMeshes.length > 0) { cubeFaceMeshes[0].parent.visible = true; cubeFaceMeshes[0].visible = false; cubeFaceMeshes[1].visible = false; cubeFaceMeshes[2].visible = false; cubeFaceMeshes[3].visible = false; cubeFaceMeshes[index].visible = true; } */ } function HideAllButMesh(index) { if (cubeScenes.length > 0 && cubeScenes[index] != undefined) { var object = cubeScenes[index]; HideAllBut(object); /* object.traverse(function(child) { child.visible = true; // TODO Fix this workaround!!! }); cubeScenes[index].children.map(function(child) { child.visible = true; // TODO Fix this workaround!!! }); */ // console.log('made visible',cubeScenes[index],cubeScenes[index].children.length) // if (cubeScenes[index].children.length > 0) // { // cubeScenes[index].children[0].visible = true; // TODO Fix this workaround!!! // } } else { // console.error('Mesh not yet defined', index); } } /* Idea: 2 stencil bits: 1. cube face 2. windows Cube face looks at just first bit Moon looks at first AND second bit - ANDs them together stencil op: * fail action - (GL_KEEP) * stencil pass & depth test fail action - (GL_KEEP) * stencil fail & depth test fail action - (GL_KEEP) stencil func: * test function - (GL_ALWAYS) * reference value, 0-255 - (0) * mask - (0xffffffff) - mask AND'd with both the reference value and the stored stencil value when the test is done. GL_NOTEQUAL - ( ref & mask ) != ( stencil & mask ) GL_EQUAL - ( ref & mask ) == ( stencil & mask ) */ /* *** use GL_KEEP, since we only modify the stencil buffer by explicitly drawing geometry into it house -- (1 & 1) == (stencil & 1) // only first bit must pass moon -- (3 & 3) == (stencil & 3) // *both* bits must pass // Clear stencil buffer context.StencilOp(context.REPLACE, context.REPLACE, context.REPLACE) context.stencilFunc(context.ALWAYS, 0, 0xffffffff); ... // Draw cube face to 1st bit of stencil context.StencilOp(context.KEEP, context.KEEP, context.KEEP) context.stencilFunc(context.ALWAYS, 1, 0xffffffff); ... // Draw windows to 2nd bit of stencil context.StencilOp(context.KEEP, context.KEEP, context.KEEP) context.stencilFunc(context.ALWAYS, 2, 0xffffffff); ... // Draw house scene w/ stencil test for 1st bit of stencil context.StencilOp(context.KEEP, context.KEEP, context.KEEP) context.stencilFunc(context.EQUAL, 1, 1); ... // Draw moon scene context.StencilOp(context.KEEP, context.KEEP, context.KEEP) context.stencilFunc(context.EQUAL, 3, 3); ... */ // ____ _ // | _ \ ___ _ __ __| | ___ _ __ // | |_) / _ \ '_ \ / _` |/ _ \ '__| // | _ < __/ | | | (_| | __/ | // |_| \_\___|_| |_|\__,_|\___|_| function DoRender(scene, camera, renderTarget, forceClear) { // Render the scene through the VREffect, but only if it's in VR mode. if (vrmgr.isVRMode()) { // effect.render(scene, camera); effect.render(scene, camera, renderTarget, forceClear) } else { renderer.render(scene, camera, renderTarget, forceClear) } } function DrawMoonHouse(firstBitStencilObject, firstBitRenderObject, secondBitStencilObject, secondBitRenderObject) { var context = renderer.context // don't update color or depth context.colorMask(false, false, false, false) context.depthMask(false) // Enable & clear stencil. context.enable(context.STENCIL_TEST) context.clearStencil(0) // Draw cube face into the stencil buffer w/ stencil value = 1. context.stencilMask(1) // Only write to 1st stencil bit. //context.depthMask(true) // Write to the depth buffer, so subsequent pass is depth-tested. context.stencilOp(context.REPLACE, context.REPLACE, context.REPLACE) context.stencilFunc(context.ALWAYS, 1, 1) HideAllBut(firstBitStencilObject) // Hide all but the cube face DoRender(scene, camera, undefined, false) // Draw windows into the stencil buffer w/ stencil value = 2. //context.depthMask(false) // Don't write to depth buffer. // Draw moon house scene to depth buffer, so its depth masks the subsequent render of windows. //renderer.setDepthTest(true) context.stencilMask(0) context.depthMask(true) // Enable write to depth buffer. context.stencilOp(context.KEEP, context.KEEP, context.KEEP) // Don't modify stencil buffer. context.stencilFunc(context.EQUAL, 1, 1) // Only draw in the cube face region HideAllBut(firstBitRenderObject); // Hide all but the moon house scene // Hide the windows - don't draw them! secondBitStencilObject.visible = false; secondBitStencilObject.traverse(function(child) {child.visible = false;}) DoRender(scene, camera, undefined, false) context.depthMask(false) // Disable write to depth buffer. context.stencilMask(2) // Only write to 2nd stencil bit. context.depthMask(true) // Enable write to depth buffer. context.stencilOp(context.KEEP, context.KEEP, context.REPLACE) // Only modify stencil for fragments that pass both stencil & depth tests. context.stencilFunc(context.ALWAYS, 2, 2) HideAllBut(secondBitStencilObject); // Hide all but the windows object. DoRender(scene, camera, undefined, false) renderer.clear(true, true, false) // Clear color, depth, but not stencil //context.stencilMask(0xffffffff) context.stencilMask(0x0) context.colorMask(true, true, true, true) // Enable write to color buffer. context.depthMask(true) // Enable write to depth buffer. // Draw moon scene context.stencilFunc(context.EQUAL, 3, 0xffffffff) // draw if == 3 context.stencilOp(context.KEEP, context.KEEP, context.KEEP) HideAllBut(secondBitRenderObject) DoRender(scene, camera, undefined, false) // NOTE: // NOTE: // NOTE: // NOTE: Uncomment this line to see how "out-of-the-box" render looks. //context.disable(context.STENCIL_TEST) // NOTE: // NOTE: // NOTE: // Draw house scene // re-enable update of color and depth // Only render where stencil is set to EXACTLY 1 context.stencilFunc( context.EQUAL, 1, 0xffffffff) // draw if == 1 // context.stencilFunc( context.EQUAL, 1, 0x1) // draw if == 1 context.stencilOp( context.KEEP, context.KEEP, context.KEEP ) HideAllBut(firstBitRenderObject) // Hide all but the moon house scene // Hide the windows - don't draw them! secondBitStencilObject.visible = false; secondBitStencilObject.traverse(function(child) {child.visible = false;}) DoRender(scene, camera, undefined, false) context.stencilMask(0xffffffff) } function DrawImpossibleCubeFace(index) { var forceClear = false; // ??? var inverse = false; // ??? // Stencil write & clear values. var writeValue = inverse ? 0 : 1; // "Reference value" for glStencilFunc() var clearValue = inverse ? 1 : 0; // clear value for glClearStencil() var context = renderer.context; // HideAllButCubeFace(index); // don't update color or depth context.colorMask(false, false, false, false); context.depthMask(false); // Enable stencil. 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( scene, camera, readBuffer, forceClear ); // renderer.render( scene, camera, writeBuffer, forceClear ); DoRender(scene, camera, undefined, forceClear) // 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 ); } /* function Initialize(index) { if (!initialized[index] && textures[index] != undefined && cubeScenes[index] != undefined) { initialized[index] = true; var object = cubeScenes[index]; object.traverse( function ( child ) { if ( child instanceof THREE.Mesh ) { // TODO Need to do this *after* texture has loaded, so setup asset setup in that order !!! child.material.map = textures[index]; // TODO ??? } } ); console.log('Initialized',index) } } */ function IsFaceVisible(cameraVector, object, face) { /* // Transform face from world space to window space. // Cull if *signed area* is negative. var normal = face.normal var cameraNormal = normal.clone().applyMatrix3(camera.matrixWorldInverse).normalize() */ // Transform face's normal from local (object) space to world space. var normal = face.normal.clone(); var normalMatrix = new THREE.Matrix3().getNormalMatrix(object.matrixWorld); var worldNormal = normal.applyMatrix3(normalMatrix).normalize(); // var normal = face.normal; var dotProduct = worldNormal.dot(cameraVector) return dotProduct < 0; } function IsCubeFaceVisible(cameraVector, cubeFaceMesh) { var faces = cubeFaceMesh.children[1].geometry.faces; var partiallyApplied_IsFaceVisible = IsFaceVisible.bind(null, cameraVector, cubeFaceMesh); return faces.some(partiallyApplied_IsFaceVisible ); } function randomIntFromInterval(min,max) { return Math.floor(Math.random()*(max-min+1)+min); } // Returns the least-recently-used scene that isn't currently associated with a visible cube face. var timeStamp = 0 // The incrementing value that scenes are tagged with each time they're "chosen". function GetHiddenScene() { timeStamp += 1 PositionCameraOrbitVR() var cameraVector = new THREE.Vector3( 0, 0, -1 ); // Camera points down -Z by default. cameraVector.applyQuaternion(camera.quaternion); // var visibleScenes = cubeFaceMeshes.filter(function(cubeFaceMesh) { return IsCubeFaceVisible(cameraVector, cubeFaceMesh); }) var visibleScenes = cubeFaceMeshes.filter(function(cubeFaceMesh) { return cubeFaceMesh.isVisible; }) visibleScenes = _.uniq(visibleScenes) visibleScenes = visibleScenes.map(function(cubeFaceMesh) { return cubeFaceMesh.scene; }) var hiddenScenes = _.difference(cubeScenes, visibleScenes); if (hiddenScenes.length == 0) { console.log('%cERROR!!!','background:red','no unused scenes available!!!',cubeScenes,visibleScenes) return undefined } else { var sortedHiddenScenes = _.sortBy(hiddenScenes, function(hiddenScene) { return hiddenScene.timeStamp == undefined ? 0 : hiddenScene.timeStamp; }) var hiddenSceneIndex = randomIntFromInterval(0, sortedHiddenScenes.length-1) var scene = sortedHiddenScenes[hiddenSceneIndex] // var scene = _.min(hiddenScenes, function(hiddenScene) { return hiddenScene.timeStamp == undefined ? 0 : hiddenScene.timeStamp; }) // NOTE: The following lines implement uniformly-random-picking. // var hiddenSceneIndex = randomIntFromInterval(0, hiddenScenes.length-1) // var scene = hiddenScenes[hiddenSceneIndex] scene.timeStamp = timeStamp // Tag the scene with the return scene } } //var cameraRotation = 0; var moonRotation = 0; function render() { // Initialize(0); // Initialize(1); // camera.position.y = 0; camera.lookAt( scene.position ); // Rotate the scene. // scene.rotation.y += 0.005; // cameraRotation += 0.005; // scene.rotation.y = cameraRotation; var cameraVector = new THREE.Vector3( 0, 0, -1 ); // Camera points down -Z by default. cameraVector.applyQuaternion(camera.quaternion); // var ray = new THREE.Raycaster(camera.position, cube.position.clone().sub(camera.position).normalize() ); // NOTE: THIS IS NEEDED FOR VISIBILITY TESTING camera.updateMatrixWorld() controls = vrmgr.isVRMode() ? controlSchemes[1] : controlSchemes[0]; controls.update(); cubeFaceMeshes.map(function(cubeFaceMesh) { /* var isVisible = IsCubeFaceVisible(cameraVector, cubeFaceMesh) */ // Get camera location in world space var result = camera.matrixWorld.applyToVector3Array(new THREE.Vector3(0,0,0)) // var cameraLocation = camera.matrixWorld.applyToVector3Array(new THREE.Vector3(0,0,0)) var cameraLocation = new THREE.Vector3() cameraLocation.applyMatrix4(camera.matrixWorld) // Get face location in world space var faceLocation = cubeFaceMesh.localToWorld(cubeFaceMesh.children[1].geometry.vertices[cubeFaceMesh.children[1].geometry.faces[0].a]); // var faceLocation = cubeFaceMesh.matrixWorld camera.matrixWorld.applyToVector3Array([THREE.Vector3(0,0,0)])[0] // Form the vector from the face to the camera location, and normalize it. var cameraToFaceVector = new THREE.Vector3() cameraToFaceVector.subVectors( faceLocation, cameraLocation ) cameraToFaceVector = cameraToFaceVector.normalize() // var isVisible = IsCubeFaceVisible(cameraVector, cubeFaceMesh) var isVisible = IsCubeFaceVisible(cameraToFaceVector, cubeFaceMesh) cubeFaceMesh.wasVisible = cubeFaceMesh.isVisible; // Use value from last frame. cubeFaceMesh.isVisible = isVisible; }); cubeFaceMeshes.map(function(cubeFaceMesh) { if (!cubeFaceMesh.wasVisible && cubeFaceMesh.isVisible) { // Cube face just became visible, assign an unused scene! var newScene = GetHiddenScene() if (newScene == undefined) console.log('%cERROR','background:red','GetHiddenScene() returned undefined'); else cubeFaceMesh.scene = newScene; // Orient scene // var face1 = mainCubeFaceMesh.children[1].geometry.faces[0] var face1 = cubeFaceMeshes[4].children[1].geometry.faces[0] // var faceN = cubeFaceMeshes[n].children[1].geometry.faces[0] var faceN = cubeFaceMesh.children[1].geometry.faces[0] var v1 = face1.normal var vN = faceN.normal var quaternion = new THREE.Quaternion().setFromUnitVectors( v1, vN ); /* cubeFaceMesh.scene.matrixAutoUpdate = true cubeFaceMesh.scene.quaternion = quaternion // cubeFaceMesh.scene.useQuaternion = true; // cubeFaceMesh.scene.updateMatrix(); */ // NOTE: **Do not auto-update (or even manually update) object's matrix** -- b/c that will clobber whatever we set the quaternion to! cubeFaceMesh.scene.matrixAutoUpdate = false; cubeFaceMesh.scene.matrix.makeRotationFromQuaternion(quaternion); // cubeFaceMesh.scene.matrix.setPosition(THREE.Vector3(0,0,0)); if (cubeFaceMesh.scene == sceneFilenameToCubeSceneMap[moonHouseFilename + '.obj']) { var moonCubeScene = sceneFilenameToCubeSceneMap['Assets3D/Box - Moon 001.obj'] moonCubeScene.matrixAutoUpdate = false; moonCubeScene.matrix.makeRotationFromQuaternion(quaternion); } /* var euler = new THREE.Euler() euler.setFromQuaternion(quaternion, 'XYZ') // console.log('%c rotate scene', 'background: #00ffff;', quaternion) console.log('%c rotate scene', 'background: #00ffff;', euler) */ } UpdateSceneViz() }); renderer.autoClear = false; renderer.autoClearColor = false; renderer.autoClearDepth = false; renderer.autoClearStencil = false; // Clear color, depth, stencil. renderer.clear(true, true, true); // ShowAll(); // HideAllButCubeFace(3); // // Clear depth. // renderer.clear(false, true, false); /* var cameraVector = new THREE.Vector3( 0, 0, -1 ); // Camera points down -Z by default. cameraVector.applyQuaternion(camera.quaternion); */ // var visibleScenes = cubeFaceMeshes.filter(function(cubeFaceMesh) { return IsCubeFaceVisible(cameraVector, cubeFaceMesh); }) var visibleCubeFaceMeshes = _.uniq(cubeFaceMeshes.filter(function(cubeFaceMesh) { return cubeFaceMesh.isVisible; })) visibleCubeFaceMeshes.map(function(visibleCubeFaceMesh) { var i = cubeFaceMeshes.indexOf(visibleCubeFaceMesh) // Clear depth & stencil. renderer.clear(false, true, true); if (visibleCubeFaceMesh.scene == sceneFilenameToCubeSceneMap[moonHouseFilename + '.obj']) { var moonCubeScene = sceneFilenameToCubeSceneMap['Assets3D/Box - Moon 001.obj'] var windowsObject scene.traverse( function ( child ) { if (child.name.indexOf('__WINDOWS__') > -1) { windowsObject = child } }); moonRotation -= 0.001; scene.getObjectByName('__THE_MOON___Icosphere.001').children[1].position.set(-3,0.25,-0.5); scene.getObjectByName('__THE_MOON___Icosphere.001').children[1].scale.set(2,2,2); scene.getObjectByName('__THE_MOON___Icosphere.001').children[1].rotation.y = moonRotation; scene.getObjectByName('__THE_MOON___Icosphere.001').children[1].updateMatrix(); /* sceneFilenameToCubeSceneMap['Assets3D/Box - Moon 001.obj'].rotation.y = moonRotation; sceneFilenameToCubeSceneMap['Assets3D/Box - Moon 001.obj'].updateMatrix(); */ DrawMoonHouse(visibleCubeFaceMesh, visibleCubeFaceMesh.scene, windowsObject, moonCubeScene) // firstBitStencilObject, firstBitRenderObject, secondBitStencilObject, secondBitRenderObject // console.log('%cFOUND','background:yellow') /* // (1) render cube face to stencil HideAllButCubeFace(i) DrawImpossibleCubeFace(i) */ /* // TODO: // (2) AND windows to stencil // (3) render moon scene to color, depth HideAllButMesh(sceneFilenameToCubeSceneMap['Assets3D/Box - Moon 001.obj']) renderer.render(scene, camera) */ } // else if (visibleCubeFaceMesh.scene == sceneFilenameToCubeSceneMap[caveFilename + '.obj']) // { // } else { HideAllButCubeFace(i); DrawImpossibleCubeFace(i); HideAllButMesh(cubeScenes.indexOf(visibleCubeFaceMesh.scene)); DoRender(scene, camera) } }) /* // MOST RECENT WORKING VERSION !!!!! var i = 0; cubeScenes.map(function(object) { // Clear depth & stencil. renderer.clear(false, true, true); HideAllButCubeFace(i); DrawImpossibleCubeFace(i); HideAllButMesh(i); renderer.render(scene, camera); i += 1; }); */ /* // Stencil each face, then draw the corresponding scene. HideAllButCubeFace(3); DrawImpossibleCubeFace(3); HideAllButMesh(1); renderer.render(scene, camera); renderer.clear(false, true, true); HideAllButCubeFace(0); DrawImpossibleCubeFace(0); HideAllButMesh(0); renderer.render(scene, camera); renderer.clear(false, true, true); HideAllButCubeFace(2); DrawImpossibleCubeFace(2); HideAllButMesh(2); renderer.render(scene, camera); */ /* HideAllButMesh(0); renderer.render(scene, camera); */ }