平行投影中哪张脸更远?

时间:2018-10-02 15:54:29

标签: javascript reactjs math geometry

我正在使用几何程序上的JavaScript(反应),该程序会创建指定的对象轴测图(更好的平行投影) 由顶点和面定义(一个面可以具有不同数量的顶点)。

enter image description here

当您不需要使面孔不透明时,它可以完美地工作,否则,在其他面孔之上应该存在其他面孔。

所以我想从最远到最近的顺序排列我的面孔列表

[
[[100, 0, 100], [50, 50, 50], [120, 170, 120], [10, 200, 150]],
[[10, 20, 30], [10, 200, 250], [50, 50, 50], [100, 30, 30]],...
]

我将使用faces.sort(sortingFunction)

我不在乎相交的脸

(它将所有对象的面孔放在一起)

sortingFunction应该如何?

您必须考虑轴测方法是如何定义的。它由 X轴和Y轴旋转定义(X旋转可以大于或小于Y旋转), Z旋转为π/ 4(90°)。 / p>

这是该应用程序的旧版本,可让您了解我的意思:http://dev_proiezioni.surge.sh/

对不起,我的英语不好。 谢谢

4 个答案:

答案 0 :(得分:2)

您要尝试的操作称为“背面剔除”。一种常见的技术是从相机的角度确定多边形表示中的点列表是按顺时针还是逆时针顺序。这需要您非常谨慎地创建顶点列表。有关更多详细信息,请查看Wikipedia文章:https://en.wikipedia.org/wiki/Back-face_culling。“实现”部分描述了必须转换为JavaScript的数学。该技术比对面孔列表进行排序要快,因为它只需要检查一次每个面孔,而不是将每个面孔与其他面孔进行比较。

答案 1 :(得分:1)

  

我不在乎相交的脸

这意味着我们可以通过在中间取点来将平原简化为点:

const vecOp = op => (a, b) => a.map((c, i) => op(c,  b[i] || b));

const add = vecOp((a, b) => a + b);
const sub = vecOp((a, b) => a - b);
const mul = vecOp((a, b) => a * b);
const div = vecOp((a, b) => a / b);
 const sum = v => v.reduce((a, b) => a + b, 0);

const middle = (a, b) =>  div(add(a, b), 2);

 const planeToPoint = ([a, b, c, d]) => middle(
   middle(a, b),
   middle(c, d)
 );

现在可以通过“更靠近相机”进行分类,可以在两个平面的中心之间绘制一条线,这将导致一个方向:

 const aToB = (a, b) => 
   sub(
    planeToPoint(b),
    planeToPoint(a)
  );

现在我们可以turn the camera rotation into a camera lookAt vector

 const rotToVec = (yaw, pitch) => ([
   Math.cos(yaw) * Math.cos(pitch),
   Math.sin(yaw) * Math.cos(pitch),
   Math.sin(pitch)
 ]);

,该方向可以与相机方向进行比较,从而在它们之间形成一个角度:

 const angle = (a, b) => sum(mul(a, b)) / sum(a) * sum(b)

现在,让我们一起把它们放在一起:

 const camVec = rotToVec(cam.yaw, cam.pitch);

 planes.sort((a, b) =>
  Math.abs(angle(aToB(a, b), camVec)) < Math.PI / 4 /*90°*/ ? 1 : -1
 );

免责声明:我既没有尝试过上面的代码,也没有使用平行投影,也不擅长数学,所以请谨慎行事,我不知道我在说什么

答案 2 :(得分:1)

对于近似解,请使用3D到3D变换,并考虑Z坐标。对于每张脸,保留最近的Z并对该Z上的脸进行排序。

要获得更精确的解决方案,请考虑使用https://en.wikipedia.org/wiki/Newell%27s_algorithm

答案 3 :(得分:0)

按与您的摄像头的距离排序。

function distanceBetweenTwoPoints (p1, p2) {
  return Math.hypot(p1.x - p2.x, p1.y - p2.y, p1.z - p2.z)
}

function sortFunction (p1, p2) {
  return distanceBetweenTwoPoints(camera, p1) > distanceBetweenTwoPoints(camera,p2) ? -1 : 1
}

根据您想要的顺序调整符号>