Unexpected Result Using Threecsg
I'm experimenting with the ThreeCSG library and am attempting to swap out the sphere or normal geometry for a custom made Shape, in this case the heart shape from the 3js examples.
Solution 1:
ThreeCSG cannot subtract a concave mesh correctly. But there is a workaround, since both halves of a heart or convex.
You can subtract the right half of the heart from a cuboid:
functiongetHeartShapeRight() {
var x = 5, y = 10;
var heartShape = newTHREE.Shape();
heartShape.moveTo(x - 5, y - 5);
heartShape.bezierCurveTo(x - 5, y - 5, x - 4, y, x, y);
heartShape.bezierCurveTo(x + 6, y, x + 6, y - 7, x + 6, y - 7);
heartShape.bezierCurveTo(x + 6, y - 11, x + 3, y - 15.4, x - 5, y - 19);
return heartShape;
}
// right cuboidvar cubeGeoR = newTHREE.CubeGeometry(125, 250, 250);
var cubeMeshR = newTHREE.Mesh(cubeGeoR);
cubeMeshR.position.x += 62.5;
var cubeBSPR = newThreeBSP(cubeMeshR);
// right part of the heartvar heartShapeR = getHeartShapeRight();
var heartGeoR = getHeartGeometry(heartShapeR);
var meshToCutR = newTHREE.Mesh( heartGeoR );
meshToCutR.scale.set(10,10,10);
meshToCutR.position.z -= 80;
// right subtractvar meshToCutBspR = newThreeBSP(meshToCutR);
var resultBspR = cubeBSPR.subtract(meshToCutBspR);
var resultMeshR = resultBspR.toMesh(newTHREE.MeshLambertMaterial({flatShading: true}));
And you can subtract the left half of the heart from a cuboid:
functiongetHeartShapeLeft() {
var x = 5, y = 10;
var heartShape = newTHREE.Shape();
heartShape.moveTo(x - 5, y - 19);
heartShape.bezierCurveTo(x - 12, y - 15.4, x - 16, y - 11, x - 16, y - 7);
heartShape.bezierCurveTo(x - 16, y - 7, x - 16, y, x - 10, y);
heartShape.bezierCurveTo(x - 7, y, x - 5, y - 5, x - 5, y - 5);
return heartShape;
}
// left cuboidvar cubeGeoL = newTHREE.CubeGeometry(125, 250, 250);
var cubeMeshL = newTHREE.Mesh(cubeGeoL);
cubeMeshL.position.x -= 62.5;
var cubeBSPL = newThreeBSP(cubeMeshL);
// left part of the heartvar heartShapeL = getHeartShapeLeft();
var heartGeoL = getHeartGeometry(heartShapeL);
var meshToCutL = newTHREE.Mesh( heartGeoL );
meshToCutL.scale.set(10,10,10);
meshToCutL.position.z -= 80;
var meshToCutBspL = newThreeBSP(meshToCutL);
// left subtractvar meshToCutBspL = newThreeBSP(meshToCutL);
var resultBspL = cubeBSPL.subtract(meshToCutBspL);
var resultMeshL = resultBspL.toMesh(newTHREE.MeshLambertMaterial({flatShading: true}));
Finally you can create a union of both halves:
// union of left an right halfvar unionBsp = resultBspL.union(resultBspR);
var unionMesh = unionBsp.toMesh(newTHREE.MeshLambertMaterial({flatShading: true}));
scene.add(unionMesh);
See the code snippet:
(functiononLoad() {
var container, camera, scene, renderer;
var grey = 0xD3D3D3;
init();
animate();
functioninit() {
container = document.getElementById('container');
initScene();
addGridHelper();
addCamera();
addLighting()
addRenderer();
addOrbitControls();
// Creates a CSG cut on the cube based on the passed meshcreateCSGDiecutHandle();
}
functioncreateCSGDiecutHandle() {
// left cuboidvar cubeGeoL = newTHREE.CubeGeometry(125, 250, 250);
var cubeMeshL = newTHREE.Mesh(cubeGeoL);
cubeMeshL.position.x -= 62.5;
var cubeBSPL = newThreeBSP(cubeMeshL);
// left part of the heartvar heartShapeL = getHeartShapeLeft();
var heartGeoL = getHeartGeometry(heartShapeL);
var meshToCutL = newTHREE.Mesh( heartGeoL );
meshToCutL.scale.set(10,10,10);
meshToCutL.position.z -= 80;
var meshToCutBspL = newThreeBSP(meshToCutL);
// left subtractvar meshToCutBspL = newThreeBSP(meshToCutL);
var resultBspL = cubeBSPL.subtract(meshToCutBspL);
var resultMeshL = resultBspL.toMesh(newTHREE.MeshLambertMaterial({flatShading: true}));
// right cuboidvar cubeGeoR = newTHREE.CubeGeometry(125, 250, 250);
var cubeMeshR = newTHREE.Mesh(cubeGeoR);
cubeMeshR.position.x += 62.5;
var cubeBSPR = newThreeBSP(cubeMeshR);
// right part of the heartvar heartShapeR = getHeartShapeRight();
var heartGeoR = getHeartGeometry(heartShapeR);
var meshToCutR = newTHREE.Mesh( heartGeoR );
meshToCutR.scale.set(10,10,10);
meshToCutR.position.z -= 80;
// right subtractvar meshToCutBspR = newThreeBSP(meshToCutR);
var resultBspR = cubeBSPR.subtract(meshToCutBspR);
var resultMeshR = resultBspR.toMesh(newTHREE.MeshLambertMaterial({flatShading: true}));
// union of left an right halfvar unionBsp = resultBspL.union(resultBspR);
var unionMesh = unionBsp.toMesh(newTHREE.MeshLambertMaterial({flatShading: true}));
scene.add(unionMesh);
}
functiongetHeartShapeRight() {
var x = 5, y = 10;
var heartShape = newTHREE.Shape();
heartShape.moveTo(x - 5, y - 5);
heartShape.bezierCurveTo(x - 5, y - 5, x - 4, y, x, y);
heartShape.bezierCurveTo(x + 6, y, x + 6, y - 7, x + 6, y - 7);
heartShape.bezierCurveTo(x + 6, y - 11, x + 3, y - 15.4, x - 5, y - 19);
return heartShape;
}
functiongetHeartShapeLeft() {
var x = 5, y = 10;
var heartShape = newTHREE.Shape();
heartShape.moveTo(x - 5, y - 19);
heartShape.bezierCurveTo(x - 12, y - 15.4, x - 16, y - 11, x - 16, y - 7);
heartShape.bezierCurveTo(x - 16, y - 7, x - 16, y, x - 10, y);
heartShape.bezierCurveTo(x - 7, y, x - 5, y - 5, x - 5, y - 5);
return heartShape;
}
functiongetHeartGeometry(heartShape) {
var extrudeSettings = {
steps: 2,
amount: 16,
bevelEnabled: true,
bevelThickness: 5,
bevelSize: 1,
bevelSegments: 1
};
returnnewTHREE.ExtrudeBufferGeometry( heartShape, extrudeSettings );
}
/**** Helper functions ****/functioncomputeBoundingBox(mesh) {
var box = newTHREE.Box3().setFromObject(mesh);
var size = box.getSize();
return {
width: size.x,
height: size.y,
size: size
}
}
/**** Basic Scene Setup ****/functioninitScene() {
scene = newTHREE.Scene();
scene.background = newTHREE.Color(0xffffff);
}
functionaddCamera() {
camera = newTHREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(349.11334070460066, 405.44010726325604, 359.3111192889029);
scene.add(camera);
}
functionaddGridHelper() {
var planeGeometry = newTHREE.PlaneGeometry(2000, 2000);
planeGeometry.rotateX(-Math.PI / 2);
var planeMaterial = newTHREE.ShadowMaterial({
opacity: 0.2
});
var plane = newTHREE.Mesh(planeGeometry, planeMaterial);
plane.position.y = -200;
plane.receiveShadow = true;
scene.add(plane);
var helper = newTHREE.GridHelper(2000, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = newTHREE.AxesHelper(1000);
scene.add(axis);
}
functionaddLighting() {
addHemisphereLight();
}
functionaddSpotLighting() {
var light = newTHREE.SpotLight(0xffffff, 1.5);
light.position.set(0, 1500, 200);
light.castShadow = true;
light.shadow = newTHREE.LightShadow(newTHREE.PerspectiveCamera(70, 1, 200, 2000));
light.shadow.bias = -0.000222;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
scene.add(light);
}
functionaddAmbientLight() {
var ambientLight = newTHREE.AmbientLight(0x404040);
scene.add(ambientLight);
}
functionaddHemisphereLight() {
var hemisphereLight = newTHREE.HemisphereLight(0xffffbb, 0x080820, 1);
scene.add(hemisphereLight);
}
functionaddRenderer() {
renderer = newTHREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
window.onresize = resize;
}
functionaddOrbitControls() {
var controls = newTHREE.OrbitControls(camera, renderer.domElement);
}
functionresize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
functionanimate() {
requestAnimationFrame(animate);
render();
}
functionrender() {
renderer.render(scene, camera);
}
})();
body {
background: transparent;
padding: 0;
margin: 0;
font-family: sans-serif;
}
#canvas {
margin: 10px auto;
width: 800px;
height: 350px;
margin-top: -44px;
}
<divid="container"></div><scriptsrc="https://threejs.org/build/three.js"></script><scriptsrc="https://threejs.org/examples/js/libs/dat.gui.min.js"></script><scriptsrc="https://threejs.org/examples/js/controls/OrbitControls.js"></script><scriptsrc="https://rawgit.com/Wilt/ThreeCSG/develop/ThreeCSG.js"></script><scriptsrc="https://threejs.org/examples/js/loaders/MTLLoader.js"></script><scriptsrc="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/LoaderSupport.js"></script><scriptsrc="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/OBJLoader2.js"></script>
Post a Comment for "Unexpected Result Using Threecsg"