Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Проблемы при освоении OpenGL. Подскажите решение. [Delphi, Windows]


Страницы:   1 2

MegaVolt ©   (2007-06-04 10:48:00) 

Занялся освоением OpenGL. Встретился с некоторыми трудностями красивых решений которых я не вижу. Подскажите как их обычно решают?

1. Разбиение невыпуклого полигона на треугольники. Можно ли это сделать автоматически? Полигон задан координатами вершин, лежит целиком в одной плоскости. Для примера можно взять букву "Ш".
Как разбить ручками я понимаю но очень хотелось бы разбивать автоматически. К алгоритму особых скоросных требований нет. Полгоны несложные поряка 10-16 вершин.

2. Вращение объекта мышкой. Есть объект например куб изначально ориентированный по осям. На экране он так и выглядит. Двигаем по экрану мышь и преобразовываем это движение в поворот по двум осям. Теперь куб повёрнут на некоторые углы и соответственно так отрисован. Теперь нужно преобразовать следующее движение мыши в углы поворота. Вот тут и возникает сложность.

так как в идеале дожно быть так:

glRotate(Углы для 2-го поворота)
glRotate(Углы для 1-го поворота)
рисуем куб.

Т.е. в матричном виде:
Rn*...*(R2*(R1*x))

Соответственно чтобы правильно осуществлять поворот нужно у себя в программе вычислять
Rn*...(R3*(R2*R1))

Есть ли другой способ осуществить задуманное? Можно ли вычитать матрицу из OpenGL? Загружать можно, домножать на мою можно а обратно извлеч можно?


Sapersky   (2007-06-05 17:28:00) [21]

Само слово "полигон" (поли == много!!!!) явно означает "многоугольник". Хотя, действительно, в 3D-графике "полигонами" часто называют треугольники. Но это скорее профессиональный жаргон, а вовсе не истина в последней инстанции :)


homm   (2007-06-05 17:11:00) [22]

> [7] Yashin ©   (04.06.07 20:47)
> Никогда не выводил полигоны, а зачем, если треугольники
> намного удобней

[9] MegaVolt © (05.06.07 11:50)
> Тем более что у меня полигоны плоские и как они будут разбиты
> на треугольники совершенно без разницы.

Полигон == треугольник!!!!
Теперь ты, Yashin, никогда впредь и не выводи полигоны, а ты, MegaVolt, так и продолжай «разбивать» их на треугольники! Вот смеху то будет :)


Rial   (2007-06-05 17:02:00) [23]

> [9] MegaVolt ©   (05.06.07 11:50)
> Одно маленькое дополнение. Не 2 вызова а три. Потому что
> появляется составляющая принадлежащая третьей оси.

Дополнение неверно.
Например, поворот по осям Z и Y вектора (X, Y, Z):

fTmp :=X * Cos(aZ) - Y * Sin(aZ);
X'   := fTmp * Cos(aY) - Z * Sin(aY);
Y'   := Y * Cos(aZ) + X * Sin(aZ);
Z'   := Z * Cos (aY) + fTmp * Sin(aY);

Очевидно, перебирая все возможные aZ, aY для заданных
X, Y, Z, покрываем все возможные значения X', Y', Z'.


> Я наоборот хочу упростить :)
> Я хочу через OpenGL считать конечную матрицу повторота.
> Т.е. загрузил начальную матрицу применил к ней первый поворот.
> Выгрузил запомнил. Когда появились новые повороты загрузил
> обратно повернул выгрузил :) В результате всё считает карточка
> :) И обратное разложение на углы даже и не понадобится так
> как уже будет готовая матрица поворота.

Глупости. А если нужно будет сделать поворот относительный ?
Ведь у тебя будут сохранены только повороты единичной матрицы.
Иногда свой велосипед изобретать полезно, но в данным случае
ты получишь частное решение, неприменимое в общем случае.


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

"Плоские полигоны" - хм ?..
А вообще рекомендую карточке "подсовывать" исключетильно треугольники,
таким образом ты получишь наилучшее быстродействие.


