我如何在threejs中制作 zoom自适应 网格帮助器,既不会变得过于密集以至于不能呈现为空白,也不会变得过于稀疏而无法完全呈现为未呈现?
function addGrid({scene}) {
let gridSize = 200000;
const grid = new THREE.GridHelper( gridSize, gridSize/100, 0x000000, 0x000000 );
grid.name = 'gridHelper';
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add( grid );
}
我应该只使用控件的change
侦听器并按照此answer中的建议对一堆值进行硬编码,以便在跨越这些值时重新呈现网格帮助程序,或者有一种简洁的数学方法可以一样吗?
此外,我找不到我可以更改的任何显式属性(例如grid.divisions
),将对象移除并将其添加到场景中效率不高吗?
我该怎么做?
答案 0 :(得分:0)
我将使用相同的网格并设置比例,也许是2个网格
const gridLevel = Math.log10(zoom * zoomAdjust);
const gridFract = THREE.Math.euclideanModulo(gridLevel, 1);
const gridZoom = Math.pow(10, Math.floor(gridLevel));
grid1.scale.setScalar(gridZoom);
grid1.material.opacity = Math.max((1 - gridFract) * 1);
grid2.scale.setScalar(gridZoom * 10);
grid2.material.opacity = Math.max(gridFract * 10) - 1;
grid2.visible = grid2.material.opacity > 0;
'use strict';
/* global THREE */
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
const zoomAdjust = 5; // change to adjust when things start/end. Try 5 or .5 for example
const zoomElem = document.querySelector('#zoom');
const fov = 75;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(10, 10, 10);
camera.lookAt(0, 0, 0);
const scene = new THREE.Scene();
function makeGrid() {
const grid = new THREE.GridHelper(200, 200);
grid.material.transparent = true;
scene.add(grid);
return grid;
}
const grid2 = makeGrid();
const grid1 = makeGrid();
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
let zoom = 1;
function render() {
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
zoomElem.textContent = zoom.toFixed(4);
camera.near = zoom / 100;
camera.far = zoom * 100;
camera.updateProjectionMatrix();
camera.position.set(zoom * -10, zoom * 5, zoom * -10);
const gridLevel = Math.log10(zoom * zoomAdjust);
const gridFract = THREE.Math.euclideanModulo(gridLevel, 1);
const gridZoom = Math.pow(10, Math.floor(gridLevel));
grid1.scale.setScalar(gridZoom);
grid1.material.opacity = Math.max((1 - gridFract) * 1);
grid2.scale.setScalar(gridZoom * 10);
grid2.material.opacity = Math.max(gridFract * 10) - 1;
grid2.visible = grid2.material.opacity > 0;
renderer.render(scene, camera);
}
render();
window.addEventListener('wheel', (e) => {
e.preventDefault();
const amount = e.deltaY;
if (e.deltaY < 0) {
zoom *= 1 - THREE.Math.clamp(e.deltaY / -500, 0, 1);
} else {
zoom *= 1 + THREE.Math.clamp(e.deltaY / 500, 0, 1);
}
zoom = THREE.Math.clamp(zoom, 0.0001, 10000);
render();
}, {passive: false});
window.addEventListener('resize', render);
}
main();
body {
margin: 0;
color: white;
font-family: monospace;
}
#c {
width: 100vw;
height: 100vh;
display: block;
}
#hud {
position: absolute;
left: 1em;
top: 1em;
}
<canvas id="c"></canvas>
<div id="hud">zoom: <span id="zoom"></span></div>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>