I have many views that I'm trying to extrude and then intersect in order to create a final polygon. The problem is that the result is not the expected, it has some floating extra parts. I need to correct this somehow, even if the solution is a method to detect these floating extra parts and erase them.
I'm using this library https://www.npmjs.com/package/three-csg-ts/v/3.1.10 to make the binary operation of intersection.
I dont know if it is a bug or if I'm doing something wrong. I've tried so many different configurations for the extrude settings but I still have the same problem.
I don't have much experience with js or ThreeJS, so I'm sorry if my code is not that readable, I've tried my best.
import './style.css'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { CSG } from 'three-csg-ts'
// Canvas
const canvas = document.querySelector('canvas.webgl')
/**
* Sizes
*/
const sizes = {
width: 1677,
height: 1287
}
// Scene
const scene = new THREE.Scene()
// View Points
const view_1 = [1019, 516, 1005, 502, 968, 481, 944, 482, 911, 492, 902, 505, 892, 510, 879, 522, 880, 595, 889, 612, 899, 619, 941, 621, 998, 620, 1011, 615, 1018, 599, 1017, 594, 1022, 575, 1023, 541]
const view_2 = [874.9, 221, 878.4, 274.3, 888.2, 296.3, 893.9, 306.1, 902.5, 320.9, 916.5, 327.1, 937.6, 337.1, 960, 329.6, 973.8, 323.1, 983.5, 314.6, 994.3, 307.3, 1008.4, 297.5, 1018, 271, 1019, 253, 1019.1, 239.5, 1006.5, 230, 996.6, 225.2, 987.8, 218.9, 958.8, 204.1, 939.5, 198.9, 892.7, 203.7]
const view_3 = [1002, 867, 985.9, 885.3, 984.7, 918.4, 986.7, 931, 994.9, 941.1, 1001.2, 957.6, 1015, 970.1, 1028.9, 980.9, 1046, 982.2, 1061.3, 980.9, 1077.6, 968.8, 1100.4, 945.5, 1103.4, 900.7, 1093.1, 879.7, 1077.1, 864, 1064.4, 855.6, 1053, 856.9, 1046, 853.7, 1025.7, 856.9, 1012, 859.4]
const view_4 = [619, 648, 592, 681, 597, 702, 607, 719.3, 624.5, 725.9, 646.2, 731.7, 658.2, 735.7, 669.3, 739.3, 680, 742.3, 690.3, 737.5, 697.1, 726.6, 690.1, 711.5, 686, 706, 683, 694, 683, 682, 674, 663, 668, 660, 659, 649, 650, 647, 644, 642, 629, 643]
const view_5 = [1282, 499, 1261, 504, 1256, 509, 1255.7, 508.2, 1251.4, 509.9, 1240, 515.5, 1227.7, 527.7, 1212.2, 587.7, 1210.9, 609, 1213.9, 615.8, 1216, 617.8, 1219.7, 623.3, 1226, 628.6, 1259.3, 625.1, 1267, 615, 1280, 561]
const views = [view_1,view_2,view_3, view_4, view_5]
//Split array in pairs
function chunk(arr, size) {
return Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
arr.slice(i * size, i * size + size))
}
//Shape constructor and extruder
const extrudeSettings = {
steps: 8,
depth: 600,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 0,
bevelOffset: 0,
bevelSegments: 1
};
var degree = 0
var pos = 0
var meshes = []
for(let view in views){
var point_list = []
var pair_array = chunk(views[view],2) //separate in pairs
for (let pair in pair_array){
point_list.push(new THREE.Vector2(-pair_array[pair][0]+sizes.width/2,-pair_array[pair][1]+sizes.height/2)) //creating vectors
}
console.log(point_list)
var shape = new THREE.Shape(point_list); //constructing the Shape
extrudeSettings.depth = 600
var shapeGeom = new THREE.ExtrudeGeometry( shape, extrudeSettings ); //Extruding the shape
//position transformations
shapeGeom.rotateX(Math.PI * 0.5);
shapeGeom.rotateZ(THREE.MathUtils.degToRad(degree));
degree += 45
const shapeMat = new THREE.MeshPhongMaterial({color: "aqua"});
shapeMat.side = THREE.DoubleSide
var shapeMesh = new THREE.Mesh(shapeGeom, shapeMat);
//more position transformations
shapeMesh.geometry.computeBoundingBox();
var boundingBox = new THREE.Box3();
boundingBox.copy( shapeMesh.geometry.boundingBox );
shapeMesh.updateMatrixWorld( true ); // ensure world matrix is up to date
boundingBox.applyMatrix4( shapeMesh.matrixWorld );
shapeMesh.position.x = shapeMesh.position.x - (boundingBox.min.x + boundingBox.max.x)/2
shapeMesh.position.y = shapeMesh.position.y - (boundingBox.min.y + boundingBox.max.y)/2
shapeMesh.position.z = shapeMesh.position.z - (boundingBox.min.z + boundingBox.max.z)/2
//adding to the scene
shapeMesh.updateMatrix()
meshes.push(shapeMesh)
scene.add(shapeMesh); //comment if doesn't want to show the extruded shapes, but only the final result
}
//Intersection
var intersection = meshes[0]
for (let mesh in meshes){
meshes[mesh].updateMatrix()
intersection = CSG.intersect(intersection,meshes[mesh])
}
intersection.material = new THREE.MeshNormalMaterial()
scene.add(intersection)
// Lights
scene.add( new THREE.HemisphereLight(0xffffbb,0x080820,2) );
/**
* Camera
*/
// Base camera
const camera = new THREE.OrthographicCamera( sizes.width / - 2, sizes.width / 2, sizes.height / 2, sizes.height / - 2, 0.1, 3000 );
camera.position.set( 0, 800, 0 );
camera.up = new THREE.Vector3( 0, 0, 1 );
scene.add(camera)
var camera_pivot = new THREE.Object3D()
scene.add( camera_pivot );
camera.lookAt( camera_pivot.position );
// Controls
const controls = new OrbitControls(camera, canvas)
controls.enableDamping = true
/**
* Renderer
*/
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
preserveDrawingBuffer: true
})
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
/**
* Animate
*/
const clock = new THREE.Clock()
const tick = () =>
{
const elapsedTime = clock.getElapsedTime()
// Update Orbital Controls
controls.update()
// Render
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
tick()
Here are some screenshots to ilustrate the problem:
I really think that the problem might be in the extrusion method I'm using, but I don't understand how it should be done to work properly. Or perhaps it's the way i'm trying to do the intersection, one by one intersecting with the previous result. I've tried to do it two objects by time and then intersect two intersection results, but with no progress.