ПК

3d движок

Зачем?

  Наверно каждый программист хотел написать, что-то по настоящему мощное, чем можно было удивить. Казалось бы все уже написано: Quake, CS и пр. Зачем? Но настоящего программиста, как ребенка разбирающего игрушку, интересует: что внутри. Как работает Quake и CS? Какие математические формулы используются для перевода из мировых координат в экранные? На этот вопрос я постараюсь дать ответ. В качестве языка программирования будет использоваться Borland Pascal 7.0. В процессе разработки я буду давать максимально подробные комментарии.

Как?

  Не буду особо докучать теорией. Скажу лишь только, что трехмерное пространство проецируется на экран с помощью тригонометрии. Каждый семиклассник знает что такое векторы и проекции.

Программа.

  Для скорости вычисления мы сразу создадим массив для хранения синусов и косинусов для углов от 0 до 359 градусов. В программе используется разрешение 640*350 т.к. этот видеорежим содержит 2 видеостраницы. maxx и maxy отвечают за правую нижнюю точку. tsin и tcos массив, содержащий sin и cos. perspective переменная отвечающая за использование перспективы, а e - коэффициент перспективы (как далеко объект от нас). rotate(Ax,Ay,Az:Integer; var p: Point3d); поворачивает точку вокруг осей Ax, Ay, Az. transform(pt3d:Point3d; var x2d,y2d:Integer); переводит из 3d в 2d. line3d(point1,point2:Point3d; color:byte); построение линии из 2х точек с заданным цветом.

  После запуска программы: q и a поворачивают вокруг оси X, w и s поворачивают вокруг оси Y, e и d поворачивают вокруг оси Z. ESC - выход. Между {-----------------} находиться прорисовка куба со стороной 200.

  Можно организовать считывание линий из файла. Можно организовать построение трехмерного графика, сферы и пр. Можно в программе использовать мышь - что еще лучше!!! Скоро в разделе Pascal появится моя работа и с мышкой и со всеми прибамбасами, просто нужно все собрать и зазиповать. Там есть программа по построению графиков, есть файлы со сферой и кубом и с поверхностями. Я уверен, что этот небольшой пример будет началом создания игры. Если у вас что-нибудь получиться - пишите alexartwww@yandex.ru! Также нужно создать алгоритм по отрезанию невидимых линий!

Скачать программу
Скачать программу для Windows написанную на Delphi.

Текст программы:
{$G+}
uses crt,graph;
type
  point3d = Record
  x,y,z:Integer;
  end;
var
  tcos,tsin:array[0..359] of Extended;
  int:Integer;
  perspective:Boolean;
  e:Integer;
  maxx,maxy,ox,oy,oz:Integer;
  gd,gm,m:Integer;
  key:Char;
  p1,p2:point3d;
const
  gr = pi/180;
