My current project involves the use of geometry where each face is represented as its own mesh. I am in need of clipping the geometry to remove a specific portion of it, with the intention of having a stenciled cap face cover the clipped edges. After reviewing and experimenting with the Three.js clipping stencil example, I have grasped the concept of utilizing a stencil to cap trimmed solid geometry. However, when applying this technique to collections of face geometries, I encounter difficulties. Below is some code that I have been working on, based on the provided example:
body { margin: 0; }
canvas { display: block; }
<script type="module">
import * as THREE from 'https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c6b2aeb4a3a386f6e8f7f4f6e8f7">[email protected]</a>/build/three.module.js';
import { OrbitControls } from 'https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b3c7dbc1d6d6f3839d8281839d82">[email protected]</a>/examples/jsm/controls/OrbitControls.js';
import { BufferGeometryUtils } from 'https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ef9b879d8a8aafdfc1dedddfc1de">[email protected]</a>/examples/jsm/utils/BufferGeometryUtils.js';
var camera, scene, renderer;
var planes, planeObjects;
init();
animate();
function createPlaneStencilGroup( geometry, plane, renderOrder )
{
var group = new THREE.Group();
var baseMat = new THREE.MeshBasicMaterial();
baseMat.depthWrite = false;
baseMat.depthTest = false;
baseMat.colorWrite = false;
baseMat.stencilWrite = true;
baseMat.stencilFunc = THREE.AlwaysStencilFunc;
// back faces
var mat0 = baseMat.clone();
mat0.side = THREE.BackSide;
mat0.clippingPlanes = [ plane ];
mat0.stencilFail = THREE.IncrementWrapStencilOp;
mat0.stencilZFail = THREE.IncrementWrapStencilOp;
mat0.stencilZPass = THREE.IncrementWrapStencilOp;
var mesh0 = new THREE.Mesh( geometry, mat0 );
mesh0.renderOrder = renderOrder;
group.add( mesh0 );
// front faces
var mat1 = baseMat.clone();
mat1.side = THREE.FrontSide;
mat1.clippingPlanes = [ plane ];
mat1.stencilFail = THREE.DecrementWrapStencilOp;
mat1.stencilZFail = THREE.DecrementWrapStencilOp;
mat1.stencilZPass = THREE.DecrementWrapStencilOp;
var mesh1 = new THREE.Mesh( geometry, mat1 );
mesh1.renderOrder = renderOrder;
group.add( mesh1 );
return group;
}
function init()
{
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 36, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.set( 2, 2, 2 );
initLights();
planes = [
new THREE.Plane( new THREE.Vector3( 0, - 1, 0 ), 0.42 ),
new THREE.Plane( new THREE.Vector3( 0, 0, - 1 ), 0.25 )
];
var material = new THREE.MeshStandardMaterial( {
color: 0x00ff00,
metalness: 0.1,
roughness: 0.75,
side: THREE.DoubleSide,
clippingPlanes: planes,
clipShadows: true,
shadowSide: THREE.DoubleSide,
} );
// Simple sphere geometry. Something I know works, for comparison.
var sphereGeom = new THREE.SphereBufferGeometry( 0.5, 32, 32 );
sphereGeom.translate( -1.1, 0, 0 );
// Make a cube out of 6 planes and merge them together
var planeGeoms ......
.......
There are currently two clipping planes in effect, a cube composed of six individual PlaneGeometries, and a solid sphere included for comparison purposes. The stencil for the cube was created using a merged BufferGeometry object formed by combining the individual planes. While the stencil for the cube appears correct in terms of shape and size, only one cap face is rendered and not aligned with either of the clipping planes. Are there additional steps required in manipulating the stencil or the clipping plane beyond what the existing example provides to make it function appropriately on this type of geometry?