Создание фрактальной плазмы

Изображение плазмы на экране (фото с экрана монитора)

Реализовать алгоритм имитации плазмы.

Рассмотрим способ построения плазмы с помощью рекурсивного задания портрета самой плазмы и дальнейшего изменения ее цветов по соответствующим уравнениям гармонических колебаний (таким образом,обеспечив плавность переходов цвета):

for (i=0;i<=170;i++){
  pal[3*i]=(63* sin(  ( (double)i/170.0) *M_PI) );
  pal[3*i+256]=(63*sin((double)i/170.0*M_PI));
  pal[(3*i+512)%768]=floor(63*sin((double)i/170*M_PI));

Здесь pal-массив,хранящий палитру(с помощью него мы будем ее задавать)

сам портрет плазмы строится таким образом:
на краях экрана берутся 4 точки и окрашиваются произвольно.
Далее берутся точки на середине расстояний между соседними точками,а также точка в середине области,и заполняются как среднее арифметическое соответственно 2 лежащих на одном соответствующем с ней отрезке или 4 для серединной.
Полученный результат отклоняется функцией ncol и присваивается соответствующему пикселу.Далее-функция вызывется рекурсивно для полученных 4 подобластей на экране.

В программе использована "прямая" работа с видеорежимом 13h ,320x200 px,256 colors

Исходный код на Си:

#include <stdio.h>
#include <dos.h>
#include <stdlib.h>
#include <conio.h>
#include <graphics.h>
#include <math.h>
#include <iostream.h>
#pragma comment(linker,"/STACK:32777216")
char Get (int x,int y);
void Set(int x,int y,char color);
unsigned char pal[769];
int ncol(int m,int n,int d)
{
int loc;
 loc=(m+n-random(n))/d;
  if (loc>255) return 255;
  if (loc<0) return 0;
  return loc;
  }
 
 void drawp(int x1,int y1,int x2,int y2)
 {
  int xn,yn,dxy,p1,p2,p3,p4;
  if ((x2-x1<2)&&(y2-y1<2)) return;
  p1=Get(x1,y1);
  p2=Get(x1,y2);
  p3=Get(x2,y1);
  p4=Get(x2,y2);
  xn=(x1+x2)/2;
  yn=(y1+y2)/2;
  dxy=3*(x2-x1+y2-y1)/4;
  if (Get(xn,y1)==0)
   Set(xn,y1,ncol(p1+p3,dxy,2));
   if (Get(x1,yn)==0)
   Set(x1,yn,ncol(p1+p2,dxy,2));
   if (Get(x2,yn)==0)
   Set(x2,yn,ncol(p3+p4,dxy,2));
   if (Get(xn,y2)==0)
   Set(xn,y2,ncol(p2+p4,dxy,2));
   Set(xn,yn,ncol(p1+p2+p3+p4,dxy,4));
   drawp(x1,y1,xn,yn);
   drawp(xn,y1,x2,yn);
   drawp(x1,yn,xn,y2);
   drawp(xn,yn,x2,y2);
  return;
 }
 
char Get (int x,int y)
{
 char color;
 asm{
 push di
 mov cx,x
 mov dx,y
 mov bl,color
 
 mov ax,0xA000
 mov es,ax
 
 
 mov ax,320
 mul dx
 add ax,cx
 mov di,ax
 
 
 mov bl,es:[di]
 mov color,bl
 pop di;
 
 
 }
 return color;
 }
 
 void Set(int x,int y,char color)
 {
   asm {
   push di
 
   mov cx,x
   mov dx,y
   mov bl,color
 
   mov ax,0xA000
   mov es,ax
 
   mov ax,320
   mul dx
   add ax,cx
   mov di,ax
 
   mov es:[di],bl
   pop di
   }
 }
 
  void init()
  {
  int i=0;
   for (i=0;i<16000*4;i++)
    Set(i%320,i/320,0);
 }
 int main()
 {
   randomize();
 
 asm MOV AX,13h;
 asm INT 10h;
 
 int cnt=0;
 int iterator;
 int i;
 
 for (i=0;i<=170;i++){
  pal[3*i]=(63* sin(  ( (double)i/170.0) *M_PI) );
  pal[3*i+256]=(63*sin((double)i/170.0*M_PI));
  pal[(3*i+512)%768]=floor(63*sin((double)i/170*M_PI));
 
  }
 
 
 
  drawp(0,0,319,199);
 
 
 
 while(!kbhit())
 {
 do while((inport(0x03DA)&&8)==0);
 while((inport(0x03DA)&&8)==8);
 delay(10);
 outport(0x3C8,cnt);
 asm{
 MOV SI,offset pal
 MOV CX,769
 MOV DX,0x3C9
 REP outsb
 }
 cnt++;
 }
 
 
   getch();
;asm MOV AX,3h;
asm INT 10h;
return 0;
}

Исходный код на Turbo Pascal:
{$A+,B-,D+,E+,F-,G+,I-,L+,N-,O-,P-,Q-,R-,S-,T-,V+,X+,Y+}
 
 
uses crt;
 
var
  i       : integer;
  counter : byte;
  pal  : array[0..768]of byte;
  screen  : array[0..63999]of byte absolute $A000:0;
 
 
 
function col(a,b,dvd : integer): integer;
var
  loc : integer;
begin
  loc:=(a+b-random(b)) div dvd;
  col:=loc;
  if loc>255 then col:=255;
  if loc<0 then col:=0
end;
 
procedure plasma(x1,y1,x2,y2 : integer);
var
  xn,yn,dxy,p1,p2,p3,p4 : integer;
begin
  if (x2-x1<2) and (y2-y1<2) then EXIT;
  p1:=screen[320*y1+x1];
  p2:=screen[320*y2+x1];
  p3:=screen[320*y1+x2];
  p4:=screen[320*y2+x2];
  xn:=(x2+x1) div 2;
  yn:=(y2+y1) div 2;
  dxy:=(x2-x1+y2-y1);
  if screen[320*y1+xn]=0 then screen[320*y1+xn]:=col(p1+p3,dxy,2);
  if screen[320*yn+x1]=0 then screen[320*yn+x1]:=col(p1+p2,dxy,2);
  if screen[320*yn+x2]=0 then screen[320*yn+x2]:=col(p3+p4,dxy,2);
  if screen[320*y2+xn]=0 then screen[320*y2+xn]:=col(p2+p4,dxy,2);
  screen[320*yn+xn]:=col(p1+p2+p3+p4,dxy,4);
  plasma(x1,y1,xn,yn);
  plasma(xn,y1,x2,yn);
  plasma(x1,yn,xn,y2);
  plasma(xn,yn,x2,y2)
end;
 
begin
  asm
    mov  ax,13h
    int  10h
  end;
 
  for i:=1 to 170 do pal[3*i]:=round(63*sin(i/170*pi));
  for i:=1 to 170 do pal[3*i+256]:=round(63*sin(i/170*pi));
  for i:=1 to 170 do pal[(3*i+512) mod 768]:=round(63*sin(i/170*pi));
  plasma(1,1,319,199);
 
  counter:=0;
  repeat
 
 
    delay(2000);
 
    port[$3C8]:=counter;
 
    asm
      mov  si,offset pal
      mov  cx,768
      mov  dx,$3C9
      rep outsb
    end;
    inc(counter);
  until keypressed;
  asm
    mov  ax,3h
    int  10h
  end;
end.

Ключевые слова: 
плазма, изменение палитры, режим 13h, цвет
ВложениеРазмер
plasmC.rar18.69 кб
plasmPas.rar5.41 кб