make view a protected member

load view from store in child class renderers instead of parent
This commit is contained in:
HF 2024-01-21 02:41:09 +01:00
parent 7f684bb47a
commit 539c5120e7
5 changed files with 95 additions and 86 deletions

View File

@ -107,7 +107,7 @@ class PixelPainterControls {
const { clientX, clientY } = event; const { clientX, clientY } = event;
this.clickTapStartTime = Date.now(); this.clickTapStartTime = Date.now();
this.clickTapStartCoords = [clientX, clientY]; this.clickTapStartCoords = [clientX, clientY];
this.clickTapStartView = [...this.renderer.view]; this.clickTapStartView = this.renderer.view;
const { viewport } = this; const { viewport } = this;
setTimeout(() => { setTimeout(() => {
if (this.isClicking) { if (this.isClicking) {
@ -254,7 +254,7 @@ class PixelPainterControls {
this.renderer.cancelStoreViewInState(); this.renderer.cancelStoreViewInState();
this.clickTapStartTime = Date.now(); this.clickTapStartTime = Date.now();
this.clickTapStartCoords = PixelPainterControls.getTouchCenter(event); this.clickTapStartCoords = PixelPainterControls.getTouchCenter(event);
this.clickTapStartView = [...this.renderer.view]; this.clickTapStartView = this.renderer.view;
if (event.touches.length > 1) { if (event.touches.length > 1) {
this.tapStartDist = PixelPainterControls.getMultiTouchDistance(event); this.tapStartDist = PixelPainterControls.getMultiTouchDistance(event);
@ -321,7 +321,7 @@ class PixelPainterControls {
// if one finger got lifted or added, reset clickTabStart // if one finger got lifted or added, reset clickTabStart
this.isMultiTab = multiTouch; this.isMultiTab = multiTouch;
this.clickTapStartCoords = [clientX, clientY]; this.clickTapStartCoords = [clientX, clientY];
this.clickTapStartView = [...this.renderer.view]; this.clickTapStartView = this.renderer.view;
this.tapStartDist = PixelPainterControls.getMultiTouchDistance(event); this.tapStartDist = PixelPainterControls.getMultiTouchDistance(event);
} else { } else {
// pan // pan
@ -333,7 +333,7 @@ class PixelPainterControls {
if (deltaX > 2 || deltaY > 2) { if (deltaX > 2 || deltaY > 2) {
this.clearTabTimeout(); this.clearTabTimeout();
} }
const { viewscale: scale } = this.renderer.view; const { viewscale: scale } = this.renderer;
this.renderer.updateView([ this.renderer.updateView([
lastPosX - (deltaX / scale), lastPosX - (deltaX / scale),
lastPosY - (deltaY / scale), lastPosY - (deltaY / scale),

View File

@ -25,8 +25,10 @@ import {
} from 'three'; } from 'three';
import { import {
THREE_CANVAS_HEIGHT, THREE_CANVAS_HEIGHT,
VIEW_UPDATE_DELAY,
} from '../core/constants'; } from '../core/constants';
const STORE_UPDATE_DELAY = VIEW_UPDATE_DELAY / 2;
// Mouse buttons // Mouse buttons
const MOUSE_BUTTONS = { const MOUSE_BUTTONS = {
LEFT: MOUSE.ROTATE, LEFT: MOUSE.ROTATE,
@ -127,7 +129,7 @@ class VoxelPainterControls {
// temp for update // temp for update
quat; quat;
quatInverse; quatInverse;
updateTime = Date.now(); storeViewInStateTime = Date.now();
prevTime = Date.now(); prevTime = Date.now();
offset = new Vector3(); offset = new Vector3();
direction = new Vector3(); direction = new Vector3();
@ -176,8 +178,6 @@ class VoxelPainterControls {
this.quat = new Quaternion() this.quat = new Quaternion()
.setFromUnitVectors(camera.up, new Vector3(0, 1, 0)); .setFromUnitVectors(camera.up, new Vector3(0, 1, 0));
this.quatInverse = this.quat.clone().invert(); this.quatInverse = this.quat.clone().invert();
this.update();
} }
dispose() { dispose() {
@ -261,7 +261,6 @@ class VoxelPainterControls {
this.rotateLeft(Math.PI * rotateDelta.x / element.clientHeight); // yes, height this.rotateLeft(Math.PI * rotateDelta.x / element.clientHeight); // yes, height
this.rotateUp(Math.PI * rotateDelta.y / element.clientHeight); this.rotateUp(Math.PI * rotateDelta.y / element.clientHeight);
this.rotateStart.copy(rotateEnd); this.rotateStart.copy(rotateEnd);
this.update();
} }
handleMouseMoveDolly(event) { handleMouseMoveDolly(event) {
@ -280,7 +279,6 @@ class VoxelPainterControls {
this.scale *= scaleDelta; this.scale *= scaleDelta;
} }
dollyStart.copy(this.dollyEnd); dollyStart.copy(this.dollyEnd);
this.update();
} }
handleMouseMovePan(event) { handleMouseMovePan(event) {
@ -294,7 +292,6 @@ class VoxelPainterControls {
panDelta.subVectors(panEnd, panStart).multiplyScalar(panSpeed); panDelta.subVectors(panEnd, panStart).multiplyScalar(panSpeed);
this.pan(panDelta.x, panDelta.y); this.pan(panDelta.x, panDelta.y);
panStart.copy(panEnd); panStart.copy(panEnd);
this.update();
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
@ -593,28 +590,24 @@ class VoxelPainterControls {
return; return;
} }
this.handleTouchMoveRotate(event); this.handleTouchMoveRotate(event);
this.update();
break; break;
case STATE.TOUCH_PAN: case STATE.TOUCH_PAN:
if (!enablePan) { if (!enablePan) {
return; return;
} }
this.handleTouchMovePan(event); this.handleTouchMovePan(event);
this.update();
break; break;
case STATE.TOUCH_DOLLY_PAN: case STATE.TOUCH_DOLLY_PAN:
if (!enableZoom && !enablePan) { if (!enableZoom && !enablePan) {
return; return;
} }
this.handleTouchMoveDollyPan(event); this.handleTouchMoveDollyPan(event);
this.update();
break; break;
case STATE.TOUCH_DOLLY_ROTATE: case STATE.TOUCH_DOLLY_ROTATE:
if (!enableZoom && !enableRotate) { if (!enableZoom && !enableRotate) {
return; return;
} }
this.handleTouchMoveDollyRotate(event); this.handleTouchMoveDollyRotate(event);
this.update();
break; break;
default: default:
this.state = STATE.NONE; this.state = STATE.NONE;
@ -713,11 +706,10 @@ class VoxelPainterControls {
this.camera.zoom = this.zoom0; this.camera.zoom = this.zoom0;
this.camera.updateProjectionMatrix(); this.camera.updateProjectionMatrix();
this.update();
this.state = STATE.NONE; this.state = STATE.NONE;
} }
update() { update(force) {
const { const {
moveRight, moveRight,
moveLeft, moveLeft,
@ -727,7 +719,8 @@ class VoxelPainterControls {
moveBackward, moveBackward,
} = this; } = this;
if (!(this.state !== STATE.NONE if (!(force
|| this.state !== STATE.NONE
|| this.forceNextUpdate || this.forceNextUpdate
|| moveRight || moveLeft || moveRight || moveLeft
|| moveUp || moveDown || moveUp || moveDown
@ -852,6 +845,10 @@ class VoxelPainterControls {
panOffset.set(0, 0, 0); panOffset.set(0, 0, 0);
this.scale = 1; this.scale = 1;
if (this.storeViewInStateTime + STORE_UPDATE_DELAY < time) {
this.renderer.storeViewInState();
}
return true; return true;
} }
} }

View File

@ -1,6 +1,9 @@
/* /*
* parent class for Renderer * parent class for Renderer
*/ */
/* eslint-disable no-underscore-dangle */
import { import {
VIEW_UPDATE_DELAY, VIEW_UPDATE_DELAY,
} from '../core/constants'; } from '../core/constants';
@ -23,17 +26,19 @@ class Renderer {
// to "subrender" known view next tick // to "subrender" known view next tick
forceNextRender = true; forceNextRender = true;
forceNextSubrender = true; forceNextSubrender = true;
// current position (subclass decies what it means), // current position
// will be changed by controls // third value can be scale (2d) or z axis (3d)
// TODO might be better as private and with a getter but no setter to avoid _view = [0, 0, 0];
// misconseption of it being writeable. Might have performance impact.
view = [0, 0, 0];
// //
#storeViewTimeout = null; #storeViewTimeout = null;
constructor(store) { constructor(store) {
this.store = store; this.store = store;
this.loadViewFromState(); //this.loadViewFromState();
}
get view() {
return [...this._view];
} }
get chunks() { get chunks() {
@ -52,7 +57,7 @@ class Renderer {
updateView(view) { updateView(view) {
for (let i = 0; i < view.length; i += 1) { for (let i = 0; i < view.length; i += 1) {
this.view[i] = view[i]; this._view[i] = view[i];
} }
} }
@ -83,7 +88,7 @@ class Renderer {
} }
render() { render() {
return this.controls.update(); return this.controls.update(this.forceNextRender);
} }
renderPixel() {} renderPixel() {}

View File

@ -3,6 +3,8 @@
* *
*/ */
/* eslint-disable no-underscore-dangle */
import { import {
TILE_ZOOM_LEVEL, TILE_ZOOM_LEVEL,
TILE_SIZE, TILE_SIZE,
@ -29,40 +31,28 @@ import pixelNotify from './PixelNotify';
class Renderer2D extends Renderer { class Renderer2D extends Renderer {
canvasId = null; canvasId = null;
viewscale; viewscale = 0;
//-- //--
centerChunk; centerChunk = [null, null];
tiledScale; tiledScale = 0;
tiledZoom; tiledZoom = 4;
hover; hover = false;
//-- //--
viewport = null; viewport = null;
//-- //--
forceNextRender; lastFetch = 0;
forceNextSubrender;
canvas; canvas;
lastFetch;
//-- //--
oldHistoricalTime; oldHistoricalTime = null;
constructor(store) { constructor(store) {
super(store); super(store);
this.is3D = false; this.is3D = false;
[,, this.viewscale] = this.view;
this.centerChunk = [null, null];
this.tiledScale = 0;
this.tiledZoom = 4;
this.canvasMaxTiledZoom = 0; this.canvasMaxTiledZoom = 0;
this.historicalCanvasMaxTiledZoom = 0; this.historicalCanvasMaxTiledZoom = 0;
this.hover = false;
this.scaleThreshold = 1; this.scaleThreshold = 1;
//-- //--
this.forceNextRender = true;
this.forceNextSubrender = true;
this.lastFetch = 0;
this.oldHistoricalTime = null;
//--
const viewport = document.createElement('canvas'); const viewport = document.createElement('canvas');
viewport.className = 'viewport'; viewport.className = 'viewport';
const viewportCtx = viewport.getContext('2d', { alpha: false }); const viewportCtx = viewport.getContext('2d', { alpha: false });
@ -124,6 +114,7 @@ class Renderer2D extends Renderer {
canvasId, canvasId,
} = state.canvas; } = state.canvas;
if (canvasId !== this.canvasId) { if (canvasId !== this.canvasId) {
// TODO doesn't immediatelly reload when change from 3d to 2d
this.canvasId = canvasId; this.canvasId = canvasId;
if (canvasId !== null) { if (canvasId !== null) {
const { const {
@ -141,9 +132,8 @@ class Renderer2D extends Renderer {
canvases[canvasId].historicalSizes, canvases[canvasId].historicalSizes,
); );
} }
// scale of 0 is impossible, so it always updates
this.view[2] = 0;
this.updateView(state.canvas.view); this.updateView(state.canvas.view);
this.forceNextRender = true;
} }
} }
@ -202,7 +192,7 @@ class Renderer2D extends Renderer {
this.viewscale = scale; this.viewscale = scale;
} }
} else { } else {
[,, scale] = this.view; [,, scale] = this._view;
} }
// clamp coords // clamp coords
const canvasMinXY = -canvasSize / 2; const canvasMinXY = -canvasSize / 2;
@ -253,7 +243,6 @@ class Renderer2D extends Renderer {
} }
} }
renderPixel( renderPixel(
i, i,
j, j,
@ -450,8 +439,8 @@ class Renderer2D extends Renderer {
state, state,
) { ) {
const { const {
_view,
viewport, viewport,
view,
viewscale, viewscale,
} = this; } = this;
const { const {
@ -468,7 +457,7 @@ class Renderer2D extends Renderer {
hover, hover,
} = state.canvas; } = state.canvas;
const [x, y] = view; const [x, y] = _view;
const [cx, cy] = this.centerChunk; const [cx, cy] = this.centerChunk;
// if we have to render pixelnotify // if we have to render pixelnotify
@ -553,18 +542,18 @@ class Renderer2D extends Renderer {
} }
if (showGrid && viewscale >= 8) { if (showGrid && viewscale >= 8) {
renderGrid(state, viewport, view, viewscale, isLightGrid); renderGrid(state, viewport, _view, viewscale, isLightGrid);
} }
if (doRenderPixelnotify) { if (doRenderPixelnotify) {
pixelNotify.render(state, viewport, view, viewscale); pixelNotify.render(state, viewport, _view, viewscale);
} }
if (hover && doRenderPlaceholder) { if (hover && doRenderPlaceholder) {
renderPlaceholder(state, viewport, view, viewscale); renderPlaceholder(state, viewport, _view, viewscale);
} }
if (hover && doRenderPotatoPlaceholder) { if (hover && doRenderPotatoPlaceholder) {
renderPotatoPlaceholder(state, viewport, view, viewscale); renderPotatoPlaceholder(state, viewport, _view, viewscale);
} }
} }
@ -704,7 +693,6 @@ class Renderer2D extends Renderer {
) { ) {
const { const {
viewport, viewport,
view,
viewscale, viewscale,
} = this; } = this;
const { const {
@ -715,7 +703,7 @@ class Renderer2D extends Renderer {
historicalCanvasSize, historicalCanvasSize,
} = state.canvas; } = state.canvas;
const [x, y] = view; const [x, y] = this._view;
const [cx, cy] = this.centerChunk; const [cx, cy] = this.centerChunk;
if (!this.forceNextRender && !this.forceNextSubrender) { if (!this.forceNextRender && !this.forceNextSubrender) {

View File

@ -44,12 +44,17 @@ const renderDistance = 150;
class Renderer3D extends Renderer { class Renderer3D extends Renderer {
scene; scene;
camera; camera;
// current chunk in center of view
centerChunk = [null, null];
// position camera is looking at // position camera is looking at
target = new Vector3(); target = new Vector3();
// red voxel cursor cube // red voxel cursor cube
rollOverMesh; rollOverMesh;
objects; // loaded objects in scene
loadedChunks; objects = [];
// map of chunkId to chunk mesh
loadedChunks = new Map();
// plane object
plane; plane;
oobGeometry; oobGeometry;
oobMaterial; oobMaterial;
@ -67,8 +72,8 @@ class Renderer3D extends Renderer {
constructor(store) { constructor(store) {
super(store); super(store);
this.is3D = true; this.is3D = true;
this.loadViewFromState();
const state = store.getState(); const state = store.getState();
this.objects = [];
// camera // camera
const camera = new PerspectiveCamera( const camera = new PerspectiveCamera(
@ -212,16 +217,14 @@ class Renderer3D extends Renderer {
window.addEventListener('resize', this.onWindowResize, false); window.addEventListener('resize', this.onWindowResize, false);
this.updateCanvasData(state); this.updateCanvasData(state);
// TODO REMOVE
window.renderer = this;
} }
get view() { get view() {
return this.target.toArray(); return this.target.toArray();
} }
set view(view) {
this.target.set(...view);
}
destructor() { destructor() {
window.removeEventListener('resize', this.onWindowResize, false); window.removeEventListener('resize', this.onWindowResize, false);
this.threeRenderer.dispose(); this.threeRenderer.dispose();
@ -236,7 +239,8 @@ class Renderer3D extends Renderer {
if (view.length !== 3) { if (view.length !== 3) {
return; return;
} }
this.view = view; console.log('go to', view);
this.target.set(...view);
this.forceNextRender = true; this.forceNextRender = true;
} }
@ -252,18 +256,18 @@ class Renderer3D extends Renderer {
if (canvasId !== this.canvasId) { if (canvasId !== this.canvasId) {
this.canvasId = canvasId; this.canvasId = canvasId;
if (canvasId !== null) { if (canvasId !== null) {
if (this.chunkLoader) { // destroy old chunks,
// destroy old chunks, // meshes need to get disposed
// meshes need to get disposed if (this.loadedChunks.length) {
if (this.loadedChunks) { this.loadedChunks.forEach((chunk) => {
this.loadedChunks.forEach((chunk) => { this.scene.remove(chunk);
this.scene.remove(chunk); });
this.objects = [this.plane]; this.loadedChunks = new Map();
});
this.chunkLoader.destructor();
}
} }
this.loadedChunks = new Map(); if (this.chunkLoader) {
this.chunkLoader.destructor();
}
this.objects = [this.plane];
const { const {
palette, palette,
canvasSize, canvasSize,
@ -275,9 +279,9 @@ class Renderer3D extends Renderer {
canvasSize, canvasSize,
); );
} }
this.updateView(view);
this.forceNextRender = true;
} }
this.updateView(view);
this.forceNextRender = true;
} }
renderPixel( renderPixel(
@ -290,6 +294,7 @@ class Renderer3D extends Renderer {
if (chunkLoader) { if (chunkLoader) {
chunkLoader.getVoxelUpdate(i, j, offset, color); chunkLoader.getVoxelUpdate(i, j, offset, color);
} }
this.forceNextSubrender = true;
} }
isChunkInView(yc, xc, zc) { isChunkInView(yc, xc, zc) {
@ -304,18 +309,13 @@ class Renderer3D extends Renderer {
if (!this.chunkLoader) { if (!this.chunkLoader) {
return; return;
} }
const state = this.store.getState(); const { canvasSize } = this.store.getState().canvas;
const {
canvasSize,
view,
} = state.canvas;
const x = view[0];
const z = view[2] || 0;
const { const {
scene, scene,
loadedChunks, loadedChunks,
chunkLoader, chunkLoader,
} = this; } = this;
const { x, z } = this.target;
const [xcMin, zcMin] = getChunkOfPixel( const [xcMin, zcMin] = getChunkOfPixel(
canvasSize, canvasSize,
x - renderDistance, x - renderDistance,
@ -374,13 +374,31 @@ class Renderer3D extends Renderer {
return; return;
} }
const controlUpdate = super.render(); const controlUpdate = super.render();
if (this.forceNextRender) {
this.reloadChunks(); // check if we enter new chunk
if (controlUpdate) {
const { canvasSize } = this.store.getState().canvas;
const prevCenterChunk = this.centerChunk;
const { x, z } = this.target;
const centerChunk = getChunkOfPixel(canvasSize, x, 0, z);
if (!prevCenterChunk
|| prevCenterChunk[0] !== centerChunk[0]
|| prevCenterChunk[1] !== centerChunk[1]
) {
this.centerChunk = centerChunk;
this.forceNextRender = true;
console.log('new cc', this.centerChunk);
}
} }
if (this.forceNextRender if (this.forceNextRender
|| this.forceNextSubrender || this.forceNextSubrender
|| controlUpdate || controlUpdate
) { ) {
if (this.forceNextRender) {
this.reloadChunks();
}
if (this.forceNextRender) { if (this.forceNextRender) {
if (this.lol !== 'force') { if (this.lol !== 'force') {
console.log(this.lol, this.lola); console.log(this.lol, this.lola);
@ -421,6 +439,7 @@ class Renderer3D extends Renderer {
this.camera.aspect = window.innerWidth / window.innerHeight; this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix(); this.camera.updateProjectionMatrix();
this.threeRenderer.setSize(window.innerWidth, window.innerHeight); this.threeRenderer.setSize(window.innerWidth, window.innerHeight);
this.forceNextSubrender = true;
} }
updateRollOverMesh(sx, sy) { updateRollOverMesh(sx, sy) {