Greetings!
I’m new in this field but I managed to implement three.js for an online ply viewer tool. But I am stuck with one problem and couldn’t find a proper solution for this issue:
I load and display a ply file. Then I create an additional box geometry which works as a selection cube. I just want to show all the points of the ply inside the box and set the opacity of the outer points of the ply point cloud to 0 with the option to switch it back on. The filtering for the points outside the selection box is not that complicated but I struggling with the concept to change the visibility of specific points.
Which geometry is the best to choose in this context? After some research, I found some approaches which used BufferGeometry because of the multiple attributes.
So what would do the trick? Looping over the positions and of the geometry and searching for the points which xyz are outside the selection box. But how do I change their visibility? And how do I reverse it?
Thanks!!
Cheers!
Stefan
I’d use THREE.ShaderMaterial()
for points.
You pass in the shader the parameters of the selection box (position and size, for example) and check, if a point inside the box. If not, then call discard
.
An SO thread about the size of points: https://stackoverflow.com/a/30548534/4045502
https://jsfiddle.net/prisoner849/fkcazcaL/
var pointsMaterial;
var loader = new THREE.PLYLoader();
loader.load('https://threejs.org/examples/models/ply/binary/Lucy100k.ply', function(geometry) {
geometry.computeVertexNormals();
var material = new THREE.MeshStandardMaterial({
color: 0x0099ff,
flatShading: true,
});
var mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add(mesh);
pointsMaterial = new THREE.ShaderMaterial({
uniforms: {
diffuse: {
value: new THREE.Color("aqua")
},
size:{
value: 5
},
scale: {
value: window.innerHeight / 2.0
},
boxPosition: {
value: new THREE.Vector3(0, 0, 0)
},
boxSize: {
value: new THREE.Vector3(1000, 200, 400)
}
},
vertexShader: `
uniform float scale;
uniform float size;
varying vec3 vPosition;
void main() {
vPosition = position;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size * ( scale / length( mvPosition.xyz ) );
gl_Position = projectionMatrix * mvPosition;
}
`,
fragmentShader: `
uniform vec3 diffuse;
uniform vec3 boxPosition;
uniform vec3 boxSize;
varying vec3 vPosition;
void main() {
vec3 halfSize = boxSize * 0.5;
vec3 absLocalPosition = abs(boxPosition - vPosition);
if(absLocalPosition.x > halfSize.x || absLocalPosition.y > halfSize.y || absLocalPosition.z > halfSize.z) {discard;}
gl_FragColor = vec4( diffuse, 1.0 );
}
`
})
var points = new THREE.Points(geometry, pointsMaterial);
scene.add(points);
render();
});
And the render()
function:
function render() {
requestAnimationFrame(render);
pointsMaterial.uniforms.boxPosition.value.y = Math.sin(Date.now() * 0.001) * 600;
renderer.render(scene, camera);
}
1 Like
AWESOME!!!
Thanks a lot! I gonna try that out. Looks very promising!
Cheers
Ok. I worked my way through. One (hopefully) last problem:
After I changed the boxPosition and the boxSize I rendered the scene but the changes were not applied.
Do I have to set a “needsUpdate” to the BufferGeometry or am I missing something completely different? In your example it is not necessary, but as far as I understood this need for update is exists (only?) for Buffergeometries.
Thanks!
Cheers
Stefan
Hi!
Is there any live example of what you’re doing? Or a link to the web site with your project?
Hi!
Found my error. Forgot to set the the parameter “.value” when I wanted to change the uniforms. Now it works like a charm! Thanks a lot!!!
1 Like