【发布时间】:2011-04-23 18:17:29
【问题描述】:
我有一个允许用户绘制多边形的 OpenGL 程序(用 Delphi 编写)。我想自动围绕一个轴(比如 Y 轴)旋转(车削)它并获得 3D 形状。
我该怎么做?
【问题讨论】:
我有一个允许用户绘制多边形的 OpenGL 程序(用 Delphi 编写)。我想自动围绕一个轴(比如 Y 轴)旋转(车削)它并获得 3D 形状。
我该怎么做?
【问题讨论】:
为简单起见,您可以强制至少一个点位于旋转轴上。您可以通过向多边形中的点的所有 x 值添加/减去相同的值以及对所有 y 值添加/减去相同的值来轻松地做到这一点。它将保持原来的形状。
其余的并不那么难。选择一个相当小的角度,比如一到两度,然后计算多边形顶点的坐标,因为它围绕轴旋转。然后用三角扇和三角条将这些点连接起来。
绕轴旋转一个点只是基本的毕达哥拉斯。在 0 度旋转时,您的二维坐标处的点在第三维中的值为 0。
假设这些点位于 X 和 Y 中,并且我们围绕 Y 旋转。原始的“X”坐标代表斜边。在旋转 1 度时,我们有:
sin(1) = z/hypotenuse
cos(1) = x/hypotenuse
(假设基于度数的三角函数)
将点 (x, y) 绕 Y 轴旋转角度 T 以生成 3d 点 (x', y', z'):
y' = y
x' = x * cos(T)
z' = x * sin(T)
因此,对于多边形边缘上的每个点,您都会生成一个以旋转轴为中心的 360 个点的圆。
现在制作一个像这样的 3d 形状:
需要注意的一点是,通常,我使用的各种三角函数以弧度为单位测量角度,而 OpenGL 使用度数。将度数转换为弧度,公式为:
degrees = radians / pi * 180
【讨论】:
基本上该策略是围绕给定轴扫描用户给出的轮廓并生成一系列连接相邻切片的三角形条带。
假设用户在 XZ 平面上绘制了多边形。此外,假设用户打算绕 Z 轴(即线 X = 0)扫描以生成旋转实体,并且多边形的一条边位于该轴上(一旦有了这个简化的情况,您可以稍后进行概括工作)。
对于足够简单的几何图形,您可以将多边形的周长视为函数 x = f(z),也就是说,假设每个 Z 值都有一个唯一的 X 值。当我们转到3D时,这个函数就变成了r = f(z),即半径在物体的长度上是唯一的。
现在,假设我们想用 M 个“切片”来近似实体,每个切片跨越 2 * Pi / M 弧度。我们也将使用 N 个“堆栈”(Z 维度中的样本)。对于每个这样的切片,我们可以构建一个三角形带,将切片 (i) 上的点与切片 (i+1) 上的点连接起来。这是一些描述该过程的伪代码:
double dTheta = 2.0 * pi / M;
double dZ = (zMax - zMin) / N;
// Iterate over "slices"
for (int i = 0; i < M; ++i) {
double theta = i * dTheta;
double theta_next = (i+1) * dTheta;
// Iterate over "stacks":
for (int j = 0; j <= N; ++j) {
double z = zMin + i * dZ;
// Get cross-sectional radius at this Z location from your 2D model (was the
// X coordinate in the 2D polygon):
double r = f(z); // See above definition
// Convert 2D to 3D by sweeping by angle represented by this slice:
double x = r * cos(theta);
double y = r * sin(theta);
// Get coordinates of next slice over so we can join them with a triangle strip:
double xNext = r * cos(theta_next);
double yNext = r * sin(theta_next);
// Add these two points to your triangle strip (heavy pseudocode):
strip.AddPoint(x, y, z);
strip.AddPoint(xNext, yNext, z);
}
}
这是基本的想法。正如 sje697 所说,您可能需要添加端盖以保持几何封闭(即实体对象,而不是壳)。但这应该足以让您继续前进。这也可以很容易地推广到环形形状(尽管在这种情况下你不会有一个一对一的 r = f(z) 函数)。
【讨论】:
如果你只是想让它旋转,那么:
glRotatef(angle,0,1,0);
将围绕 Y 轴旋转。如果你想要一台车床,那么这要复杂得多。
【讨论】: