最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Threejs apply clipping to specific area of the object - Stack Overflow

programmeradmin3浏览0评论

I'm using THREE.Plane to clip my STL model.

localPlane = new THREE.Plane( new THREE.Vector3( 0, -1, 0 ), 4);
.
.
.
material = new THREE.MeshPhongMaterial( {
    color: 0xffffff,
    side: THREE.DoubleSide,
    clippingPlanes: [
        localPlane,
    ],
    clipShadows: true
} );

It's working; but the problem is that the whole object's top is clipped by this infinity sized plane. I want it to clip just a small part of it (It seems that there is no way to scale THREE.Plane)

I also tried using ThreeCSG.js but it seems inconvenient with STL objects!

Here is what I get:

I'm using THREE.Plane to clip my STL model.

localPlane = new THREE.Plane( new THREE.Vector3( 0, -1, 0 ), 4);
.
.
.
material = new THREE.MeshPhongMaterial( {
    color: 0xffffff,
    side: THREE.DoubleSide,
    clippingPlanes: [
        localPlane,
    ],
    clipShadows: true
} );

It's working; but the problem is that the whole object's top is clipped by this infinity sized plane. I want it to clip just a small part of it (It seems that there is no way to scale THREE.Plane)

I also tried using ThreeCSG.js but it seems inconvenient with STL objects!

Here is what I get:

Share Improve this question edited Jun 2, 2017 at 16:26 pouria asked Jun 2, 2017 at 9:43 pouriapouria 1,0089 silver badges22 bronze badges 4
  • Can you provide an image example showing what you mean by "clip just a small part of it"? And yes, THREE.Plane in infinite, as are clipping planes you provide to a material. – TheJim01 Commented Jun 2, 2017 at 13:59
  • @TheJim01 I added an image – pouria Commented Jun 2, 2017 at 16:26
  • Yes, the image you've shared is the expected behavior. But what do you expect to see? For example, do you only want the clip to apply to a single grid of your floor? – TheJim01 Commented Jun 2, 2017 at 16:36
  • @TheJim01 I want it to apply only to half of the bone's top and the other half remain uncut. not cutting through the top. – pouria Commented Jun 2, 2017 at 16:38
Add a ment  | 

2 Answers 2

Reset to default 5

Yes, the removal of the intersection of clipping planes is supported in three.js. You can use a pattern like this one:

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

Also, see the three.js example.

three.js r.85

Edit: Follow WestLangley's advice. I'll leave this her as an alternate though less efficient means of performing the clipping.

Clipping planes are infinite. There's no getting around that. So what can you do? Multiple clipping planes in multiple render passes!

To do this, you'll need to turn off auto-clearing, and do your own manual buffer clearing.

renderer = new THREE.WebGLRenderer();    
renderer.autoClear = false;

Now let's say plane1 is the clipping plane you currently have.

material = new THREE.MeshPhongMaterial( {
    ...
    clippingPlanes: [
        plane1,
    ],
    clipShadows: true
} );

var myMesh = new THREE.Mesh(geometry, material);

That clips the top half of myMesh when you call render. So you want to work with the remainder.

First, make another plane, plane2, be the inverse of plane1. plane2 will then clip the BOTTOM of myMesh. But if you render one pass using plane1, and another using plane2, then you're back with a full mesh. So you'll need a third clip plane, plane3, which clips only the desired half of myMesh. Putting plane2 and plane3 in the same render pass will result in only 1/4 of myMesh rendering.

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
    ];

Then when you go to render, clear the draw buffers first, then call two render passes, updating the clip planes between them.

// 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);

The first pass renders the bottom of the model, and the second pass renders half of the top.

ETA: Example

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/build/three.js", function() {
    addScript("https://threejs/examples/js/controls/TrackballControls.js", function() {
      addScript("https://threejs/examples/js/libs/stats.min.js", function() {
        threeReady();
      })
    })
  })
})();

发布评论

评论列表(0)

  1. 暂无评论