Модераторы: Snowy, Alexeis, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Глобальное позиционирование освещения в OpenGL, Проблема с отображением на объектах в различных системах координат 
:(
    Опции темы
MoDErahN
  Дата 2.6.2009, 15:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 2.6.2009

Репутация: нет
Всего: нет



Народ, в общем трабл такой. Пишу прожку для моделирования 3D систем, все пашет нормально, кроме освещения.
Оно ведет себя жутко странно, вроде бы я его включаю до всех преобразований матриц, а в итоге оно отображаеться для всех объектов с разными векторами направления. Причем даже не с соответствующим вектором в системе координат самого объекта, а с каким-то неясно-непонятным вектором.
Вот ссыль на бинарник и модель: http://slil.ru/27717863
Запускаем прогу, тусим в "Визуализацию моделей", там правый клик на окошке с надписью "Новая модель" и выбираем "Открыть модель", выбираем файлик, тот что в архиве с прогой, и смело жмем "Начать визуализацию". Чтобы было проще увидеть в чем трабл, можно поставить скорость где-то на 0,1. Ориентация в пространстве просто мышкой.


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

Код
//###################################################
//### внизу процедуры вывода объектов ###############
//###################################################

Procedure PaintSSphere(Sph: TSSphere);
Var
  i: byte;
Begin
  glBegin(GL_TRIANGLES);
  For i := 1 to 8 do
  Begin
    glColor4fv(@Sph.Color[Sph.Triangle[i].F]);
    glNormal3fv(@Sph.Normal[Sph.Triangle[i].F]);
    glVertex3fv(@Sph.Vartex[Sph.Triangle[i].F]);
    glColor4fv(@Sph.Color[Sph.Triangle[i].S]);
    glNormal3fv(@Sph.Normal[Sph.Triangle[i].S]);
    glVertex3fv(@Sph.Vartex[Sph.Triangle[i].S]);
    glColor4fv(@Sph.Color[Sph.Triangle[i].T]);
    glNormal3fv(@Sph.Normal[Sph.Triangle[i].T]);
    glVertex3fv(@Sph.Vartex[Sph.Triangle[i].T]);
  End;
  glEnd;
End;

Procedure PaintMSphere(Sph: TMSphere);
Var
  i: byte;
Begin
  glBegin(GL_TRIANGLES);
  For i := 1 to 48 do
  Begin
    glColor4fv(@Sph.Color[Sph.Triangle[i].F]);
    glNormal3fv(@Sph.Normal[Sph.Triangle[i].F]);
    glVertex3fv(@Sph.Vartex[Sph.Triangle[i].F]);
    glColor4fv(@Sph.Color[Sph.Triangle[i].S]);
    glNormal3fv(@Sph.Normal[Sph.Triangle[i].S]);
    glVertex3fv(@Sph.Vartex[Sph.Triangle[i].S]);
    glColor4fv(@Sph.Color[Sph.Triangle[i].T]);
    glNormal3fv(@Sph.Normal[Sph.Triangle[i].T]);
    glVertex3fv(@Sph.Vartex[Sph.Triangle[i].T]);
  End;
  glEnd;
End;

Procedure PaintHSphere(Sph: THSphere);
Var
  i: byte;
Begin
  glBegin(GL_TRIANGLES);
  For i := 1 to 120 do
  Begin
    glColor4fv(@Sph.Color[Sph.Triangle[i].F]);
    glNormal3fv(@Sph.Normal[Sph.Triangle[i].F]);
    glVertex3fv(@Sph.Vartex[Sph.Triangle[i].F]);
    glColor4fv(@Sph.Color[Sph.Triangle[i].S]);
    glNormal3fv(@Sph.Normal[Sph.Triangle[i].S]);
    glVertex3fv(@Sph.Vartex[Sph.Triangle[i].S]);
    glColor4fv(@Sph.Color[Sph.Triangle[i].T]);
    glNormal3fv(@Sph.Normal[Sph.Triangle[i].T]);
    glVertex3fv(@Sph.Vartex[Sph.Triangle[i].T]);
  End;
  glEnd;
End;

Procedure PaintCirc(Circ: TCirc);
Var
  i: byte;
Begin
  glBegin(GL_TRIANGLES);
  glNormal3f(0, -1, 0);
  For i := 1 to 216 do
  Begin
    glColor4fv(@Circ.Color[Circ.Triangle[i].F]);
    glVertex3fv(@Circ.Vartex[Circ.Triangle[i].F]);
    glColor4fv(@Circ.Color[Circ.Triangle[i].T]);
    glVertex3fv(@Circ.Vartex[Circ.Triangle[i].T]);
    glColor4fv(@Circ.Color[Circ.Triangle[i].S]);
    glVertex3fv(@Circ.Vartex[Circ.Triangle[i].S]);
  End;
  glNormal3f(0, 1, 0);
  For i := 1 to 216 do
  Begin
    glColor4fv(@Circ.Color[Circ.Triangle[i].F]);
    glVertex3fv(@Circ.Vartex[Circ.Triangle[i].F]);
    glColor4fv(@Circ.Color[Circ.Triangle[i].S]);
    glVertex3fv(@Circ.Vartex[Circ.Triangle[i].S]);
    glColor4fv(@Circ.Color[Circ.Triangle[i].T]);
    glVertex3fv(@Circ.Vartex[Circ.Triangle[i].T]);
  End;
  glEnd;
End;

Procedure LightOn(Light: TLight);
Begin
  glEnable(GLLight[VM.lights]);
  glLightfv(GLLight[VM.lights], GL_AMBIENT, @Light.FonColor);
  glLightfv(GLLight[VM.lights], GL_DIFFUSE, @Light.GlColor);
  glLightf(GLLight[VM.lights], GL_LINEAR_ATTENUATION, Light.con);
  glLightfv(GLLight[VM.lights], GL_POSITION, @Light.Pos);
End;

Function GetPointOrb(a, b, stang, speed: real): TGLPoint;
Var
  ang: real;
Begin
  ang := stang / 57.2956 + speed * 6.2832 * VM.RealTime;
  ang := ang - round(ang / 6.2832  - 0.5) * 6.2832;
  GetPointOrb[1] := 0;
  GetPointOrb[0] := cos(ang) * a;
  GetPointOrb[2] := sin(ang) * b;
End;

Procedure DisableLights;
Var
  i: integer;
Begin
  For i := 0 to 7 do glDisable(GLLight[i]);
End;

Procedure TVM.SetLights(Root: TOT);
Var
  i: byte;
Begin
  DisableLights;
  lights := 0;
  i := 0;
  While (i <= length(Root.Child) - 1) and (lights < 7) do
  Begin
    if Root.Child[i].Obj.ObjType = 5 then
    Begin
      LightOn(Root.Child[i].Obj.LT);
      inc(lights);
    End;
    inc(i);
  End;
End;

//###################################################
//### внизу логическая структура отрисовки ##########
//###################################################

Procedure TVM.GlobalPaint(Root: TOT);
Var
  Pnt: TGLPoint;
  ang: real;
  i: integer;
Begin
  glPushMatrix; // <-- (Матрицу в стек)

  if Root <> TreeRoot then
  Begin //вращаем ось орбиты и смещаемся в точку на орбите
    glRotatef(Root.Obj.Rotorb[1][0], Root.Obj.Rotorb[1][1], Root.Obj.Rotorb[1][2], Root.Obj.Rotorb[1][3]);
    glRotatef(Root.Obj.Rotorb[2][0], Root.Obj.Rotorb[2][1], Root.Obj.Rotorb[2][2], Root.Obj.Rotorb[2][3]);
    glRotatef(Root.Obj.Rotorb[3][0], Root.Obj.Rotorb[3][1], Root.Obj.Rotorb[3][2], Root.Obj.Rotorb[3][3]);
    Pnt := GetPointOrb(Root.Obj.a, Root.Obj.b, Root.Obj.stang, Root.Obj.rotspeed);
    glTranslatef(Pnt[0], Pnt[1], Pnt[2]);
  End;

  if Root.Obj.ObjType in [1..4] then
  Begin //вращаем ось объекта и масштабируем
    glPushMatrix; // <-- (Матрицу в стек)
    glRotatef(Root.Obj.Rotspin[1][0], Root.Obj.Rotspin[1][1], Root.Obj.Rotspin[1][2], Root.Obj.Rotspin[1][3]);
    glRotatef(Root.Obj.Rotspin[2][0], Root.Obj.Rotspin[2][1], Root.Obj.Rotspin[2][2], Root.Obj.Rotspin[2][3]);
    glRotatef(Root.Obj.Rotspin[3][0], Root.Obj.Rotspin[3][1], Root.Obj.Rotspin[3][2], Root.Obj.Rotspin[3][3]);
    ang := Root.Obj.stspin + 360 * Root.Obj.spinspeed * RealTime;
    ang := ang - round(ang / 360  - 0.5) * 360;
    glRotatef(ang, 0, 1, 0);

    glScalef (Root.Obj.radius * 2, Root.Obj.radius * 2, Root.Obj.radius * 2); // * 2 потому что модели имеют границы в 0.5
  End;

  if Root.Obj.shadowed = false then glDisable(GL_LIGHTING); //если у объекта отключено затенение, то вырубаем освещение

  case Root.Obj.ObjType of
    1: PaintSSphere(Root.Obj.SS);
    2: PaintMSphere(Root.Obj.MS);
    3: PaintHSphere(Root.Obj.HS);
    4: PaintCirc(Root.Obj.CR);
  end;

  if Root.Obj.shadowed = false then glEnable(GL_LIGHTING);

  if Root.Obj.ObjType in [1..4] then
  Begin
    glPopMatrix; // --> (Матрицу из стека)
  End;

  If Length(Root.Child) > 0 then
  Begin
    For i := 0 to Length(Root.Child) - 1 do GlobalPaint(Root.Child[i]);
  End;

  glPopMatrix; // --> (Матрицу из стека)
End;

//###################################################
//### внизу перехватчик сообщения отрисовки окна ####
//###################################################

procedure TimeProc(uTimerID, uMessage: UINT;dwUser, dw1, dw2: DWORD) stdcall; //процедура обработки мультимедийного таймера 
begin
  InvalidateRect(VM.Handle, nil, False); //обновляем окно
end;

procedure TVM.WMPaint(var Msg: TWMPaint); //перехватчик сообщения отрисовки окна
var
  ps: TPaintStruct;
begin
  //расчет реального времени
  TimerTime := GetTickCount - StartTime;
  RealTime := LRTime + TimerTime * TimeSpeed / 1000;

  //расчет координат камеры
  Cam.Eye.X := sin(camgorang) * camrad * cos(camvertang);
  Cam.Eye.Z := cos(camgorang) * camrad * cos(camvertang);
  Cam.Eye.Y := sin(camvertang) * camrad;

  BeginPaint(Handle, ps); //начало отрисовки

  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); //очистка буферов цвета и глубины

  glLoadIdentity;

  //установка камеры
  gluLookAt (Cam.Eye.X, Cam.Eye.Y, Cam.Eye.Z,
            Cam.Target.X, Cam.Target.Y, Cam.Target.Z,
            Cam.RVect.X, Cam.RVect.Y, Cam.RVect.Z);

  //установка освещения
  SetLights(TreeRoot);

  //отрисовка объектов
  GlobalPaint(TreeRoot);

  SwapBuffers(DC); //"выбрасываем" на экран

  EndPaint(Handle, ps); //завершаем отрисовку
end;


Оно поворачивает источник света вместе с объектом, даже не вместе, а с удвоенным углом, т.е. если объект делает оборот вокруг своей оси (т.е. система координат в которой он рисуется делает 1 оборот относительно глобальной системы отсчета) источник света делает два оборота относительно глобальной системы отсчета.

Вот вращение сферы, вид сверху.
user posted image

Есть идеи?

Не стесняемся в предположениях, буду рад любой идее, уже часов 5 убил на попытки это отладить.

Это сообщение отредактировал(а) MoDErahN - 2.6.2009, 19:14
PM MAIL   Вверх
RomanEEP
Дата 6.6.2009, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: 1
Всего: 8



Цитата(MoDErahN @  2.6.2009,  15:10 Найти цитируемый пост)
Оно поворачивает источник света вместе с объектом

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

Для решения этой проблемы в OpenGL есть введены 2 матрицы преобразований GL_PROJECTION и GL_MODELVIEW. Вся геометрия (включая позиции источников света) умножаются на матрицу GL_MODELVIEW, затем вычисляется освещение, геометрия умножается на матрицу камеры GL_PROJECTION и растеризуется.

т.е тебе нужно сделать примерно так:
Код

  glMatrixMode(GL_ROJECTION);
  glLoadIdentity;
  gluLookAt (Cam.Eye.X, Cam.Eye.Y, Cam.Eye.Z,
            Cam.Target.X, Cam.Target.Y, Cam.Target.Z,
            Cam.RVect.X, Cam.RVect.Y, Cam.RVect.Z);
  glMatrixMode(GL_MODELVEW);
  GlobalPaint(TreeRoot);


PM MAIL   Вверх
MoDErahN
  Дата 8.6.2009, 00:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 2.6.2009

Репутация: нет
Всего: нет



А вот и нет. На матрицу проекции домнажаются координаты вершин, а корректировка освещенности вершин прогоняется тока через modelview матрицу.

Проблема решена, там просто модельки брались из сторонней проги. И координаты там заданы были в левостороннем базисе. Я инвертировал X координату вершин, и совсем забыл про нормали. Т.е. я их X не инвертировал. В итоге имеем ежик наоборот с нормалями, отсюда и блуждающий свет.
Все пофикшено.
PM MAIL   Вверх
RomanEEP
Дата 8.6.2009, 07:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: 1
Всего: 8



Цитата(MoDErahN @  8.6.2009,  00:53 Найти цитируемый пост)
А вот и нет. На матрицу проекции домнажаются координаты вершин, а корректировка освещенности вершин прогоняется тока через modelview матрицу

Так я об этом тебе и написал. И ты задаешь матрицу проекции не в GL_PROJECTION, а в GL_MODELVIEW
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Звук, графика и видео"
Girder
Snowy
Alexeis

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • По вопросам разработки игр стоит заглянуть сюда

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Girder, Snowy.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Звук, графика и видео | Следующая тема »


 




[ Время генерации скрипта: 0.0656 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.