Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.01.27;
Скачать: CL | DM;

Вниз

Как рисовать 3D и 2D объекты в одной сцене?   Найти похожие ветки 

 
Creative   (2006-12-12 16:05) [0]

Есть процедура
procedure RenderScene:
begin
A.Render; // А и В - произвольные объекты
B.render;
end;


Метод Render объектов А и В обычную процедуру рисования
glPushMatrix;
...// трансформации
....//рисование
glPopMatrix;

НО: Объект А должен находиться в двумерном пространстве и иметь фиксированный размер и координату(например это какое то системное окошко, индикатор, кнопка и так далее), а объект B - находиться в трехмерном пространстве и подвергаться различного рода трансформациям (собственно объекты, которые видит пользователь).

Как совместить рисование первого и второго?

Мне кажется, что проблема в том, что в Resize можно описать только ОДНУ систему координат - либо glOrtho, либо gluPerspective, хотя возможно я и ошибаюсь.


 
Fredy314 ©   (2006-12-12 18:52) [1]

Ну так пусть будут системные окошка в перспективе, красиво расставить их в 3-Д чтоб все думали что так надо, а чтоб поворачивались вместе с камерой  думаю сможешь сделать.


 
Rial ©   (2006-12-12 19:58) [2]

glOrtho или gluPerspective всего лишь выполняют
некоторые операции с матрицами OpenGL.
Надо сначала сделать
glLoadIdentify(), настроить все как надо
для Ortho, запомнить все текущие матрицы в
некоторую область памяти.
Теперь опять грузим единичную, настраиваем
все для режима перспективы и тоже ее сохраняем.

Теперь по мере необходимости загружаем нужные матрицы.
Вот и все, все просто :)

Вот вырезанный кусок кода, который может навести на
умную мысль:

    TGLMatrix = Array [0..3, 0..3] of GLFloat;

    TGLMatrixes = record
     Model : TGLMatrix;
     Proj  : TGLMatrix;
     Tex   : TGLMatrix;
    end;

    PGLMatrixes = ^ TGLMatrixes;

procedure riglSaveMatrix(Const PMatrixes : PGLMatrixes);
begin
With PMatrixes^ do begin
 glGetFloatv(GL_PROJECTION_MATRIX, @Proj);
 glGetFloatv(GL_MODELVIEW_MATRIX,  @Model);
 glGetFloatv(GL_TEXTURE_MATRIX,    @Tex);
end;//With
end;

procedure riglLoadMatrix(Const PMatrixes : PGLMatrixes);
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);
end;


 
RzCoDer ©   (2006-12-12 20:11) [3]

glOrtho


 
Creative   (2006-12-13 10:32) [4]


> Теперь по мере необходимости загружаем нужные матрицы.


Я извиняюсь за тупой вопрос, я правильно понимаю, что на экране будет отображаться и объект, нарисованный в перспективе, и объект, нарисованный в орто? Загрузка последующей матрицы не стирает предыдущую?

А как в таком случае будет выглядеть ResizeScene? Ему ведь пофигу какие объекты и в какой момент нарисованы, он ведь просто пересчитывает размер области вывода и утанавливает какую-то одну проекцию. Не ставить же прорисовку в Resize?


 
Vga ©   (2006-12-13 14:20) [5]

> Я извиняюсь за тупой вопрос, я правильно понимаю, что на
> экране будет отображаться и объект, нарисованный в перспективе,
> и объект, нарисованный в орто? Загрузка последующей матрицы
> не стирает предыдущую?

Стирает, но все, что нарисовано с помощью первой матрицы останется. А с новой матрицей будет рисоваться поверх.

> А как в таком случае будет выглядеть ResizeScene? Ему ведь
> пофигу какие объекты и в какой момент нарисованы, он ведь
> просто пересчитывает размер области вывода и утанавливает
> какую-то одну проекцию. Не ставить же прорисовку в Resize?

Он даже не влияет на то, что уже нарисовано (не считая изменения вьюпорта). Resize влияет только на то, что будет нарисовано после него (если я правильно понял, как у тебя сделано). Тебе предлагают в Resize посчитать матрицы для данного разрешения и сохранить их в переменные. А потом при отрисовке грузить нужную матрицу (загрузил 3D, отрисовал трехмерные объекты, загрузил 2D, отрисовал двухмерные объекты).


 
Creative   (2006-12-13 16:03) [6]

Я на правах примера поступила проще: написала процедуру DrawScene:

