///////////////////////////////////////////////////////////////////
// Это пример 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();
}
/// Вот и все



[Назад]