ThreeJS亮点/投影仪

时间:2017-02-05 06:53:30

标签: javascript html5 three.js projector

如何在平面顶部的3d对象下添加2d精灵,以显示我的对象被突出显示/选中?

另外,我如何在不平坦的地形上做到这一点?

我附上了一张示例图片,以便更好地解释我的问题:

enter image description here

1 个答案:

答案 0 :(得分:2)

我不确定使用精灵是个好主意。

正如你所说的不平坦地形,使用不平坦的东西更好。例如,球体或圆柱体,材质为.alphaMap

为了我们的选择效果,我们需要一些像戒指一样的东西。

enter image description here

假设您选择了球体,那么您可以从文件中设置其材质alphaMap或从画布中动态创建纹理:

// alpha texture
var canvas = document.createElement("canvas");
canvas.width = 128;
canvas.height = 128;
var ctx = canvas.getContext("2d");
var gradient = ctx.createLinearGradient(0, 0, 0, 128);
gradient.addColorStop(0.35, "black");
gradient.addColorStop(0.475, "white");
gradient.addColorStop(0.525, "white");
gradient.addColorStop(0.65, "black");
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 128, 128);
var alphaTexture = new THREE.Texture(canvas);
alphaTexture.needsUpdate = true;

关于.alphaMap

alpha贴图是一种灰度纹理,用于控制整个表面的不透明度(黑色:完全透明;白色:完全不透明)。默认值为null。 仅使用纹理的颜色,忽略alpha通道(如果存在)。对于RGB和RGBA纹理,WebGL渲染器在采样此纹理时将使用绿色通道,因为在DXT压缩和未压缩的RGB 565格式中为绿色提供了额外的精度。仅亮度和亮度/ alpha纹理也将按预期工作。

这就是我们为什么只有黑白的原因。

让我们用黄色环创建一个最简单的NPC对象,表明我们的NPC被选中:

var npc = function() {
  var geom = new THREE.SphereGeometry(4, 4, 2);
  geom.translate(0, 4, 0);
  var mesh = new THREE.Mesh(geom, new THREE.MeshLambertMaterial({
    color: Math.random() * 0xffffff
  }));

  // highlighter
  geom.computeBoundingSphere();
  var sphereGeom = new THREE.SphereGeometry(geom.boundingSphere.radius, 32, 24);
  var sphereMat = new THREE.MeshBasicMaterial({
    color: "yellow", // yellow ring
    transparent: true, // to make our alphaMap work, we have to set this parameter to `true`
    alphaMap: alphaTexture 
  });
  var sphere = new THREE.Mesh(sphereGeom, sphereMat);
  sphere.visible = false;
  mesh.add(sphere);
  mesh.userData.direction = new THREE.Vector3(Math.random() - 0.5, 0, Math.random() - 0.5).normalize();
  mesh.userData.speed = Math.random() * 5 + 5;
  mesh.position.set(
    Math.random() * (worldWidth - 10) - (worldWidth - 10) * 0.5,
    10,
    Math.random() * (worldDepth - 10) - (worldDepth - 10) * 0.5
  );
  scene.add(mesh);
  return mesh;
}

其余的并不是那么困难。 我们需要一系列NPC,我们将检查交叉点

var npcs = [];
for (var i = 0; i < 10; i++) {
  npcs.push(npc());
}

然后在mousedown事件中,我们会选择一个NPC(取自interactive cubes示例并根据我们的需要进行修改):

window.addEventListener('mousedown', onMouseDown, false);

function onMouseDown(event) {
  if (event.button != 2) return;
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

  selector.setFromCamera( mouse, camera );
    var intersects = selector.intersectObjects( npcs );
    if ( intersects.length > 0 ) {
      if ( INTERSECTED != intersects[ 0 ].object ) {
        if ( INTERSECTED ) INTERSECTED.children[0].visible = INTERSECTED.selected;
        INTERSECTED = intersects[ 0 ].object;
        INTERSECTED.selected = INTERSECTED.children[0].visible;
        INTERSECTED.children[0].visible = true;
      }
    } else {
      if ( INTERSECTED ) INTERSECTED.children[0].visible = INTERSECTED.selected;
      INTERSECTED = null;
    }
}

jsfiddle示例。在这里,您可以使用鼠标右键选择对象。