procedure transform(pt3d:Point3d; var x2d,y2d:Integer);
var
Thit:Real;
begin
if perspective then
begin
Thit:=1/(1-pt3d.x/e);
x2d:= trunc(maxx/2+pt3d.y*thit);
y2d:= trunc(maxy/2-pt3d.z*thit);
end
else
begin
x2d:=trunc(maxx/2+round(pt3d.y));
y2d:=trunc(maxy/2-round(pt3d.z));
end;
end;
procedure rotate(Ax,Ay,Az:Integer; var p: Point3d);
var
s1,s2,s3,c1,c2,c3:Extended;
Puit:Point3d;
begin
s1:=tsin[trunc(ax)];
c1:=tcos[trunc(ax)];
s2:=tsin[trunc(ay)];
c2:=tcos[trunc(ay)];
s3:=tsin[trunc(az)];
c3:=tcos[trunc(az)];
puit.x:=trunc(p.x*(c2*c3)+p.y*(c2*s3)-p.z*s2);
puit.y:=trunc(p.x*(s1*s2*c3-c1*s3)+p.y*(s1*s2*s3+c1*c3)+p.z*(s1*c2));
puit.z:=trunc(p.x*(c1*s2*c3+s1*s3)+p.y*(c1*s2*s3-s1*c3)+p.z*(c1*c2));
p:=puit;
end;
procedure linec(x1,y1,x2,y2:Integer; color:byte);
begin
setcolor(color);line(x1,y1,x2,y2);
end;
procedure line3d(point1,point2:Point3d; color:byte);
var
x1,x2,y1,y2:Integer;
begin
transform(point1,x1,y1);
transform(point2,x2,y2);
if ((x1 > 0) and (x1 < maxx)) or ((y1 > 0) and (y1 < maxy)) then linec(x1,y1,x2,y2,color);
end;
Begin
perspective:=true;
e:=300;
for int := 0 to 359 do
begin
tsin[int]:=sin(int*gr);
tcos[int]:=cos(int*gr);
end;
gd:=9;gm:=1;
InitGraph(gd,gm,'');
maxx:=640;
maxy:=350;
m:=0;
repeat
key:=#0;
if keypressed then key:=readkey;
if key = #113 then ox:=ox-1;
if key = #97 then ox:=ox+1;
if key = #119 then oy:=oy-1;
if key = #115 then oy:=oy+1;
if key = #101 then oz:=oz-1;
if key = #100 then oz:=oz+1;
if ox > 359 then ox:=ox-359;
if ox < 0 then ox:=359-(0-ox);
if oy > 359 then oy:=oy-359;
if oy < 0 then oy:=359-(0-oy);
if oz > 359 then oz:=oz-359;
if oz < 0 then oz:=359-(0-oz);
m:=1-m;
setactivepage(m);
cleardevice;
{-----------------------}
p1.x:=-100;
p1.y:=-100;
p1.z:=100;
p2.x:=100;
p2.y:=-100;
p2.z:=100;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,15);
p1.x:=100;
p1.y:=-100;
p1.z:=100;
p2.x:=100;
p2.y:=100;
p2.z:=100;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,15);
p1.x:=100;
p1.y:=100;
p1.z:=100;
p2.x:=-100;
p2.y:=100;
p2.z:=100;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,15);
p1.x:=-100;
p1.y:=100;
p1.z:=100;
p2.x:=-100;
p2.y:=-100;
p2.z:=100;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,15);
p1.x:=-100;
p1.y:=-100;
p1.z:=-100;
p2.x:=100;
p2.y:=-100;
p2.z:=-100;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,15);
p1.x:=100;
p1.y:=-100;
p1.z:=-100;
p2.x:=100;
p2.y:=100;
p2.z:=-100;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,15);
p1.x:=100;
p1.y:=100;
p1.z:=-100;
p2.x:=-100;
p2.y:=100;
p2.z:=-100;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,15);
p1.x:=-100;
p1.y:=100;
p1.z:=-100;
p2.x:=-100;
p2.y:=-100;
p2.z:=-100;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,15);
p1.x:=100;
p1.y:=100;
p1.z:=-100;
p2.x:=100;
p2.y:=100;
p2.z:=100;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,15);
p1.x:=-100;
p1.y:=100;
p1.z:=-100;
p2.x:=-100;
p2.y:=100;
p2.z:=100;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,15);
p1.x:=100;
p1.y:=-100;
p1.z:=-100;
p2.x:=100;
p2.y:=-100;
p2.z:=100;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,15);
p1.x:=-100;
p1.y:=-100;
p1.z:=-100;
p2.x:=-100;
p2.y:=-100;
p2.z:=100;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,15);
{OX}
p1.x:=150;
p1.y:=0;
p1.z:=0;
p2.x:=0;
p2.y:=0;
p2.z:=0;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,14);
{OY}
p1.x:=0;
p1.y:=150;
p1.z:=0;
p2.x:=0;
p2.y:=0;
p2.z:=0;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,14);
{OZ}
p1.x:=0;
p1.y:=0;
p1.z:=150;
p2.x:=0;
p2.y:=0;
p2.z:=0;
rotate(ox,oy,oz,p1);
rotate(ox,oy,oz,p2);
line3d(p1,p2,14);
{-----------------------}
setvisualpage(m);
until (key = #27);
closegraph;
end.

© Проект Alex'а О проекте