glPushMatrix;
glOrtho();
// манипуляции над матрицами
//отрисовка объекта
glPopMatrix;

glPushMatrix;
gluPerspective();
// манипуляции над матрицами
//отрисовка объекта
glPopMatrix;

Все рисуется именно так как надо, и я заметила, что в Resize вообще можно не ставить теперь пересчет матриц, кажется и так все ресайзится. Скажите - я что-то не упустила, это глупо?

И еще вопрос: не могу найти в документации - есть такой стиль окна, чтобы оно могло масштабироваться только пропорционально, или это самому задавать нало?


 
RzCoDer ©   (2006-12-13 16:18) [7]

лучше сначало рисовать 3D объект а после него уже всё 2D


 
Creative   (2006-12-13 16:39) [8]


> лучше сначало рисовать 3D объект а после него уже всё 2D


А почему? Это единственная претензия?


 
MeF Dei Corvi ©   (2006-12-13 16:49) [9]


> А почему?

Потому, что при определенном стечении обстоятельств(например, при включенном DepthTest) 3д объект может перекрыть 2д, несмотря на то, что 2д нарисован позднее. Если я не прав, поправьте :)

> есть такой стиль окна, чтобы оно могло масштабироваться
> только пропорционально, или это самому задавать нало?

Насколько я знаю, такого стиля нет, хотя могу и ошибаться. Скорее всего, придётся регулировать это программно.


 
Creative   (2006-12-13 16:54) [10]

Меня очень волнует реакция на вот это утверждение:

я заметила, что в Resize вообще можно не ставить теперь пересчет матриц, кажется и так все ресайзится


 
MeF Dei Corvi ©   (2006-12-13 17:31) [11]


> Меня очень волнует реакция на вот это утверждение:

Что именно волнует? :) Смену проекции в Resize помещают только затем, чтобы уменьшить количество вычислений, производимых процессором и видеокартой, т.к. Resize вызывается только при смене размеров окна, когда Draw вызывается при перерисовке, а перерисовка обычно происходит во много раз чаще, чем Resize. В данном случае, менять проекцию придётся в любом случае. Если производительность - не критичный фактор(т.е. если пара миллисекунд не важна), то можно оставить как есть.


 
Creative   (2006-12-13 17:34) [12]


> MeF Dei Corvi ©   (13.12.06 16:49) [9]
> > А почему?Потому, что при определенном стечении обстоятельств(например,
>  при включенном DepthTest) 3д объект может перекрыть 2д,
>  несмотря на то, что 2д нарисован позднее. Если я не прав,
>  поправьте :)


Вот кстати и вопрос на тему, что за чем рисовать: Я рисую 3D объект, потом 2D объект (квадрат), а потом хочу вывести надписть поверх квадрата (с помощью glPrint("Caption")). Но надпись явно лежит ПОД кнопкой. Почему и как с этим бороться?


 
MeF Dei Corvi ©   (2006-12-13 17:41) [13]

Попробуй так:
glPushMatrix;
gluPerspective();
...
glPopMatrix;


glDisable(GL_DEPTH_TEST);
glPushMatrix;
glOrtho();
...
glPopMatrix;

glEnable(GL_DEPTH_TEST);


 
Creative   (2006-12-13 17:47) [14]


> MeF Dei Corvi ©   (13.12.06 17:41) [13]


Получилось, получилось!!!!!! Спасибо :-)


 
Creative   (2006-12-13 17:59) [15]

А может кто-нибудь объяснить, почему угол наклона в направлении оси X задается именно отношением ширины области вывода к ее высоте?


 
Piroxyline ©   (2006-12-13 19:16) [16]

Имхо, это уже к создателям OpenGL"я


 
Piroxyline ©   (2006-12-13 19:19) [17]

Хотя, наверное, из-за подобной картины:


         |
   A\--| B
       \ |
-------+-------
         |\
       C|-\ D
         |   \

koeff = AB/CD

Или что-то типа такого. По крайней мере, мы похожую картину сейчас по физике разбирали


 
Creative   (2006-12-14 11:13) [18]


> Rial ©   (12.12.06 19:58) [2]


Я попробовала написать сохранение матриц:

type

TGLMatrix = Array [0..3, 0..3] of GLFloat;

   TGLMatrixes = record
    Model : TGLMatrix;
    Proj  : TGLMatrix;
    Tex   : TGLMatrix;
   end;

   PGLMatrixes = ^TGLMatrixes;

   procedure SaveMatrix(Const PMatrixes : PGLMatrixes);
   procedure LoadMatrix(Const PMatrixes : PGLMatrixes);

