多边形 Z 排序
Polygon Z Ordering
我目前正在尝试编写一个仅使用多边形的 2D 3D“渲染器”。
在渲染之前,我通过计算一个 Z 值对多边形进行排序,如下所示:
double z = (v1.getZ()+v2.getZ()+v3.getZ());
我的多边形由每三个向量 (X,Y,Z) 组成
然后我对多边形进行排序,这样我就可以使用画家算法方法:
int i = 0;
for (Poly polygon : polyZSort) {
if(polygon.getRealZ()>z) {
break;
}
i++;
}
polyZSort.add(i, polygon);
那么渲染就这么简单:
for (Poly poly : polyZSort) {
OVector v1 = poly.getV1();
v1 = form.doTransform(v1);
OVector v2 = poly.getV2();
v2 = form.doTransform(v2);
OVector v3 = poly.getV3();
v3 = form.doTransform(v3);
g2d.setColor(poly.getColor());
Polygon pl = new Polygon();
pl.addPoint(getX(v1.getX()),getY(v1.getY()));
pl.addPoint(getX(v2.getX()),getY(v2.getY()));
pl.addPoint(getX(v3.getX()),getY(v3.getY()));
g2d.fillPolygon(pl);
// black border line
g2d.setColor(Color.BLACK);
g2d.drawLine(
getX(v1.getX()),
getY(v1.getY()),
getX(v2.getX()),
getY(v2.getY())
);
g2d.drawLine(
getX(v2.getX()),
getY(v2.getY()),
getX(v3.getX()),
getY(v3.getY())
);
g2d.drawLine(
getX(v3.getX()),
getY(v3.getY()),
getX(v1.getX()),
getY(v1.getY())
);
}
这有效,即使有多个立方体(但仅在大多数情况下):
但是在某些位置,顺序似乎是错误的:
有人知道问题出在哪里吗?
这是“故障”的视频 https://vimeo.com/552355610
您遗漏了重要的步骤……应该这样做:
输入是 3D 三角形列表,输出是 3D 三角形列表
开始时输出列表为空
“2D”屏幕投影每个处理过的三角形并保留原始 z 值
所以它仍然是 3D,但是 x,y
是屏幕位置并且 z 是相机坐标系中的“原始”z
值。
检查投影后每个处理过的三角形是否与输出列表中已有的三角形相交。
如果没有交集,则只需将这个三角形按原样添加到输出列表即可。
如果它确实相交,您需要重新对所有相交的三角形和新三角形进行三角剖分,以免发生相交。并将这些新三角形添加到输出列表(同时从输出列表中删除原始相交三角形)。
这里有 2 个重叠三角形的例子:
如您所见,它可以创建很多新三角形,并且通常新三角形与多个三角形相交,因此您需要对重叠部分的每个三角形递归执行此操作,或者创建所有相交三角形的列表首先并立即重新对它们进行三角测量...
整个场景处理后 Z 按中点 z 值对输出列表排序
这一步你已经掌握了。
使用 2D 三角形渲染渲染排序后的输出列表
这一步你已经掌握了。
如您所见,您需要一个大小取决于场景中的三角形数量和重叠部分的缓冲区。此外,这种方法非常复杂(对于菜鸟程序员来说不是很好的选择)并且只能用于非常简单的场景。对于更复杂的,使用 Z 缓冲区更容易和更快。然而,除了缓冲区本身之外,它还需要三角形的 3D 渲染(因此还有一个插值和每个像素条件)。如您所见,z 排序的 O(1)
而不是 O(n.log(n))
。
我目前正在尝试编写一个仅使用多边形的 2D 3D“渲染器”。
在渲染之前,我通过计算一个 Z 值对多边形进行排序,如下所示:
double z = (v1.getZ()+v2.getZ()+v3.getZ());
我的多边形由每三个向量 (X,Y,Z) 组成
然后我对多边形进行排序,这样我就可以使用画家算法方法:
int i = 0;
for (Poly polygon : polyZSort) {
if(polygon.getRealZ()>z) {
break;
}
i++;
}
polyZSort.add(i, polygon);
那么渲染就这么简单:
for (Poly poly : polyZSort) {
OVector v1 = poly.getV1();
v1 = form.doTransform(v1);
OVector v2 = poly.getV2();
v2 = form.doTransform(v2);
OVector v3 = poly.getV3();
v3 = form.doTransform(v3);
g2d.setColor(poly.getColor());
Polygon pl = new Polygon();
pl.addPoint(getX(v1.getX()),getY(v1.getY()));
pl.addPoint(getX(v2.getX()),getY(v2.getY()));
pl.addPoint(getX(v3.getX()),getY(v3.getY()));
g2d.fillPolygon(pl);
// black border line
g2d.setColor(Color.BLACK);
g2d.drawLine(
getX(v1.getX()),
getY(v1.getY()),
getX(v2.getX()),
getY(v2.getY())
);
g2d.drawLine(
getX(v2.getX()),
getY(v2.getY()),
getX(v3.getX()),
getY(v3.getY())
);
g2d.drawLine(
getX(v3.getX()),
getY(v3.getY()),
getX(v1.getX()),
getY(v1.getY())
);
}
这有效,即使有多个立方体(但仅在大多数情况下):
但是在某些位置,顺序似乎是错误的:
有人知道问题出在哪里吗? 这是“故障”的视频 https://vimeo.com/552355610
您遗漏了重要的步骤……应该这样做:
输入是 3D 三角形列表,输出是 3D 三角形列表
开始时输出列表为空
“2D”屏幕投影每个处理过的三角形并保留原始 z 值
所以它仍然是 3D,但是
x,y
是屏幕位置并且 z 是相机坐标系中的“原始”z
值。检查投影后每个处理过的三角形是否与输出列表中已有的三角形相交。
如果没有交集,则只需将这个三角形按原样添加到输出列表即可。
如果它确实相交,您需要重新对所有相交的三角形和新三角形进行三角剖分,以免发生相交。并将这些新三角形添加到输出列表(同时从输出列表中删除原始相交三角形)。
这里有 2 个重叠三角形的例子:
如您所见,它可以创建很多新三角形,并且通常新三角形与多个三角形相交,因此您需要对重叠部分的每个三角形递归执行此操作,或者创建所有相交三角形的列表首先并立即重新对它们进行三角测量...
整个场景处理后 Z 按中点 z 值对输出列表排序
这一步你已经掌握了。
使用 2D 三角形渲染渲染排序后的输出列表
这一步你已经掌握了。
如您所见,您需要一个大小取决于场景中的三角形数量和重叠部分的缓冲区。此外,这种方法非常复杂(对于菜鸟程序员来说不是很好的选择)并且只能用于非常简单的场景。对于更复杂的,使用 Z 缓冲区更容易和更快。然而,除了缓冲区本身之外,它还需要三角形的 3D 渲染(因此还有一个插值和每个像素条件)。如您所见,z 排序的 O(1)
而不是 O(n.log(n))
。