Можно ли сделать только части компонента невидимыми? - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть концепция взаимодействия, которую я хочу построить, используя Aframe. Сцена состоит из 2 компонентов.

  1. мяч
  2. куб с элементами внутри него

Элементы внутри куба не видны, потому что оболочка закрывает их.

Теперь сложная часть : шар имеет радиус, который скрывает часть оболочки внутри своего радиуса.

Я думаю, что картинка была бы хороша для разъяснения:

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 голосов
/ 05 сентября 2018

Просто вариант с решением, упомянутым в моем комментарии:

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>
0 голосов
/ 04 сентября 2018

Попробуйте csg.js с three.js с THREEBSP: https://github.com/sshirokov/ThreeBSP

Вот пример:

var box = new THREE.Mesh( new THREE.BoxGeometry( 10, 1, 10 ) );
var cube_bsp = new ThreeBSP( box );

var cutgeo = new THREE.SphereGeometry( 1, 16, 8 );
var sub =  new THREE.Mesh( cutgeo );
var substract_bsp  = new ThreeBSP( sub );
var subtract_bsp  = cube_bsp.subtract( substract_bsp );

var result = subtract_bsp.toMesh(); 

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

...