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

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

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 27.12.2012, 22:13   #1
Kate_Denali
 
Регистрация: 21.04.2010
Сообщений: 3
По умолчанию Задание источника света в Delphi

Здравствуйте. Такая проблема. Нужно, чтобы на вращающейся фигуре отображались тени в зависимости от источника света. В данном случае получилось только затемнить фигуру полностью. Подскажите, в чем проблема, пожалуйста.

Код:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormResize(Sender: TObject);
    procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
    procedure FormDestroy(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    { Private declarations }
    DC : HDC;
    hrc: HGLRC;
    ry : GLfloat;
    light0_position: array [0..3] of glfloat;

  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

const
  CW = 8;  //количество точек объекта
  CP = 12;  //количество полигонов

type
  T3DPoint = record
    X, Y, Z: Integer;
  end;
  T2DPoint = TPoint;

var
  W: array [1..CW] of T3DPoint;  //мировые координаты
  V: array [1..CW] of T2DPoint;  //видовые координаты
  Z: array [1..CW] of Integer;   //глубина точек
  P: array [1..CP] of record     //полигоны
    A: array [1..3] of Byte;     //номера точек, из которых состоит полигон
    mZ: Integer;                 //среднее значение глубины полигона
  end;
  Sort: array [1..CP] of Byte;   //массив для сортировки
  Scale: Integer;                //масштаб
  Teta, Phi: Single;             //углы
  BufMain, BufEmpty: TBitMap;    //буферы для вывода и очистки
  MDown: Boolean;                //нажата ли кнопка мыши
  MPos: T2DPoint;                //положение курсора мыши

procedure Get2D;
var I: Integer;
begin
  //преобразование мировых координат в видовые с помощью
  //матрицы преобразований
  for I := 1 to CW do
  begin
    V[I].X := Round(Scale * (
              W[I].X*(- Sin(Teta)) +
              W[I].Y*(  Cos(Teta)))) + Form1.Width shr 1;
    V[I].Y := Round(Scale * (
              W[I].X*(  Cos(Phi) * Cos(Teta)) +
              W[I].Y*(  Cos(Phi) * Sin(Teta)) +
              W[I].Z*(- Sin(Phi)))) + Form1.Height shr 1;
    Z[I]   := Round(Scale * (
              W[I].X*(- Sin(Phi) * Cos(Teta)) +
              W[I].Y*(- Sin(Phi) * Sin(Teta)) +
              W[I].Z*(- Cos(Phi))));
  end;
  //нахождение средней глубины полигонов:
  //так как данная глубина кроме сортировки нигде не используется, то
  //можно опустить деление на 3 - это увеличит производительность
  //алгоритма, сохранив его функциональность
  for I := 1 to CP do
    P[I].mZ := Z[P[I].A[1]] + Z[P[I].A[2]] + Z[P[I].A[3]];
end;

procedure DrawTriangle(A1, A2, A3: T2DPoint);
var
  A: array [1..3] of T2DPoint;
begin
  A[1] := A1;
  A[2] := A2;
  A[3] := A3;
  BufMain.Canvas.Polygon(A);
end;

procedure DrawPolygon(A1, A2, A3: T2DPoint);
var Nz: Integer;
begin
  //сначала нужно посчитать Z-составляющую нормали, чтобы знать,
  //нужно ли вообще рисовать полигон
  Nz := A1.X * (A2.Y - A3.Y) + A2.X * (A3.Y - A1.Y) + A3.X * (A1.Y - A2.Y);
  //если полигон виден, то нарисовать его
  if Nz < 0 then
    DrawTriangle(A1, A2, A3);
end;

procedure DrawObject;
var
  B: Boolean;
  I: Integer;
begin
  //очистить буфер от старого изображения
  BufMain.Canvas.Draw(0, 0, BufEmpty);
  //сортировка граней
  B := True;
  while B do
  begin
    B := False;
    for I := 1 to (CP - 1) do
      //если глубина меньше, то переместить ближе к концу массива
      if (P[Sort[I]].mZ < P[Sort[I + 1]].mZ) then
      begin
        Sort[I] := Sort[I] + Sort[I + 1];
        Sort[I + 1] := Sort[I] - Sort[I + 1];
        Sort[I] := Sort[I] - Sort[I + 1];
        B := True;
      end;
  end;
  //нарисовать полигоны
  for I := 1 to CP do
    DrawPolygon(V[P[Sort[I]].A[1]], V[P[Sort[I]].A[2]], V[P[Sort[I]].A[3]]);

  //вывести содержимое на экран
  Form1.Canvas.Draw(0, 0, BufMain);
end;
Kate_Denali вне форума Ответить с цитированием
Старый 27.12.2012, 22:15   #2
Kate_Denali
 
Регистрация: 21.04.2010
Сообщений: 3
По умолчанию

Код:
procedure TForm1.FormCreate(Sender: TObject);
var
  I,koef: Integer;
begin
  //задание координат объекта
  W[1].X := -5;   W[1].Y :=  -2;   W[1].Z := -5;
  W[2].X := -5;   W[2].Y :=  -2;   W[2].Z := 2;
  W[3].X := -5;   W[3].Y := 2;   W[3].Z := 5;
  W[4].X := -5;   W[4].Y := 2;   W[4].Z := -2;
  W[5].X :=  5;   W[5].Y := 2;   W[5].Z := 2;
  W[6].X := 5;   W[6].Y :=  2;   W[6].Z :=  2;
  W[7].X := 5;   W[7].Y := 2;   W[7].Z :=  2;
  W[8].X :=  5;   W[8].Y := 2;   W[8].Z :=  2;

  //задание точек, образующих полигоны
  P[1].A[1]  := 1;   P[1].A[2]  := 4;   P[1].A[3]  := 2;
  P[2].A[1]  := 2;   P[2].A[2]  := 4;   P[2].A[3]  := 3;
  P[3].A[1]  := 5;   P[3].A[2]  := 6;   P[3].A[3]  := 8;
  P[4].A[1]  := 6;   P[4].A[2]  := 7;   P[4].A[3]  := 8;
  P[5].A[1]  := 1;   P[5].A[2]  := 2;   P[5].A[3]  := 5;
  P[6].A[1]  := 2;   P[6].A[2]  := 6;   P[6].A[3]  := 5;
  P[7].A[1]  := 2;   P[7].A[2]  := 3;   P[7].A[3]  := 6;
  P[8].A[1]  := 3;   P[8].A[2]  := 7;   P[8].A[3]  := 6;
  P[9].A[1]  := 3;   P[9].A[2]  := 4;   P[9].A[3]  := 7;
  P[10].A[1] := 4;   P[10].A[2] := 8;   P[10].A[3] := 7;
  P[11].A[1] := 4;   P[11].A[2] := 1;   P[11].A[3] := 8;
  P[12].A[1] := 1;   P[12].A[2] := 5;   P[12].A[3] := 8;

  //начальная сортировка
  for I := 1 to CP do
    Sort[I] := I;
  //начальный масштаб
  Scale := 20;
  //углы обзора
  Teta := 1;
  Phi := 1;
  //создание буферов
  BufMain := TBitMap.Create;
  BufEmpty := TBitMap.Create;
  BufEmpty.Height := Form1.ClientHeight;
  BufEmpty.Width := Form1.ClientWidth;
  BufMain.Height := Form1.ClientHeight;
  BufMain.Width := Form1.ClientWidth;
  //получить видовые координаты
  Get2D;
  //цвет рисуемых линий - черный

  BufMain.Canvas.Pen.Color := RGB(100,0,0);
  BufMain.Canvas.brush.Color:=RGB(50+koef,0,0);



      light0_position[0]:= 0.0;
      light0_position[1]:= 0.0;
      light0_position[2]:= 1.0;
      light0_position[3]:= 1.0;
      DC := GetDC (Handle);
      hrc := wglCreateContext(DC);
      wglMakeCurrent(DC, hrc);
      glClearColor (0.5, 0.5, 0.75, 1.0); // цвет фона
      glEnable(GL_LIGHT0);
      glLightfv(GL_LIGHT0, GL_POSITION, @light0_position);
      ry := 0.0;

end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  //вывести начальную проекцию объекта
     DrawObject;
end;
Kate_Denali вне форума Ответить с цитированием
Старый 27.12.2012, 22:15   #3
Kate_Denali
 
Регистрация: 21.04.2010
Сообщений: 3
По умолчанию

Код:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  MDown := True;
  MPos.X := X;
  MPos.Y := Y;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if MDown then
  begin
    //изменить углы
    Teta := Teta + 0.01 * (MPos.X - X);
    Phi := Phi + 0.01 * (MPos.Y - Y);
    MPos.X := X;
    MPos.Y := Y;
    //получить видовые координаты
    Get2D;
    //вывести проекцию объекта
    DrawObject;
  end;
end;

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

//при изменении размеров окна необходимо перерисовать изображение
procedure TForm1.FormResize(Sender: TObject);
begin
  BufEmpty.Height := Form1.ClientHeight;
  BufEmpty.Width := Form1.ClientWidth;
  BufMain.Height := Form1.ClientHeight;
  BufMain.Width := Form1.ClientWidth;
  Get2D;
  DrawObject;
end;

//процедура масштабрования колесом мыши
procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
begin
  if (WheelDelta > 0) then
  begin
    if (Scale < 200) then
      Inc(Scale, 2);
  end else
  if (WheelDelta < 0) then
  begin
    if (Scale > 2) then
      Dec(Scale, 2);
  end;
  Get2D;
  DrawObject;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  BufMain.Free;
  BufEmpty.Free;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
 if Key = 40 then
 begin
    //изменить углы
//    Teta := Teta + 0.01 * (MPos.X - 10);
    Phi := Phi + 0.01 * (MPos.Y - 5);
//    MPos.X := MPos.X-10;
//    MPos.Y := MPos.Y-1;
    //получить видовые координаты
    Get2D;
    //вывести проекцию объекта
    DrawObject;
 end        ;
 if Key = 38 then
 begin
    //изменить углы
//    Teta := Teta + 0.01 * (MPos.X - 10);
    Phi := Phi + 0.01 * (MPos.Y + 5);
//    MPos.X := MPos.X-10;
//    MPos.Y := MPos.Y-1;
    //получить видовые координаты
    Get2D;
    //вывести проекцию объекта
    DrawObject;
 end        ;
 if Key = 40 then
 begin
    //изменить углы
//    Teta := Teta + 0.01 * (MPos.X - 10);
    Phi := Phi + 0.01 * (MPos.Y - 5);
//    MPos.X := MPos.X-10;
//    MPos.Y := MPos.Y-1;
    //получить видовые координаты
    Get2D;
    //вывести проекцию объекта
    DrawObject;
 end        ;
 if Key = 37 then
 begin
    //изменить углы
    Teta := Teta + 0.01 * (MPos.X - 10);
//    Phi := Phi + 0.01 * (MPos.Y + 5);
//    MPos.X := MPos.X-10;
//    MPos.Y := MPos.Y-1;
    //получить видовые координаты
    Get2D;
    //вывести проекцию объекта
    DrawObject;
 end        ;
 if Key = 39 then
 begin
    //изменить углы
    Teta := Teta + 0.01 * (MPos.X + 10);
//    Phi := Phi + 0.01 * (MPos.Y + 5);
//    MPos.X := MPos.X-10;
//    MPos.Y := MPos.Y-1;
    //получить видовые координаты
    Get2D;
    //вывести проекцию объекта
    DrawObject;
 end        ;



end;

end.
Kate_Denali вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка при смене источника звука по умолчанию (Delphi) vasiliy_09_05 Win Api 2 28.08.2012 17:57
Движение со скоростью света и быстрее скорости света - Сверхсветовое движение Alar Свободное общение 354 13.11.2011 21:32
Алгоритмы нахождения источника света =Student= Мультимедиа в Delphi 2 11.06.2010 07:31
Фиксация источника света в OpenGL Rin Мультимедиа в Delphi 5 29.03.2010 22:44
delphi с управлением света khasanov_ruslan Помощь студентам 2 24.04.2009 11:53