345 lines
7.7 KiB
ObjectPascal
345 lines
7.7 KiB
ObjectPascal
unit Geometry;
|
||
|
||
{$mode ObjFPC}{$H+}
|
||
|
||
interface
|
||
|
||
uses
|
||
Classes, SysUtils;
|
||
|
||
type
|
||
{ Вершины }
|
||
Vertex = record
|
||
x, y, z: Real; { Координаты вершины }
|
||
end;
|
||
{ Ребра }
|
||
Edge = record
|
||
src, dest: Integer; { Индексы соединяемых вершин }
|
||
end;
|
||
|
||
Object3D = class
|
||
public
|
||
vertices: array of Vertex; { вершины }
|
||
edges: array of Edge; { ребра }
|
||
xc, yc, zc: Real; { координаты центра объекта }
|
||
vx, vy, vz: Real; { значения составляющих его скорости }
|
||
xa, ya, za: Real; { скорость вращения вокруг оси }
|
||
|
||
constructor Create(var center, velocity, axis: Vertex);
|
||
|
||
procedure MoveCenter();
|
||
end;
|
||
|
||
Matrix = array[1..4, 1..4] of Real; { матрица 4x4 }
|
||
Column = array[1..4] of Real; { столбец }
|
||
|
||
function CopyObject3D(Shape: Object3D): Object3D;
|
||
|
||
{ умножение матрицы на матрицу }
|
||
function MMMult(lhs, rhs: Matrix): Matrix;
|
||
{ умножение матрицы на столбец }
|
||
function MCMult(lhs: Matrix; rhs: Column): Column;
|
||
{ матрица поворота модели }
|
||
function RotateMatrix(xa, ya, za: Real): Matrix;
|
||
function MoveMatrix(tx, ty, tz: Real): Matrix;
|
||
function ResizeMatrix(sx, sy, sz: Real): Matrix;
|
||
procedure RotateShape(Shape: Object3D);
|
||
procedure MoveShape(Shape: Object3D; Width, Height: Real);
|
||
procedure ResizeShape(var Shape: Object3D; sx, sy, sz: Real);
|
||
|
||
implementation
|
||
|
||
constructor Object3D.Create(var center, velocity, axis: Vertex);
|
||
const
|
||
size = 10;
|
||
cubeVertices: array of Vertex = (
|
||
(x: -size; y: -size; z: -size),
|
||
(x: -size; y: size; z: -size),
|
||
(x: size; y: size; z: -size),
|
||
(x: size; y: -size; z: -size),
|
||
(x: -size; y: -size; z: size),
|
||
(x: -size; y: size; z: size),
|
||
(x: size; y: size; z: size),
|
||
(x: size; y: -size; z: size)
|
||
);
|
||
cubeEdges: array of Edge = (
|
||
(src: 0; dest: 1),
|
||
(src: 1; dest: 2),
|
||
(src: 2; dest: 3),
|
||
(src: 3; dest: 0),
|
||
(src: 4; dest: 5),
|
||
(src: 5; dest: 6),
|
||
(src: 6; dest: 7),
|
||
(src: 7; dest: 4),
|
||
(src: 0; dest: 4),
|
||
(src: 1; dest: 5),
|
||
(src: 2; dest: 6),
|
||
(src: 3; dest: 7)
|
||
);
|
||
begin
|
||
vertices := cubeVertices;
|
||
edges := cubeEdges;
|
||
xc := center.x;
|
||
yc := center.y;
|
||
zc := center.z;
|
||
vx := velocity.x;
|
||
vy := velocity.y;
|
||
vz := velocity.z;
|
||
xa := axis.x;
|
||
ya := axis.y;
|
||
za := axis.z
|
||
end;
|
||
|
||
procedure Object3D.MoveCenter();
|
||
begin
|
||
xc := xc + Vx;
|
||
yc := yc + Vy;
|
||
zc := zc + Vz
|
||
end;
|
||
|
||
function CopyObject3D(Shape: Object3D): Object3D;
|
||
begin
|
||
CopyObject3D.vertices := Copy(Shape.vertices, 0);
|
||
CopyObject3D.edges := Copy(Shape.edges, 0);
|
||
|
||
CopyObject3D.xc := Shape.xc;
|
||
CopyObject3D.yc := Shape.yc;
|
||
CopyObject3D.zc := Shape.zc
|
||
end;
|
||
|
||
function MMMult(lhs, rhs: Matrix): Matrix;
|
||
var
|
||
i, j, k: Integer;
|
||
r: Matrix;
|
||
s: Real;
|
||
begin
|
||
for i := 1 to 4 do
|
||
for j := 1 to 4 do
|
||
begin
|
||
s := 0;
|
||
for k := 1 to 4 do
|
||
s := s + lhs[i, k] * rhs[k, j];
|
||
r[i, j] := s;
|
||
end;
|
||
MMMult := r;
|
||
end;
|
||
|
||
function MCMult(lhs: Matrix; rhs: Column): Column;
|
||
var
|
||
k, i: Integer;
|
||
s: Real;
|
||
r: Column;
|
||
begin
|
||
for i := 1 to 4 do { аналогично MMMult }
|
||
begin
|
||
s := 0;
|
||
|
||
for k := 1 to 4 do
|
||
s := s + lhs[i, k] * rhs[k];
|
||
r[i] := s;
|
||
end;
|
||
|
||
MCMult := r;
|
||
end;
|
||
|
||
function RotateMatrix(xa, ya, za: Real): Matrix;
|
||
var
|
||
xr, yr, zr: Matrix;
|
||
begin
|
||
{ матрица поворота вокруг оси Ox }
|
||
xr[1, 1] := 1;
|
||
xr[1, 2] := 0;
|
||
xr[1, 3] := 0;
|
||
xr[1, 4] := 0;
|
||
|
||
xr[2, 1] := 0;
|
||
xr[2, 2] := Cos(xa);
|
||
xr[2, 3] := -Sin(xa);
|
||
xr[2, 4] := 0;
|
||
|
||
xr[3, 1] := 0;
|
||
xr[3, 2] := Sin(xa);
|
||
xr[3, 3] := Cos(xa);
|
||
xr[3, 4] := 0;
|
||
|
||
xr[4, 1] := 0;
|
||
xr[4, 2] := 0;
|
||
xr[4, 3] := 0;
|
||
xr[4, 4] := 1;
|
||
|
||
{ матрица поворота вокруг оси Oy }
|
||
yr[1, 1] := Cos(ya);
|
||
yr[1, 2] := 0;
|
||
yr[1, 3] := Sin(ya);
|
||
yr[1, 4] := 0;
|
||
|
||
yr[2, 1] := 0;
|
||
yr[2, 2] := 1;
|
||
yr[2, 3] := 0;
|
||
yr[2, 4] := 0;
|
||
|
||
yr[3, 1] := -Sin(ya);
|
||
yr[3, 2] := 0;
|
||
yr[3, 3] := Cos(ya);
|
||
yr[3, 4] := 0;
|
||
|
||
yr[4, 1] := 0;
|
||
yr[4, 2] := 0;
|
||
yr[4, 3] := 0;
|
||
yr[4, 4] := 1;
|
||
|
||
{ матрица поворота вокруг оси Oz }
|
||
zr[1, 1] := Cos(za);
|
||
zr[1, 2] := -Sin(za);
|
||
zr[1, 3] := 0;
|
||
zr[1, 4] := 0;
|
||
|
||
zr[2, 1] := Sin(za);
|
||
zr[2, 2] := Cos(za);
|
||
zr[2, 3] := 0;
|
||
zr[2, 4] := 0;
|
||
|
||
zr[3, 1] := 0;
|
||
zr[3, 2] := 0;
|
||
zr[3, 3] := 1;
|
||
zr[3, 4] := 0;
|
||
|
||
zr[4, 1] := 0;
|
||
zr[4, 2] := 0;
|
||
zr[4, 3] := 0;
|
||
zr[4, 4] := 1;
|
||
|
||
RotateMatrix := MMMult(MMMult(xr, yr), zr)
|
||
end;
|
||
|
||
function MoveMatrix(tx, ty, tz: Real): Matrix;
|
||
begin
|
||
MoveMatrix[1, 1] := 1;
|
||
MoveMatrix[1, 2] := 0;
|
||
MoveMatrix[1, 3] := 0;
|
||
MoveMatrix[1, 4] := tx;
|
||
|
||
MoveMatrix[2, 1] := 0;
|
||
MoveMatrix[2, 2] := 1;
|
||
MoveMatrix[2, 3] := 0;
|
||
MoveMatrix[2, 4] := ty;
|
||
|
||
MoveMatrix[3, 1] := 0;
|
||
MoveMatrix[3, 2] := 0;
|
||
MoveMatrix[3, 3] := 1;
|
||
MoveMatrix[3, 4] := tz;
|
||
|
||
MoveMatrix[4, 1] := 0;
|
||
MoveMatrix[4, 2] := 0;
|
||
MoveMatrix[4, 3] := 0;
|
||
MoveMatrix[4, 4] := 1
|
||
end;
|
||
|
||
function ResizeMatrix(sx, sy, sz: Real): Matrix;
|
||
begin
|
||
ResizeMatrix[1, 1] := sx;
|
||
ResizeMatrix[1, 2] := 0;
|
||
ResizeMatrix[1, 3] := 0;
|
||
ResizeMatrix[1, 4] := 0;
|
||
|
||
ResizeMatrix[2, 1] := 0;
|
||
ResizeMatrix[2, 2] := sy;
|
||
ResizeMatrix[2, 3] := 0;
|
||
ResizeMatrix[2, 4] := 0;
|
||
|
||
ResizeMatrix[3, 1] := 0;
|
||
ResizeMatrix[3, 2] := 0;
|
||
ResizeMatrix[3, 3] := sz;
|
||
ResizeMatrix[3, 4] := 0;
|
||
|
||
ResizeMatrix[4, 1] := 0;
|
||
ResizeMatrix[4, 2] := 0;
|
||
ResizeMatrix[4, 3] := 0;
|
||
ResizeMatrix[4, 4] := 1
|
||
end;
|
||
|
||
procedure RotateShape(Shape: Object3D);
|
||
var
|
||
rm: Matrix;
|
||
i: Integer;
|
||
c: Column;
|
||
begin
|
||
rm := RotateMatrix(Shape.xa, Shape.ya, Shape.za); { сгенерировать матрицу вращения }
|
||
c[4] := 1; { последний элемент столбца всегда равен единице }
|
||
|
||
for i := 0 to High(Shape.vertices) do { цикл по всем вершинам }
|
||
begin { High(a) возвращает верхний индекс массива a }
|
||
c[1] := Shape.vertices[i].x; { инициализация столбца }
|
||
c[2] := Shape.vertices[i].y;
|
||
c[3] := Shape.vertices[i].z;
|
||
|
||
c := MCMult(rm, c); { вызов преобразования }
|
||
|
||
Shape.vertices[i].x := c[1]; { внесение изменений в модель }
|
||
Shape.vertices[i].y := c[2]; { в соответствии с полученным }
|
||
Shape.vertices[i].z := c[3] { результатом преобразования }
|
||
end
|
||
end;
|
||
|
||
procedure MoveShape(Shape: Object3D; Width, Height: Real);
|
||
begin
|
||
if Shape.xc > Width then
|
||
begin
|
||
Shape.xc := Width;
|
||
Shape.Vx := -Shape.Vx
|
||
end;
|
||
if Shape.xc < -Width then
|
||
begin
|
||
Shape.xc := -Width;
|
||
Shape.Vx := -Shape.Vx
|
||
end;
|
||
|
||
if Shape.yc > Height then
|
||
begin
|
||
Shape.yc := Height;
|
||
Shape.Vy := -Shape.Vy
|
||
end;
|
||
if Shape.yc < -Height then
|
||
begin
|
||
Shape.yc := -Height;
|
||
Shape.Vy := -Shape.Vy
|
||
end;
|
||
|
||
if Shape.zc > 500 then
|
||
begin
|
||
Shape.zc := 500;
|
||
Shape.Vz := -Shape.Vz
|
||
end;
|
||
if Shape.zc < 200 then
|
||
begin
|
||
Shape.zc := 200;
|
||
Shape.Vz := -Shape.Vz
|
||
end;
|
||
end;
|
||
|
||
procedure ResizeShape(var Shape: Object3D; sx, sy, sz: Real);
|
||
var
|
||
mm: Matrix;
|
||
i: Integer;
|
||
c: Column;
|
||
begin
|
||
mm := ResizeMatrix(sx, sy, sz);
|
||
c[4] := 1;
|
||
|
||
for i := 0 to High(Shape.vertices) do
|
||
begin
|
||
c[1] := Shape.vertices[i].x;
|
||
c[2] := Shape.vertices[i].y;
|
||
c[3] := Shape.vertices[i].z;
|
||
|
||
c := MCMult(mm, c);
|
||
|
||
Shape.vertices[i].x := c[1];
|
||
Shape.vertices[i].y := c[2];
|
||
Shape.vertices[i].z := c[3]
|
||
end
|
||
end;
|
||
|
||
end.
|
||
|