
The following is a document I wrote up on how the wt world is set up.  It
took me a bit longer than expected to complete, so it doesn't look like I'm
going to get wt 0.04 up tonight.  Sorry--I'll shoot for tomorrow night
for 0.04.

--Chris Laurel
claurel@mr.net

--------------------------------------------------------------------------

This is a quick description of the wt world file.  There's no guarantee that
it will not be changing in the future, of course.



The world file itself may not make much sense without a discussion of the
internal world structures.

The first thing to understand is that the world in wt is not truly three
dimensional.  It is cannot render general polygons.  It can handle only
horizontal floors or vertical walls.  This limitation is key to wt's speed.

The world structure in world.h looks like this:

typedef struct {
     Table *vertices;
     Table *walls;
     Table *regions;
     Table *textures;
} World;


Definitions:
	Vertices are points on a plane.
	Walls connect two vertices and separate two regions.
	Regions are not necessarily connected areas that
	    are surrounded by walls.

Here is the vertex structure from world.h:

typedef struct {
     fixed x, y;
     fixed tx, ty, proj;      /* transformed coordinates */
} Vertex;

The important fields for this discussion are the x and y coordinates.  The
other fields are not stored in the world field, but are generated each time
a frame is rendered.  I'll cover that sometime when I describe how the
renderer works.

Ok . . . the vertex structure is pretty basic.  Like the definition says, it's
just a point in two-space.  The wall structure is more interesting:

typedef struct {
     Vertex *vertex1, *vertex2;
     Texture *surface_texture;
     Region *front, *back;
     fixed xphase, yphase;
     fixed xscale, yscale;
     Boolean opaque;
} Wall;

vertex1 and vertex2 are the two wall endpoints.  surface_texture is the
texture which is mapped on the wall.  xphase, yphase, xscale, and yscale
control how the texture is drawn on the wall.  xphase and yphase are numbers
between 0 and 1.  The determine where the origin of the texture is with
respect to the origin of the wall.  The wall origin lies in the plane of the
wall at vertex1 and height zero.  If the x and y phase are zero, then the
texture origin coincides with the wall origin.  If the x and y phase are
both 0.5, then the wall origin coincides with the center of the texture.
The xphase and yphase fields are critical for getting wall sections to
join seamlessly (you'll notice that this is not done in my current sample
world files.  Adjusting the texture phases will be a function of a
world editor program.)

While the scale fields of the wall structure do indeed control how the
texture map is sized, the would be more appropriately called 'frequencies'
(The incorrect name persists because I've been too lazy to change it.)
X and y scale factors of 0.1 would make a single tile of texture cover
one hundred times as much wall area (not one-hundreth as much.)

The opaque field is something that will be used in future versions of wt.

One thing that may puzzle you is the fact that there are no heights listed
in the wall structure.  That's because the height of the wall is determined
by the regions in front and in back of it.


Here's the region structure:

typedef struct {
     fixed floor, ceiling;
     Texture *floor_tex, *ceiling_tex;
} Region;

floor is the floor height and ceiling is the ceiling height.  I know this
is obvious but I'll say it anyway:  floor_tex is the texture map which will
appear on the floor of the region and ceiling_tex is the one which will appear
on the ceiling.

Here's a simple diagram which should help you understand how region heights
interact with walls.  The diagram depicts a edge-on view of a couple walls.
This exact arrangement of walls occurs with the windows of the castle.


                     wall 1         wall 2
                       |              |
          ==ceiling====|              |==ceiling===
                       |===ceiling====|
          wall 1         wall 1 back      wall 2
          front             and           front
                         wall 2 back
                       |====floor=====|
                       |              |
          ====floor====|              |====floor====

(Sorry--no spiffy PostScript figures . . .)

I hope that it's clear from this diagram how everything works, because I
can't think of an explanation to accompany it.

Here's an important rule to keep in mind when thinking about walls.  If
you are standing within a closed loop of walls, then:

   - You are in front of the the walls if they are oriented clockwise
   - You are in back of the walls if the are oriented counterclockwise

I mentioned before that regions need not be connected.  This may seem strange
at first, but it's a very useful property for regions to have.  I'll again
bring up the case of the castle windows:  all four of them are the same
region.  The neat thing about this is that I can modify the height of the
bottom of all windows by changing just one number:  the floor height of
the windows' region.


Now that you've been briefed on the internal world structure, the world
file should be pretty easy to figure out.  It maps almost directly to
the internal structure.

The world file consists of four parts: a texture block, a vertex block,
a region block, and a walls block.  The four blocks must appear in this
order.  Each block consists of an arbitrary number of entries.  The
entries in all blocks each consist of the block name followed by a list
of parameters.

Here are the formats for each type of world file entry:

texture <texture name> <texture file>
vertex <x> <y>
region <floor height> <ceiling height> <floor texture name> <ceiling texture>
wall <start vertex #> <end vertex #> <texture name>
     <front region #> <back region #>
     <xscale> <yscale> <xphase> <yphase>


There are a number of restrictions which must be observed in world files.

- Textures which are to be used as floors must be either 64x64 or 128x128.
  (I'll eventually add support for 256x256 textures--it's trivial to do.)
- Textures which are to be used as walls must have be 64 or 128 pixels
  vertically and a power of two pixels horizontally.
- Walls may not intersect.
- Walls should not be more than 255 units long.  This is necessary in order
  to avoid fixed point overflows.
- Walls should not be shorter than 1/256 units.  This limitation is due
  to fixed point roundoff errors.
- Regions should not have heights less than -128 or greater than 127


This description should make it clear that we'll need a more sophisticated
world designer than a text editor.

The format of wt's worldfile is independent of the rendering engine.  Once
the world data has be slurped into a world structure, it doesn't matter to
the renderer how it got there.  This leaves open the possibility for
alternate world file formats, like Russ Nelson's (nelson@crynwr.com) 
orld in Tcl changes.  This patch lets wt use a Tcl program as a world
file (and more . . .) and will eventually be integrated into the wt
distribution.  There will be a lot more news on Tcl and wt in the near
future.  (People who don't have Tcl:  don't worry--I'll continue to support
the graphics engine with the old world file format as well.  It will be
a compile time option.)