var
 OrthoMatrix : PGLMatrixes;
 PerspMatrix : PGLMatrixes;

implementation

procedure SaveMatrix(Const PMatrixes : PGLMatrixes);
begin
With PMatrixes^ do begin
glGetFloatv(GL_PROJECTION_MATRIX, @Proj);
glGetFloatv(GL_MODELVIEW_MATRIX,  @Model);
glGetFloatv(GL_TEXTURE_MATRIX,    @Tex);
end;//With
end;

procedure TCWnd.ResizeGLScene(Width, Height: integer);
begin
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity;
 glOrtho(0, Width, Height, 0, -1, 1);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity;
 glViewport(0, 0, Width, Height);
 SaveMatrix(OrthoMatrix);

 glMatrixMode(GL_PROJECTION);
 glLoadIdentity;
 gluPerspective(30, Width/Height, 1.0, 15.0);
 glRotate(30,1.0,0.0,0.0);
 glRotate(60,0.0,1.0,0.0);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity;
 glViewport(0, 0, Width, Height);
 SaveMatrix(PerspMatrix);
end;


Но вероятно я как то неправильно сделала, и PMatrixes^  = NIL. Поправьте меня, пожалуйста.


 
Vga ©   (2006-12-14 12:50) [19]

> [18] Creative   (14.12.06 11:13)

А память под матрицы выделить? Либо GetMem(OrthoMatrix, SizeOf(TGLMatrixes)) и то же для второй. Еще можно убрать объявление PGLMatrixes и передавать TGLMatrixes как var в SaveMatrix и как const в Loadmatrix


 
Creative   (2006-12-14 12:56) [20]


> А память под матрицы выделить? Либо GetMem(OrthoMatrix,
> SizeOf(TGLMatrixes)) и то же для второй. Еще можно убрать
> объявление PGLMatrixes и передавать TGLMatrixes как var
> в SaveMatrix и как const в Loadmatrix


А я проше сделала (ладно, может и не проще, понятнее для меня) - сделала TGLMatrixes не рекордом, а классом и создала две переменные-объекты класса. Все работает, проекции грузятся, как раз то, что я хотела.
Этот способ не хуже?

Я кстати не мгу понять: почему в обоих процедурах (Save, Load) - аргумент - константа?


 
Vga ©   (2006-12-14 13:40) [21]

> [20] Creative   (14.12.06 12:56)
> Я кстати не мгу понять: почему в обоих процедурах (Save,
> Load) - аргумент - константа?

Я тоже. Можно const оттуда убрать. Смысла передавать указатель по ссылке - не вижу.


 
Rial ©   (2006-12-15 01:31) [22]

> [21] Vga ©   (14.12.06 13:40)
> > [20] Creative   (14.12.06 12:56)
> > Я кстати не мгу понять: почему в обоих процедурах (Save,
> > Load) - аргумент - константа?
> Я тоже. Можно const оттуда убрать. Смысла передавать указатель
> по ссылке - не вижу.

Нет, вы конечно правы.
Код с Const и без него будет сгенерирован компилятором
абсолютно идентичный.
Но вот только указатель это или нет - это тут очевидно.
А следить за каждой такой мелочью порой очень сложно :)
Если бы аргумент был TGLMatrixes - потери были бы налицо.
Так что это страховка на будущее.


> [10] Creative   (13.12.06 16:54)
> Меня очень волнует реакция на вот это утверждение:
>
> я заметила, что в Resize вообще можно не ставить теперь
> пересчет матриц, кажется и так все ресайзится

Все дело в том, что в gluPerspective используется ArcTan.
А это достаточно медленная арифметическая операция, что иногда критично.
Resize иногда выполняется 2-3 раза за всю работу приложения.


> [20] Creative   (14.12.06 12:56)
> А я проше сделала (ладно, может и не проще, понятнее для
> меня) - сделала TGLMatrixes не рекордом, а классом и создала
> две переменные-объекты класса.


Это правильнее безусловно. Но есть одна мелочь. Не исключаю,
что у меня кривые руки, но когда я переводил достаточно большой кусок
кода OpenGL на ООП (объектов вышло достаточно много), то потерял 20%
производительности. Так что главное - не "намельчить".


 
Creative   (2006-12-15 10:18) [23]


> Rial ©   (15.12.06 01:31) [22]
когда я переводил достаточно
> большой кусоккода OpenGL на ООП (объектов вышло достаточно
> много), то потерял 20%производительности. Так что главное
> - не "намельчить".


