pnext / three-loader

Point cloud loader for ThreeJS, based on the core parts of Potree
Other
194 stars 88 forks source link

Usage of IClipBox #128

Closed mandre96 closed 4 months ago

mandre96 commented 10 months ago

Hello, I have not been able to use the IClipBox class successfully, even though I have implemented it properly.

When I set the clipbox on the point cloud material, it clips the entire cloud.

If I set the clip mode to HIGHLIGHT_INSIDE, nothing happens either.

Is there an example that works? Is this feature fully functional?

Image of HIGHLIGHT_INSIDE not working:

https://freeimage.host/i/J9vqlUX

mandre96 commented 10 months ago

`export default class ClipBox extends THREE.Object3D {

private static _counter = 0;
private _dimension = new THREE.Vector3(1, 1, 1);
private _material:THREE.Material;
private _box:THREE.Mesh;
private _frame:THREE.LineSegments;
private _planeFrame:THREE.LineSegments;
private _clipBox: IClipBox;

public get clipBox(): IClipBox {
    return this._clipBox;
}

constructor() {
    super();
    ClipBox._counter += 1;
    this.name = "clip_volume_" + ClipBox._counter;

    //Creates Geometry
    const boxGeometry = new THREE.BoxGeometry(1, 1, 1);
    boxGeometry.computeBoundingBox();

    const boxFrameGeometry = this.generateBoxFrameGeometry();
    const planeFrameGeometry = this.generatePlaneFrameGeometry();

    this._material = new THREE.MeshBasicMaterial( {
        color: 0x00ff00, 
        transparent: true, 
        opacity: 0.3,
        depthTest: true, 
        depthWrite: false} );

    //Box Mesh
    this._box = new THREE.Mesh(boxGeometry, this._material);
    this._box.geometry.computeBoundingBox();
    this.add(this._box);

    //Box Frame
    this._frame = new THREE.LineSegments( boxFrameGeometry, new THREE.LineBasicMaterial({color: 0x000000}));
    this.add(this._frame);
    this._planeFrame = new THREE.LineSegments( planeFrameGeometry, new THREE.LineBasicMaterial({color: 0xff0000}));
    this.add(this._planeFrame);

    // set default thickness
    this.setScaleZ(0.1);

    const mat = this._box.matrix.clone();
    const inverse = mat.invert();

    this._clipBox = {box: this._box.geometry.boundingBox!, inverse:inverse , matrix:this._box.matrix, position: this.position};

    //console.log(this._clipBox);

}`

The LargeCloudManagerClass sets it

` public setClipMode(value:ClipMode) { for (let index = 0; index < this._largeScaleClouds.length; index++) { const potreeCloud = this._largeScaleClouds[index]; potreeCloud.material.clipMode = value } }

/**

Using the keyboard keys to test it on Controls class:

`else if (key == 'v') { //this._volumeTool.togglePolygonMode(); this._dunaApplication.largePointCloudManager.setClipMode(ClipMode.CLIP_OUTSIDE); } else if (key == 't') { //this._areaTool.togglePolygonMode(); this._dunaApplication.largePointCloudManager.setClipMode(ClipMode.HIGHLIGHT_INSIDE); } else if (key == 'n') { //this._dunaApplication.togglePointPickLabels(); this._dunaApplication.largePointCloudManager.setClipMode(ClipMode.CLIP_HORIZONTALLY); } else if (key == 'b') { //this._areaTool.polygonEdges = 7; this._dunaApplication.largePointCloudManager.setClipMode(ClipMode.CLIP_VERTICALLY); } else if (key == ',') { clip = new ClipBox(); clip.position.set(100, 100, 50); clip.setScaleX(100); clip.setScaleY(100); clip.setScaleZ(100); this._dunaApplication.scene.add(clip)

  this._dunaApplication.largePointCloudManager.setClipBoxes([clip.clipBox]);

}`
mandre96 commented 4 months ago

In case anyone has the same problem, after a very long time a i figured ou it was a inverse matrix error. Here is a complete class for using a scalable clipbox attached to a potree cloud. Cheers!

`import { IClipBox, PointCloudOctree } from '@pnext/three-loader'; import * as THREE from 'three'; import { TransformControls } from 'three/examples/jsm/controls/TransformControls'; import Controls from '../Controls'; import Utils from '../utils/Utils';

