# Trimming point cloud with BoxGeometry as reference

**URL:** <https://discourse.threejs.org/t/trimming-point-cloud-with-boxgeometry-as-reference/58952>\
**Category:** Questions\
**Tags:** pointcloud\
**Created:** [December 6, 2023, 11:22am UTC](https://discourse.threejs.org/t/trimming-point-cloud-with-boxgeometry-as-reference/58952 "2023-12-06T11:22:50Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![kraff](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/kraff/32/40778_2.png) [@kraff](https://discourse.threejs.org/u/kraff)\
**Post date:** [December 6, 2023, 11:22am UTC](https://discourse.threejs.org/t/trimming-point-cloud-with-boxgeometry-as-reference/58952/1 "2023-12-06T11:22:50Z")

</div>

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.

```javascript
  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.

---

<div class="post-metadata">

**Author:** ![prisoner849](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prisoner849/32/535_2.png) [@prisoner849](https://discourse.threejs.org/u/prisoner849)\
**Post date:** [December 6, 2023, 1:11pm UTC](https://discourse.threejs.org/t/trimming-point-cloud-with-boxgeometry-as-reference/58952/2 "2023-12-06T13:11:19Z")

</div>

You can modify PointsMaterial and pass information about boxes in uniforms, or in DataTexture - creativity is up to you.

non-modified PointsMaterial:

 ![изображение](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/1/c/1ccea92ae3ea7e50c6066250fa34d2c07c37f389.png)

modified PointsMaterial:  
change color, if a point is inside a box

 ![изображение](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/f/1/f1479bca83856f99ce9a02726ddf5bc3e4afd750.png)

trimmed by boxes

 ![изображение](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/6/c/6c147f3c5097e86fd7230e6c183f8d85db1abb74.png)

---

<div class="post-metadata">

**Author:** ![kraff](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/kraff/32/40778_2.png) [@kraff](https://discourse.threejs.org/u/kraff)\
**Post date:** [December 18, 2023, 9:00am UTC](https://discourse.threejs.org/t/trimming-point-cloud-with-boxgeometry-as-reference/58952/3 "2023-12-18T09:00:24Z")

</div>

@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.

 ![Screenshot 2023-12-18 170123](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/5/1/510c495e267fafa5d6a42389547beff52eb77616.jpeg)  
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`**

```javascript
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 );'
  )

```

```javascript
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,
  }
}

```

---

<div class="post-metadata">

**Author:** ![prisoner849](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prisoner849/32/535_2.png) [@prisoner849](https://discourse.threejs.org/u/prisoner849)\
**Post date:** [December 18, 2023, 9:26am UTC](https://discourse.threejs.org/t/trimming-point-cloud-with-boxgeometry-as-reference/58952/4 "2023-12-18T09:26:28Z")

</div>

Maybe I overlooked something 🤔  
Do you apply matrices to box helpers somewhere in your code?

---

<div class="post-metadata">

**Author:** ![kraff](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/kraff/32/40778_2.png) [@kraff](https://discourse.threejs.org/u/kraff)\
**Post date:** [December 18, 2023, 10:50am UTC](https://discourse.threejs.org/t/trimming-point-cloud-with-boxgeometry-as-reference/58952/5 "2023-12-18T10:50:41Z")

</div>

It’s basically the same thing, except with the non-inverted modelMatrix being applied on the box3.

```javascript
const { center, rotation, extent } = cuboid

const modelMatrix = new Matrix4().compose(
  new Vector3(...center),
  new Quaternion().setFromRotationMatrix(new Matrix4().setFromMatrix3(new Matrix3().fromArray(rotation))),
  new Vector3(1, 1, 1)
)

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)
).applyMatrix4(modelMatrix)

```

---

<div class="post-metadata">

**Author:** ![prisoner849](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prisoner849/32/535_2.png) [@prisoner849](https://discourse.threejs.org/u/prisoner849)\
**Post date:** [December 18, 2023, 7:29pm UTC](https://discourse.threejs.org/t/trimming-point-cloud-with-boxgeometry-as-reference/58952/6 "2023-12-18T19:29:09Z")

</div>

`.applyMatrix4()` on `Box3` will give you another AABB.  
That’s how it works under the hood: [three.js/src/math/Box3.js at 09fe0527a9aa5aaca7aaf17531e6c0d0efaa8c59 · mrdoob/three.js · GitHub](https://github.com/mrdoob/three.js/blob/09fe0527a9aa5aaca7aaf17531e6c0d0efaa8c59/src/math/Box3.js#L438L457)

---

<div class="post-metadata">

**Author:** ![prisoner849](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/prisoner849/32/535_2.png) [@prisoner849](https://discourse.threejs.org/u/prisoner849)\
**Post date:** [December 18, 2023, 7:38pm UTC](https://discourse.threejs.org/t/trimming-point-cloud-with-boxgeometry-as-reference/58952/7 "2023-12-18T19:38:35Z")

</div>

You need to apply that matrix to `Box3Helper`, something like this: [Edit fiddle - JSFiddle - Code Playground](https://jsfiddle.net/prisoner849/mwdr9eqs/)