А как вы оцениваете производительность программы? Время выпорнения операций? Или что это?
Не намельчить - в смысле - не пытаться сделать классы из всего, чего только можно?


 
Rial ©   (2006-12-15 16:40) [24]

> [23] Creative   (15.12.06 10:18)
> А как вы оцениваете производительность программы? Время
> выпорнения операций? Или что это?

1. Количество кадров, которые успевают отрисоваться.
Подходит только если кадры рисуются постоянно и нет
счетчика ограничейний. Способ самый ущербный.
2. Обжее время, затраченное на выполнение все операций
поделить на прошедшее время. Имеется ввиду не разовая
задача, конечно, а отрисовка с относительно постоянным
количеством кадров.
3.Операции считать. Можно посчитать с точностью до
+- 0.1 мс. Статистика, разные условия выполнения и т.п.
Статистику лучше считать временно дав RealTime.

> Не намельчить - в смысле - не пытаться сделать классы из
> всего, чего только можно?

Вот это в точку подмечено.
Особенно заметно это там, где производятся
арифметические рассчеты.
Если класс заменяет record с двумя полями,
а значение полей извлекаются через виртуальные методы
родителя, да еще через что то типа
function GetValue : TValue;
begin
Result:=FValue;
end;

то тут почуствуешь в полной мере все "достоинства" ооп :)
Итог - замедление раз в 5-10.


 
Creative   (2006-12-15 16:50) [25]


> 1. Количество кадров, которые успевают отрисоваться.


FPS?


> нет счетчика ограничейний.


а что такое счетчик ограничений?


> Статистику
> лучше считать временно дав RealTime.


а что значит "временно дать RealTime"?


> Если класс заменяет
> record с двумя полями,а значение полей извлекаются через
> виртуальные методыродителя, да еще через что то типаfunction
> GetValue : TValue;begin Result:=FValue;end;то тут почуствуешь
> в полной мере все "достоинства" ооп :)Итог - замедление
> раз в 5-10.


Вот так так...а я то думала, чо расписывать извлечение значений полей через GetValue - это ужас как круто....

Я правильно понимаю, что использоваться рекорд - быстрее, а класс - многофункциональнее? Или есть еще принципиальные различия? Я напрмимер по странному стечению обстоятельств сначала научилась работать с классами, а про рекорды узнала позже, поэтому тебперь мне с ними трудно.


 
Rial ©   (2006-12-15 17:28) [26]

> [25] Creative   (15.12.06 16:50)
> FPS?

Да, оно самое.


> а что такое счетчик ограничений?

Ну, например, счетчик такого типа, что не разрешает
перерисовывать экран чаще, чем раз в 20мс.
Вообще, имхо, лучше делать постоянное FPS,
потому как наверняка есть еще какие рассчеты,
а не только вывод на экран. А рассчеты наверняка
четко привязаны ко времени
(ну хотябы падение тела в реальном времени).
Смыла не вижу перерисовывать экран чаще, чем эго
содержимое должно изменяться.


> а что значит "временно дать RealTime"?

Приоритет процесса.
procedure SetPriority(Const PriorityClass, ThreadClass : Integer);
Var ProcessID : DWORD;
   ProcessHandle : THandle;
   ThreadHandle : THandle;
begin
ProcessID;=GetCurrentProcessID;
ProcessHandle:=OpenProcess(PROCESS_SET_INFORMATION, False, ProcessID);
SetPriorityClass(ProcessHandle, PriorityClass);
ThreadHandle:=GetCurrentThread;
SetThreadPriority(ThreadHandle, ThreadClass)
end;



> Вот так так...а я то думала, чо расписывать извлечение значений
> полей через GetValue - это ужас как круто....

Круто, конечно.
Но это в итоге лишнии инструкции call и ret.
Так то, с т.з. переменных класса, это те же
поля записей.
Name:=MyClass.FName;
Name:=MyRecord.Name;

- разницы особой нет.
Только в случае с классом получаем лишнюю инструкцию move,
ибо переменная MyClass - своего рода указатель на запись.
Может, я мелочный, конечно. Но, имхо, все эти мелочи
со временем могут в большой ком снежный сложиться.

> Я правильно понимаю, что использоваться рекорд - быстрее,
> а класс - многофункциональнее? Или есть еще принципиальные
> различия?

