Box Overflow Clipping Three JS

huangapple go评论64阅读模式
英文:

Box Overflow Clipping Three JS

问题

使用three.js有没有办法裁剪或隐藏对象超出其父级的部分?例如,我有一个盒子和一个球体,就像这张图片上的样子:球体在盒子内

我想裁剪或隐藏球体超出盒子外部的部分。简单来说,我需要类似于CSS中overflow:hidden的逻辑。

我在three.js方面非常新手,请不要因为我问了一些愚蠢的问题而批评我。无论如何,我的代码在这里:

// 简单的例子
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import { OrbitControls } from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls";

let renderer, scene, camera, controls;

init();
animate();

function init() {
    // 渲染器
    renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    renderer.autoClear = false;
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    console.log(renderer);
    // 场景
    scene = new THREE.Scene();

    // 相机
    camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 10000);
    camera.position.set(0, 0, 40);

    // 控制器
    controls = new OrbitControls(camera, renderer.domElement);
    const materialA = new THREE.MeshStandardMaterial({
        roughness: 0,
        metalness: 0,
        color: 0xffffff,
    });
    const materialB = new THREE.MeshPhysicalMaterial({
        roughness: 0,
        transmission: 1,
        thickness: 0.5,
    });
    const sphere = new THREE.Mesh(new THREE.SphereGeometry(5, 30, 30), materialA);
    sphere.position.set(5, 0, 0);

    const box = new THREE.Mesh(new THREE.BoxGeometry(12, 12, 12), materialB);
    scene.add(box);

    const light = new THREE.DirectionalLight('white', 1);
    light.position.set(10, 10, 0);
    const light2 = new THREE.DirectionalLight('white', 1);
    light2.position.set(-10, -10, -10);
    scene.add(sphere, box, light, light2);
}

function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}
英文:

Using three js is there any way to clip or hide object out of its parent? For example i have a box and a sphere inside of this box like on image: sphere inside box

I want to clip or hide the part of sphere that is outside of the box. To put it simply, i need similar logic like css overflow:hidden works;

I am very new working with three.js, don't judge me if i'm asking something dumb. Anyways,my code is here:

// Simple example
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import {OrbitControls} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls";
let renderer, scene, camera, controls;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer({alpha:true, antialias:true});
renderer.autoClear = false;
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
console.log(renderer)
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set(0, 0, 40);
// controls
controls = new OrbitControls( camera, renderer.domElement );
const materialA =  new THREE.MeshStandardMaterial({
roughness: 0,
metalness: 0,
color: 0xffffff,
})
const materialB = new THREE.MeshPhysicalMaterial({
roughness: 0,
transmission: 1,
thickness: 0.5
});
const sphere = new THREE.Mesh(new THREE.SphereGeometry(-5,30,30),materialA);
sphere.position.set(5, 0, 0)
const box = new THREE.Mesh(new THREE.BoxGeometry(12,12,12),materialB);
scene.add(box);
const light = new THREE.DirectionalLight('white', 1);
light.position.set(10, 10, 0);
const light2 = new THREE.DirectionalLight('white', 1);
light2.position.set(-10, -10, -10);
scene.add(sphere, box,light,light2);
}
function animate() {	
requestAnimationFrame( animate );
renderer.render( scene, camera );
}

答案1

得分: 0

以下是已翻译的内容:

  • One solution is to using clipping as you suggest.
    一种解决方法是使用剪裁,正如您所建议的那样。

  • You have some example here: https://threejs.org/examples/?q=clip
    您可以在这里找到一些示例:https://threejs.org/examples/?q=clip

  • First you have to enable local clipping on the renderer (see WebGLRenderer.localClippingEnabled).
    首先,您需要在渲染器上启用局部剪裁(参见 WebGLRenderer.localClippingEnabled)。

  • Then you can add some clipping planes to specify the area you want to clip. For this, you can use the Math class.
    然后,您可以添加一些剪裁平面来指定要剪裁的区域。为此,您可以使用Math类

  • Enable local clipping:
    启用局部剪裁:

    renderer.localClippingEnabled = true;
    
  • Create a plane:
    创建一个平面:

    const clipPlane1 = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0);
    clipPlane1.translate(new THREE.Vector3(6, 0, 0));
    
  • And finally, specify the plane in the material:
    最后,在材质中指定平面:

    clippingPlanes: [clipPlane1],
    clipIntersection: true
    
  • Here is your entire code:
    这是您的完整代码:

