I am using PCDLoader to load my pointcloud. I also have several meshes with BoxGeometry to be used as reference on trimming the pointcloud. Specifically any points outside the Box needs to be removed. I’ve used clippingPlanes for 1 cuboid but I don’t think it’ll work with multiple cuboids, or at least I could not get it to work.
Following is what I used for single cuboid.
const [vertex0, vertex1, vertex2, vertex3, vertex4, vertex5, vertex6] = getVerticesFromCuboid(editingCuboid)
const plane1 = new Plane().setFromCoplanarPoints(vertex2, vertex1, vertex0)
const plane2 = new Plane().setFromCoplanarPoints(vertex0, vertex1, vertex4)
const plane3 = new Plane().setFromCoplanarPoints(vertex1, vertex2, vertex5)
const plane4 = new Plane().setFromCoplanarPoints(vertex2, vertex3, vertex6)
const plane5 = new Plane().setFromCoplanarPoints(vertex4, vertex3, vertex0)
const plane6 = new Plane().setFromCoplanarPoints(vertex4, vertex5, vertex6)
material.clippingPlanes = [plane1, plane2, plane3, plane4, plane5, plane6]
Any tips on how to get it working with multiple cuboids? Preferably non-destructive (opacity 0 the outer points?) since the cuboids can be modified.
@prisoner849 Thanks for the pointers! I managed to get it working with uniforms and shaders but for some reason the rotation is a little off and I couldn’t figure out why.
The yellow lines is the mask rendered with box3helper and as you can see each of them is slightly rotated from the actual box. The box is correct but the affected points are not.
Some pointers on why this is happening would be grateful!
onBeforeCompile
const uniformsData = maskRegions.filter((region) => !region.invisible).map(generateCuboidUniforms)
const uniforms = {
maskRegion: { value: uniformsData },
}
shader.uniforms = { ...(shader.uniforms || {}), ...uniforms }
shader.vertexShader = shader.vertexShader.replace(
`void main() {`,
`
varying vec4 fragPosition;
void main() {
fragPosition = modelMatrix * vec4(position, 1.0);
`
)
shader.fragmentShader = shader.fragmentShader
.replace(
`void main() {`,
`
struct Region {
mat4 modelMatrix;
vec3 min;
vec3 max;
};
uniform Region maskRegion[${uniformsData.length}];
varying vec4 fragPosition;
bool checkWithin(Region region)
{
// we need fragment position localized to the mask region
vec4 localPos = region.modelMatrix * fragPosition;
// Check if the fragment is inside the cube in its local space
return all(greaterThanEqual(localPos.xyz, region.min)) && all(lessThanEqual(localPos.xyz, region.max));
}
void main() {
bool toDiscard = ${shouldNotDiscard ? 'false' : 'true'};
float defaultOpacity = opacity;
float updatedOpacity = ${shouldNotDiscard ? '0.05' : '0.0'};
for(int i=0; i<${uniformsData.length}; i++)
{
if (checkWithin(maskRegion[i]))
{
updatedOpacity = defaultOpacity;
toDiscard = false;
}
}
if (toDiscard) {
discard;
return;
}
`
)
.replace(
'vec4 diffuseColor = vec4( diffuse, opacity );',
'vec4 diffuseColor = vec4( diffuse, updatedOpacity );'
)
export const generateCuboidUniforms = (cuboid: Cuboid) => {
const { center, rotation, extent } = cuboid
const boundingBox = new Box3(
new Vector3(-extent[0] / 2, -extent[1] / 2, -extent[2] / 2),
new Vector3(extent[0] / 2, extent[1] / 2, extent[2] / 2)
)
// Calculate the model matrix
const modelMatrix = new Matrix4()
modelMatrix
.compose(
new Vector3(...center),
new Quaternion().setFromRotationMatrix(new Matrix4().setFromMatrix3(new Matrix3().fromArray(rotation))),
new Vector3(1, 1, 1)
)
.invert()
return {
modelMatrix,
min: boundingBox.min,
max: boundingBox.max,
}
}