export default class ClipBox extends THREE.Object3D { private _pointCloud: PointCloudOctree; private _controls: Controls; private _box: THREE.Mesh; private _frame: THREE.LineSegments; private _planeFrame: THREE.LineSegments; private _transform: TransformControls;

//Events private _onChange!: (event: THREE.Event) => void; private _onDraggingChanged!: (event: THREE.Event) => void;

public get transform(): TransformControls { return this._transform; }

private _clipBox: IClipBox;

public get box(): THREE.Mesh { return this._box; }

public get clipBox(): IClipBox { return this._clipBox; }

private _material: THREE.Material;

constructor(pointCloud: PointCloudOctree, camera: THREE.Camera, renderer: THREE.Renderer, controls: Controls ) { super(); this._transform = new TransformControls(camera, renderer.domElement); this._pointCloud = pointCloud; this._controls = controls; //Creates Geometry const boxGeometry = new THREE.BoxGeometry(1, 1, 1); boxGeometry.computeBoundingBox();

this._material = new THREE.MeshBasicMaterial({
  color: 0x00fff0,
  transparent: true,
  opacity: 0.2,
  depthTest: true,
  depthWrite: false,
});

//Box Mesh
this._box = new THREE.Mesh(boxGeometry, this._material);
this._box.geometry.computeBoundingBox();
this.add(this._box);
//Create Frames
this._frame = new THREE.LineSegments(this.generateBoxFrameGeometry(), new THREE.LineBasicMaterial({ color: 0xffff00 }));
this._box.add(this._frame);
this._planeFrame = new THREE.LineSegments(this.generatePlaneFrameGeometry(), new THREE.LineBasicMaterial({ color: 0xff0000 }));
this._box.add(this._planeFrame);
//calculate point cloud total bounding box
const bbox = this.computeCloudBoundingBox();
// make a BoxGeometry of the same size as Box3
const dimensions = new THREE.Vector3().subVectors(bbox.max, bbox.min);
//Scale it
this._box.scale.set(dimensions.x, dimensions.y, dimensions.z);
this._box.updateMatrix();
const matrix = new THREE.Matrix4().setPosition(dimensions.addVectors(bbox.min, bbox.max).multiplyScalar(0.5));
this._box.applyMatrix4(matrix);
const inverse = this._box.matrix.clone().invert();
//creates the clipbox object
this._clipBox = { box: this._box.geometry.boundingBox!, inverse: inverse, matrix: this._box.matrix, position: this._box.position };

//attach transform scale control
this._transform.attach(this._box);
this._transform.setMode('scale');
this._transform.setSize(0.5);

this.add(this.transform);

//Activates event listeners
this.activateEventListeners();

//activate clipbox
this._pointCloud.material.setClipBoxes([this._clipBox]);

}

private onChange(event: THREE.Event) { this.updateClipbox(); }

private onDraggingChanged(event: THREE.Event) { this._controls.controls.enabled = !event.value; }

private activateEventListeners() { this._onChange = this.onChange.bind(this); this._onDraggingChanged = this.onDraggingChanged.bind(this);

//Updates IClipbox on Transfrom change
this._transform.addEventListener('change', this._onChange);

//Disables Controls on dragging
this._transform.addEventListener('dragging-changed', this._onDraggingChanged);

}

public dispose() { this._transform.removeEventListener('change', this._onChange); this._transform.removeEventListener('dragging-changed', this._onDraggingChanged); }

private generatePlaneFrameGeometry(): THREE.BufferGeometry { const vertices = []; const planeFrameGeometry = new THREE.BufferGeometry(); // middle line vertices.push(new THREE.Vector3(-0.5, -0.5, 0.0)); vertices.push(new THREE.Vector3(-0.5, 0.5, 0.0)); vertices.push(new THREE.Vector3(0.5, 0.5, 0.0)); vertices.push(new THREE.Vector3(0.5, -0.5, 0.0)); vertices.push(new THREE.Vector3(-0.5, 0.5, 0.0)); vertices.push(new THREE.Vector3(0.5, 0.5, 0.0)); vertices.push(new THREE.Vector3(-0.5, -0.5, 0.0)); vertices.push(new THREE.Vector3(0.5, -0.5, 0.0));

planeFrameGeometry.setFromPoints(vertices);

return planeFrameGeometry;

}

private generateBoxFrameGeometry(): THREE.BufferGeometry { const boxFrameGeometry = new THREE.BufferGeometry(); const vertices = []; // bottom vertices.push(new THREE.Vector3(-0.5, -0.5, 0.5)); vertices.push(new THREE.Vector3(0.5, -0.5, 0.5)); vertices.push(new THREE.Vector3(0.5, -0.5, 0.5)); vertices.push(new THREE.Vector3(0.5, -0.5, -0.5)); vertices.push(new THREE.Vector3(0.5, -0.5, -0.5)); vertices.push(new THREE.Vector3(-0.5, -0.5, -0.5)); vertices.push(new THREE.Vector3(-0.5, -0.5, -0.5)); vertices.push(new THREE.Vector3(-0.5, -0.5, 0.5)); // top vertices.push(new THREE.Vector3(-0.5, 0.5, 0.5)); vertices.push(new THREE.Vector3(0.5, 0.5, 0.5)); vertices.push(new THREE.Vector3(0.5, 0.5, 0.5)); vertices.push(new THREE.Vector3(0.5, 0.5, -0.5)); vertices.push(new THREE.Vector3(0.5, 0.5, -0.5)); vertices.push(new THREE.Vector3(-0.5, 0.5, -0.5)); vertices.push(new THREE.Vector3(-0.5, 0.5, -0.5)); vertices.push(new THREE.Vector3(-0.5, 0.5, 0.5)); // sides vertices.push(new THREE.Vector3(-0.5, -0.5, 0.5)); vertices.push(new THREE.Vector3(-0.5, 0.5, 0.5)); vertices.push(new THREE.Vector3(0.5, -0.5, 0.5)); vertices.push(new THREE.Vector3(0.5, 0.5, 0.5)); vertices.push(new THREE.Vector3(0.5, -0.5, -0.5)); vertices.push(new THREE.Vector3(0.5, 0.5, -0.5)); vertices.push(new THREE.Vector3(-0.5, -0.5, -0.5)); vertices.push(new THREE.Vector3(-0.5, 0.5, -0.5));

boxFrameGeometry.setFromPoints(vertices);

return boxFrameGeometry;

}

public setPosition(position: THREE.Vector3) { this._box.position.set(position.x, position.y, position.z);

this.updateClipbox();

}

public setScale(scale: THREE.Vector3) { this._box.scale.set(scale.x, scale.y, scale.z); this.updateClipbox(); }

private updateClipbox() { this._box.updateMatrix(); const inverse = this._box.matrix.clone().invert(); this._clipBox = { box: this._box.geometry.boundingBox!, inverse: inverse, matrix: this._box.matrix, position: this._box.position }; this._pointCloud.material.setClipBoxes([this._clipBox]); }

/**

}`