绘制四边形的顶点顺序
Order of vertex for drawing quad
我需要在 3D 中绘制 n 个平面space。四边形是由两点创建的平面,通过一种算法,我得到了 4 个顶点来绘制四边形。我遇到的问题是顶点的顺序显然会影响结果。这就是我的意思:
但是当平面是水平而不是垂直时:
我可以想象两种可能的解决方案。使用三角形并组合它们或正确排序顶点。我不知道如何做第二个想法。我试过使用三角形,但我遇到了同样的问题。
# self.planos = [('A', (500, 500, 10), (-500, 500, 10), (-500, -500, 10), (500, -500, 10))] for horizontal
# self.planos = [('A', (-500, 10, 500), (500, 10, 500), (-500, 10, -500), (500, 10, -500))] for vertical
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glDepthMask(GL_FALSE)
glBegin(GL_QUADS)
glColor(0.5, 0.5, 0.1, 0.5)
for i in range(len(self.planos)):
glVertex(self.planos[i][1][0], self.planos[i][1][2], self.planos[i][1][1])
glVertex(self.planos[i][2][0], self.planos[i][2][2], self.planos[i][2][1])
glVertex(self.planos[i][3][0], self.planos[i][3][2], self.planos[i][3][1])
glVertex(self.planos[i][4][0], self.planos[i][4][2], self.planos[i][4][1])
glEnd()
glDepthMask(GL_TRUE)
glDisable(GL_BLEND)
获取四个顶点绘制平面的交集代码:
In init method:
#Vertices of the cube
self.v = (Point3D(500, 500, 500), Point3D(-500, 500, 500), Point3D(-500, -500, 500),
Point3D(500, -500, 500), Point3D(500, 500, -500), Point3D(-500, 500, -500),
Point3D(-500, -500, -500), Point3D(500, -500, -500))
# Edges of the cube
self.a = (Segment3D(self.v[0], self.v[1]), Segment3D(self.v[1], self.v[2]),
Segment3D(self.v[2], self.v[3]), Segment3D(self.v[3], self.v[0]),
Segment3D(self.v[0], self.v[4]), Segment3D(self.v[1], self.v[5]),
Segment3D(self.v[2], self.v[6]), Segment3D(self.v[3], self.v[7]),
Segment3D(self.v[4], self.v[5]), Segment3D(self.v[5], self.v[6]),
Segment3D(self.v[6], self.v[7]), Segment3D(self.v[7], self.v[4]))
# Algorithm for getting 4 points
def plano_limites(self, point1, point2, point3):
plano = Plane(Point3D(point1), Point3D(point2), Point3D(point3))
good = []
for i in range(12):
a = intersection(plano, self.a[i]) # Sympy intersection
if a:
good.append(a[0])
return good
首先,请注意您的交集可能会导致多于或少于四个顶点。但是由于这个区域总是凸的,所以你可以简单地用三角形扇形画出来。
要对顶点进行排序,您需要平面的法线 n
和所有顶点的质心 c
v_i
:
c = 1/(number of vertices) * (v_1 + v_2 + v3 + ...)
那么,我们需要一个以z轴为法线的坐标系。为此,我们可以简单地定义一个任意的其他方向向量 d
并定义 x = normalize(cross(d, normal)), y = cross(normal, x)
。对于 d
与 normal
重合的情况,我们需要替代 d
.
然后我们可以在这个坐标系中计算任意一个顶点的代表角度:
angle_i = atan2(dot(x, v_i - c), dot(y, v_i - c))
按这个角度排序就完成了。
多亏了 Nico 的回答,我才能够学会如何为自己做这件事,但我认为写一篇完整的文章会很有用,因为我仍然需要进一步学习才能理解这里发生了什么。
我们需要找到一个 x- 和 y-axis,其中 z-axis 与法线对齐,我们通过取任意向量 other
的叉积来实现。如果 other
向量与法线重合,我们将需要使用不同的向量。如果两个向量的点积等于 1,则它们重合。
通过在 right-hand 坐标系中使用 (0, 1, 0)
的 other
向量(或 (0, 0, -1)
在它们重合的情况下),我们将生成更容易理解的 x-和 y-axis 个向量。这对算法来说无关紧要,但我发现这是我自己理解中最初遗漏的最关键的部分。
通过使用 (0, 1, 0)
的另一个向量,当平面的法线为 (0, 0, 1)
时,x-axis 将为 (1, 0, 0)
而 y-axis 将为(0, 1, 0)
.
通过使用 (0, 0, -1)
的另一个向量,当平面的法线为 (0, 1, 0)
时,x-axis 将为 (1, 0, 0)
而 y-axis 将为(-1, 0, 0)
.
这可以很容易地通过使用你的右手并转动你的手指指向正面 z-axis(朝向你自己)来轻松建模。
def order_on_plane(vertices, normal):
# Find the centroid of the vertices
centroid = (0, 0, 0)
for v in vertices:
centroid = add(centroid, v)
centroid = scale(centroid, 1 / len(vertices))
# Determine the 'other' vector, used to create the axis vectors
other = (0, 1, 0)
# If the other vector coincides with the normal vector, we need to use a different other
if math.fabs(math.fabs(dot(other, normal)) - 1.0) < 0.0001:
other = (0, 0, -1)
# Create the axis vectors
x_axis = normalize(cross(other, normal))
y_axis = normalize(cross(normal, x_axis))
# Sort by angle as a vector from the centroid
angles = []
for v in vertices:
vector = sub(v, centroid)
x_pos = dot(vector, x_axis)
y_pos = dot(vector, y_axis)
# y_pos is passed in first for east counter clockwise convention
angle = math.atan2(y_pos, x_pos)
angles.append(angle)
# Sort vertices by angle
vertices = sorted(zip(angles, vertices), key=lambda x: x[0])
vertices = list(map(lambda x: x[1], vertices))
return vertices
我需要在 3D 中绘制 n 个平面space。四边形是由两点创建的平面,通过一种算法,我得到了 4 个顶点来绘制四边形。我遇到的问题是顶点的顺序显然会影响结果。这就是我的意思:
我可以想象两种可能的解决方案。使用三角形并组合它们或正确排序顶点。我不知道如何做第二个想法。我试过使用三角形,但我遇到了同样的问题。
# self.planos = [('A', (500, 500, 10), (-500, 500, 10), (-500, -500, 10), (500, -500, 10))] for horizontal
# self.planos = [('A', (-500, 10, 500), (500, 10, 500), (-500, 10, -500), (500, 10, -500))] for vertical
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glDepthMask(GL_FALSE)
glBegin(GL_QUADS)
glColor(0.5, 0.5, 0.1, 0.5)
for i in range(len(self.planos)):
glVertex(self.planos[i][1][0], self.planos[i][1][2], self.planos[i][1][1])
glVertex(self.planos[i][2][0], self.planos[i][2][2], self.planos[i][2][1])
glVertex(self.planos[i][3][0], self.planos[i][3][2], self.planos[i][3][1])
glVertex(self.planos[i][4][0], self.planos[i][4][2], self.planos[i][4][1])
glEnd()
glDepthMask(GL_TRUE)
glDisable(GL_BLEND)
获取四个顶点绘制平面的交集代码:
In init method:
#Vertices of the cube
self.v = (Point3D(500, 500, 500), Point3D(-500, 500, 500), Point3D(-500, -500, 500),
Point3D(500, -500, 500), Point3D(500, 500, -500), Point3D(-500, 500, -500),
Point3D(-500, -500, -500), Point3D(500, -500, -500))
# Edges of the cube
self.a = (Segment3D(self.v[0], self.v[1]), Segment3D(self.v[1], self.v[2]),
Segment3D(self.v[2], self.v[3]), Segment3D(self.v[3], self.v[0]),
Segment3D(self.v[0], self.v[4]), Segment3D(self.v[1], self.v[5]),
Segment3D(self.v[2], self.v[6]), Segment3D(self.v[3], self.v[7]),
Segment3D(self.v[4], self.v[5]), Segment3D(self.v[5], self.v[6]),
Segment3D(self.v[6], self.v[7]), Segment3D(self.v[7], self.v[4]))
# Algorithm for getting 4 points
def plano_limites(self, point1, point2, point3):
plano = Plane(Point3D(point1), Point3D(point2), Point3D(point3))
good = []
for i in range(12):
a = intersection(plano, self.a[i]) # Sympy intersection
if a:
good.append(a[0])
return good
首先,请注意您的交集可能会导致多于或少于四个顶点。但是由于这个区域总是凸的,所以你可以简单地用三角形扇形画出来。
要对顶点进行排序,您需要平面的法线 n
和所有顶点的质心 c
v_i
:
c = 1/(number of vertices) * (v_1 + v_2 + v3 + ...)
那么,我们需要一个以z轴为法线的坐标系。为此,我们可以简单地定义一个任意的其他方向向量 d
并定义 x = normalize(cross(d, normal)), y = cross(normal, x)
。对于 d
与 normal
重合的情况,我们需要替代 d
.
然后我们可以在这个坐标系中计算任意一个顶点的代表角度:
angle_i = atan2(dot(x, v_i - c), dot(y, v_i - c))
按这个角度排序就完成了。
多亏了 Nico 的回答,我才能够学会如何为自己做这件事,但我认为写一篇完整的文章会很有用,因为我仍然需要进一步学习才能理解这里发生了什么。
我们需要找到一个 x- 和 y-axis,其中 z-axis 与法线对齐,我们通过取任意向量 other
的叉积来实现。如果 other
向量与法线重合,我们将需要使用不同的向量。如果两个向量的点积等于 1,则它们重合。
通过在 right-hand 坐标系中使用 (0, 1, 0)
的 other
向量(或 (0, 0, -1)
在它们重合的情况下),我们将生成更容易理解的 x-和 y-axis 个向量。这对算法来说无关紧要,但我发现这是我自己理解中最初遗漏的最关键的部分。
通过使用 (0, 1, 0)
的另一个向量,当平面的法线为 (0, 0, 1)
时,x-axis 将为 (1, 0, 0)
而 y-axis 将为(0, 1, 0)
.
通过使用 (0, 0, -1)
的另一个向量,当平面的法线为 (0, 1, 0)
时,x-axis 将为 (1, 0, 0)
而 y-axis 将为(-1, 0, 0)
.
这可以很容易地通过使用你的右手并转动你的手指指向正面 z-axis(朝向你自己)来轻松建模。
def order_on_plane(vertices, normal):
# Find the centroid of the vertices
centroid = (0, 0, 0)
for v in vertices:
centroid = add(centroid, v)
centroid = scale(centroid, 1 / len(vertices))
# Determine the 'other' vector, used to create the axis vectors
other = (0, 1, 0)
# If the other vector coincides with the normal vector, we need to use a different other
if math.fabs(math.fabs(dot(other, normal)) - 1.0) < 0.0001:
other = (0, 0, -1)
# Create the axis vectors
x_axis = normalize(cross(other, normal))
y_axis = normalize(cross(normal, x_axis))
# Sort by angle as a vector from the centroid
angles = []
for v in vertices:
vector = sub(v, centroid)
x_pos = dot(vector, x_axis)
y_pos = dot(vector, y_axis)
# y_pos is passed in first for east counter clockwise convention
angle = math.atan2(y_pos, x_pos)
angles.append(angle)
# Sort vertices by angle
vertices = sorted(zip(angles, vertices), key=lambda x: x[0])
vertices = list(map(lambda x: x[1], vertices))
return vertices