> [10] @!!ex_   (05.06.07 12:31)

Присоединяюсь, просто хотелось полнее раскрыть суть вопроса. :)


@!!ex_   (2007-06-05 12:31:00) [24]

> Одно маленькое дополнение. Не 2 вызова а три. Потому что
> появляется составляющая принадлежащая третьей оси.

LOL. Зачем ТРИ вращения??? Вроде как бы любой поворот достигается двумя вращениями.


> Я наоборот хочу упростить :)
> Я хочу через OpenGL считать конечную матрицу повторота.
> Т.е. загрузил начальную матрицу применил к ней первый поворот.
> Выгрузил запомнил. Когда появились новые повороты загрузил
> обратно повернул выгрузил :) В результате всё считает карточка
> :) И обратное разложение на углы даже и не понадобится так
> как уже будет готовая матрица поворота.

Как то странно упрощаешь... Через попу.
glLoadIdeti
glPushMatrix
glPopMatrix


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

glu и glut работают на ЦПУ. И никакого отношения к карточке не имеют.
Я могу еще раз повторить банальность:
ВСЕ что делает карточка - получает вершину, преобразует, получает  треугольник, преобразует и выводит.
Ну еще может в роли хранилища данных выступать, для текстурок, например. ВСЕ. Запомните! Карточка не будет вам НИЧЕГО разбивать.


@!!ex_   (2007-06-05 12:31:00) [25]

Чорт.
glLoadIdentity


MegaVolt   (2007-06-05 11:50:00) [26]

Rial
>Про (3) нечего сказать, извини уж, что так вышло. ;)

Ничего. Подождём может кто подскажет. За совет по делу огромное спасибо. Это то что я искал.

>Еще углы - еще поворот. Таким образом этот вектор у тебя
>будет "образцом" поворота.
>Перед отрисовкой получай из вектора всего 2 угла поворота
>по осям и делай только 2 вызова glRotate.

Одно маленькое дополнение. Не 2 вызова а три. Потому что появляется составляющая принадлежащая третьей оси.

>Матрицы... вот тут то как раз ты зря пытаешься усложнить себе жизнь.

Я наоборот хочу упростить :)
Я хочу через OpenGL считать конечную матрицу повторота. Т.е. загрузил начальную матрицу применил к ней первый поворот. Выгрузил запомнил. Когда появились новые повороты загрузил обратно повернул выгрузил :) В результате всё считает карточка :) И обратное разложение на углы даже и не понадобится так как уже будет готовая матрица поворота.

Yashin
>Никогда не выводил полигоны, а зачем, если треугольники намного удобней

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

Итак остался только третий вопрос. Кто может помочь выручайте.


@!!ex_   (2007-06-05 10:01:00) [27]

> [7] Yashin ©   (04.06.07 20:47)

Хм. Это у художников полигон - квад, а у порграммеров, полигон - простейший элемент геометрии, то бишь треугольник. :)
Во всяком случае в том обществе, где я кручусь.


Yashin   (2007-06-04 20:47:00) [28]

Никогда не выводил полигоны, а зачем, если треугольники намного удобней


Rial   (2007-06-04 19:05:00) [29]

Про (3) нечего сказать, извини уж, что так вышло. ;)

получит матрицы:
With PMatrixes^ do begin
 glGetFloatv(GL_Projection_Matrix, @Proj);
 glGetFloatv(GL_ModelView_Matrix,  @Model);
 glGetFloatv(GL_Texture_Matrix,    @Tex);
end;//With);

установить матрицы:
Var
   MatrixMode : GLInt;
begin
glGetIntegerv (GL_MATRIX_MODE, @MatrixMode);
With PMatrixes^ do begin
 glMatrixMode(GL_PROJECTION);
 glLoadMatrixF(@Proj);
 glMatrixMode(GL_MODELVIEW);
 glLoadMatrixF(@Model);
 glMatrixMode(GL_TEXTURE);
 glLoadMatrixF(@Tex);
end;//With
glMatrixMode(MatrixMode);

