Я использую THREE.Plane для клипа моей модели STL.
localPlane = new THREE.Plane( new THREE.Vector3( 0, -1, 0 ), 4);
.
.
.
material = new THREE.MeshPhongMaterial( {
color: 0xffffff,
side: THREE.DoubleSide,
clippingPlanes: [
localPlane,
],
clipShadows: true
} );
Он работает; но проблема в том, что весь объект вершины обрезается этой плоскостью бесконечности. Я хочу, чтобы он скопировал только небольшую часть (кажется, что нет возможности масштабировать THREE.Plane)
Я также попытался использовать ThreeCSG.js, но это кажется неудобным для объектов STL!
Вот что я получаю:
Да, удаление пересечения плоскостей отсечения поддерживается в три раза. Вы можете использовать шаблон, подобный этому:
// clipping planes
var localPlanes = [
new THREE.Plane( new THREE.Vector3( - 1, 0, 0 ), 1 ),
new THREE.Plane( new THREE.Vector3( 0, - 1, 0 ), 1 )
];
// material
var material = new THREE.MeshPhongMaterial( {
color: 0xffffff,
side: THREE.DoubleSide,
clippingPlanes: localPlanes,
clipIntersection: true
} );
Также см. Пример three.js.
three.js r.85
Изменить: Следуйте совету WestLangley. Я оставлю это ее альтернативным, хотя и менее эффективным средством для выполнения обрезки.
Сжимающие плоскости бесконечны. Там не обойтись. Так что ты можешь сделать? Несколько плоскостей отсечения в нескольких передачах!
Для этого вам необходимо отключить автоматическую очистку и выполнить собственную очистку буфера вручную.
renderer = new THREE.WebGLRenderer();
renderer.autoClear = false;
Теперь предположим, что plane1
- это плоскость отсечения, которую вы в настоящее время имеете.
material = new THREE.MeshPhongMaterial( {
...
clippingPlanes: [
plane1,
],
clipShadows: true
} );
var myMesh = new THREE.Mesh(geometry, material);
Это myMesh
верхнюю половину myMesh
когда вы вызываете рендер. Поэтому вы хотите работать с остальными.
Сначала сделайте другую плоскость, плоскость plane2
, обратной plane1
. plane2
затем myMesh
BOTTOM myMesh
. Но если вы сделаете один проход с использованием plane1
, а другой с помощью plane2
, то вы вернетесь с полной сеткой. Таким образом, вам понадобится третий клип-самолет, plane3
, который plane3
только желаемую половину myMesh
. Помещение plane2
и plane3
в один проход рендеринга приведет только к 1/4 рендеринга myMesh
.
var pass1ClipPlanes = [
plane1
],
pass2ClipLanes = [
plane2, // this plane is the inverse of plane 1, so it clips the opposite of plane1
plane3 // this clips the left/right half of the model
];
Затем, когда вы переходите к рендерингу, сначала очищайте буферы рисования, затем вызывайте два прохода рендеринга, обновляя плоскости клипов между ними.
// clear the draw buffers
renderer.clear();
// clip the top
myMesh.material.clipPlanes = pass1ClipPlanes;
renderer.render(scene, camera);
// clip the bottom and one side
myMesh.material.clipPlanes = pass2ClipPlanes;
renderer.render(scene, camera);
Первый проход отображает нижнюю часть модели, а второй проход отображает половину вершины.
ETA: пример
var renderer, scene, camera, controls, stats;
var cube,
pass1ClipPlanes,
pass2ClipPlanes;
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000;
function init() {
document.body.style.backgroundColor = "slateGray";
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.localClippingEnabled = true;
renderer.autoClear = false;
document.body.appendChild(renderer.domElement);
document.body.style.overflow = "hidden";
document.body.style.margin = "0";
document.body.style.padding = "0";
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 50;
scene.add(camera);
controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.dynamicDampingFactor = 0.5;
controls.rotateSpeed = 3;
var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0';
document.body.appendChild(stats.domElement);
resize();
window.onresize = resize;
// POPULATE EXAMPLE
var plane1 = new THREE.Plane(new THREE.Vector3(0, -1, 0), 0),
plane2 = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0),
plane3 = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0);
pass1ClipPlanes = [plane1];
pass2ClipPlanes = [plane2, plane3];
var cubeGeo = new THREE.BoxBufferGeometry(10, 10, 10),
cubeMat = new THREE.MeshPhongMaterial({
color: "red",
side: THREE.DoubleSide
});
cube = new THREE.Mesh(cubeGeo, cubeMat);
scene.add(cube);
animate();
}
function resize() {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
if (renderer && camera && controls) {
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
controls.handleResize();
}
}
function render() {
renderer.clear();
cube.material.clippingPlanes = pass1ClipPlanes;
renderer.render(scene, camera);
cube.material.clippingPlanes = pass2ClipPlanes;
renderer.render(scene, camera);
}
function animate() {
requestAnimationFrame(animate);
render();
controls.update();
stats.update();
}
function threeReady() {
init();
}
(function() {
function addScript(url, callback) {
callback = callback || function() {};
var script = document.createElement("script");
script.addEventListener("load", callback);
script.setAttribute("src", url);
document.head.appendChild(script);
}
addScript("https://threejs.org/build/three.js", function() {
addScript("https://threejs.org/examples/js/controls/TrackballControls.js", function() {
addScript("https://threejs.org/examples/js/libs/stats.min.js", function() {
threeReady();
})
})
})
})();
Uncaught TypeError: Cannot read property 'normal' of null
at wa.copy (three.min.js:458)
at b (three.min.js:130)
at ig.setState (three.min.js:131)
at n (three.min.js:139)
at Xd.renderBufferDirect (three.min.js:171)
at f (three.min.js:38)
at f (three.min.js:38)
at Je.render (three.min.js:42)
three.js
(а не three.min.js
), чтобы мы могли видеть реальный стек вызовов?