如何在three.js场景中使对象仅对一台摄像机可见
Posted
技术标签:
【中文标题】如何在three.js场景中使对象仅对一台摄像机可见【英文标题】:How to make objects visible to only one camera in a three.js scene 【发布时间】:2016-03-10 01:30:29 【问题描述】:我使用 three.js 为 3D 场景创建了一个嵌入轨迹球相机控制器。目前,这使用了一个小立方体、一个圆圈和一个放置在世界原点的正交相机。但是,这三个对象在场景本身中仍然可见,如通过主摄像机查看的那样。 (在下面的演示代码中,我特意将立方体设置为 10x10x10,以便清晰可见,但可以做得更小。)
此外,作为主场景一部分的元素通过原点在插图中可见。例如:插图中可以看到属于主场景的AxisHelper。
是否可以在 three.js/webgl 中使某些对象仅对某些摄像机可见?
如果不是,那么一种解决方法是将跟踪球功能所需的对象放置在主摄像头无法看到的深空,但如果可能的话,我更喜欢更纯粹的解决方案。
演示:http://codepen.io/anon/pen/MKWrOr
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.js"></script>
<style>
body
margin: 0;
overflow: hidden;
</style>
</head>
<body>
<div id="WebGL-output"></div>
<script>
function init()
var scene = new THREE.Scene()
var renderer = new THREE.WebGLRenderer()
var camera
var cameras = []
var WIDTH = window.innerWidth
var HEIGHT = window.innerHeight
;(function createPerspectiveCamera()
var FOV = 45
var ASPECT = WIDTH / HEIGHT
var NEAR = 1
var FAR = 360
camera = new THREE.PerspectiveCamera(FOV, ASPECT, NEAR, FAR)
camera.position.x = 100
camera.position.y = 100
camera.position.z = 100
camera.viewport = x: 0, y: 0, width: WIDTH, height: HEIGHT
camera.lookAt(scene.position)
cameras.push(camera)
)()
;(function initializeRenderer()
renderer.setClearColor(new THREE.Color(0xEEEEFF))
renderer.setSize(WIDTH, HEIGHT)
renderer.autoClear = false;
document.getElementById("WebGL-output").appendChild(renderer.domElement)
;(function render()
var viewport
renderer.setViewport( 0, 0, WIDTH, HEIGHT );
renderer.clear();
cameras.forEach(function (camera)
viewport = camera.viewport // custom property
renderer.setViewport(
viewport.x
, viewport.y
, viewport.width
, viewport.height
)
renderer.render(scene, camera)
)
requestAnimationFrame(render)
)()
)()
;(function createCameraController()
var viewport =
x: WIDTH - 100
, y: HEIGHT - 100
, width: 100
, height: 100
var circle =
x: WIDTH - 50
, y: 50
, radius: 50
var settings =
viewport: viewport
, circle: circle
addCameraController(scene, camera, cameras, settings)
)()
// Something to look at
scene.add(new THREE.AxisHelper(70))
function addCameraController(scene, camera, cameras, settings)
var controlCamera
var viewport = settings.viewport
// For mouse interactions
var centreX = settings.circle.x
var centreY = settings.circle.y
var radius = settings.circle.radius
var radius2 = radius * radius
var rotationMatrix = new THREE.Matrix4()
var pivotMatrix = new THREE.Matrix4()
var startMatrix = new THREE.Matrix4()
var start = new THREE.Vector3()
var end = new THREE.Vector3()
var angle
camera.matrixAutoUpdate = false /** takes control of main camera **/
;(function createControlCameraCubeAndCircle()
var side = 10
var radius = Math.sqrt(side/2 * side/2 * 3)
;(function createCamera()
controlCamera = new THREE.OrthographicCamera(
-radius, radius
, radius, -radius
, -radius, radius
);
controlCamera.viewport = viewport
controlCamera.rotation.copy(camera.rotation)
// If matrixAutoUpdate is set immediately, the camera rotation is
// not applied
setTimeout(function ()
controlCamera.matrixAutoUpdate = false
, 1)
scene.add(controlCamera)
cameras.push( controlCamera )
)()
;(function createCompanionCube()
var cube = new THREE.Object3D()
var cubeGeometry = new THREE.BoxGeometry( side, side, side )
var lineMaterial = new THREE.LineBasicMaterial(
color: 0xffffff
, transparent: true
, opacity: 0.5
)
var faceMaterial = new THREE.MeshPhongMaterial(
color: 0x006699
, emissive: 0x006699
, shading: THREE.FlatShading
, transparent: true
, opacity: 0.2
)
cube.add(
new THREE.LineSegments(
new THREE.WireframeGeometry( cubeGeometry )
, lineMaterial
)
)
cube.add(
new THREE.Mesh(
cubeGeometry
, faceMaterial
)
)
// cube.add(new THREE.AxisHelper(radius))
scene.add(cube);
)()
;(function createCircle()
var circleGeometry = new THREE.CircleGeometry( radius, 36 );
var material = new THREE.MeshBasicMaterial(
color: 0xccccff
);
var circle = new THREE.Mesh( circleGeometry, material );
controlCamera.add( circle );
circle.translateZ(-radius)
)()
)()
window.addEventListener("mousedown", startDrag, false)
function startDrag(event)
var x = event.clientX - centreX
var y = centreY - event.clientY
var delta2 = x * x + y * y
if (delta2 > radius2)
return
var z = Math.sqrt(radius2 - delta2)
start.set(x, y, z)
window.addEventListener("mousemove", drag, false)
window.addEventListener("mouseup", stopDrag, false)
function drag(event)
var delta
x = event.clientX - centreX
y = centreY - event.clientY
delta2 = x * x + y * y
if (delta2 > radius2)
// constrain to adge of sphere
delta = Math.sqrt(delta2)
x = x / delta * radius
y = y / delta * radius
z = 0
else
z = Math.sqrt(radius2 - delta2)
end.set(x, y, z)
angle = start.angleTo(end)
start.cross(end).normalize()
rotationMatrix.makeRotationAxis(start, -angle)
controlCamera.matrix.multiply(rotationMatrix)
controlCamera.matrixWorldNeedsUpdate = true
rotationMatrix.extractRotation(camera.matrixWorld)
start.applyMatrix4(rotationMatrix).normalize()
rotationMatrix.makeRotationAxis(start, -angle)
camera.applyMatrix(rotationMatrix)
camera.matrixWorldNeedsUpdate = true
start.copy(end)
function stopDrag(event)
window.removeEventListener("mousemove", drag, false)
window.removeEventListener("mouseup", stopDrag, false)
window.onload = init
</script>
</body>
</html>
【问题讨论】:
相关帖子:***.com/questions/16226693/…. 【参考方案1】:three.js 支持图层。
如果对象和相机共享一个公共层,则该对象对相机可见。默认情况下,相机和所有对象都在第 0 层。
例如,
camera.layers.enable( 1 ); // camera now sees default layer 0 and layer 1
camera.layers.set( 1 ); // camera now sees only layer 1
mesh.layers.set( 1 ); // mesh is in layer 1
three.js r.75
【讨论】:
请记住在用户帮助您时接受答案。谢谢。以上是关于如何在three.js场景中使对象仅对一台摄像机可见的主要内容,如果未能解决你的问题,请参考以下文章
如何将fbxloader加载的摄像头添加到three.js中的场景?