DarkOne’s Wolf3D source tutorial ¹3.

Knee-Deep in the Brick

 

The purpose of this tutorial is to make textured floor/ceiling in Wolf3D. This feature will give your engine the best boost in visual quality, so let’s get to work:

 

We’ll work in WL_DRAW.C file:

 

First find the following line:

 

unsigned  wallheight[MAXVIEWWIDTH;

 

And modify it like this:

 

unsigned  wallheight[MAXVIEWWIDTH], min_wallheight;

 

Then add following lines to the end of CalcHeight function:

 

int  CalcHeight (void)

{

<..>

<.here is original CalcHeight code.>

<..>

 

// update min_wallheight

  asm mov bx,[min_wallheight]

  asm cmp ax,bx

  asm jae noupdate:

  asm mov [min_wallheight],ax

noupdate:;

}

 

Then add the following macro declaration just before the start of vgaCeiling array declaration:

 

#define USE_TEX(page) (0x0000|(page))

 

/*

** use USE_TEX(n) to use floor/ceiling textures for given level

** n should be 1..255 !!!

** it is MAP-ID (from FloEdit). First texture goes to floor, second to ceiling

*/

 

unsigned vgaCeiling[]=

 

Now we are about to write the main texturing code: add this function just after vgaCeiling array declaration:

 

// ------------------------- * Textured flats * -------------------------

 

/*

** Draw Textured Floor/Ceiling

*/

void DrawFlats(unsigned tex_f, unsigned tex_c)

{

  int x, y, y0, halfheight;

  unsigned top_offset0, bot_offset0, top_offset, bot_offset;

  unsigned top_add, bot_add;

  byte p, color;

  byte far *src_bot, far *src_top;

 

  fixed dist;            // distance to row projection

  fixed tex_step;        // global step per one screen pixel

  fixed gu, gv, du, dv; // global texture coordinates

  int u, v;              // local texture coordinates

 

// ------ * prepare * --------

  halfheight=viewheight>>1;

  y0=min_wallheight>>3;      // starting y value

  if(y0>halfheight) return;  // view obscued by walls

  if(y0==0) y0=1;           // don't let division by zero

  top_offset0=80*(halfheight-y0-1);  // and will decrease by 80 each row

  bot_offset0=80*(halfheight+y0);  // and will increase by 80 each row

 

  src_bot=PM_GetPage(tex_f); // load floor texture

  src_top=PM_GetPage(tex_c); // load ceiling texture

 

// draw horizontal lines

  for(p=0; p<4; p++)

  {

    asm mov ax,0x0102

    asm mov cl,[p]

    asm shl ah,cl

    asm mov dx,0x3c4

    asm out dx,ax

 

    for(y=y0, top_offset=top_offset0, bot_offset=bot_offset0; y<halfheight; y++, top_offset-=80, bot_offset+=80)

    {

      dist=(heightnumerator/y)<<5;

 

      gu= viewx+FixedByFrac(dist, viewcos);

      gv=-viewy+FixedByFrac(dist, viewsin);

 

      tex_step=(dist<<8)/viewwidth/175;

 

      du= FixedByFrac(tex_step, viewsin);

      dv=-FixedByFrac(tex_step, viewcos);

 

      gu-=((viewwidth>>1)-p)*du;

      gv-=((viewwidth>>1)-p)*dv; // starting point (leftmost)

 

      du<<=2; // 4pix step

      dv<<=2;

 

      for(x=p, top_add=top_offset, bot_add=bot_offset; x<viewwidth; x+=4, top_add++, bot_add++)

      {

        if(wallheight[x]>>3<=y)

        {

          u=(gu>>10)&63; v=(gv>>10)&63;

 

          color=*(src_top+((63-u)<<6)+(63-v));

 

// draw top pixel using [color]

          asm mov es,[screenseg]

          asm mov di,[bufferofs]

          asm add di,[top_add]

 

          asm mov al,[color]

          asm mov es:[di],al

 

          color=*(src_bot+(u<<6)+(63-v));

 

// draw bottom pixel using [color]

          asm mov es,[screenseg]

          asm mov di,[bufferofs]

          asm add di,[bot_add]

 

          asm mov al,[color]

          asm mov es:[di],al

        }

        gu+=du; gv+=dv;

      }

    }

  }

}

 

Be careful with it, it’s big and it’s easy to miss something. After that change VGAClearScreen like this:

 

void VGAClearScreen(unsigned ceiling)

{

    //

    // clear the screen

    //

 

As you see I’ve removed ceiling variable from the function and added a parameter with the same name.

The last thing we will modify is ThreeDRefresh function:

 

void ThreeDRefresh (void)

{

    int tracedir;

    unsigned ceiling;

    boolean flats;

 

<..>

 

//

// follow the walls from there to the right, drawwing as we go

//

 

    ceiling=vgaCeiling[gamestate.episode*10+mapon];

 

    if((ceiling>>8)==(ceiling&0xFF))

    {

          VGAClearScreen(ceiling);

          flats=false;

    }

    else

    {

          flats=true;

          ceiling=((ceiling&0xFF)-1)<<1;

    }

 

    WallRefresh();

 

    if(flats)

          DrawFlats(ceiling, ceiling+1); // draw textured floor/ceiling

 

Ok, enough coding, let’s learn how to use this feature. First you should find a pair of images: one for floor, one for ceiling texture. They should look like texture, of course this is not a must, but it would look silly. I selected the following images:

 

 

 

Then I used something called like F*Edit to import them to my data files. I used indexes 62 and 63 (note that first index must be even and second index must be equal to first plus 1. This would make MAP-ID the same for both of them!), and remembered MAP-ID, 32 in this case.

Then I’ve chosen a level(s) to be textured using these textures (for simplicity it would be e1m1).

So I modified vgaCeiling array like that:

 

unsigned vgaCeiling[]=

{

#ifndef SPEAR

 USE_TEX(32),0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0xbfbf,

 0x4e4e,0x4e4e,0x4e4e,0x1d1d,0x8d8d,0x4e4e,0x1d1d,0x2d2d,0x1d1d,0x8d8d,

 0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x1d1d,0x2d2d,0xdddd,0x1d1d,0x1d1d,0x9898,

 

 0x1d1d,0x9d9d,0x2d2d,0xdddd,0xdddd,0x9d9d,0x2d2d,0x4d4d,0x1d1d,0xdddd,

 0x7d7d,0x1d1d,0x2d2d,0x2d2d,0xdddd,0xd7d7,0x1d1d,0x1d1d,0x1d1d,0x2d2d,

 0x1d1d,0x1d1d,0x1d1d,0x1d1d,0xdddd,0xdddd,0x7d7d,0xdddd,0xdddd,0xdddd

#else

 0x6f6f,0x4f4f,0x1d1d,0xdede,0xdfdf,0x2e2e,0x7f7f,0x9e9e,0xaeae,0x7f7f,

 0x1d1d,0xdede,0xdfdf,0xdede,0xdfdf,0xdede,0xe1e1,0xdcdc,0x2e2e,0x1d1d,0xdcdc

#endif

};

 

Note that I used MAP-ID, I remembered!

That’s all. I’ve built .exe and started it. Here is a result:

 

 

Voila! That’s it!

 

I hope this thing helped you on your way to create the best Wolf3D conversion ever made. If so, just drop me a line on DarkOne@navigators.lv. I wish to see your work!

 

--

© 2002 DarkOne; part of NewWolf project

http://wolfgl.narod.ru

DarkOne@navigators.lv