Ну, рекод  - это не более чем более удобный доступ
к области памяти.
Например, есть Data : Pointer, в ней лежат Integer и 2 Byte.
Намного удобнее и понятнее сделать так:
TRec = packed record
I : Integer;
B1, B2 : Byte;
end;
PRec = ^TRec;
...
PRec(Data)^.B2:=10;


Чем вот так:

PByteArray(Data)^[SizeOf(Integer) + SizeOf(Byte) * 2]:=10;

А класс - это нечто намного большее.
Слышали Вы про виртуальные, абстрактные методы и т.п.
Они разработку значительно упрощают.
И целостность данных позволяют грамотно обеспечить.
Все до тех пор, пока не идет война за каждый тик процессора :)


 
MeF Dei Corvi ©   (2006-12-15 21:54) [27]


> > а что значит "временно дать RealTime"?

У меня такие процессы вешают всю систему сразу же :)


 
Creative   (2006-12-18 10:36) [28]


> Ну, рекод  - это не более чем более удобный доступк
> области памяти.Например, есть Data : Pointer, в ней лежат
> Integer и 2 Byte.Намного удобнее и понятнее сделать так:
> TRec = packed record
> I : Integer;
> B1, B2 : Byte;end;
> PRec = ^TRec;
...
> PRec(Data)^.B2:=10;
> Чем вот так:PByteArray(Data)^[SizeOf(Integer)
> + SizeOf(Byte) * 2]:=10;


А почему  PRec = ^TRec, а не Rec: TRec?


>А класс - это нечто намного большее.
> Слышали Вы про виртуальные, абстрактные методы и т.п.Они
> разработку значительно упрощают.И целостность данных позволяют
> грамотно обеспечить.Все до тех пор, пока не идет война за
> каждый тик процессора :)


А что тогда? Опять возвращаются к рекордам?


 
Creative   (2006-12-18 10:37) [29]


> У меня такие процессы вешают всю систему сразу же :)


А почему?


 
Rial ©   (2006-12-18 14:04) [30]

> [29] Creative   (18.12.06 10:37)
> > У меня такие процессы вешают всю систему сразу же :)
> А почему?

Ну, по идее, если процесс получает RealTime и начинает усиленно
работать, что все процессорное время уходит только на него.
Не спасет даже Ctrl+Alt+Del. Но до таких крайностей не
обязательно же доводить :)

I>
> А почему  PRec = ^TRec, а не Rec: TRec?

Ну так Data - указатель же.
Привести указатель с TRec не получится, а к указателю на TRec -
запросто. Точнее, получится, но придется копировать данные,
например, так:
Move(Data^, Rec, SizeOf(Rec));
что при больших размерах TRec не очень хорошо.

P.S. А почему Data - указатель ? :)
Ну а что это еще может быть, не понятно. Выделили память,
считали, например, и файла все в область памяти и бегаем
по указателю с разными смещениями.


> А что тогда? Опять возвращаются к рекордам?

Да нет. Я не совсем это имел ввиду.
Просто всему свое место. Не надо на одном зацикливаться.
Если разработка идет несколькими людьми, то классы
предпочтительнее. Или если проект очень большой и потом
будет сложно разобраться без классов (лучше большие
модули все же запихнуть в них).
А если человек один, и он уверен, что правильно
везде после использования финализирует переменные,
освободит память и т.п., то почему бы и не рекорды.

Что то много как то у меня слов получается, о больном потому что :)


 
Creative   (2006-12-18 14:34) [31]


> Что то много как то у меня слов получается, о больном потому
> что :)


почему о больном? не уверены, много вас или мало? :-)


 
Rial ©   (2006-12-18 17:04) [32]

Нет, уверен, меньше нас :)
Просто я все жду, когда же сюда сбегутся
защитники классов, ООП, VCL ...
Их же явно больше. Затопчут.
Ну да простит их всевышний, многие не ведают, что творят %)

Есть простой способ в Delphi кстати.
Там же можно посмотреть генерируемый asm - код.
Вот по нему очень легко понять, какой алгоритм
более оптимальный.



Страницы: 1 вся ветка

Текущий архив: 2008.01.27;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.017 c
3-1190618612
MZ
2007-09-24 11:23
2008.01.27
Узнать количество измененных записей


15-1198165013
Jimmy
2007-12-20 18:36
2008.01.27
DVD Rip


2-1198490583
AlinaVK
2007-12-24 13:03
2008.01.27
CreateGUID


2-1198515716
Dark
2007-12-24 20:01
2008.01.27
SW_HIDE


15-1198354859
I
2007-12-22 23:20
2008.01.27
Художественная литература на английском