2017-06-02 449 views
1

我正在使用THREE.Plane裁剪我的STL模型。Threejs将裁剪应用到对象的特定区域

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对象!

这里是我所得到的: The whole model is cut through top

+0

你能否提供展示你的“剪辑的只是一小部分”的意思是一个形象的例子?是的,“THREE.Plane”的数量是无限的,剪切面也是你提供给材料的。 – TheJim01

+0

@ TheJim01我添加了一张图片 – pooria

+0

是的,您分享的图片是预期的行为。但你期望看到什么?例如,您是否只希望剪辑应用于您的地板的单个网格? – TheJim01

回答

3

是,去除剪切平面的相交在three.js所支持。您可以使用如下图案:

// 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 example

three.js所r.85

+0

谢谢你的回复。是的,这是工作,但只为两架飞机。我必须切开骨头以适应假肢,所以我需要几架飞机。当我使用clipIntersection将所有平面添加到localPlanes数组时,根本没有任何限制! – pooria

+0

感谢您提出这个问题。在我发布我的回复之后,我才发现这一点,我比我的建议更喜欢它,我只是没有时间提供新的答案。 – TheJim01

+0

@ TheJim01是的,我必须感谢你们这两个人。但我的问题是这两种方法似乎只适用于两架飞机。 – pooria

1

编辑:按照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的上半部分。所以你想和剩下的人一起工作。

首先,制作另一架飞机,plane2,与plane1相反。然后plane2将剪下myMesh的BOTTOM。但是,如果您使用plane1进行了一次传球,而另一次使用了plane2,那么您将回到完整网状。所以你需要第三个剪辑平面,plane3,它只剪辑所需的一半myMesh。将plane2plane3放在同一渲染过程中将导致只有myMesh渲染的1/4。

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(); 
 
     }) 
 
    }) 
 
    }) 
 
})();

+0

感谢您的回答。但现在我得到这个错误:'未捕获的类型错误:无法读取属性'空'' '在wa.copy(three.min.js:458)' '在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)' '在f(three.min.js:38)' 'at f(three.min.js:38)' 'at Je.render(three.min.js:42)' – pooria

+0

'你可以请切换到使用' three.js'(而不是'three.min.js'),所以我们可以看到实际的调用堆栈? – TheJim01

+0

对不起,这是因为Plane变量名称中的拼写错误。它可以工作,但现在的问题是,当我尝试移动对象时,它会不断提供此错误:未捕获的TypeError:未能在'WebGLRenderingContext'上执行'shaderSource':参数1的类型不是'WebGLShader' – pooria