Type
    TGLMatrix = Array [0 .. 3, 0 .. 3] of GLFloat;
    TGLMatrixes = record
     Model : TGLMatrix;
     Proj  : TGLMatrix;
     Tex   : TGLMatrix;
    end;
    PGLMatrixes = ^ TGLMatrixes;

Только это немного неверное решение.
Задай сналача единичный вектор (1, 0, 0).
Получаешь первые два угла по каким то осям - поверни
его с помощью формул поворота на эти углы.
Еще углы - еще поворот. Таким образом этот вектор у тебя
будет "образцом" поворота.
Перед отрисовкой получай из вектора всего 2 угла поворота
по осям и делай только 2 вызова glRotate.
Эта два угла можно получить с помощью одного преобразования,
обратного повороту.
Матрицы... вот тут то как раз ты зря пытаешься усложнить себе жизнь.

Поворот делать просто:
procedure chCoords(Const X, Y, Cs, Sn : GLFloat; Var OutX, OutY : GLFloat);
begin
OutX:=X * Cs - Y * Sn;
OutY:=Y * Cs + X * Sn;
end;


MegaVolt   (2007-06-04 18:09:00) [30]

>Ну, это же скучно. :) Зачем искать легкие пути ?..

Как раз и открыл тему по поиску лёгких путей.
По другим вопросам есть что сказать?


Rial   (2007-06-04 17:47:00) [31]

> [2] Sapersky   (04.06.07 15:00)
> Есть же вроде стандартные средства тесселяции, gluTess<...>

Ну, это же скучно. :) Зачем искать легкие пути ?..


MegaVolt   (2007-06-04 15:36:00) [32]

>Есть же вроде стандартные средства тесселяции, gluTess<...>

Есть но я их не заметил. Спасибо то что доктор прописал.

Вопрос 2 остаётся открытым. и ещё добавляется новый:

3. При триангуляции полигона в местах соприкосновения граней треугольников получаются небольшие просветы. Что то похожее на прозрачную паутинку. Как от этого можно избавиться?


Sapersky   (2007-06-04 15:00:00) [33]

Есть же вроде стандартные средства тесселяции, gluTess<...>


Rial   (2007-06-04 14:56:00) [34]

По первому вопросу могу предложить свой способ с использованием текстуры.
Как грузить текстуры, как их потом использовать - это все из другой басни.
Я предлагаю лишь несложный алгоритм, отвечающий твоим требованиям
с соблюдением определенной степени точности (если размер грани
будет не меньше 2х пикселей относительно размера текстуры).
Для построения используется любой замкнутый набор из точек в
области единичного прямоугольника: допустимы самопересечения и т.п.
Вобщем, если будет желание, алгоритм можно выдрать без проблем. :)

Type
    //точка в 2д пространстве
    TPos2f = record
     //соответствующие координаты
     X : GLFloat;
     Y : GLFloat;
    end;

    //массив из точек
    TPos2fArray = Array[0 .. 0] of TPos2f;

Var
   pPoints  : PPos2fArray;

function CoordToAngle(Const X, Y : Single) : Single;
begin
If (X = 0.0) then begin
 If (Y >= 0.0) then Result := HalfPi
               else Result := - HalfPi;
 Exit;
end;
Result :=ArcTan2(Y, X);
end;

procedure FindFreePoint(Const X1, Y1, X2, Y2, X3, Y3, fStep : Single; Var X, Y : Single);
Var
   A1, A2, A, AK : Single;
   Sn, Cs : Extended;
begin
A1 :=CoordToAngle(X1 - X2, Y1 - Y2);
A2 :=CoordToAngle(X3 - X2, Y3 - Y2);
A  :=(A2 + A1) / 2.0;
If(A2 - A1 > Pi) or (A1 - A2 > Pi) then
 A := A + Pi;
AK :=Abs(A2 - A1);
AK :=Min(AK, Abs(TwoPi - AK));
AK :=Max(AK, 0.01);
AK :=Min(fStep / Sin(AK), (Hypot(X1 - X2, Y1 - Y2) + Hypot(X3 - X2, Y3 - Y2)));
SinCos(A, Sn, Cs);
X := X2 + Cs * AK;
Y := Y2 + Sn * AK;
end;

