根据需要找到立方体的上面

时间:2015-12-09 11:08:34

标签: three.js 3d intersection raycasting

我试图解决的一般问题是找出立方体的哪个面向上。立方体可以一次向任何方向滚动90°。如果某个脸朝上,立方体就会消失。我正在使用补间来旋转立方体并改变它的位置。

我正在尝试通过创建一个新光线来解决这个问题,它的原点设置在立方体的正上方,并且它的方向向下延伸一小段距离,因此它只与立方体的上面相交。 violet thingy on top of die is ray cast downward into the cube

到目前为止一切顺利。当我按console.log()检查时,我将我的立方体作为交叉对象,但是当我尝试通过faceIntersect.face访问交叉面时,它似乎是未定义的。

有问题的功能:

function checkUpperFace(posX, posZ) {

  // get position from passed x- and z-values (y is always above cube)
  // and set direction and length of ray
  var position = new THREE.Vector3( posX, 3, posZ );
  var direction = new THREE.Vector3(0, -1, 0);
  var far = 2;
  // create ray, that goes downwards from above the cube
  var cubeRaycaster = new THREE.Raycaster( position, direction, 0, far );
  // get intersection with upper face of rolled cube
  var faceIntersect = cubeRaycaster.intersectObject( currentCube );

  // add a helper to see the ray
  var arrowHelper = new THREE.ArrowHelper( direction, position, far, 0x770077 );
  scene.add( arrowHelper );

  console.log(faceIntersect); // object is shown with everything I want to know
  console.log(faceIntersect.face); // is shown to be undefined

}

2 个答案:

答案 0 :(得分:1)

最后我以@unx推荐的方式做到了但是我真的想避免使用巨大的if-else语句,所以我使用了一个数组rotationLibrary,它具有相应顶面的所有可能旋转死但是由于我用来旋转和移动骰子的补间,它的旋转值并不是真正的点,因此我很难与固定的旋转值进行比较,因为我在数组中使用它们。

所以我将骰子的旋转值“标准化”为可用于将它们与rotationLibrary中的值进行比较的值。最后一步是将结果存储/更新到多维数据集对象本身的顶部,这样我就可以随时获取它。

// spawn condition:
// 1 on top, 2 facing camera, 3 facing right (seen from camera),
// 4 facing left (see 3), 5 facing away from camera, 6 facing down
var rotationLibrary = [
    {x: 0,      y: 0,   z: 0,   face: 1},
    {x: 0,      y: 90,  z: 0,   face: 1},
    {x: 180,    y: 0,   z: 180, face: 1},
    {x: 0,      y: -90, z: 0,   face: 1},
    {x: -90,    y: 0,   z: 0,   face: 2},
    {x: -90,    y: 0,   z: 90,  face: 2},
    {x: -90,    y: 0,   z: 180, face: 2},
    {x: -90,    y: 0,   z: -90, face: 2},
    {x: 0,      y: 0,   z: 90,  face: 3},
    {x: 90,     y: 90,  z: 0,   face: 3},
    {x: -90,    y: -90, z: 0,   face: 3},
    {x: -90,    y: 90,  z: 180, face: 3},
    {x: 180,    y: 0,   z: -90, face: 3},
    {x: 0,      y: 0,   z: -90, face: 4},
    {x: 90,     y: -90, z: 0,   face: 4},
    {x: -90,    y: 90,  z: 0,   face: 4},
    {x: 180,    y: 0,   z: 90,  face: 4},
    {x: 90,     y: 0,   z: 0,   face: 5},
    {x: 90,     y: 0,   z: -90, face: 5},
    {x: 90,     y: 0,   z: 180, face: 5},
    {x: 90,     y: 0,   z: 90,  face: 5},
    {x: 90,     y: 90,  z: 90,  face: 5},
    {x: 0,      y: 0,   z: 180, face: 6},
    {x: 180,    y: -90, z: 0,   face: 6},
    {x: 180,    y: 90,  z: 0,   face: 6},
    {x: 180,    y: 0,   z: 0,   face: 6}
];

function checkRotationsToGetUpperFace(cube) {
  // create object with "normalized" (brought to quarter-circle-degree-values) degrees
  var normalizedRotation = {
    x: 0,
    y: 0,
    z: 0
  };
  normalizedRotation.x = getNormalizedDegree(cube.rotation._x);
  normalizedRotation.y = getNormalizedDegree(cube.rotation._y);
  normalizedRotation.z = getNormalizedDegree(cube.rotation._z);

  // go through the library that has all the degrees with the corresponding upper face
  for (var i = 0; i < rotationLibrary.length; i++) {
    // check if the objects match, then get the face
    if (rotationLibrary[i].x == normalizedRotation.x &&
      rotationLibrary[i].y == normalizedRotation.y &&
      rotationLibrary[i].z == normalizedRotation.z) {
      cube.face = rotationLibrary[i].face;
    }
  }

  // reattach cube for correct movement later
  THREE.SceneUtils.attach(cube, scene, pivot);
}

function getNormalizedDegree(rotationValue) {
    // transform rotation value into degree value
  var rotValue = rotationValue / (Math.PI / 180);

  // default value is 0, so only check if it should be 90°, 180° or -90°
  var normalizedDegree = 0;
  // x between 45° and 135° ( ~ 90)
  if (rotValue > 45 && rotValue < 135) {
    normalizedDegree = 90;
  }
  // x between -45° and -135° ( ~ -90)
  else if (rotValue < -45 && rotValue > -135) {
    normalizedDegree = -90;
  }
  // x between 135° and 215° or x between -135° and -215° ( ~ 180)
  else if ((rotValue > 135 && rotValue < 215) || (rotValue < -135 && rotValue > -215)) {
    normalizedDegree = 180;
  }

  return normalizedDegree;
}

http://jsfiddle.net/b2an3pq7/3/

答案 1 :(得分:0)

可能不是你的光线投射问题的解决方案,而是另一种方法:为什么不通过比较旋转欧拉角来简单地检测上面?例如。 (伪代码):

if(cube.rotation.x % 360 == 0)
{
    // upper face upwards
}
else if(cube.rotation.x % 360 == 90)
{
    // left face upwards
}

您必须处理价值容差(85° - 95°)负旋转值和超出PI * 2范围的值,但除此之外,还不是那么容易吗?