2017-06-02 266 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