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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вектора нормали в OpenGL, определить вектор нормали оч сложно 
:(
    Опции темы
nght_elf
Дата 6.4.2008, 21:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Народ помогите пожалуйста дописать програмку.
Её суть- просто построить некоторуя фигуру, которую я построил, но не смог разобраться с освещением..
Вот её код, да, к стати, что-то мне подсказывает, что реализация задачи выполнена через заднее место..
Если вы увидете способ, как такую фигуру построить подругому- напишите плиз..

Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Menus,
  OpenGL;

type
  TfrmGL = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormResize(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  private
    DC : HDC;
    hrc: HGLRC;
  end;

var
  frmGL: TfrmGL;
  Down:boolean=false;
  wrkX,wrkY:integer;

implementation

{$R *.DFM}

procedure TfrmGL.FormPaint(Sender: TObject);
const d=700;
var i:integer;
begin
 glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);    


  glBegin(GL_QUADS);
  for i:=0 to d do begin
    //glNormal3f(?(i),?(i),?(i));
    glVertex3f(sin(2*pi*i/d), 0, cos(2*pi*i/d));
    glVertex3f(sin(2*pi*(i+1)/d), 0, cos(2*pi*(i+1)/d));
    glVertex3f(sin(2*pi*(i+1)/d), -i/d, cos(2*pi*(i+1)/d));
    glVertex3f(sin(2*pi*i/d), -i/d, cos(2*pi*i/d));end;
  glEnd;

 SwapBuffers(DC);
end;

procedure SetDCPixelFormat (hdc : HDC);
var
 pfd : TPixelFormatDescriptor;
 nPixelFormat : Integer;
begin
 FillChar (pfd, SizeOf (pfd), 0);
 pfd.dwFlags  := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
 nPixelFormat := ChoosePixelFormat (hdc, @pfd);
 SetPixelFormat (hdc, nPixelFormat, @pfd);
end;


procedure TfrmGL.FormCreate(Sender: TObject);
begin
 DC := GetDC (Handle);
 SetDCPixelFormat(DC);
 hrc := wglCreateContext(DC);
 wglMakeCurrent(DC, hrc);
 glClearColor (0.5, 0.5, 0.75, 1.0); 
 glEnable (GL_LIGHTING);
 glEnable (GL_LIGHT0);
 glEnable (GL_DEPTH_TEST);
end;

procedure TfrmGL.FormDestroy(Sender: TObject);
begin
 wglMakeCurrent(0, 0);
 wglDeleteContext(hrc);
 ReleaseDC (Handle, DC);
 DeleteDC (DC);
end;

procedure TfrmGL.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
 If Key = VK_ESCAPE then Close;
end;

procedure TfrmGL.FormResize(Sender: TObject);
begin
 glViewport(0, 0, ClientWidth, ClientHeight);
 glMatrixMode (GL_PROJECTION);
 glLoadIdentity;
 glFrustum (-1, 1, -1, 1, 4, 10);
 glMatrixMode (GL_MODELVIEW);
 glLoadIdentity;


 glTranslatef(0.0, 0.0, -8.0);  

 glRotatef(10.0, 1.0, 0.0, 0.0); 
 glRotatef(20.0, 0.0, 1.0, 0.0); 
 InvalidateRect(Handle, nil, False);
end;


procedure TfrmGL.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Down := True;
  wrkX := X;
  wrkY := Y;
end;

procedure TfrmGL.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
    Down := False;
end;

procedure TfrmGL.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
   If Down then begin
     glRotatef (X - wrkX, 0.0, 1.0, 0.0);
     glRotatef (Y - wrkY, 1.0, 0.0, 0.0);
     InvalidateRect(Handle, nil, False);
     wrkX := X;
     wrkY := Y;
  end;
end;

end.


фигура- часть цилиндра, построенного из множества(400 шт) прямоугольников.. я находил вектора номали по стандартному способу- но лажа в том, что прямоугольники в данном примере практически сводятся к отрезку, т.к. их ширина стремится к нулю.. К сожалению число 700 здесь необходимо, и предложения уменьшить число плоскостей не подходит, к поставленной мне задачи..
PM MAIL   Вверх
DragonFire
Дата 7.4.2008, 10:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 14.8.2005
Где: Москва

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



Когда-то давно, классе в 10 писал прожку...
Там надо было загрузить из 3Дмакса объект с нормальным освещением.

Я стоил нормали к каждой вершине по алгоритму:
Перебираются все вершины фигуры, для каждой из них:
1) Перебираются все грани (плоскости), содержащие вершину
2) Находится нормаль к этой плоскости (по 3 точкам)
3) Все вектора нормалей суммируются
4) Происходит нормировка полученного вектора
5) Все данные передаются в OpenGL