// 简单示例
import * as THREE from 'three';
import { OrbitControls } from 'https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls';

let renderer, scene, camera, controls;

init();
animate();

function init() {
    // 渲染器
    renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    renderer.autoClear = false;
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.localClippingEnabled = true;
    document.body.appendChild(renderer.domElement);
    console.log(renderer);
    
    // 场景
    scene = new THREE.Scene();
    
    // 相机
    camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 10000);
    camera.position.set(0, 0, 40);
    
    // 平面
    const clipPlane1 = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0);
    clipPlane1.translate(new THREE.Vector3(6, 0, 0));
    
    // 控制器
    controls = new OrbitControls(camera, renderer.domElement);
    const materialA = new THREE.MeshStandardMaterial({
        roughness: 0,
        metalness: 0,
        color: 0xffffff,
        clippingPlanes: [clipPlane1],
        clipIntersection: true,
    });
    const materialB = new THREE.MeshPhysicalMaterial({
        roughness: 0,
        transmission: 1,
        thickness: 0.5,
    });
    const sphere = new THREE.Mesh(new THREE.SphereGeometry(-5, 30, 30), materialA);
    sphere.position.set(5, 0, 0);
    
    const box = new THREE.Mesh(new THREE.BoxGeometry(12, 12, 12), materialB);
    scene.add(box);
    
    const light = new THREE.DirectionalLight('white', 1);
    light.position.set(10, 10, 0);
    const light2 = new THREE.DirectionalLight('white', 1);
    light2.position set(-10, -10, -10);
    scene.add(sphere, box, light, light2);
}

function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}

<details>
<summary>英文:</summary>
One solution is to using clipping as you suggest.
You have some example here: https://threejs.org/examples/?q=clip
First you have to enable local clipping on the renderer
(see [WebGLRenderer.localClippingEnabled][1]). Then you can add some clipping planes to specify the area you want to clip. For this, you can use the [Math class][2].
So in your example, you have to:
Enable local clipping:
renderer.localClippingEnabled = true;
Create a plane:
const clipPlane1 = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0);
clipPlane1.translate(new THREE.Vector3(6, 0, 0));
And finally, specify the plane in the material:
clippingPlanes: [clipPlane1],
clipIntersection: true
---
Here is your entire code:
// Simple example
import * as THREE from &#39;three&#39;;
import { OrbitControls } from &#39;https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls&#39;;
let renderer, scene, camera, controls;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.autoClear = false;
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.localClippingEnabled = true;
document.body.appendChild(renderer.domElement);
console.log(renderer);
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 0, 40);
// planes
const clipPlane1 = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 0);
clipPlane1.translate(new THREE.Vector3(6, 0, 0));
// controls
controls = new OrbitControls(camera, renderer.domElement);
const materialA = new THREE.MeshStandardMaterial({
roughness: 0,
metalness: 0,
color: 0xffffff,
clippingPlanes: [clipPlane1],
clipIntersection: true,
});
const materialB = new THREE.MeshPhysicalMaterial({
roughness: 0,
transmission: 1,
thickness: 0.5,
});
const sphere = new THREE.Mesh(new THREE.SphereGeometry(-5, 30, 30), materialA);
sphere.position.set(5, 0, 0);
const box = new THREE.Mesh(new THREE.BoxGeometry(12, 12, 12), materialB);
scene.add(box);
const light = new THREE.DirectionalLight(&#39;white&#39;, 1);
light.position.set(10, 10, 0);
const light2 = new THREE.DirectionalLight(&#39;white&#39;, 1);
light2.position.set(-10, -10, -10);
scene.add(sphere, box, light, light2);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
[1]: https://threejs.org/docs/index.html?q=renderer#api/en/renderers/WebGLRenderer.localClippingEnabled
[2]: https://threejs.org/docs/index.html?q=plane#api/en/math/Plane
</details>

huangapple
  • 本文由 发表于 2023年3月3日 19:33:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/75626570.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定