繁体   English   中英

如何在Three.js的透视相机上创建旋转?

[英]How to create rotation on perspective camera on Three.js?

我已经在Three.js构建了一些3D-TileMap。

目前,我的PerspectiveCamera遇到问题。 我不会添加诸如“ Map rotating或“ zooming类的摄影机处理功能。 缩放始终有效,这里我仅使用field of viewmousewheel

但是,如何实现地图旋转? 当我使用camera的坐标修改xyz时 ,我误会了计算结果。

这是我目前的工作:

 function Input(renderer, camera) { var press = false var sensitivity = 0.2 renderer.domElement.addEventListener('mousemove', event => { if(!press){ return } camera.position.x += event.movementX * sensitivity camera.position.y += event.movementY * sensitivity camera.position.z += event.movementY * sensitivity / 10 }) renderer.domElement.addEventListener('mousedown', () => { press = true }) renderer.domElement.addEventListener('mouseup', () => { press = false }) renderer.domElement.addEventListener('mouseleave', () => { press = false }) renderer.domElement.addEventListener('mousewheel', event => { // Add MIN/MAX LIMITS const ratio = camera.position.y / camera.position.z camera.position.y -= (event.wheelDelta * sensitivity * ratio) camera.position.z -= (event.wheelDelta * sensitivity) camera.updateProjectionMatrix() }) } var controls; const Type = 'WebGL'; // WebGL or Canvas var _width, _height, CUBE_SIZE, GRID, TOTAL_CUBES, WALL_SIZE, HALF_WALL_SIZE, MAIN_COLOR, SECONDARY_COLOR, cubes, renderer, camera, scene, group var clock = new THREE.Clock(); clock.start(); var FOV = 45; _width = window.innerWidth _height = window.innerHeight CUBE_SIZE = 80 /* width, height */ GRID = 12 /* cols, rows */ TOTAL_CUBES = (GRID * GRID) WALL_SIZE = (GRID * CUBE_SIZE) HALF_WALL_SIZE = (WALL_SIZE / 2) MAIN_COLOR = 0xFFFFFF SECONDARY_COLOR = 0x222222 cubes = [] var directions = []; var normalized = []; switch(Type) { case 'WebGL': renderer = new THREE.WebGLRenderer({antialias: true}) break; case 'Canvas': renderer = new THREE.CanvasRenderer({antialias: true}) break; } camera = new THREE.PerspectiveCamera(FOV, (_width / _height), 0.1, 10000) scene = new THREE.Scene() group = new THREE.Object3D() /* -- -- */ setupCamera(0, 0, 800) setupBox(group) setupFloor(group) setupCubes(group) setupLights(group) group.position.y = 10 group.rotation.set(-60 * (Math.PI/180), 0, -45 * (Math.PI/180)) scene.add(group) setupRenderer(document.body) window.addEventListener('resize', resizeHandler, false) new Input(renderer, camera); /* -- -- */ function resizeHandler() { _width = window.innerWidth _height = window.innerHeight renderer.setSize(_width, _height) camera.aspect = _width / _height camera.updateProjectionMatrix() } /* -- CAMERA -- */ function setupCamera(x, y, z) { camera.position.set(x, y, z) scene.add(camera) } /* -- BOX -- */ function setupBox(parent) { var i, boxesArray, geometry, material boxesArray = [] geometry = new THREE.BoxGeometry(WALL_SIZE, WALL_SIZE, 0.05) geometry.faces[8].color.setHex(SECONDARY_COLOR) geometry.faces[9].color.setHex(SECONDARY_COLOR) geometry.colorsNeedUpdate = true material = new THREE.MeshBasicMaterial({ color : MAIN_COLOR, vertexColors : THREE.FaceColors, overdraw: 0.5 }) for (i = 0; i < 5; i++) { boxesArray.push(new THREE.Mesh(geometry, material)) } // back boxesArray[0].position.set(0, HALF_WALL_SIZE, -HALF_WALL_SIZE) boxesArray[0].rotation.x = 90 * (Math.PI/180) // right boxesArray[1].position.set(HALF_WALL_SIZE, 0, -HALF_WALL_SIZE) boxesArray[1].rotation.y = -90 * (Math.PI/180) // front boxesArray[2].position.set(0, -HALF_WALL_SIZE, -HALF_WALL_SIZE) boxesArray[2].rotation.x = -90 * (Math.PI/180) // left boxesArray[3].position.set(-HALF_WALL_SIZE, 0, -HALF_WALL_SIZE) boxesArray[3].rotation.y = 90 * (Math.PI/180) // bottom boxesArray[4].position.set(0, 0, -WALL_SIZE) boxesArray.forEach(function(box) { box.renderOrder = 1; parent.add(box) }); } /* -- FLOOR -- */ function setupFloor(parent) { var i, tilesArray, geometry, material tilesArray = [] geometry = new THREE.PlaneBufferGeometry(WALL_SIZE, WALL_SIZE) material = new THREE.MeshLambertMaterial({ color : MAIN_COLOR, overdraw: 1 }) for (i = 0; i < 8; i++) { tilesArray.push(new THREE.Mesh(geometry, material)) } tilesArray[0].position.set(-WALL_SIZE, WALL_SIZE, 0) tilesArray[1].position.set(0, WALL_SIZE, 0) tilesArray[2].position.set(WALL_SIZE, WALL_SIZE, 0) tilesArray[3].position.set(-WALL_SIZE, 0, 0) tilesArray[4].position.set(WALL_SIZE, 0, 0) tilesArray[5].position.set(-WALL_SIZE, -WALL_SIZE, 0) tilesArray[6].position.set(0, -WALL_SIZE, 0) tilesArray[7].position.set(WALL_SIZE, -WALL_SIZE, 0) tilesArray.forEach(function(tile) { tile.receiveShadow = true tile.renderOrder = 4; parent.add(tile) }) } /* -- CUBES --*/ function setupCubes(parent) { var i, geometry, material, x, y, row, col geometry = new THREE.BoxGeometry(CUBE_SIZE, CUBE_SIZE, 0.05) material = new THREE.MeshPhongMaterial( { map: new THREE.TextureLoader().load('http://ak.game-socket.de/assets/grass.png'), normalMap: new THREE.TextureLoader().load('http://ak.game-socket.de/assets/paper_low_nmap.png'), overdraw: 1, depthTest: true, depthWrite: true } ); x = 0 y = 0 row = 0 col = 0 for (i = 0; i < TOTAL_CUBES; i++) { cubes.push(new THREE.Mesh(geometry, material)) if ((i % GRID) === 0) { col = 1 row++ } else col++ x = -(((GRID * CUBE_SIZE) / 2) - ((CUBE_SIZE) * col) + (CUBE_SIZE/2)) y = -(((GRID * CUBE_SIZE) / 2) - ((CUBE_SIZE) * row) + (CUBE_SIZE/2)) cubes[i].position.set(x, y, 0) } cubes.forEach(function(cube, index) { if(index % 2 == 0) { directions[index] = -1; normalized[index] = false; } else { directions[index] = 1; normalized[index] = true; } cube.castShadow = true cube.receiveShadow = true cube.rotation.x = 0; cube.renderOrder = 3; cube.doubleSide = true; parent.add(cube) }) } /* -- LIGHTS -- */ function setupLights(parent) { var light, soft_light light = new THREE.DirectionalLight(MAIN_COLOR, 1.25) soft_light = new THREE.DirectionalLight(MAIN_COLOR, 1.5) light.position.set(-WALL_SIZE, -WALL_SIZE, CUBE_SIZE * GRID) light.castShadow = true soft_light.position.set(WALL_SIZE, WALL_SIZE, CUBE_SIZE * GRID) parent.add(light).add(soft_light) } /* -- RENDERER -- */ function setupRenderer(parent) { renderer.setSize(_width, _height) renderer.setClearColor(MAIN_COLOR, 1.0); parent.appendChild(renderer.domElement) } var speed = 0.003; var reach = 40; function render() { var delta = clock.getDelta(); requestAnimationFrame(render); cubes.forEach(function(cube, index) { cube.castShadow = true cube.receiveShadow = true if(directions[index] >= 1) { ++directions[index]; if(directions[index] >= reach) { directions[index] = -1 } cube.rotation.x += speed; } else if(directions[index] <= -1) { --directions[index]; if(directions[index] <= -reach) { directions[index] = 1 } cube.rotation.x -= speed; } }); renderer.render(scene, camera) } render(); 
 html, body, canvas { padding: 0; margin: 0; width: 100%; height: 100%; display: block; } 
 <script src="https://rawcdn.githack.com/mrdoob/three.js/dev/build/three.min.js"></script> <script src="https://rawcdn.githack.com/mrdoob/three.js/dev/examples/js/renderers/CanvasRenderer.js"></script> <script src="https://rawcdn.githack.com/mrdoob/three.js/dev/examples/js/renderers/Projector.js"></script> <script src="https://rawcdn.githack.com/mrdoob/three.js/dev/examples/js/controls/TrackballControls.js"></script> <script src="https://rawcdn.githack.com/mrdoob/three.js/dev/examples/js/shaders/ParallaxShader.js"></script> 

通过选项,我不希望旋转/缩放达到地图的末端-例如,用户无法在地图下查看。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM