Программа построения трехмерных L-фракталов (язык Си) .
#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <string.h>
#include <graphics.h>
#define XO 0
#define YO -200
#define ZO 0
#define DIRXO 0
#define DIRYO 1
#define DIRZO 0
#define STEP 10
#define ALPHA 0.392
#define VPXO 0
#define VPYO 0
#define VPZO 1
typedef struct v {float x,y,z;} vector;
typedef float matrix[3][3] ;
float stack[250][6] ;
int gd,gm,si,i,step;
char s [100] ;
char ss [16000];
matrix ru, rl,rh;
vector direct,vp;
float xp,yp,alpha,x,y,z;
/* Функции преобразования координат */
int xe (float x) { return((int)(x+320));}
int ye (float y) { return((int)(240-y));}
/* Функции получения перспективной
проекции точки с координатами (x,y,z)
на плоскость (XOY) в направлении вектора vp */
float prx (float x,float z., vector vp)
{ return (x-(z/vp.z)*vp.x); }
float pry (float y,float z,vector vp)
{ return (y-(z/vp.z)*vp.y); }
/* Функция умножения вектора на матрицу */
void mult(vector* v,matrix r)
{
float tempx/tempy,tempz;
tempx=v->x*r[0][0]+v->y*r[1][0]+v->z*r[2][0];
tempy=v->x*r[0][1]+v->y*r[1][1]+v->z*r[2][1];
tempz=v->x*r[0][2]+v->y*r[1][2]+v->z*r[2][2];
v->x=tempx; v->y=tempy; v->z=tempz;
}
/* Функция записывает в стек текущее
состояние
(координаты точки, направление) */
void push(float x,float у,float z,float vx,float vy,float vz)
{ si++;
stack[si][0]=x; stack[si][1]=y; stack[si] [2]=z;
stack[si][3]=vx; stack[si][4] =vy; staclc[si] [5]=vz;
}
/* Функция извлекает один элемент стека */
void pop(float* x,float* у,float* z,float* vx,float*-vy/float* vz)
{ *x=stack[si][0]; *y=stack[si][1]; *z=stack[si][2] ;
*vx=stack[si][3]; *vy=stack[si][4]; *vz=stack[si][5] ;
si--;
}
/* Функция заполняет матрицу ru для
поворота вокруг оси OZ на угол alpha */
void makeru(float alpha)
{
ru[0][0]=cos(alpha); ru[0][1]=-sin(alpha); ru[0][2]=0;
ru[l][0]=sin(alpha); ru[l][1]=cos(alpha);
ru[l][2]=0;
ru[2][0]=0;
ru[2][l]=0;
ru[2][2]=l;
}
/* Функция заполняет матрицу rl для
поворота вокруг оси OY на угол alpha */
void makeri(float alpha)
{
rl[0][0]=cos(alpha); rl[0][l]=0; rl[0][2]=-sin(alpha) ;
rl[l][0]=0;
rl[l][l]=l; rl[l][2]=0;
rl[2][0]=sin(alpha); rl[2][l]=0; rl[2][2]=cos(alpha) ;
}
/* Функция заполняет матрицу rh для
поворота вокруг оси ОХ на угол alpha */
void makerh(float alpha)
{
rh[0][0]=l; rh[0][l]=0;
rh[O][2]=0;
rh[l][0]=0; rh[l][1]=cos(alpha);
rh[1][2]=-sin (alpha) ;
rh[2][0]=0; rh[2][1]=sin(alpha);
rh[2][2]=cos(alpha) ;
}
/* Функция читает данные из файла filename */
void readfra(char *filename, char *s)
{ unsigned int i,n;
FILE *f=fopen(filename,"rt") ;
fgets(s,90,f) ;
fclose(f);
s[strlen(s)-l]='\0';
}
/* Функция получения строки для рисования
фрактала */
void lstring(int n)
{
int i,j,l,k,t;
l=strlen(s);
k=l;
for (j=0;j<strlen(s);j++) ss[j]=s[j];
ss[strlen(ss)]='\0';
for (t=l;t<=n;t++)
{ i=0;
while (i<=l)
{ if (ss[i]=='F')
{ for (j=l-l;j>=i+l;j—)
ss[j+k-l]=ss[j];
for (j=0;j<strlen(s);j++) { ss[i]=s[j]; i++;}
l=l+strlen(s)-1;
ss[l]='\0';
}
else i++;
}
}
}
/* Функция рисования фрактала */
void ldraw(void)
{ float c1,c2,c3,col;
float x1,y1,z1;
xp=prx(x,z,vp) ;
yp=pry(y,z,vp) ;
moveto(xe(xp),ye(yp));
for (i=0;i<strlen(ss);i++)
switch (ss[i])
{ case 'F': x=x+step*direct.x; y=y+step*direct.y;
z=z+step*direct.z;
xp=prx(x,z,vp) ;
yp=pry(y,z,vp) ;
lineto(xe(xp),ye(yp)) ;
break;
case ' [': push(x,y,z,direct.x,direct.y,direct.z);
break;
case ']': pop(&x,&y,&z,&x1,&y1,&z1);
direct.x=x1; direct.y=y1; direct.z=z1;
xp=prx(x,z,vp);
yp=pry(y,z,vp);
moveto (xe(xp),ye(yp));
break;
case '+': makeru(alpha);
mult(&direct,ru);
break;
case '-': makeru(-alpha);
mult(&direct,ru);
break;
case '&': makerl(alpha);
mult(&direct,rl);
break;
case '^': makerl(-alpha);
mult(&direct,rl);
break;
case '<': makerh(alpha);
mult(&direct,rh);
break;
case '>': makerh(-alpha);
mult(&direct,rh);
break;
case '|': direct.x=-direct.x;
direct.y=-direct.y;
direct.z=-direct.z;
break;
}
}
void main(int argc,char* argv[])
{
FILE *f;
int inrec;
printf("Глубина рекурсии:\n");
scanf("%d",&inrec);
x=XO; y=YO; z=ZO; si=-1;
direct.x=DIRXO; direct.y=DIRYO; direct.z=DIRZO;
readfra(argv[1],s);
lstring(inrec);
puts(ss);
getch();
gd=DETECT;
initgraph(&gd,&gm,"");
setlinestyie(О,О,З);
setcolor(WHITE) ;
alpha=ALPHA;
step=STEP;
vp.x=VPXO; vp.y-VPYO; vp.z=VPZO;
ldraw() ;
getch() ;
closegraph() ;
}
"Библиотечка" для режима VGA 13h (320х200х256 цветов)
#pragma inline
#inciude <dos.h>
// Установка режима 13h 256 цветов
void set256(void)
{ asm { mov al,13h
mov ah,0
int lOh
}
}
// Установка режима 3 (текстовый)
void setTEXT(void)
{ asm { mov al,3
mov ah,0
int lOh
}
}
// Поставить точку прямой записью в память в
режиме 256 цветов
void putpixel256(int x,int у,unsigned char с)
{ unsigned char far *vmem=(unsigned char far *)(MK_FP(OxAOOO,0));
vmem[y*320+x]=c;
}
// Установка всех 256 регистров палитры.
Передаются сегмент и смещение таблицы
void SetVgaDAC(unsigned seg_tabie,unsigned off_table)
{
asm {
push ds
push es
xor ax,ax
mov es,ax
mov dx,es:[463h]
add dx,6
pop es
in al,dx
nop
nop
test al,08h
jz wait_on
}
wait_off:
asm {
in al,dx
nop
nop
test al,08h
jnz wait_off
}
wait_on:
asm {
in al,dx
nop
nop
test al,08h
jz wait_on
mov dx,3c8h
mov ax,0
out dx.al
nop
nop
mov ax/seg_table
mov ds,ax
mov si,off_table
mov cx,(256*3)
mov dx,3c9h
cld
}
get_reg:
asm {
lodsb
out dx,al
nop
nop
loop get_reg
pop ds
}
}