是否可以仅使组件的一部分不可见?

时间:2018-09-04 18:39:18

标签: three.js aframe

我有一个要使用Aframe构建的交互概念。 场景由2个部分组成。

  1. 其中包含元素的多维数据集

由于外壳将其封闭,因此多维数据集内部的元素不可见。

现在棘手的部分:球具有半径,可以将壳体的一部分隐藏在半径内。

我认为图片有助于澄清:

first image: cube with object inside; second image: circle with its radius; third image: case of cube dissapears inside radius of ball

  • 使用Aframe或three.js可以吗?
  • 我该如何处理?

编辑:错字

2 个答案:

答案 0 :(得分:1)

在带有THREEBSP的three.js中尝试使用csg.js:https://github.com/sshirokov/ThreeBSP

这是一个例子:

{"type":{"description":"Type"}}

http://jsfiddle.net/L0rdzbej/151/

答案 1 :(得分:1)

在我的评论中提到的解决方案只是一个选择:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(-5, 8, -8).setLength(8);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target = new THREE.Vector3(0, 2, 0);
controls.update();

var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(-10, 10, 10);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.25));

scene.add(new THREE.GridHelper(4, 4, 0x404040, 0x404040));

// boxes
var boxGeom = new THREE.BoxBufferGeometry();
boxGeom.translate(0, 0.5, 0);
var boxMaterial = new THREE.MeshLambertMaterial({
  color: "gray"
});
for (let x = 0; x <= 1; x++) {
  for (let z = 0; z <= 1; z++) {
    let box = new THREE.Mesh(boxGeom, boxMaterial);
    box.position.set(x - 0.5, 0, z - 0.5).multiplyScalar(1.5);
    box.scale.set(1, Math.abs(x) + Math.abs(z) + 1, 1);
    scene.add(box);
  }
}

// wrapping box
var wrappingBoxGeom = new THREE.BoxBufferGeometry(4, 4, 4);
wrappingBoxGeom.translate(0, 2, 0);
var wrappingBoxMaterial = getMaterial({
  diffuse: 0xaaaaaa,
  inside: false
});
var wrappingBox = new THREE.Mesh(wrappingBoxGeom, wrappingBoxMaterial);
scene.add(wrappingBox);

var clock = new THREE.Clock();
var time = 0;

render();

function render() {
  requestAnimationFrame(render);
  time += clock.getDelta();
  wrappingBoxMaterial.uniforms.clippingSphere.value.x = Math.sin(time) * 2;
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script>
  var sphereRadius = {
    value: 2.5
  };

  function getMaterial(params) {

    var diffuse = params.diffuse === undefined ? 0xffffff : params.diffuse;
    var diffuseBack = params.diffuseBack === undefined ? diffuse : params.diffuseBack;

    var inside = params.inside === undefined ? true : params.inside;
    inside = inside ? 1 : -1;

    let lambert = new THREE.ShaderMaterial({
      uniforms: THREE.UniformsUtils.merge([THREE.ShaderLib.lambert.uniforms, {
        clippingSphere: {
          value: new THREE.Vector4()
        },
        diffuseBack: {
          value: new THREE.Color()
        }
      }]),

      vertexShader: THREE.ShaderLib.lambert.vertexShader
        .replace(/varying vec3 vLightFront;/g, 'varying vec3 vLightFront;\nvarying vec4 worldPosition;')
        .replace(/#include <worldpos_vertex>/g, 'worldPosition = modelMatrix * vec4( transformed, 1.0 );'),

      fragmentShader: THREE.ShaderLib.lambert.fragmentShader
        .replace(/uniform float opacity;/g, 'uniform float opacity;\nuniform vec4 clippingSphere;\nuniform vec3 diffuseBack;')
        .replace(/varying vec3 vLightFront;/g, 'varying vec3 vLightFront;\nvarying vec4 worldPosition;')
        .replace(/#include <clipping_planes_fragment>/g, '#include <clipping_planes_fragment>\n if (distance(worldPosition.xyz, clippingSphere.xyz) * sign(clippingSphere.w) > clippingSphere.w) discard;')
        .replace(/#include <dithering_fragment>/g, '#include <dithering_fragment>\n if (!gl_FrontFacing) gl_FragColor.xyz = diffuseBack;'),

      lights: true,

      side: THREE.DoubleSide
    });

    lambert.uniforms.clippingSphere.value.set(0, 3, -1, sphereRadius.value * inside);
    lambert.uniforms.diffuse.value.set(diffuse);
    lambert.uniforms.diffuseBack.value.set(diffuseBack);

    return lambert;
  }
</script>