///////////////////////////////////////////////////////////////////
// Это пример 2d-bumping'а, поясняющий текст файла 2dbump_r.txt
// В программе нет никакой оптимизации и никакого ассемблера.
// Даже более того: эта прoграмма может послужить примером того,
// как не надо писать программы ;)
// Основной упор делается не на скорость выполнения, а на максимально
// понятную реализацию алгоритма. (оптимизированная версия с критичными
// участками, реализованными на ассемблере, работает в 2-3 раза быстрее)
//
// - при запуске показываются используемые палитры (0->255)
// - карта окружения
// - исходная картинка
// - рельефная картинка, меняющая свой коэффициент рельефности от -5 до 5
// через каждые 30 кадров, с двигающимся источником света.
//
//
// Fedor Tsiplakov, 2:5022/73.10
/////////////////////////////////////////////////////////
#include < time.h >
#include < math.h >
#include < string.h >
#include < stdlib.h >
#include < dos.h >
#include < conio.h >
#include < stdio.h >
#define UINT unsigned int
#define UCHAR unsigned char
char far* screen=(char far*)MK_FP(0xA000,0); // указатель на экран
char far* font=(char far*)MK_FP(0xF000,0xFA6E);//указатель на шрифты 8х8
char * bumptext="2D-BUMP";// выводимый текст
char *vb; // Буфер с картой высот (bmap)
char *fb; // вспомогательный буфер.
char *envmap; // карта окружения
int lx=160; // координата X источника света
int ly=100; // координата Y источника света
int bumpness=0;// коэффициент рельефности
float den=100; // размер пятна (радиус. <128, иначе обрезается границами
// буфера )
float tint=255;// максимальная яркость пятна
int frames=0; // количество отображенных кадров
clock_t t; // начальное время
int dx=2; // приращение X координаты источника света
int dy=2; // =====\==== Y ====\===== ====\==== ==\==
int db=1; // приращение коэффициента рельефности
////////////////// установить графический режим mode //////////////////
/// mode - номер нужного режима (0x13 - 320x200x256)
//////////////////////////////////////
void setmode(int mode){asm{mov ax,mode;int 0x10}}
////////////////// Нарисовать одну точку ////////////////
/// xcoord,ycoord- координаты точки
/// color - цвет точки
/// buf - указатель на буфер 320х200
/////////////////////////////////////////////////////////
inline void draw(UINT xcoord,UINT ycoord,UCHAR color,char * buf)
{buf[(ycoord<<6)+(ycoord<<8)+xcoord]=color;}
///////////////////// создать красную равномерную палитру //////////////
void setpalette1(void) { for (UINT i=0;i<256;i++){
outp(0x3c8,i);outp(0x3c9,i>>2);outp(0x3c9,i>>4);outp(0x3c9,i>>6);}}
///////////////////// создать серую равномерную палитру ///////////////////
void setpalette2(void){ for (UINT i=0;i<256;i++){
outp(0x3c8,i);outp(0x3c9,i>>2);outp(0x3c9,i>>2);outp(0x3c9,i>>2);}}
///////////////////// вспомогательная функция для отображения палитры ////
void testpal (void){for(int i=0;i<256;i++){for(int jj=0;jj<200;jj++){
draw(i,jj,i,screen);}}}
//////////////// нарисовать задний план ////////////////////////////////
void drawtest(void)
{ srand(22);
for (UINT i=64000-320;i<64000;i++){vb[i]=random(256);};
for (i=64000-320;i>0;i--){int cc=vb[i+319]+vb[i+320]+vb[i+321];
screen[i]=vb[i]=(cc/3>0)?cc/3-2:cc/3;}
}
///////////////// размытие буфера /////////////////////
void blur(void)
{ for (UINT i=0;i<64000;i++){screen[i]=fb[i]=((
vb[i-319]+vb[i-320]+vb[i-321]+
vb[i-1 ]+vb[i ]+vb[i+1 ]+
vb[i+319]+vb[i+320]+vb[i+321])/9);}
for (i=0;i<64000;i++){vb[i]=fb[i];}
}
/////////////////// нарисовать символ //////////////////
/// x,y- координаты верхнего левого угла
/// sx,sy - размеры квадрата (одной точки буквы)
/// l - рисуемый символ
/// color - цвет символа
///////////////////////////////////////////////////////
void draw_letter(UINT x,UINT y,UINT sx,UINT sy,UCHAR l,UCHAR color)
{ UCHAR mask;int a,b;
for (int i=0;i<8;i++) // высота
{ UCHAR sline=font[l*8+i];mask=0x80;// binary 10000000
for (int j=0;j<8;j++) // ширина
{ if (sline&mask)
{for (a=0;a>=1;}}
}
/////////// нарисовать текст //////////////
///nx,ny - координаты левого верхнего угла текста
///sx,sy - размеры одной точки изображения
///kern - расстояние между буквами
///text - указатель на текст
///color - цвет надписи
///////////
void draw_text (UINT nx,UINT ny,UINT sx,UINT sy,
UINT kern,char * text,UCHAR color)
{ int i; for (i=0;i0?z:0;
envmap[i*255+j]=(char)(z*tint);}}
}
//////////////// сама процедура bumping'a //////////////////
// n - коэффициент рельефности
// при n<0 - надпись "вдавлена", при n>0 - "выдавлена"
////////////////////////////////////////////////////////////
void do_bump (int n)
{int x,y,nx,ny,py;
int d=(int)den;
for (y=0;y<200;y++){ py=y*320;
for (x=0;x<320;x++){
nx=(vb[py+x]-vb[py+x+n])-(lx-x)+d;
if (nx<0||nx>254) nx=0;
ny=(vb[py+x]-vb[py+320*n+x])-(ly-y)+d;
if (ny<0||ny>254) ny=0;
screen[py+x]=envmap[ny*255+nx];}}
}
////////////////////////////////////////////////////////////
///////////////////////// main code ////////////////////////
////////////////////////////////////////////////////////////
void main(void)
{
///////////////////// init buffers ////////////////////////
if ((fb=(char *)malloc (64321))==NULL)
{printf("not enough memory for fb");exit(0);};
if ((vb=(char *)malloc(64321))==NULL)
{printf("not enough memory for vb");exit(0);};
if ((envmap=(char *)malloc (65535L))==NULL)
{printf("not enough memory for envmap");exit(0);};
///////// /////////// //////////// ///////////// ///////////
setmode(0x13); // установить режим 320х200х256
create_env(); // рассчитать карту окружения
setpalette1();testpal();getch(); // показать первую палитру
setpalette2();testpal();getch(); // показать вторую палитру
for (int ii=0;ii<256;ii++){
for (int jj=0;jj<256;jj++){screen[320*jj+ii]=envmap[jj*255+ii];}};
getch(); /// показать карту окружения
setpalette1();
drawtest(); // нарисовать задний фон
draw_text(20,70,5,6,2,bumptext,254); // нанести на него надпись
//blur();
blur(); /// несколько раз размыть получившуюся картинку
blur();
blur();
getch();
setpalette2();
t=clock();
while (!kbhit()){
if (lx<1||lx>319) dx=-dx; //проверить координаты источника света на
if (ly<1||ly>199) dy=-dy; //попадание в границы экрана
if (!(frames%30)) {
if (bumpness<-5||bumpness>5) {db=-db;};bumpness+=db;};
// каждый тридатый кадр изменять коэффициент рельефности
lx+=dx; // вычислить новые координаты источника света
ly+=dy; //
do_bump(bumpness);// нарисовать очередной кадр рельефа
frames++; // увеличить счетчик кадров
};
t=clock()-t; // вычислить затраченное время
setmode(0x3);// установить текстовой режим
printf("%f",frames*CLK_TCK/t);// напечатать примерное количество
// кадров в секунду
getch();
}
/// Вот и все
[Назад]