function Inhalt(Const AX1, AY1, AX2, AY2, BX1, BY1, BX2, BY2 : Single; Const bFl : Boolean) : Boolean;

function GetK(Const X, Y : Single) : Single;
begin
 If (X = 0.0) then Result:=1.0e+4
              else Result:=Y / X;
end;

Var
   X, Y : Single;

function Insect(Const X1, X2, Y1, Y2 : Single) : Boolean;
begin
 Result :=((X >= X1) and (X <= X2)) or ((X <= X1) and (X >= X2))
          and
          ((Y >= Y1) and (Y <= Y2)) or ((Y <= Y1) and (Y >= Y2));
end;

Var
   AK, BK : Single;
begin
AK :=GetK(AX2 - AX1, AY2 - AY1);
BK :=GetK(BX2 - BX1, BY2 - BY1);
X  :=GetK(AK - BK, BY1 - AY1);
If(AY1 > AY2) then
 Y :=AY2 + BK * X
              else
 Y :=AY1 + AK * X;
Result :=(Insect(AX1, AX2, AY1, AY2)) and (Insect(BX1, BX2, BY1, BY2));
end;

function TMainForm.Reinspect(Const X1, Y1, X2, Y2 : Single; Const Index : Integer; Const bFl : Boolean) : Boolean;
Var
   I : Integer;
begin
Result :=True;
For I:=0 to FCount - 2 do
 If (I <> Index)and
    (Inhalt(X1, Y1, X2, Y2, pPoints^[I].X, pPoints^[I].Y, pPoints^[I + 1].X, pPoints^[I + 1].Y, bFl))
 then
  Exit;
Result:=False;
end;

procedure TMainForm.BuildTex;
Const
     nSize = 512;
     AlphaOptions : TAlphaOptions =
     (
      Enabled    : True;
      R          : 0.56;
      G          : 0.33;
      B          : 0.11;
      AMulti     : -5.0;
      TexVisible : $20
      );
Var
   I      : Integer;
   Bitmap : TExBitmap;
   nC     : Integer;
   bX, bY : Single;
begin
If(Not FFilled) then
 Exit;
Bitmap:=TExBitmap.Create;
Try
 With Bitmap do begin
  Width  :=nSize;
  Height :=nSize;
  Canvas.Brush.Color :=clBlack;
  Canvas.Rectangle(0, 0, nSize, nSize);
  Canvas.Pen.Width :=1;
  Canvas.Pen.Color :=clWhite;
  //рисуем линии
  nC :=nSize div 2;
  For I:=0 to FCount - 2 do begin
   Canvas.MoveTo(Round(nC * (1.0 + pPoints^[I].X)),     Round(nC * (1.0 - pPoints^[I].Y)));
   Canvas.LineTo(Round(nC * (1.0 + pPoints^[I + 1].X)), Round(nC * (1.0 - pPoints^[I + 1].Y)));
  end;
  Canvas.Brush.Color :=clWhite;
  For I:=0 to FCount - 3 do
    If(I = 0) or
      (Reinspect(pPoints^[I].X, pPoints^[I].Y, pPoints^[I + 1].X, pPoints^[I + 1].Y, I, False))then begin
    FindFreePoint(pPoints^[I].X, pPoints^[I].Y,
                  pPoints^[I + 1].X, pPoints^[I + 1].Y,
                  pPoints^[I + 2].X, pPoints^[I + 2].Y,
                  2.0 / nC, bX, bY);
    Canvas.FloodFill(Round(nC * (1.0 + bX)),     Round(nC * (1.0 - bY)), clWhite, fsBorder);
   end;
//   bitmap.SaveToFile('Tmp.bmp');
  If(Tex <> Nil) then
   RTex.Delete(Tex);
  Tex := RTex.CreateTexture(Bitmap, False, @AlphaOptions);
 end;//With Bitmap
Finally
 Bitmap.Free;
end;
end;


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо