This article will explain how Three.js controls the display and hiding of objects, including the following methods:
- visible property;
- layers property.
The following will introduce the simple usage of the above methods and some differences between them through simple examples. If there are no special instructions, the following source code takes the r105
version as an example:
visible property
visible
is a property of Object3D . The object will only be rendered if visible
is true
. Object3D
35cc71852add796b75627ccd4ecf9453---的对象都可以通过该属性去控制它的显示与否,比如: Mesh
, Group
, Sprite
, Light
etc.
Take a simple example:
// 控制单个物体的显示和隐藏
const geometry = new THREE.PlaneGeometry(1, 1) // 1*1的一个平面
const planeMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 }) // 红色平面
const plane = new THREE.Mesh(geometry, planeMaterial)
plane.visible = false // 不显示单个物体
scene.add(plane)
// 控制一组物体的显示和隐藏
const geometry = new THREE.PlaneGeometry(1, 1)
const planeMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
const plane = new THREE.Mesh(geometry, planeMaterial)
const group = new THREE.Group()
group.add(plane)
group.visible = false // 不显示一组物体
scene.add(group)
As can be seen from the following example, when we want to control the display and hiding of a group of objects, we can put these objects into a Group
Group
and only control the display and Just hide it.
The code logic of this block is implemented in the --- d4308f33bb04f1f8ec6d3b3046c3bf5a projectObject
method of WebGLRenderer.js.
First, the render
method is called in the projectObject
method:
this.render = function ( scene, camera ) {
// ...
projectObject( scene, camera, 0, _this.sortObjects );
// ...
}
projectObject
The method is defined as follows:
function projectObject( object, camera, groupOrder, sortObjects ) {
if ( object.visible === false ) return; // 注释1:visible属性是false直接返回
// ...
var children = object.children; // 注释2:递归应用在children上
for ( var i = 0, l = children.length; i < l; i ++ ) {
projectObject( children[ i ], camera, groupOrder, sortObjects ); // 注释2:递归应用在children上
}
}
As can be seen from Note 1, if the Group
of visible
is false
, then it will not be called recursively on children
It can achieve the effect of controlling the display and hiding of a group of objects through Group
.
当visible
是false
的时候, Raycaster
的intersectObject
intersectObjects
Inside. The code logic of this block is in Raycaster.js :
intersectObject: function ( object, recursive, optionalTarget ) {
// ...
intersectObject( object, this, intersects, recursive ); // 注释1:调用了公共方法intersectObject
// ...
},
intersectObjects: function ( objects, recursive, optionalTarget ) {
// ...
for ( var i = 0, l = objects.length; i < l; i ++ ) {
intersectObject( objects[ i ], this, intersects, recursive ); // 注释1:循环调用了公共方法intersectObject
}
// ...
}
// 注释1:公共方法intersectObject
function intersectObject( object, raycaster, intersects, recursive ) {
if ( object.visible === false ) return; // 注释1:如果visible是false,直接return
// ...
}
As can be seen from Note 1, if Group
or a single object visible
is false
, it will not be detected.
layers property
The layers property of Object3D is a Layers object. Any object that inherits Object3D
has this property, for example Camera
. Raycaster
Although not inherited from Object3D
, it also has the layers
attribute (r113 and above).
Like the visible
property above, the --- layers
property can also control the display and hiding of objects, and the behavior of Raycaster
. An object is visible when it has at least one same layer as the camera, otherwise it is invisible. Likewise, the intersection test will only be done when the object and Raycaster
have at least one of the same layers. Here, it is emphasized that there is at least one , because Layers
can set multiple layers.
Layers
a total of 32
layers, 0
to 31
layers. Internally represented as:
layer | value (binary, 32 bits) | illustrate |
---|---|---|
0 | 00000000000000000000000000000001 | bit 32 is 1 |
1 | 00000000000000000000000000000010 | bit 31 is 1 |
2 | 00000000000000000000000000000100 | Bit 30 is 1 |
3 | 00000000000000000000000000001000 | bit 29 is 1 |
... | ... | ... |
30 | 010000000000000000000000000000000 | bit 2 is 1 |
31 | 10000000000000000000000000000000 | 1st bit is 1 |
Layers
can be set to have multiple layers at the same time:
-
Layers
的enable
disable
关闭当前层,参数是上面表格中的0
到31
. - Only the current layer can be opened by the
Layers
set
method of0
31
. - You can use the
Layers
method oftest
to determine whether twoLayers
objects have at least one common layer .
When multiple layers are turned on, it is actually the binary in the above table that performs a bitwise OR operation. For example, if the --- 0
, 2
, 31
layers are enabled at the same time , then the internally stored value is 10000000000000000000000000000101
layers
property is enabled by default only 0
layer.
Still the above example, let's see how to control the display and hide of objects:
// 控制单个物体的显示和隐藏
const geometry = new THREE.PlaneGeometry(1, 1)
const planeMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
const plane = new THREE.Mesh(geometry, planeMaterial)
plane.layers.set(1) // 设置平面只有第1层,相机默认是在第0层,所以该物体不会显示出来
scene.add(plane)
// 控制一组物体的显示和隐藏
const geometry = new THREE.PlaneGeometry(1, 1)
const planeMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
const plane = new THREE.Mesh(geometry, planeMaterial)
const group = new THREE.Group()
group.layers.set(1) // 注释1: 设置group只有第一层,相机默认是在第0层,但是此时平面物体还是显示出来了?
group.add(plane)
scene.add(group)
Set a single object layer
to see that the object is successfully not displayed. However, when we set layer
group
we found that group
of children
(plane object) is still displayed. So, what is the reason for this? Let's take a look at the source code, the same as above projectObject
method:
function projectObject( object, camera, groupOrder, sortObjects ) {
if ( object.visible === false ) return;
var visible = object.layers.test( camera.layers ); // 注释1:判断物体和相机是否存在一个公共层
if ( visible ) { // 注释1:如果存在,对物体进行下面的处理
// ...
}
var children = object.children; // 注释1:不管该物体是否和相机存在一个公共层,都会对children进行递归
for ( var i = 0, l = children.length; i < l; i ++ ) {
projectObject( children[ i ], camera, groupOrder, sortObjects );
}
}
As can be seen from the above note 1, even if the object and the camera do not have a common layer, it does not affect the children
display of the object. This also explains why group
is set to layers
above, but plane objects can still be displayed. From this point of view, the layers
and visible
properties differ in how they control how objects are shown and hidden.
Same as the visible
attribute, let's look at the effect of Layers
on Raycaster
. I also looked at the Raycaster.js file, but found that there is no layers
field at all. Later, I looked at the latest version of r140
:
function intersectObject( object, raycaster, intersects, recursive ) {
if ( object.layers.test( raycaster.layers ) ) { // 注释1:判断物体和Raycaster是否有公共层
object.raycast( raycaster, intersects );
}
if ( recursive === true ) { // 注释1:不管该物体和Raycaster是否有公共层,都不影响children
const children = object.children;
for ( let i = 0, l = children.length; i < l; i ++ ) {
intersectObject( children[ i ], raycaster, intersects, true );
}
}
}
Different from the previous, visible
and layers
can be used to control the display and hide of objects, visible
and layers
only one db7cf7af9---can be used To control the behavior of Raycaster
, which one takes effect, you can see the migration guide of Three.js .
It can be seen that from the r114
version, the visible
is abolished, and the behavior of layers
is controlled by Raycaster
:
r113 → r114
Raycaster honors now invisible 3D objects in intersection tests. Use the new property Raycaster.layers for selectively ignoring 3D objects during raycasting.
Summarize
As can be seen from the above, there are differences between visible
and layers
in controlling the display and hiding of objects, Raycaster
and so on.
When the object's visible
property is false
and the layers
property test fails, the behavior is summarized as follows:
Attributes | Whether the object is displayed | Whether the children of the object are displayed | Whether the object is raycaster tested | Whether the children of the object are tested by raycaster |
---|---|---|---|---|
visible | no | no | No (below version r114) | No (below version r114) |
layers | no | Yes | No (above version r113) | Yes |
I hope everyone has gained something, and if there are any mistakes, please leave a message for discussion.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。