
Эксперт
  
Профиль
Группа: Завсегдатай
Сообщений: 1650
Регистрация: 25.12.2004
Репутация: нет Всего: 23
|
Вот могу привести пример - моя лаба: создай файл matrices3D.pas и кинь его в папку проекта, затем подключи его к проекту. matrices3D.pas: | Код | {типы данных и процедуры для построения трехмерных преобразований координат}
unit matrices3D;
interface
uses Graphics, SysUtils;
{используемые типы данных} type //тип данных для описания одной вершины в пространстве //в однородных координатах TVertex = array [0..3] of double;
//тип данных для описания матрицы преобразования координат //в пространстве TTransform = array [0..3, 0..3] of double;
{Используемые подпрограммы}
//вычисляет матрицу сложного преобразования координат //[T]:=[T1]*[T2] procedure CombineTransform(var T : TTransform; const T1, T2 : TTransform);
//осуществляет преобразование матрицы [V] исходных координат //вершин объекта, умножая ее на матрицу [T]: [TV] = [V]*[T] procedure ApplyTransform(var V1, V : array of TVertex; const T : TTransform);
//осуществляет нормализацию однородных координат вершин //фигуры в матрице V, деля координаты каждой вершины на четвертую //координату H procedure NormCoors(var V : array of TVertex);
implementation
//вычисляет матрицу сложного преобразования координат //[T]:=[T1]*[T2] procedure CombineTransform(var T : TTransform; const T1, T2 : TTransform); var i, j, k: integer; Tmp : TTransform; begin //перемножим матрицы [T1] и [T2] for i := 0 to 3 do for j := 0 to 3 do begin Tmp[i, j] := 0; for k := 0 to 3 do Tmp[i, j] := Tmp[i, j] + T1[i, k] * T2[k, j]; end; //вернем результат T := Tmp; end;
//осуществляет преобразование матрицы [V] исходных координат //вершин объекта, умножая ее на матрицу [T]: [TV] = [V]*[T] procedure ApplyTransform(var V1, V : array of TVertex; const T : TTransform); var i, j, k : integer; VT : TVertex; begin //пройдем по всем вершинам for i := 0 to High(V) do begin //вычислим координаты i-й вершины for j:= 0 to 3 do begin VT[j] := 0; //вычислим j-ую координату for k := 0 to 3 do VT[j] := VT[j] + V[i, k] * T[k, j]; end; //переместим координаты i-ой вершины из временного //массива VT в массив V V1[i] := VT; end; end;
//осуществляет нормализацию однородных координат вершин //фигуры в матрице V, деля координаты каждой вершины на четвертую //координату H procedure NormCoors(var V : array of TVertex); var i : integer; H : double; begin for i := 0 to High(V) do begin H := V[i, 3]; //координата H V[i, 0] := V[i, 0] / H; //координата X V[i, 1] := V[i, 1] / H; //координата Y V[i, 2] := V[i, 2] / H; //координата Z V[i, 3] := 1; //координата H становится равной 1 end; end;
end. |
Код главного модуля - файл Unit1.pas: | Код | unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, wire3D, matrices3D, ExtCtrls;
type TForm1 = class(TForm) Timer1: TTimer; procedure FormPaint(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
V: array [0..3] of TVertex = (
(-350, 0, -150, 1), (-575, 130, -150, 1), (-575, -130, -150, 1), (-500, 0, 150, 1) ) ;
P: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (500, 0, 0, 1) ) ;
P2: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-500, 0, 0, 1) ) ;
C: TTransform = (
(0, 0, -1, 0), (1, 0, 0, 0), (0, -1, 0, 0), (250, 250, 0, 1) ) ;
Rz: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) ;
Pp: TTransform = (
(0, 0, 0, -1/500), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) ;
T: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) ;
L1: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (500, 0, 0, 1) ) ;
L: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (-500, 0, 0, 1) ) ;
//-------------------------------------------- // Вправо PyRight: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 20, 0, 1) ) ;
// Влево PyLeft: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, -20, 0, 1) ) ; //--------------------------------------------
// Вверх PzUp: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 20, 1) ) ;
// Вниз PzDown: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, -20, 1) ) ; //--------------------------------------------
RxLeft: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) ;
RxRight: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) ; //--------------------------------------------
//Уменьшение/увеличение (матрица сжатия/растяжения: [0;1] ) объекта:
RxSmall: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) ;
RxBig: TTransform = (
(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) ;
fi : double = pi / 90;
implementation
{$R *.dfm}
procedure TForm1.FormPaint(Sender: TObject);
var
Vp: array [0..3] of TVertex;
begin
Canvas.TextOut(100,100,'кнопки управления: +/-'); Canvas.TextOut(100,120,'кнопки управления: Delete/PageDown'); Canvas.TextOut(100,140,'кнопки управления: Влево/Вправо и Вврех/Вниз'); Canvas.TextOut(100,160,'кнопки управления: Shift + Влево/Вправо и Shift + Вврех/Вниз');
ApplyTransform(Vp, V, L);
ApplyTransform(Vp, Vp, Pp); NormCoors(Vp);
ApplyTransform(Vp, Vp, C);
DrawWireFace(Canvas, Vp[0], Vp[1], Vp[2]); DrawWireFace(Canvas, Vp[1], Vp[2], Vp[3]); DrawWireFace(Canvas, Vp[2], Vp[3], Vp[0]); DrawWireFace(Canvas, Vp[3], Vp[0], Vp[1]);
end;
procedure TForm1.Timer1Timer(Sender: TObject); begin
//ApplyTransForm(V, V, T);
ApplyTransForm(V, V, Rz); //ApplyTransForm(V, V, Rz); //ApplyTransForm(V, V, Rz);
Refresh;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Rz[0,0] := cos(fi); Rz[1,0] := -sin(fi); Rz[1,1] := cos(fi); Rz[0,1] := sin(fi);
RxLeft[1,1] := cos(fi); RxLeft[1,2] := sin(fi); RxLeft[2,1] := -sin(fi); RxLeft[2,2] := cos(fi);
RxRight[1,1] := cos(-fi); RxRight[1,2] := sin(-fi); RxRight[2,1] := -sin(-fi); RxRight[2,2] := cos(-fi);
// Сжатие: RxSmall[0,0] := 0.99; //Koefficient; RxSmall[1,1] := 0.99; RxSmall[2,2] := 0.99;
// Растяжение: RxBig[0,0] := 1.01; RxBig[1,1] := 1.01; RxBig[2,2] := 1.01;
//CombineTransform(T, P, Rz); //CombineTransform(T, T, P2);
// Преобразование в локальную систему координат: ApplyTransform(V, V, L1); end;
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin
// Перемещение вдоль локальной оси влево и вправо: (матрица PyLeft и PyRight - слева) if (Key = VK_LEFT) and (ssShift in Shift) then CombineTransform(L, PyLeft, L); //fi := - pi / 90; if (Key = VK_RIGHT) and (ssShift in Shift) then CombineTransform(L, PyRight, L); //ApplyTransform(V, V, Py);
// Перемещение: (матрица PyLeft и PyRight - справа) if Key = VK_LEFT then CombineTransform(L, L, PyLeft); //fi := - pi / 90; if Key = VK_RIGHT then CombineTransform(L, L, PyRight); //ApplyTransform(V, V, Py);
if Key = VK_UP then CombineTransform(L, L, PzUp); if Key = VK_DOWN then CombineTransform(L, L, PzDown);
// Перемещение вдоль локальной оси вверх и вниз: (матрица PzUp и PzDown - слева) if (Key = VK_UP) and (ssShift in Shift) then CombineTransform(L, PzUp, L); //fi := - pi / 90; if (Key = VK_DOWN) and (ssShift in Shift) then CombineTransform(L, PzDown, L); //ApplyTransform(V, V, Py);
// Поворот влево if Key = VK_DELETE then CombineTransform(L, RxLeft, L);
// Поворот вправо: if Key = VK_NEXT then CombineTransform(L, RxRight,L);
// Уменьшить объект: if Key = 189 then begin CombineTransform(L, L, RxSmall); end;
// Увеличить объект: if Key = 187 then begin CombineTransform(L, L, RxBig); end;
//FormCreate(Sender);
end;
end. |
Подключи файл Wire3D.pas в папку проекта: | Код | {модуль содержит процедуры для каркасного изображения трехмерных объектов}
unit wire3D;
interface
uses Types, SysUtils, Graphics, matrices3D;
//Рисует треугольную грань по координатам проекций ее трех вершин V0, V1, V2. //Координаты заданы в пространственной системе координат, плосокость Oxy, //начало и оси x и y которой совпадают соответственно с плоскостью экрана, //началом и осями x и у экранной системы координат procedure DrawWireFace(const Canvas : TCanvas; const V0, V1, V2 : TVertex);
//Рисует ребро по координатам его концевых вершин V0 и V1. //Координаты заданы в пространственной системе координат, плосокость Oxy, //начало и оси x и y которой совпадают соответственно с плоскостью экрана, //началом и осями x и у экранной системы координат procedure DrawEdge(const Canvas : TCanvas; const V0, V1 : TVertex);
implementation
//Рисует треугольную грань по координатам проекций ее трех вершин V0, V1, V2. //Координаты заданы в пространственной системе координат, плосокость Oxy, //начало и оси x и y которой совпадают соответственно с плоскостью экрана, //началом и осями x и у экранной системы координат procedure DrawWireFace(const Canvas : TCanvas; const V0, V1, V2 : TVertex); begin Canvas.Polyline([ Point(round(V0[0]),round(V0[1])), Point(round(V1[0]),round(V1[1])), Point(round(V2[0]),round(V2[1])), Point(round(V0[0]),round(V0[1])) ]); end;
//Рисует ребро по координатам его концевых вершин V0 и V1. //Координаты заданы в пространственной системе координат, плосокость Oxy, //начало и оси x и y которой совпадают соответственно с плоскостью экрана, //началом и осями x и у экранной системы координат procedure DrawEdge(const Canvas : TCanvas; const V0, V1 : TVertex); var i : integer; begin Canvas.Polyline([ Point(round(V0[0]),round(V0[1])), Point(round(V1[0]),round(V1[1])) ]); end;
end. |
В данный момент нет под рукой Delfi, но думаю, что работать должно Это сообщение отредактировал(а) Voldemar2004 - 25.4.2007, 11:55
--------------------
i_i (';') (V) 
|