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

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

Как рисовать 3D и 2D объекты в одной сцене? [Delphi, Windows]


Страницы:   1 2

Creative ©   (2006-12-12 16:05:00) 

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


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

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

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

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


Rial   (2006-12-18 17:04:00) [1]

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

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


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


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


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


Rial   (2006-12-18 14:04:00) [3]

> [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 10:37:00) [4]


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


А почему?


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


> Ну, рекод  - это не более чем более удобный доступк
> области памяти.Например, есть 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?


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


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


MeF Dei Corvi   (2006-12-15 21:54:00) [6]


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

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


Rial   (2006-12-15 17:28:00) [7]

> [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;

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


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


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


FPS?


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


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


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


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


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


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

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


Rial   (2006-12-15 16:40:00) [9]

> [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 10:18:00) [10]


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


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


Rial   (2006-12-15 01:31:00) [11]

> [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%
производительности. Так что главное - не "намельчить".


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

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

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


Creative   (2006-12-14 12:56:00) [13]


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


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

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


Vga   (2006-12-14 12:50:00) [14]

> [18] Creative   (14.12.06 11:13)

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


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


> 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. Поправьте меня, пожалуйста.


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

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


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

koeff = AB/CD

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


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

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


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

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


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


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


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


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

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


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

glEnable(GL_DEPTH_TEST);


Страницы:   1 2

Наверх

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