我使用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>
答案 0 :(得分:19)
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