У меня есть код, но там все повязано на объектак и векторах, но мб поможет, вот процедура нормировки:
Код

procedure T3DObject.BuildNormals;
var i,j,k,p:integer;
    tmp:TVector3D;
    camera:TVector3D;
begin
  Camera.X:=0;
  Camera.Y:=0;
  Camera.Z:=-1*cos(3.14*Angle.z/180);
  for i:=1 to Count do begin
  for p:=0 to 2 do begin
      Vertexes[planes[i][p]].Normal.Free;
      for j:=1 to Count do for k:=0 to 2 do
      if (vertexes[planes[i][p]].x=vertexes[planes[j][k]].x) and (vertexes[planes[i][p]].y=vertexes[planes[j][k]].y) and (vertexes[planes[i][p]].z=vertexes[planes[j][k]].z) then begin
        tmp:=Normal3D(
          vertexes[planes[j][0]].x,vertexes[planes[j][0]].y,vertexes[planes[j][0]].z,
          vertexes[planes[j][1]].x,vertexes[planes[j][1]].y,vertexes[planes[j][1]].z,
          vertexes[planes[j][2]].x,vertexes[planes[j][2]].y,vertexes[planes[j][2]].z);
        Vertexes[planes[i][p]].Normal:=SumVectors(Vertexes[planes[i][p]].Normal,tmp);
      end;
      Vertexes[planes[i][p]].Normal.Normalize;
  end;
  end;
end;


Добавлено через 1 минуту и 47 секунд
Это вдогонку:
Код

type
  TArray3D=array[0..2] of Extended;
  TVertexNumber=byte;
  TPlane=array[0..2] of TVertexNumber;

  TVertexes=array[TVertexNumber] of TVertex;
  TPlanes=array[TVertexNumber] of TPlane;


type
  T3DObject=object
      Center:TVertex;
      Angle:TVertex;
      Scale:Single;
      Vertexes:TVertexes;
      Planes:TPlanes;
      Count:Integer;
      CountVertex:Integer;
      ViewNormals:Boolean;
      R:Single;
    private
    public
      procedure New;
      procedure LoadFromFile(FileName:String);
      procedure LoadFromASE(FileName:String);
      procedure View(Camera:TCamera);
      procedure BuildNormals;
  end;



--------------------
PM MAIL ICQ   Вверх
nght_elf
Дата 8.4.2008, 20:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Поясни алгоритм поподробнее пожалуйста.
PM MAIL   Вверх
Alexeis
Дата 8.4.2008, 21:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

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



nght_elf, векторное произведение 2х векторов дает вектор нормали, но его нужно нормировать на единицу, т.е. разделить каждую из координат на длину вектора нормали. В зависимость от того как задавать порядок вершин по часовой или против получается либо внутренняя нормаль либо наружная. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
DragonFire
Дата 8.4.2008, 22:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 14.8.2005
Где: Москва

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



Alexeis, Именно) линал азы...

А алгоритм... Строим нормали к каждой вершине. Сначало большой цикл по всем вершинам.
Вначале вектор нормали к вершине - нулевой.
1) Перебираются все грани (плоскости), содержащие вершину 
Тут цикл, который проходит по всем граням. Если текущая вершина принадлежит грани, то мы прибавляем к уже полученному вектору нормали вершины (на самом первом шаге - к нулевому вектору), нормаль к плоскости.
2) Находится нормаль к этой плоскости (по 3 точкам)
Тут берутся 3 вершины любые принадлежащие грани, по ним строится нормаль ( как это сделать где-то на форуме было, ищи по "нормаль к плоскости по трем точкам").
3) Происходит нормировка полученного вектора
Тут цикл по вершинам заканчивается. И ПОлученные вектора нормалей все делятся на свои длины.
4) Все данные передаются в OpenGL
Тут вроде все ясно - перед каждой glVertex вызываем glNormal


--------------------
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Звук, графика и видео"
Girder
Snowy
Alexeis

Запрещено:

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

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

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

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


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

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


 




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


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

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