OpenGL: Как перевести 2D-фигуру в 3D? - PullRequest
5 голосов
/ 07 ноября 2010

У меня есть программа OpenGL (написанная на Delphi), которая позволяет пользователю рисовать многоугольник. Я хочу, чтобы он автоматически вращался (токарный станок) вокруг оси (скажем, Y asix) и получал трехмерную фигуру.

Как я могу это сделать?

Ответы [ 3 ]

5 голосов
/ 07 ноября 2010

Для простоты вы можете заставить хотя бы одну точку лежать на оси вращения.Это можно легко сделать, добавив / вычтя одно и то же значение для всех значений x и одинаковое значение для всех значений y точек в многоугольнике.Он сохранит первоначальную форму.

Остальное не так уж сложно.Выберите довольно маленький угол, скажем, один или два градуса, и определите координаты вершин многоугольника, когда он вращается вокруг оси.Затем просто соедините точки с веерными треугольниками и треугольными полосами.

Поворот точки вокруг оси - это просто базовый Пифагор.При повороте на 0 градусов у вас есть точки в их 2-й координате со значением 0 в третьем измерении.

Предположим, что точки находятся в X и Y, и мы вращаемся вокруг Y. Исходная координата 'X' представляет гипотенузу.При 1 градусе вращения имеем:

sin(1) = z/hypotenuse
cos(1) = x/hypotenuse

(при условии тригонометрических функций, основанных на градусах)

Чтобы повернуть точку (x, y) на угол T вокруг оси Y, чтобы получить3d точка (x ', y', z '):

y' = y
x' = x * cos(T)
z' = x * sin(T)

Таким образом, для каждой точки на краю вашего многоугольника вы создаете круг из 360 точек с центром на оси вращения.

Теперь создайте 3d-фигуру, например, так:

  1. создайте GL 'треугольный веер', используя вашу центральную точку и первый массив повернутых точек
  2. для каждого последующего массива,создайте треугольную полосу, используя точки в массиве, а точки в предыдущем массиве
  3. завершите, создав еще один треугольный веер с центром в центральной точке и используя точки в последнем массиве

Стоит отметить, что обычно используемые мной триггерные функции измеряют углы в радианах, а OpenGL использует градусы.Чтобы преобразовать градусы в радианы, формула:

degrees = radians / pi * 180
1 голос
/ 07 ноября 2010

По сути, стратегия состоит в том, чтобы развернуть профиль, заданный пользователем, вокруг заданной оси и сгенерировать серию треугольных полос, соединяющих смежные слои.

Предположим, что пользователь нарисовал многоугольник в плоскости XZ.Далее, предположим, что пользователь намеревается развернуться вокруг оси Z (т. Е. Линии X = 0), чтобы создать тело вращения, и что один край многоугольника лежит на этой оси (вы можете обобщить позже, когда у вас будет этот упрощенный случайрабочий).

Для достаточно простой геометрии вы можете рассматривать периметр многоугольника как функцию x = f (z), то есть предположить, что для каждого значения Z существует уникальное значение X.Когда мы переходим в 3D, эта функция становится r = f (z), то есть радиус уникален по длине объекта.

Теперь предположим, что мы хотим приблизить тело с M "кусочками"каждый охват 2 * пи / м радиан.Мы также будем использовать 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)).

0 голосов
/ 07 ноября 2010

Если вы просто хотите, чтобы он вращался, то:

glRotatef(angle,0,1,0);

будет вращать его вокруг оси Y.Если вы хотите токарный станок, то это гораздо сложнее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...