Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Последние темы форума

Показать новые сообщения »

Почтовая рассылка

Подписчиков: 11650
Последний выпуск: 19.06.2015

Общий алгоритм рисования вращающихся "непрозрачных" 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) 

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
Аноним
Мне нравитсяМне не нравится
28 февраля 2005, 11:55:19
Простите, любезный, это не алгоритм - это его реализация. Ну и что с этим "припаскаленым" алгоритмом делать?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог