三js CSG问题与挤压形状相交
我有很多意见,我试图挤出然后相交以创建最终的多边形。问题在于结果不是预期的,它具有一些浮动的零件。即使解决方案是检测这些漂浮的额外零件并擦除它们的方法,我也需要以某种方式纠正此问题。
我正在使用此库 https://www.npmjs.com /package/three-csg-ts/v/3.1.10 进行交集的二进制操作。
我不知道这是否是错误,还是我做错了什么。我在挤出设置中尝试了许多不同的配置,但是我仍然有同样的问题。
我对JS或三J的经验不多,所以很抱歉,如果我的代码不那么可读,我已经尽力了。
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()
以下是一些屏幕截图,可以解决问题:
sstatic.net/yzbi9.png“ alt =“挤压形状的交叉”>
我真的认为问题可能是在我使用的挤出方法中,但是我不明白该如何完成正常工作。也许这是我试图进行十字路口的方式,与先前的结果相交。我试图按时间进行两个对象,然后相交两个相交结果,但没有进展。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,在使用您的代码一段时间后,我认为我的结果是正确的。
正如您猜到的那样,问题在于交叉点:
这里有问题。如果我已经正确理解了,
老实说,我不确定问题是什么,也许是您将第一个Intersectee设置为网眼[0],然后将整个网格阵列循环,与自己至少相交。当我添加
时,如果(网格[mesh] .geometry.uuid ===网格[0]。geometry.uuid)继续;
进入循环,似乎已经工作得很好,但是我会' T将其作为解决方案。我建议的解决方案是将代码的整个相交部分替换为:
首先,我用功能更大的 foreach -prause替换了循环以更新矩阵。
第二,我使用 csg.Intersect 都立即使用网格数组中的所有网格。
这会导致这样的形状:
。
PS感谢您的有趣交叉代码!我只涉足了三分,并阅读了有关CSG的文章,所以两者都玩起来真的很有趣。 这是我的codesandbox 。
Well, after playing around with your code for a while, I think my result is correct.
As you guessed, the problem lies here in the intersection part:
There is something wrong here. If I have understood correctly, by the associative property of logical intersection of sets, it shouldn't matter if you do the intesection mesh by mesh (someone correct me if I'm wrong), so the problem isn't that.
To be honest, I'm not sure what the issue is, maybe it's that you set your first intersectee as mesh[0] and then loop the whole mesh array, intersecting at least one shape with itself. When I added
if(meshes[mesh].geometry.uuid === meshes[0].geometry.uuid) continue;
into the loop, that seemed to work pretty nicely already, but I wouldn't propose that as a solution.The solution I'm proposing is to replace that whole intersection part of the code with:
First, I replaced the loop with a more functional
forEach
-clause to update the matrices.Second, I used spread syntax to call
CSG.intersect
with all of the meshes in the mesh array at once.This results in a shape like this:
I am not 100% sure if that is the correct result of intersecting so many polygons, but it looks relatively clean and doesn't have any extra floating parts like in your example.
P.S Thanks for the fun intersection code! I have only dabbled with Three.js and read about CSG, so it was really fun to play around with both. Here is my codesandbox.