如何在三维空间中绘制两个相对的圆圈
我正在尝试使用Python的Pyglet库绘制一个3D网络。
我用球体来表示蛋白质,这些球体是根据它们的坐标(x, y, z)直接绘制的,而不是先在(0,0,0)的位置绘制再移动到目标位置。现在我想用圆柱体把这些球体连接起来。我打算通过计算每个球体坐标周围的一圈顶点来实现这个目标,然后用四边形把它们连接起来。
不过,我在计算这些顶点时遇到了一些困难,想让两个圆圈能够面对彼此。
这是我目前的代码:
class Cylinder(object):
def __init__(self, start, end, radius, slices, batch, group=None):
"""
:param start: The (x,y,z) coordinates of the cylinder's start point
:type start: (float, float, float)
:param end: The (x,y,z) coordinates of the cylinder's end point
:type end: (float, float, float)
:param radius: The radius of the cylinder
:type radius: float
:param slices: Number of sections to divide the cylinder into
:type slices: int
:param batch: The pyglet batch to add the cylinder to
:type batch: pyglet.graphics.Batch
:param group: The pyglet group to add the cylinder to
:type group: int
"""
self.start_x, self.start_y, self.start_z = start
self.end_x, self.end_y, self.end_z = end
self.num_vertices = 6 * slices
self.num_faces = slices
self.num_indexes = 4 * self.num_faces
self.vertices = numpy.zeros(self.num_vertices, dtype=numpy.float)
self.normals = numpy.zeros(self.num_vertices, dtype=numpy.float)
self.indexes = numpy.zeros(self.num_indexes, dtype=numpy.uint32)
step = 2 * pi / slices
lat = 0
lon = 0
for i in xrange(slices):
sin_lat = sin(lat)
cos_lat = cos(lat)
sin_lon = sin(lon)
cos_lon = cos(lon)
# Calculate vertex positions
sx = self.start_x + radius * cos_lon * sin_lat
sy = self.start_y + radius * sin_lon * sin_lat
sz = self.start_z + radius * cos_lat
ex = self.end_x + radius * cos_lon * sin_lat
ey = self.end_y + radius * sin_lon * sin_lat
ez = self.end_z + radius * cos_lat
# Calculate vertex normals
snx = cos_lon * sin_lat
sny = sin_lon * sin_lat
snz = cos_lat
enx = cos_lon * sin_lat
eny = sin_lon * sin_lat
enz = cos_lat
# Add vertex positions and normals to
index = 6 * i
self.vertices[index:index + 6] = (sx, sy, sz, ex, ey, ez)
self.normals[index:index + 6] = (snx, sny, snz, enx, eny, enz)
# Go to next vertex pair
lat += step
for i in xrange(slices):
self.indexes[4 * i:4 * i + 4] = ((2 * i),
(2 * i + 2) % (self.num_vertices // 3),
(2 * i + 3) % (self.num_vertices // 3),
(2 * i + 1))
if batch:
self.vertex_list = batch.add_indexed(len(self.vertices) // 3,
gl.GL_QUADS,
group,
self.indexes,
('v3f/static', self.vertices),
('n3f/static', self.normals))
def delete(self):
self.vertex_list.delete()
任何帮助都将非常感激!
1 个回答
0
为什么需要面对面的圆圈呢?
要构建一个管子,你需要以下步骤:
- 先计算从点A到点B的向量AB,以及它的垂直方向(我们叫它Norm);
- 把这个垂直方向的长度缩放到管子的半径大小;
开始添加顶点来构建管子,顶点的数量叫做Seg:
I := 0; for K := 0 to Seg-1 do begin TubeCos := Cos(K/Seg*2*pi); TubeSin := Sin(K/Seg*2*pi); Vert[I].Normal := (-Norm.X*TubeSin, TubeCos, -Norm.Y*TubeSin); Vert[I].Vert := (A.X-Norm.X*TubeRad*TubeSin, TubeRad*TubeCos, A.Y-Norm.Y*TubeRad*TubeSin); I++; Vert[I].Normal := (-Norm.X*TubeSin, TubeCos, -Norm.Y*TubeSin); Vert[I].VertB := (B.X-Norm.X*TubeRad*TubeSin, TubeRad*TubeCos, B.Y-Norm.Y*TubeRad*TubeSin); I++; end;
把这些顶点连接成三角形(连接的顺序很重要) //在这个例子中 0-1-2, 2-3-1, 2-3-4, 4-5-3, ...