Общий алгоритм рисования вращающихся "непрозрачных" 3-мерных фигур
{Borland Pascal 7.0 CUBE.PAS: Общий алгоритм рисования вращающихся "непрозрачных" 3-мерных фигур Classic example. Modify by V.Ivanov} uses Graph, Crt; procedure DrawCube; label nextj; type cube=array[1..8] of record x,y,z:integer end; {verts-координаты (xyz) вершин фигуры} const verts:cube=( (x: 1; y: 1; z: 1), {1-я вершина} (x: 1; y: 1; z:-1), {2} (x: 1; y:-1; z: 1), {3} (x: 1; y:-1; z:-1), {4} (x:-1; y: 1; z: 1), {5} (x:-1; y: 1; z:-1), {6} (x:-1; y:-1; z: 1), {7} (x:-1; y:-1; z:-1)); {8} {g- это описания из каких вершин в состоят грани (в массиве лежат номера точек в нумерации verts) } g:array[1..6, 1..4] of shortint= ((1,2,4,3), (1,2,6,5), (1,3,7,5), (3,4,8,7), (2,4,8,6), (5,6,8,7)); var Alfa,Beta,Gamma, {проекции единичного вектора поворота (его длина=1)} Teta, {Угол поворота точек пространства} DT:real; {Приращение (прибавка) угла Teta} c:cube; {Массив для координат вращаемых вершин} procedure Rotate(var x,y,z:integer); {Поворот точки вокруг единичного вектора (Alfa, Beta, Gamma) на угол Teta} var cosT, sinT, One_cosT, AOne_cosT, BOne_cosT,GsinT:real; xn,yn,zn:integer; begin {Это сложное преобразование взято из справочника по стереометрии} cosT:=cos(Teta); sinT:=sin(Teta); One_cosT :=1.0-cosT; AOne_cosT:=Alfa*One_cosT; BOne_cosT:=Beta*One_cosT; GsinT:=Gamma*sinT; xn:=trunc( x*( cosT + Alfa * AOne_cosT)+ y*( GsinT + Beta * AOne_cosT)+ z*(-Beta*sinT + Gamma * AOne_cosT)); yn:=trunc( x*(-GSinT + Beta * AOne_cosT)+ y*( cosT + Beta * BOne_cosT)+ z*( Alfa*sinT + Gamma * BOne_cosT)); zn:=trunc( x*( Beta*sinT + Gamma * AOne_cosT)+ y*(-alfa*sinT + Gamma * BOne_cosT)+ z*( cosT + Gamma*Gamma*One_cosT)); x:=xn; y:=yn; z:=zn; delay(1); end; function minz:integer; {нахождение самой "задней" точки, т.е. с минимальным z (ось z идет от нас)} var j,m:integer; begin m:=1; for j:=2 to 8 do if c[j].z< c[m].z then m:=j; minz:=m; end; var Pnts:array[1..5] of record {Буфер для рисования точек грани через FillPoly} x,y:integer end; min:integer; {номер самой "задней" точки} x0,y0:integer; {Центр изображения} a: integer; {Коэф. увеличения изображения} i,j,k:integer; {Параметры циклов} page:word; {Текущая видео страница} begin page:=0; x0:=120; y0:=100; a:=40; Alfa:=0.6; Beta:=0.7; Gamma:=sqrt(1.0-Alfa*Alfa-Beta*Beta); {3-мерная теорема Пифагора} Teta:=0; DT:=2*Pi/100;{2.0*Pi/20;} {Масштабируем и поворачиваем все вершины на угол Teta} for i:=1 to 8 do begin c[i].x:=verts[i].x*a; c[i].y:=verts[i].y*a; c[i].z:=verts[i].z*a; Rotate(c[i].x,c[i].y,c[i].z) end; min:=MinZ; {находим самую заднюю вершину} SetVisualPage((Page+1)mod 2); for k:=0 to 2500 do begin SetActivePage(page); {Делаем активной невидимую страницу} {Рисуем 6 граней} for j:=1 to 6 do begin {Пропуск невидимой грани содержащей самую "заднюю" точку} for i:=1 to 4 do if min=g[j,i] then goto nextj; {goto необходим!} {Проходим по вершинам грани} for i:=1 to 4 do begin {Берем проекцию вершины на плоскость xoy (т.е. коорд. x и у) } Pnts[i].x:=x0+c[g[j,i]].x; Pnts[i].y:=y0+trunc(0.775*c[g[j,i]].y) {0.775- к-т сжатия EGA HI} end; SetFillStyle(SolidFill, word(j+8)); {Каждой грани своя закраска} {Pnts[5]:=Pnts[1];} {Это нужно при DrawPoly} FillPoly(4,Pnts); {Рисуем грань} nextJ: end; SetVisualPage(Page); {Показываем рисунок: делаем видимой страницу} SetActivePage((Page+1)mod 2); {Делаем активной невид. стр. для Bar} {Поворачиваем вершины} for i:=1 to 8 do begin c[i].x:=verts[i].x*a; c[i].y:=verts[i].y*a; c[i].z:=verts[i].z*a; Rotate(c[i].x,c[i].y,c[i].z) end; min:=MinZ; SetFillStyle(SolidFill, Black); Bar(0,0,x0*2,y0*2); {Стираем старое изображение на невид. стр.} Teta:=Teta+DT; {Увеличиваем угол поворота} Page:=(Page+1)mod 2; {Меняем страницу (0-> 1; 1->0) } if KeyPressed then exit; {Если нажали клавишу - конец} end; end; var drv,mode:integer; begin drv:=EGA; mode:=EGAHI; InitGraph(drv,mode,'C:\compilat\tp\bgi'); DrawCube; end. --- * Origin: I like: Pas, Delphi, C++, Asm, Physics (2:5030/433.20)
Оставить комментарий
Комментарии
1.
28 февраля 2005, 11:55:19
Простите, любезный, это не алгоритм - это его реализация. Ну и что с этим "припаскаленым" алгоритмом делать?