屏幕空间中投影球体的半径 [英] Radius of projected sphere in screen space
本文介绍了屏幕空间中投影球体的半径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
在投影到屏幕空间后,我试图找到球体的可见大小(以像素为单位).球体以原点为中心,相机正对着它.因此,投影球体应该是二维的完美圆.我知道这个 完成的小演示.分别使用n
/f
, m
/p
和 s
/w
键对.屏幕空间中渲染的黄色线段显示了屏幕空间中球体半径的计算结果.此计算在函数 computeProjectedRadius()
中完成.
projected-sphere.js
:
"使用严格";函数计算投影半径(fovy,d,r){变量 fov;fov = fovy/2 * Math.PI/180.0;//返回 1.0/Math.tan(fov) * r/d;//错误的返回 1.0/Math.tan(fov) * r/Math.sqrt(d * d - r * r);//对}功能演示(){this.width = 0;this.height = 0;this.scene = null;this.mesh = null;this.camera = null;this.screenLine = null;this.screenScene = null;this.screenCamera = null;this.renderer = null;this.fovy = 60.0;this.d = 10.0;this.r = 1.0;this.pr = computeProjectedRadius(this.fovy, this.d, this.r);}Demo.prototype.init = function() {var 方面;无功光;var 容器;this.width = window.innerWidth;this.height = window.innerHeight;//世界场景方面 = this.width/this.height;this.camera = new THREE.PerspectiveCamera(this.fovy, aspect, 0.1, 100.0);this.scene = new THREE.Scene();this.scene.add(THREE.AmbientLight(0x1F1F1F));光 = 新 THREE.DirectionalLight(0xFFFFFF);light.position.set(1.0, 1.0, 1.0).normalize();this.scene.add(light);//屏幕场景this.screenCamera = new THREE.OrthographicCamera(-aspect, aspect,-1.0, 1.0,0.1, 100.0);this.screenScene = new THREE.Scene();this.updateScenes();this.renderer = new THREE.WebGLRenderer({抗锯齿:真});this.renderer.setSize(this.width, this.height);this.renderer.domElement.style.position = "relative";this.renderer.autoClear = false;container = document.createElement('div');container.appendChild(this.renderer.domElement);document.body.appendChild(container);}Demo.prototype.render = function() {this.renderer.clear();this.renderer.setViewport(0, 0, this.width, this.height);this.renderer.render(this.scene, this.camera);this.renderer.render(this.screenScene, this.screenCamera);}Demo.prototype.updateScenes = function() {var 几何;this.camera.fov = this.fovy;this.camera.updateProjectionMatrix();如果(this.mesh){this.scene.remove(this.mesh);}this.mesh = 新的 THREE.Mesh(新的 THREE.SphereGeometry(this.r, 16, 16),新的 THREE.MeshLambertMaterial({颜色:0xFF0000}));this.mesh.position.z = -this.d;this.scene.add(this.mesh);this.pr = computeProjectedRadius(this.fovy, this.d, this.r);如果(this.screenLine){this.screenScene.remove(this.screenLine);}几何=新三.几何();geometry.vertices.push(new THREE.Vector3(0.0, 0.0, -1.0));geometry.vertices.push(new THREE.Vector3(0.0, -this.pr, -1.0));this.screenLine = new THREE.Line(几何学,新的 THREE.LineBasicMaterial({颜色:0xFFFF00}));this.screenScene = new THREE.Scene();this.screenScene.add(this.screenLine);}Demo.prototype.onKeyDown = 函数(事件){控制台日志(事件.keyCode)开关(事件.keyCode){case 78://'n'this.d/= 1.1;this.updateScenes();休息;case 70://'f'this.d *= 1.1;this.updateScenes();休息;case 77://'m'this.r/= 1.1;this.updateScenes();休息;case 80://'p'这个.r * = 1.1;this.updateScenes();休息;case 83://'s'this.fovy/= 1.1;this.updateScenes();休息;case 87://'w'这个.fovy *= 1.1;this.updateScenes();休息;}}Demo.prototype.onResize = 函数(事件){var 方面;this.width = window.innerWidth;this.height = window.innerHeight;this.renderer.setSize(this.width, this.height);方面 = this.width/this.height;this.camera.aspect = 方面;this.camera.updateProjectionMatrix();this.screenCamera.left = -aspect;this.screenCamera.right = 方面;this.screenCamera.updateProjectionMatrix();}函数 onLoad() {无功演示;演示 = 新演示();演示.init();函数动画循环(){演示.render();window.requestAnimationFrame(animationLoop);}函数 onResizeHandler(event) {demo.onResize(事件);}函数 onKeyDownHandler(event) {demo.onKeyDown(事件);}window.addEventListener('resize', onResizeHandler, false);window.addEventListener('keydown', onKeyDownHandler, false);window.requestAnimationFrame(animationLoop);}
index.html
:
<头><title>投影球体</title><风格>身体 {背景色:#000000;}</风格><script src="http://cdnjs.cloudflare.com/ajax/libs/three.js/r61/three.min.js"></script><script src="projected-sphere.js"></script>头部><body onLoad="onLoad()"><div id="容器"></div>