diff --git a/src/controls/VoxelPainterControls.js b/src/controls/VoxelPainterControls.js index e7288b12..560232db 100644 --- a/src/controls/VoxelPainterControls.js +++ b/src/controls/VoxelPainterControls.js @@ -24,9 +24,6 @@ import { Vector2, Vector3, } from 'three'; -import { - setViewCoordinates, -} from '../store/actions'; import { THREE_CANVAS_HEIGHT, } from '../core/constants'; @@ -56,7 +53,6 @@ const STATE = { const CHANGE_EVENT = { type: 'change' }; const START_EVENT = { type: 'start' }; const END_EVENT = { type: 'end' }; -const EPS = 0.000001; /* * configuration @@ -73,10 +69,6 @@ const maxPolarAngle = Math.PI; // radians // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. const minAzimuthAngle = -Infinity; // radians const maxAzimuthAngle = Infinity; // radians -// Set to true to enable damping (inertia) -// If damping is enabled, you must call controls.update() in your animation loop -const enableDamping = false; -const dampingFactor = 0.05; // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. // Set to false to disable zooming const enableZoom = true; @@ -103,7 +95,6 @@ class VoxelPainterControls extends EventDispatcher { renderer; domElement; state; - // // Set to false to disable this control enabled = true; // "target" sets the location of focus, where the object orbits around @@ -128,7 +119,6 @@ class VoxelPainterControls extends EventDispatcher { // scale = 1; panOffset = new Vector3(); - zoomChanged = false; rotateStart = new Vector2(); rotateEnd = new Vector2(); rotateDelta = new Vector2(); @@ -146,23 +136,22 @@ class VoxelPainterControls extends EventDispatcher { updateTime = Date.now(); prevTime = Date.now(); offset = new Vector3(); - lastPosition = new Vector3(); - lastQuaternion = new Quaternion(); direction = new Vector3(); velocity = new Vector3(); vec = new Vector3(); - constructor(renderer, camera, domElement, store) { + constructor(renderer, camera, target, domElement, store) { super(); this.renderer = renderer; this.camera = camera; this.domElement = domElement; this.store = store; // - this.target = new Vector3(); - this.target0 = this.target.clone(); - this.position0 = this.camera.position.clone(); - this.zoom0 = this.camera.zoom; + this.target = target; + // + this.target0 = target.clone(); + this.position0 = camera.position.clone(); + this.zoom0 = camera.zoom; this.state = STATE.NONE; this.onContextMenu = this.onContextMenu.bind(this); @@ -336,7 +325,7 @@ class VoxelPainterControls extends EventDispatcher { } else if (event.deltaY > 0) { this.dollyIn(this.getZoomScale()); } - this.update(); + this.forceNextUpdate = true; } handleTouchStartRotate(event) { @@ -468,30 +457,24 @@ class VoxelPainterControls extends EventDispatcher { case 87: // w this.moveForward = true; break; - case 37: // left case 65: // a this.moveLeft = true; break; - case 40: // down case 83: // s this.moveBackward = true; break; - case 39: // right case 68: // d this.moveRight = true; break; - case 69: // E this.moveUp = true; break; - case 67: // C this.moveDown = true; break; - default: break; } @@ -513,30 +496,24 @@ class VoxelPainterControls extends EventDispatcher { case 87: // w this.moveForward = false; break; - case 37: // left case 65: // a this.moveLeft = false; break; - case 40: // down case 83: // s this.moveBackward = false; break; - case 39: // right case 68: // d this.moveRight = false; break; - case 69: // E this.moveUp = false; break; - case 67: // C this.moveDown = false; break; - default: break; } @@ -756,15 +733,12 @@ class VoxelPainterControls extends EventDispatcher { case 0: mouseAction = MOUSE_BUTTONS.LEFT; break; - case 1: mouseAction = MOUSE_BUTTONS.MIDDLE; break; - case 2: mouseAction = MOUSE_BUTTONS.RIGHT; break; - default: mouseAction = -1; } @@ -774,7 +748,6 @@ class VoxelPainterControls extends EventDispatcher { this.handleMouseDownDolly(event); this.state = STATE.DOLLY; break; - case MOUSE.ROTATE: if (event.ctrlKey || event.metaKey) { this.handleMouseDownPan(event); @@ -784,7 +757,6 @@ class VoxelPainterControls extends EventDispatcher { this.state = STATE.ROTATE; } break; - case MOUSE.PAN: if (event.ctrlKey || event.metaKey) { this.handleMouseDownRotate(event); @@ -794,7 +766,6 @@ class VoxelPainterControls extends EventDispatcher { this.state = STATE.PAN; } break; - default: this.state = STATE.NONE; } @@ -833,14 +804,26 @@ class VoxelPainterControls extends EventDispatcher { this.state = STATE.NONE; } - setView(view) { - if (view.length !== 3) { - return; - } - this.target.set(...view); - } - update() { + const { + moveRight, + moveLeft, + moveUp, + moveDown, + moveForward, + moveBackward, + } = this; + + if (!(this.state !== STATE.NONE + || this.forceNextUpdate + || moveRight || moveLeft + || moveUp || moveDown + || moveForward || moveBackward + )) { + return false; + } + this.forceNextUpdate = false; + const { camera, target, @@ -863,15 +846,6 @@ class VoxelPainterControls extends EventDispatcher { velocity.set(0, 0, 0); } - const { - moveRight, - moveLeft, - moveUp, - moveDown, - moveForward, - moveBackward, - } = this; - direction.x = Number(moveRight) - Number(moveLeft); direction.y = Number(moveUp) - Number(moveDown); direction.z = Number(moveForward) - Number(moveBackward); @@ -898,9 +872,7 @@ class VoxelPainterControls extends EventDispatcher { this.prevTime = time; - const { position } = camera; - - offset.copy(position).sub(this.target); + offset.copy(camera.position).sub(this.target); // rotate offset to "y-axis-is-up" space offset.applyQuaternion(this.quat); @@ -908,13 +880,8 @@ class VoxelPainterControls extends EventDispatcher { // angle from z-axis around y-axis spherical.setFromVector3(offset); - if (enableDamping) { - spherical.theta += sphericalDelta.theta * dampingFactor; - spherical.phi += sphericalDelta.phi * dampingFactor; - } else { - spherical.theta += sphericalDelta.theta; - spherical.phi += sphericalDelta.phi; - } + spherical.theta += sphericalDelta.theta; + spherical.phi += sphericalDelta.phi; // restrict theta to be between desired limits spherical.theta = Math.max( @@ -941,11 +908,7 @@ class VoxelPainterControls extends EventDispatcher { if (panOffset.length() > 1000) { panOffset.set(0, 0, 0); } - if (enableDamping) { - target.addScaledVector(panOffset, dampingFactor); - } else { - target.add(panOffset); - } + target.add(panOffset); /* if (scope.target.y < 10.0) { scope.target.y = 10.0; @@ -969,58 +932,15 @@ class VoxelPainterControls extends EventDispatcher { // rotate offset back to "camera-up-vector-is-up" space offset.applyQuaternion(this.quatInverse); - position.copy(target).add(offset); + this.camera.position.copy(target).add(offset); camera.lookAt(target); - if (enableDamping) { - sphericalDelta.theta *= (1 - dampingFactor); - sphericalDelta.phi *= (1 - dampingFactor); - panOffset.multiplyScalar(1 - dampingFactor); - - if (panOffset.length() < 0.2 && panOffset.length() !== 0.0) { - panOffset.set(0, 0, 0); - this.store.dispatch(setViewCoordinates(target.toArray())); - this.renderer.storeViewInState(); - } else if (panOffset.length() !== 0.0) { - if (time > this.updateTime + 500) { - this.updateTime = time; - this.store.dispatch(setViewCoordinates(target.toArray())); - this.renderer.storeViewInState(); - } - } - /* - if (Math.abs(sphericalDelta.theta) < rotationFinishThreshold - && sphericalDelta.theta != 0.0 - && Math.abs(sphericalDelta.phi) < rotationFinishThreshold - && sphericalDelta.phi != 0.0) { - sphericalDelta.set(0, 0, 0); - console.log(`rotation finished`); - } - */ - } else { - sphericalDelta.set(0, 0, 0); - panOffset.set(0, 0, 0); - } - + sphericalDelta.set(0, 0, 0); + panOffset.set(0, 0, 0); this.scale = 1; - // update condition is: - // min(camera displacement, camera rotation in radians)^2 > EPS - // using small-angle approximation cos(x/2) = 1 - x^2 / 8 - - if (this.zoomChanged - || this.lastPosition.distanceToSquared(camera.position) > EPS - || 8 * (1 - this.lastQuaternion.dot(camera.quaternion)) > EPS - ) { - this.dispatchEvent(CHANGE_EVENT); - - this.lastPosition.copy(camera.position); - this.lastQuaternion.copy(camera.quaternion); - this.zoomChanged = false; - return true; - } - - return false; + this.dispatchEvent(CHANGE_EVENT); + return true; } } diff --git a/src/globe.js b/src/globe.js index c81e52f8..86f6141d 100644 --- a/src/globe.js +++ b/src/globe.js @@ -1,4 +1,19 @@ -import * as THREE from 'three'; +import { + MeshPhongMaterial, + TextureLoader, + Color, + Scene, + PerspectiveCamera, + WebGLRenderer, + AmbientLight, + DirectionalLight, + Mesh, + SphereGeometry, + MeshBasicMaterial, + BackSide, + Raycaster, + Vector2, +} from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; import TrackballControls from 'three-trackballcontrols'; @@ -50,27 +65,27 @@ document.addEventListener('DOMContentLoaded', () => { const [canvasIdent, canvasId, canvasSize, x, y] = parseHashCoords(); - const canvasTexture = new THREE.MeshPhongMaterial({ - map: new THREE.TextureLoader().load(`./tiles/${canvasId}/texture.webp`), - bumpMap: new THREE.TextureLoader().load(`./assets3d/normal${canvasId}.jpg`), + const canvasTexture = new MeshPhongMaterial({ + map: new TextureLoader().load(`./tiles/${canvasId}/texture.webp`), + bumpMap: new TextureLoader().load(`./assets3d/normal${canvasId}.jpg`), bumpScale: 0.02, - specularMap: new THREE.TextureLoader() + specularMap: new TextureLoader() .load(`./assets3d/specular${canvasId}.jpg`), - specular: new THREE.Color('grey'), + specular: new Color('grey'), }); let width = window.innerWidth; let height = window.innerHeight; - const scene = new THREE.Scene(); + const scene = new Scene(); - const camera = new THREE.PerspectiveCamera(45, width / height, 0.01, 1000); + const camera = new PerspectiveCamera(45, width / height, 0.01, 1000); camera.position.z = 4.0; - const renderer = new THREE.WebGLRenderer(); + const renderer = new WebGLRenderer(); renderer.setSize(width, height); - scene.add(new THREE.AmbientLight(0x333333)); + scene.add(new AmbientLight(0x333333)); let controls = null; let object = null; @@ -82,7 +97,7 @@ document.addEventListener('DOMContentLoaded', () => { renderer.render(scene, camera); } - const light = new THREE.DirectionalLight(0xffffff, 0.7); + const light = new DirectionalLight(0xffffff, 0.7); light.position.set(10, 6, 10); scene.add(light); @@ -129,11 +144,11 @@ document.addEventListener('DOMContentLoaded', () => { webglEl.appendChild(renderer.domElement); - const stars = new THREE.Mesh( - new THREE.SphereGeometry(90, 64, 64), - new THREE.MeshBasicMaterial({ - map: new THREE.TextureLoader().load('./assets3d/starfield.png'), - side: THREE.BackSide, + const stars = new Mesh( + new SphereGeometry(90, 64, 64), + new MeshBasicMaterial({ + map: new TextureLoader().load('./assets3d/starfield.png'), + side: BackSide, }), ); scene.add(stars); @@ -153,8 +168,8 @@ document.addEventListener('DOMContentLoaded', () => { /* * update coords */ - const raycaster = new THREE.Raycaster(); - const mouse = new THREE.Vector2(); + const raycaster = new Raycaster(); + const mouse = new Vector2(); const coorbox = document.getElementById('coorbox'); function onDocumentMouseMove(event) { if (!object) { diff --git a/src/ui/Chunk3D.js b/src/ui/Chunk3D.js index f5896cb4..2fa63e20 100644 --- a/src/ui/Chunk3D.js +++ b/src/ui/Chunk3D.js @@ -6,7 +6,12 @@ /* We have to look for performance here not for good looking code */ /* eslint-disable prefer-destructuring */ -import * as THREE from 'three'; +import { + MeshLambertMaterial, + Mesh, + BufferGeometry, + BufferAttribute, +} from 'three'; import Chunk from './Chunk'; import { @@ -69,7 +74,7 @@ const faceCorners = [ ], ]; -const material = new THREE.MeshLambertMaterial({ +const material = new MeshLambertMaterial({ vertexColors: true, }); @@ -79,7 +84,7 @@ class Chunk3D extends Chunk { ready = false; palette; // Object buffer; // Uint8Array - mesh = null; // THREE.Mesh + mesh = null; // Mesh faceCnt; // number lastPixel; // number heightMap; // Array @@ -344,36 +349,36 @@ class Chunk3D extends Chunk { const geometry = (this.mesh) ? this.mesh.geometry - : new THREE.BufferGeometry(); + : new BufferGeometry(); geometry.setAttribute( 'position', - new THREE.BufferAttribute( + new BufferAttribute( positions, 3, ), ); geometry.setAttribute( 'normal', - new THREE.BufferAttribute( + new BufferAttribute( normals, 3, ), ); geometry.setAttribute( 'color', - new THREE.BufferAttribute( + new BufferAttribute( colors, 3, true, ), ); - geometry.setIndex(new THREE.BufferAttribute(indices, 1)); + geometry.setIndex(new BufferAttribute(indices, 1)); geometry.computeBoundingSphere(); geometry.setDrawRange(0, this.faceCnt * 6); if (!this.mesh) { - this.mesh = new THREE.Mesh(geometry, material); + this.mesh = new Mesh(geometry, material); this.mesh.name = this.key; } diff --git a/src/ui/InfiniteGridHelper.js b/src/ui/InfiniteGridHelper.js index 2903e96b..43217f14 100644 --- a/src/ui/InfiniteGridHelper.js +++ b/src/ui/InfiniteGridHelper.js @@ -7,20 +7,26 @@ /* eslint-disable max-len */ -import * as THREE from 'three'; +import { + Mesh, + Color, + PlaneBufferGeometry, + ShaderMaterial, + DoubleSide, +} from 'three'; -export default class InfiniteGridHelper extends THREE.Mesh { +export default class InfiniteGridHelper extends Mesh { constructor(size1, size2, color, distance, axes = 'xzy') { - color = color || new THREE.Color('white'); + color = color || new Color('white'); size1 = size1 || 10; size2 = size2 || 100; distance = distance || 8000; const planeAxes = axes.substring(0, 2); - const geometry = new THREE.PlaneBufferGeometry(2, 2, 1, 1); - const material = new THREE.ShaderMaterial({ + const geometry = new PlaneBufferGeometry(2, 2, 1, 1); + const material = new ShaderMaterial({ - side: THREE.DoubleSide, + side: DoubleSide, uniforms: { uSize1: { value: size1 }, diff --git a/src/ui/Renderer.js b/src/ui/Renderer.js index c3657190..70a92588 100644 --- a/src/ui/Renderer.js +++ b/src/ui/Renderer.js @@ -19,8 +19,14 @@ class Renderer { chunkLoader = null; // needs to be known for lazy loading THREE is3D = null; + // force renderer to rebuild whole view or + // to "subrender" known view next tick + forceNextRender = true; + forceNextSubrender = true; // current position (subclass decies what it means), // will be changed by controls + // TODO might be better as private and with a getter but no setter to avoid + // misconseption of it being writeable. Might have performance impact. view = [0, 0, 0]; // #storeViewTimeout = null; diff --git a/src/ui/Renderer3D.js b/src/ui/Renderer3D.js index 0f83b5f2..705aae21 100644 --- a/src/ui/Renderer3D.js +++ b/src/ui/Renderer3D.js @@ -3,7 +3,22 @@ * */ -import * as THREE from 'three'; +import { + Vector2, + Vector3, + PerspectiveCamera, + Scene, + AmbientLight, + DirectionalLight, + FogExp2, + BoxBufferGeometry, + MeshBasicMaterial, + Mesh, + Raycaster, + PlaneBufferGeometry, + MeshLambertMaterial, + WebGLRenderer, +} from 'three'; import Sky from './Sky'; import InfiniteGridHelper from './InfiniteGridHelper'; @@ -28,6 +43,8 @@ const renderDistance = 150; class Renderer3D extends Renderer { scene; camera; + // position camera is looking at + target = new Vector3(); rollOverMesh; objects; loadedChunks; @@ -43,8 +60,6 @@ class Renderer3D extends Renderer { pressTime; pressCdTime; multitap; - //-- - forceNextRender = false; constructor(store) { super(store); @@ -53,7 +68,7 @@ class Renderer3D extends Renderer { this.objects = []; // camera - const camera = new THREE.PerspectiveCamera( + const camera = new PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, @@ -64,19 +79,19 @@ class Renderer3D extends Renderer { this.camera = camera; // scene - const scene = new THREE.Scene(); - // scene.background = new THREE.Color(0xf0f0f0); + const scene = new Scene(); + // scene.background = new Color(0xf0f0f0); this.scene = scene; // lights - const ambientLight = new THREE.AmbientLight(0x222222); + const ambientLight = new AmbientLight(0x222222); scene.add(ambientLight); - // const directionalLight = new THREE.DirectionalLight(0xffffff); + // const directionalLight = new DirectionalLight(0xffffff); // directionalLight.position.set(1, 1.2, 0.8).normalize(); - const directionalLight = new THREE.DirectionalLight(0xffffff, 1); + const directionalLight = new DirectionalLight(0xffffff, 1); directionalLight.position.set(80, 80, 75); - const contourLight = new THREE.DirectionalLight(0xffffff, 0.4); + const contourLight = new DirectionalLight(0xffffff, 0.4); contourLight.position.set(-80, 80, -75); scene.add(directionalLight); scene.add(contourLight); @@ -85,7 +100,7 @@ class Renderer3D extends Renderer { sky.scale.setScalar(450000); scene.add(sky); - scene.fog = new THREE.FogExp2(0xffffff, 0.003); + scene.fog = new FogExp2(0xffffff, 0.003); const effectController = { turbidity: 10, @@ -104,31 +119,31 @@ class Renderer3D extends Renderer { uniforms.sunPosition.value.set(400000, 400000, 400000); // hover helper - const rollOverGeo = new THREE.BoxBufferGeometry(1, 1, 1); - const rollOverMaterial = new THREE.MeshBasicMaterial({ + const rollOverGeo = new BoxBufferGeometry(1, 1, 1); + const rollOverMaterial = new MeshBasicMaterial({ color: 0xff0000, opacity: 0.5, transparent: true, }); - this.rollOverMesh = new THREE.Mesh(rollOverGeo, rollOverMaterial); + this.rollOverMesh = new Mesh(rollOverGeo, rollOverMaterial); scene.add(this.rollOverMesh); // grid - // const gridHelper = new THREE.GridHelper(100, 10, 0x555555, 0x555555); + // const gridHelper = new GridHelper(100, 10, 0x555555, 0x555555); const gridHelper = new InfiniteGridHelper(1, 10); scene.add(gridHelper); // - this.raycaster = new THREE.Raycaster(); - this.mouse = new THREE.Vector2(); + this.raycaster = new Raycaster(); + this.mouse = new Vector2(); this.multitap = 0; // Plane Floor - const geometry = new THREE.PlaneBufferGeometry(1024, 1024); + const geometry = new PlaneBufferGeometry(1024, 1024); geometry.rotateX(-Math.PI / 2); - const plane = new THREE.Mesh( + const plane = new Mesh( geometry, - new THREE.MeshLambertMaterial({ color: 0xcae3ff }), + new MeshLambertMaterial({ color: 0xcae3ff }), ); scene.add(plane); this.plane = plane; @@ -136,20 +151,20 @@ class Renderer3D extends Renderer { this.plane.position.y = -0.1; // Out of bounds plane - const oobGeometry = new THREE.PlaneBufferGeometry( + const oobGeometry = new PlaneBufferGeometry( THREE_TILE_SIZE, THREE_TILE_SIZE, ); oobGeometry.rotateX(-Math.PI / 2); oobGeometry.translate(THREE_TILE_SIZE / 2, 0.2, THREE_TILE_SIZE / 2); - const oobMaterial = new THREE.MeshLambertMaterial({ + const oobMaterial = new MeshLambertMaterial({ color: '#C4C4C4', }); this.oobGeometry = oobGeometry; this.oobMaterial = oobMaterial; // renderer - const threeRenderer = new THREE.WebGLRenderer({ + const threeRenderer = new WebGLRenderer({ preserveDrawingBuffer: true, }); threeRenderer.setPixelRatio(window.devicePixelRatio); @@ -163,11 +178,11 @@ class Renderer3D extends Renderer { const controls = new VoxelPainterControls( this, camera, + this.target, domElement, store, ); - controls.enableDamping = true; - controls.dampingFactor = 0.10; + // TODO doesn't work like this anymore controls.maxPolarAngle = Math.PI / 2; controls.minDistance = 10.00; controls.maxDistance = 100.00; @@ -201,6 +216,14 @@ class Renderer3D extends Renderer { this.updateCanvasData(state); } + get view() { + return this.target.toArray(); + } + + set view(view) { + this.target.set(...view); + } + destructor() { window.removeEventListener('resize', this.onWindowResize, false); this.threeRenderer.dispose(); @@ -211,7 +234,11 @@ class Renderer3D extends Renderer { super.destructor(); } - updateView() { + updateView(view) { + if (view.length !== 3) { + return; + } + this.view = view; this.forceNextRender = true; } @@ -251,15 +278,10 @@ class Renderer3D extends Renderer { ); } } - this.controls.setView(view); + this.updateView(view); this.forceNextRender = true; } - // eslint-disable-next-line class-methods-use-this - updateScale() { - return null; - } - renderPixel( i, j, @@ -319,7 +341,7 @@ class Renderer3D extends Renderer { let chunk = null; if (xc < 0 || zc < 0 || xc >= chunkMaxXY || zc >= chunkMaxXY) { // if out of bounds - chunk = new THREE.Mesh(this.oobGeometry, this.oobMaterial); + chunk = new Mesh(this.oobGeometry, this.oobMaterial); } else { chunk = chunkLoader.getChunk(xc, zc, true); } @@ -353,12 +375,44 @@ class Renderer3D extends Renderer { if (!this.threeRenderer) { return; } - super.render(); + const controlUpdate = super.render(); if (this.forceNextRender) { this.reloadChunks(); - this.forceNextRender = false; } - this.threeRenderer.render(this.scene, this.camera); + if (this.forceNextRender || this.forceNextSubRender || controlUpdate) { + if (this.forceNextRender) { + if (this.lol !== 'force') { + console.log(this.lol, this.lola); + this.lol = 'force'; + this.lola = 0; + } + this.lola += 1; + } else if (this.forceNextSubRender) { + if (this.lol !== 'sub') { + console.log(this.lol, this.lola); + this.lol = 'sub'; + this.lola = 0; + } + this.lola += 1; + } else if (controlUpdate) { + if (this.lol !== 'update') { + console.log(this.lol, this.lola); + this.lol = 'update'; + this.lola = 0; + } + this.lola += 1; + } + this.threeRenderer.render(this.scene, this.camera); + this.forceNextRender = false; + this.forceNextSubRender = false; + } else { + if (this.lol !== 'skip') { + console.log(this.lol, this.lola); + this.lol = 'skip'; + this.lola = 0; + } + this.lola += 1; + } } onWindowResize() { @@ -385,15 +439,17 @@ class Renderer3D extends Renderer { rollOverMesh, store, } = this; + const state = store.getState(); const { fetchingPixel, - } = store.getState().fetching; + } = state.fetching; mouse.set( (clientX / innerWidth) * 2 - 1, -(clientY / innerHeight) * 2 + 1, ); + console.log('move mouse'); raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObjects(objects); if (intersects.length > 0) { @@ -403,13 +459,25 @@ class Renderer3D extends Renderer { .floor() .addScalar(0.5); if (fetchingPixel - || target.clone().sub(camera.position).length() > 120) { - rollOverMesh.position.y = -10; + || target.clone().sub(camera.position).length() > 120 + ) { + if (rollOverMesh.position.y !== -10) { + // unsetHover ? + rollOverMesh.position.y = -10; + this.forceNextSubRender = true; + } } else { + const { hover: prevHover } = state.canvas; rollOverMesh.position.copy(target); - const hover = target - .toArray().map((u) => Math.floor(u)); - this.store.dispatch(setHover(hover)); + const hover = target.toArray().map((u) => Math.floor(u)); + if (!prevHover + || prevHover[0] !== hover[0] + || prevHover[1] !== hover[1] + || prevHover[2] !== hover[2] + ) { + this.store.dispatch(setHover(hover)); + this.forceNextSubRender = true; + } } } } diff --git a/src/ui/Sky.js b/src/ui/Sky.js index 19a8bde9..3531ed32 100644 --- a/src/ui/Sky.js +++ b/src/ui/Sky.js @@ -17,22 +17,29 @@ /* eslint-disable max-len */ -import * as THREE from 'three'; +import { + Vector3, + Mesh, + ShaderMaterial, + BackSide, + BoxGeometry, + UniformsUtils, +} from 'three'; -export default class Sky extends THREE.Mesh { +export default class Sky extends Mesh { static isSky = true; constructor() { const shader = Sky.SkyShader; - const material = new THREE.ShaderMaterial({ + const material = new ShaderMaterial({ name: 'SkyShader', fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, - uniforms: THREE.UniformsUtils.clone(shader.uniforms), - side: THREE.BackSide, + uniforms: UniformsUtils.clone(shader.uniforms), + side: BackSide, depthWrite: false, }); - super(new THREE.BoxGeometry(1, 1, 1), material); + super(new BoxGeometry(1, 1, 1), material); } } @@ -51,10 +58,10 @@ Sky.SkyShader = { value: 0.8, }, sunPosition: { - value: new THREE.Vector3(), + value: new Vector3(), }, up: { - value: new THREE.Vector3(0, 1, 0), + value: new Vector3(0, 1, 0), }, }, vertexShader: