Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Мультимедиа в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.06.2009, 15:40   #1
MoDErahN
 
Регистрация: 15.06.2008
Сообщений: 8
Лампочка Глобальное позиционирование освещения в OpenGL

Народ, в общем трабл такой. Пишу прожку для моделирования 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;
MoDErahN вне форума Ответить с цитированием
Старый 02.06.2009, 15:40   #2
MoDErahN
 
Регистрация: 15.06.2008
Сообщений: 8
По умолчанию

Код:
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;
Не стесняемся в предположениях, буду рад любой идее, уже часов 5 убил на попытки это отладить.

Последний раз редактировалось MoDErahN; 02.06.2009 в 19:59.
MoDErahN вне форума Ответить с цитированием
Старый 02.06.2009, 19:12   #3
Selestis
Форумчанин
 
Аватар для Selestis
 
Регистрация: 21.01.2009
Сообщений: 719
По умолчанию

Попробуйте задавать свет между glMatrixMode(GL_MODELVIEW) и GlobalPoint(TreeRoot). И что-то у вас многовато преобразований с матрицами... У меня работает такая структура:
Код:
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(Lense,W/H,dNear,dFar);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;

gluLookAt(X,Y,Z,TargetSpot[0],TargetSpot[1],TargetSpot[2],0,1,0);
glLightfv(GL_LIGHT0, GL_AMBIENT, @Light.Color);
glLightfv(GL_LIGHT0, GL_DIFFUSE, @Light.Color);
LightPos:=VectorSubtract(Camera.Position.AsVector,Light.Pos);
glLightfv(GL_LIGHT0, GL_POSITION, @LightPos);
glPushMatrix;
Draw;
glPopMatrix;
И всё вроде бы..
Изобретатель велосипедов
Selestis вне форума Ответить с цитированием
Старый 02.06.2009, 19:58   #4
MoDErahN
 
Регистрация: 15.06.2008
Сообщений: 8
По умолчанию

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

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


Есть идеи?
MoDErahN вне форума Ответить с цитированием
Старый 02.06.2009, 20:28   #5
Selestis
Форумчанин
 
Аватар для Selestis
 
Регистрация: 21.01.2009
Сообщений: 719
По умолчанию

Что-то так сразу не соображу... Попробуйте вместо GlobalDraw просто отрисовать какую-ньть сферу или другой квад и поворачивать так же, просто чтобы понять ошибка в WMPaint или в самой отрисовке 3d. Напишите что выйдет. и ещё, чисто ля эксперимента попробуйте переместить задание света до gluLookAt
Изобретатель велосипедов
Selestis вне форума Ответить с цитированием
Старый 02.06.2009, 20:59   #6
MoDErahN
 
Регистрация: 15.06.2008
Сообщений: 8
По умолчанию

Вот код, делаеться один поворот, и просто выводится сфера. Источник света все так же летает с удвоенной скоростью вращения.

Код:
procedure TVM.WMPaint(var Msg: TWMPaint); //перехватчик сообщения отрисовки окна
var
  ps: TPaintStruct;
  ang: real;
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;

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

  //установка камеры
  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);

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

  glPushMatrix;
  ang := 360 * RealTime;
  ang := ang - round(ang / 360  - 0.5) * 360;
  glRotatef(ang, 0, 1, 0);
  PaintHSphere(TreeRoot.Child[0].Obj.HS);
  glPopMatrix;

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

  EndPaint(Handle, ps); //завершаем отрисовку
end;
И самое смешное, что все начинает работать нормально(применительно конкретно к этому коду), если добавить пару строк так:

Код:
  glPushMatrix;
  ang := 360 * RealTime;
  ang := ang - round(ang / 360  - 0.5) * 360;
  glRotatef(ang, 0, 1, 0);
  glPushMatrix; //добавлено
  glRotatef(ang, 0, 1, 0); //добавлено
  SetLights(TreeRoot); //добавлено
  glPopMatrix; //добавлено
  PaintHSphere(TreeRoot.Child[0].Obj.HS);
  glPopMatrix;
Нет, ну я еще бы понял логику, если бы помогло
glRotatef(-ang, 0, 1, 0);
но вот почему помогло
glRotatef(ang, 0, 1, 0);
я вообще не понимаю

Последний раз редактировалось MoDErahN; 02.06.2009 в 21:58.
MoDErahN вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Про позиционирование Risk07 HTML и CSS 6 18.05.2009 12:58
Позиционирование каретки Spice Win Api 1 25.03.2009 04:51
Глобальное использование переменных DISAITE Помощь студентам 1 16.03.2009 16:21
Позиционирование элемента vlad2423 HTML и CSS 7 09.03.2009 20:28
Разметка страницы (позиционирование элементов) wall66 PHP 1 11.10.2008 18:19