MuckyFoot-UrbanChaos/fallen/Source/qmap.cpp
2017-05-20 11:14:17 +10:00

1271 lines
20 KiB
C++

//
// A whole new world...
//
#include "game.h"
#include <MFStdLib.h>
#include "qmap.h"
#include "c:\fallen\ddengine\headers\qeng.h"
//
// The actual data declared in the header file...
//
UWORD QMAP_texture[QMAP_MAX_TEXTURES];
SLONG QMAP_texture_upto;
QMAP_Style QMAP_style[QMAP_MAX_STYLES];
SLONG QMAP_style_upto;
QMAP_Road QMAP_road[QMAP_MAX_ROADS];
SLONG QMAP_road_upto;
QMAP_Cube QMAP_cube[QMAP_MAX_CUBES];
SLONG QMAP_cube_upto;
QMAP_Gtex QMAP_gtex[QMAP_MAX_GTEXES];
SLONG QMAP_gtex_upto;
QMAP_Cable QMAP_cable[QMAP_MAX_CABLES];
SLONG QMAP_cable_upto;
SBYTE QMAP_height[QMAP_MAX_HEIGHTS];
SLONG QMAP_height_upto;
QMAP_Hmap QMAP_hmap[QMAP_MAX_HMAPS];
SLONG QMAP_hmap_upto;
QMAP_Fence QMAP_fence[QMAP_MAX_FENCES];
SLONG QMAP_fence_upto;
QMAP_Light QMAP_light[QMAP_MAX_LIGHTS];
SLONG QMAP_light_upto;
QMAP_Prim QMAP_prim[QMAP_MAX_PRIMS];
SLONG QMAP_prim_upto;
UWORD QMAP_all[QMAP_MAX_ALL];
SLONG QMAP_all_upto;
QMAP_Map QMAP_map[QMAP_MAPSIZE][QMAP_MAPSIZE];
QMAP_Point QMAP_point[QMAP_MAX_POINTS];
UWORD QMAP_point_free;
QMAP_Face QMAP_face[QMAP_MAX_FACES];
UWORD QMAP_face_free;
void QMAP_init()
{
SLONG x;
SLONG z;
QMAP_Map *qm;
//
// Initialise all data structures.
//
QMAP_style_upto = 0;
QMAP_road_upto = 0;
QMAP_cube_upto = 0;
QMAP_gtex_upto = 0;
QMAP_cable_upto = 0;
QMAP_height_upto = 0;
QMAP_hmap_upto = 0;
QMAP_fence_upto = 0;
QMAP_light_upto = 0;
QMAP_prim_upto = 0;
QMAP_all_upto = 0;
//
// Clear the map.
//
memset(QMAP_map, 0, sizeof(QMAP_map));
for (x = 0; x < QMAP_MAPSIZE; x++)
for (z = 0; z < QMAP_MAPSIZE; z++)
{
qm = &QMAP_map[x][z];
//
// Nothing to do in here!
//
}
//
// Setup the linked lists of points and faces.
//
QMAP_draw_init();
}
void QMAP_compress_all(void)
{
SLONG x;
SLONG z;
SLONG total_all;
UWORD *comp;
SLONG comp_upto;
QMAP_Map *qm;
comp = (UWORD *) MemAlloc(sizeof(UWORD) * QMAP_MAX_ALL);
comp_upto = 0;
if (comp)
{
for (x = 0; x < QMAP_MAPSIZE; x++)
for (z = 0; z < QMAP_MAPSIZE; z++)
{
qm = &QMAP_map[x][z];
total_all = QMAP_TOTAL_ALL(qm);
ASSERT(comp_upto + total_all <= QMAP_MAX_ALL);
memcpy(&comp[comp_upto], &QMAP_all[qm->index_all], sizeof(UWORD) * total_all);
qm->index_all = comp_upto;
comp_upto += total_all;
}
//
// Copy the compressed array over the real array.
//
memcpy(QMAP_all, comp, sizeof(UWORD) * QMAP_MAX_ALL);
QMAP_all_upto = comp_upto;
MemFree(comp);
}
}
//
// Makes sure there is then given amount of room at the end of the all array.
// Returns TRUE on success.
//
SLONG QMAP_make_room_at_the_end_of_the_all_array(SLONG elements)
{
//
// Enough room already?
//
if (QMAP_all_upto + elements <= QMAP_MAX_ALL)
{
return TRUE;
}
//
// Compress the array.
//
QMAP_compress_all();
if (QMAP_all_upto + elements <= QMAP_MAX_ALL)
{
return TRUE;
}
//
// No room, even after compression :o(
//
return FALSE;
}
void QMAP_add_road(
SLONG x1, SLONG z1,
SLONG x2, SLONG z2)
{
SLONG i;
SLONG x;
SLONG z;
SLONG mx;
SLONG mz;
SLONG size_x;
SLONG size_z;
SLONG total_all;
SLONG before;
SLONG after;
QMAP_Map *qm;
if (QMAP_road_upto >= QMAP_MAX_ROADS)
{
//
// Not enough memory to add the road.
//
MSG_add("Not enough road memory to add the road.");
return;
}
SATURATE(x1, 0, QMAP_SIZE);
SATURATE(z1, 0, QMAP_SIZE);
SATURATE(x2, 0, QMAP_SIZE);
SATURATE(z2, 0, QMAP_SIZE);
if (x1 > x2) {SWAP(x1,x2);}
if (z1 > z2) {SWAP(z1,z2);}
size_x = x2 - x1;
size_z = z2 - z1;
SATURATE(size_x, 1, 255);
SATURATE(size_z, 1, 255);
QMAP_road[QMAP_road_upto].x = x1;
QMAP_road[QMAP_road_upto].z = z1;
QMAP_road[QMAP_road_upto].size_x = size_x;
QMAP_road[QMAP_road_upto].size_z = size_z;
//
// Add this road to all the squares it overlaps.
//
for (x = x1 & ~0x1f; x < x2; x += 32)
for (z = z1 & ~0x1f; z < z2; z += 32)
{
mx = x >> 5;
mz = z >> 5;
qm = &QMAP_map[mx][mz];
//
// Make sure there is enough room at the end of the array.
//
total_all = QMAP_TOTAL_ALL(qm);
if (!QMAP_make_room_at_the_end_of_the_all_array(total_all + 1))
{
MSG_add("Not enough all memory to add the road.");
return;
}
//
// Copy this squares all info to the end of the array and
// insert an extra road at the same time.
//
before = QMAP_ALL_INDEX_ROADS(qm) - qm->index_all;
after = total_all - before;
//
// Copy all the stuff before the roads.
// Insert the new road.
// Copy all the stuff after the roads.
//
memcpy(&QMAP_all[QMAP_all_upto], &QMAP_all[qm->index_all], sizeof(UWORD) * before);
QMAP_all[QMAP_all_upto + before] = QMAP_road_upto;
memcpy(&QMAP_all[QMAP_all_upto + before + 1], &QMAP_all[qm->index_all + before], sizeof(UWORD) * after);
//
// Update the numbers...
//
qm->num_roads += 1;
qm->index_all = QMAP_all_upto;
QMAP_all_upto += 1;
QMAP_all_upto += total_all;
}
QMAP_road_upto += 1;
}
void QMAP_add_cube(
SLONG x1, SLONG z1,
SLONG x2, SLONG z2,
SLONG height)
{
SLONG i;
SLONG x;
SLONG z;
SLONG mx;
SLONG mz;
SLONG size_x;
SLONG size_y;
SLONG size_z;
SLONG total_all;
SLONG before;
SLONG after;
QMAP_Map *qm;
if (QMAP_cube_upto >= QMAP_MAX_CUBES)
{
//
// Not enough memory to add the cube.
//
MSG_add("Not enough cube memory to add the cube.");
return;
}
SATURATE(x1, 0, QMAP_SIZE);
SATURATE(z1, 0, QMAP_SIZE);
SATURATE(x2, 0, QMAP_SIZE);
SATURATE(z2, 0, QMAP_SIZE);
if (x1 > x2) {SWAP(x1,x2);}
if (z1 > z2) {SWAP(z1,z2);}
size_x = x2 - x1;
size_y = height;
size_z = z2 - z1;
SATURATE(size_x, 1, 32);
SATURATE(size_y, 1, 32);
SATURATE(size_z, 1, 32);
QMAP_cube[QMAP_cube_upto].x = x1;
QMAP_cube[QMAP_cube_upto].z = z1;
QMAP_cube[QMAP_cube_upto].size_x = size_x;
QMAP_cube[QMAP_cube_upto].size_y = size_y;
QMAP_cube[QMAP_cube_upto].size_z = size_z;
QMAP_cube[QMAP_cube_upto].flag = 0;
QMAP_cube[QMAP_cube_upto].style[0] = 0;
QMAP_cube[QMAP_cube_upto].style[1] = 0;
QMAP_cube[QMAP_cube_upto].style[2] = 0;
QMAP_cube[QMAP_cube_upto].style[3] = 0;
QMAP_cube[QMAP_cube_upto].style[4] = 0;
//
// Add this cube to all the squares it overlaps.
//
for (x = x1 & ~0x1f; x < x2; x += 32)
for (z = z1 & ~0x1f; z < z2; z += 32)
{
mx = x >> 5;
mz = z >> 5;
qm = &QMAP_map[mx][mz];
//
// Make sure there is enough room at the end of the array.
//
total_all = QMAP_TOTAL_ALL(qm);
if (!QMAP_make_room_at_the_end_of_the_all_array(total_all + 1))
{
MSG_add("Not enough all memory to add the cube.");
return;
}
//
// Copy this squares all info to the end of the array and
// insert an extra cube at the same time.
//
before = QMAP_ALL_INDEX_CUBES(qm) - qm->index_all;
after = total_all - before;
//
// Copy all the stuff before the cubes.
// Insert the new cube.
// Copy all the stuff after the cubes.
//
memcpy(&QMAP_all[QMAP_all_upto], &QMAP_all[qm->index_all], sizeof(UWORD) * before);
QMAP_all[QMAP_all_upto + before] = QMAP_cube_upto;
memcpy(&QMAP_all[QMAP_all_upto + before + 1], &QMAP_all[qm->index_all + before], sizeof(UWORD) * after);
//
// Update the numbers...
//
qm->num_cubes += 1;
qm->index_all = QMAP_all_upto;
QMAP_all_upto += 1;
QMAP_all_upto += total_all;
}
QMAP_cube_upto += 1;
}
//
// Compresses the prim array.
//
void QMAP_compress_prim_array(void)
{
SLONG x;
SLONG z;
QMAP_Map *qm;
QMAP_Prim *comp;
SLONG comp_upto;
comp = (QMAP_Prim *) MemAlloc(sizeof(QMAP_Prim) * QMAP_MAX_PRIMS);
comp_upto = 0;
if (comp)
{
for (x = 0; x < QMAP_MAPSIZE; x++)
for (z = 0; z < QMAP_MAPSIZE; z++)
{
qm = &QMAP_map[x][z];
ASSERT(comp_upto + qm->num_prims <= QMAP_MAX_PRIMS);
memcpy(&comp[comp_upto], &QMAP_prim[qm->index_prim], sizeof(QMAP_Prim) * qm->num_prims);
qm->index_prim = comp_upto;
comp_upto += qm->num_prims;
}
//
// Copy the compressed array over the real array.
//
memcpy(QMAP_all, comp, sizeof(QMAP_Prim) * QMAP_MAX_PRIMS);
QMAP_prim_upto = comp_upto;
}
}
void QMAP_add_prim(
SLONG x,
SLONG y,
SLONG z,
SLONG prim,
SLONG yaw)
{
SLONG prim_x;
SLONG prim_y;
SLONG prim_z;
SLONG prim_yaw;
SLONG mx = x >> 21;
SLONG mz = z >> 21;
QMAP_Map *qm;
if (!WITHIN(mx, 0, QMAP_MAPSIZE - 1) ||
!WITHIN(mz, 0, QMAP_MAPSIZE - 1))
{
//
// Off the map.
//
return;
}
qm = &QMAP_map[mx][mz];
//
// Is there enough room at the end of the prim array for
// this squares' prims plus one more?
//
if (QMAP_prim_upto + qm->num_prims + 1 > QMAP_MAX_PRIMS)
{
//
// Make room by compressing the prim array.
//
QMAP_compress_prim_array();
if (QMAP_prim_upto + qm->num_prims + 1 > QMAP_MAX_PRIMS)
{
//
// Still not enough room. Even after compression :o(
//
MSG_add("Not enough prim memory to add another prim.");
return;
}
}
//
// Copy the prims to the end of the array.
//
memcpy(&QMAP_prim[QMAP_prim_upto], &QMAP_prim[qm->index_prim], sizeof(QMAP_Prim) * qm->num_prims);
qm->index_prim = QMAP_prim_upto;
QMAP_prim_upto += qm->num_prims;
//
// The coordinates of the new prim. (x,z) are relative to the mapsquare
// the prim is in and y is relative to the floor at (x,z). They all
// are in 3-bits per block fixed point.
//
prim_x = (x >> 13) & 0xff;
prim_z = (z >> 13) & 0xff;
prim_y = (y >> 13);
SATURATE(prim_y, 0, 255);
prim_yaw = yaw >> 3;
//
// Tag a new prim on the end.
//
ASSERT(WITHIN(QMAP_prim_upto, 0, QMAP_MAX_PRIMS - 1));
QMAP_prim[QMAP_prim_upto].x = prim_x;
QMAP_prim[QMAP_prim_upto].y = prim_y;
QMAP_prim[QMAP_prim_upto].z = prim_z;
QMAP_prim[QMAP_prim_upto].prim = prim;
QMAP_prim[QMAP_prim_upto].yaw = prim_yaw;
qm->num_prims += 1;
QMAP_prim_upto += 1;
}
SLONG QMAP_calc_height_at(SLONG x, SLONG z)
{
//
// Easy for now!
//
return 0;
}
void QMAP_get_cube_coords(
UWORD cube,
SLONG *x1, SLONG *y1, SLONG *z1,
SLONG *x2, SLONG *y2, SLONG *z2)
{
SLONG mid_x;
SLONG mid_z;
QMAP_Cube *qc;
ASSERT(WITHIN(cube, 0, QMAP_cube_upto - 1));
qc = &QMAP_cube[cube];
//
// The cube we are creating.
//
ASSERT(WITHIN(qc->size_x, 1, 32));
ASSERT(WITHIN(qc->size_y, 1, 32));
ASSERT(WITHIN(qc->size_z, 1, 32));
//
// If you change this code, change the code in QMAP_create_cube() too!
//
*x1 = qc->x;
*z1 = qc->z;
*x2 = *x1 + qc->size_x;
*z2 = *z1 + qc->size_z;
mid_x = *x1 + *x2 << 7;
mid_z = *z1 + *z2 << 7;
mid_x &= 0xffff0000;
mid_z &= 0xffff0000;
*y1 = QMAP_calc_height_at(mid_x, mid_z);
*y1 >>= 8;
*y2 = *y1 + qc->size_y;
}
void QMAP_draw_init()
{
SLONG i;
QMAP_point_free = 1;
for (i = 1; i < QMAP_MAX_POINTS - 1; i++)
{
QMAP_point[i].next = i + 1;
}
QMAP_point[QMAP_MAX_POINTS - 1].next = 0;
QMAP_face_free = 1;
for (i = 1; i < QMAP_MAX_FACES - 1; i++)
{
QMAP_face[i].next = i + 1;
}
QMAP_face[QMAP_MAX_FACES - 1].next = 0;
}
//
// Returns the texture to use on square coord (x,y) on a
// rectange of (size_x, size_y) using the given style.
//
UWORD QMAP_get_style_texture(
SLONG x,
SLONG y,
SLONG size_x,
SLONG size_y,
UWORD style)
{
SLONG cx;
SLONG cy;
SLONG mid;
SLONG index;
UWORD texture;
QMAP_Style *qs;
ASSERT(WITHIN(style, 0, QMAP_style_upto - 1));
qs = &QMAP_style[style];
if (qs->flag & QMAP_STYLE_WRAP_X)
{
switch(qs->size_x)
{
case 1: cx = 0; break;
case 2: cx = x & 1; break;
case 4: cx = x & 3; break;
default:
cx = x % qs->size_x;
break;
}
}
else
{
if (x == 0)
{
cx = 0;
}
else
if (x >= qs->size_x - 1)
{
cx = qs->size_x - 1;
}
else
{
mid = qs->size_x - 2;
switch(mid)
{
case 0: cx = 0;
case 1: cx = 1;
default:
cx = rand() % mid;
cx += 1;
break;
}
}
}
if (qs->flag & QMAP_STYLE_WRAP_Y)
{
switch(qs->size_y)
{
case 1: cy = 0; break;
case 2: cy = y & 1; break;
case 4: cy = y & 3; break;
default:
cy = y % qs->size_y;
break;
}
}
else
{
if (y == 0)
{
cy = 0;
}
else
if (y >= qs->size_y - 1)
{
cy = qs->size_y - 1;
}
else
{
mid = qs->size_y - 2;
switch(mid)
{
case -1:
case 0: cy = 0; break;
case 1: cy = 1; break;
default:
cy = rand() % mid;
cy += 1;
break;
}
}
}
ASSERT(WITHIN(cx, 0, qs->size_x - 1));
ASSERT(WITHIN(cy, 0, qs->size_y - 1));
index = cy * qs->size_x + cx;
index += qs->index;
ASSERT(WITHIN(index, 0, QMAP_texture_upto - 1));
texture = QMAP_texture[index];
return texture;
}
//
// Create the faces for given cube.
//
void QMAP_create_cube(QMAP_Draw *qd, SLONG map_x, SLONG map_z, SLONG cube)
{
SLONG i;
SLONG j;
SLONG x;
SLONG y;
SLONG z;
SLONG x1;
SLONG y1;
SLONG z1;
SLONG x2;
SLONG y2;
SLONG z2;
SLONG mx1;
SLONG mz1;
SLONG mx2;
SLONG mz2;
SLONG lx1;
SLONG lz1;
SLONG lx2;
SLONG lz2;
SLONG look_x;
SLONG look_z;
SLONG look_x1;
SLONG look_y1;
SLONG look_z1;
SLONG look_x2;
SLONG look_y2;
SLONG look_z2;
SLONG k1;
SLONG k2;
SLONG base;
SLONG index;
SLONG cube_look;
SLONG width;
ULONG mask;
ULONG clip;
UWORD p_index;
UWORD f_index;
ULONG face_on[32]; // 128 bytes of stack!
QMAP_Cube *qc;
QMAP_Cube *qc_look;
QMAP_Map *qm_look;
QMAP_Point *qp;
QMAP_Face *qf;
ASSERT(WITHIN(cube, 0, QMAP_cube_upto - 1));
qc = &QMAP_cube[cube];
//
// The cube we are creating.
//
QMAP_get_cube_coords(
cube,
&x1, &y1, &z1,
&x2, &y2, &z2);
//
// The mapsquare we are creating the cube in.
//
mx1 = map_x + 0 << 5;
mz1 = map_z + 0 << 5;
mx2 = map_x + 1 << 5;
mz2 = map_z + 1 << 5;
//
// Clip the cube to the mapsquare.
//
lx1 = MAX(x1, mx1);
lz1 = MAX(z1, mz1);
lx2 = MIN(x2, mx2);
lz2 = MIN(z2, mz2);
//
// For each edge of the cube: XS
//
if (x1 < mx1)
{
//
// This edge of the cube is not on the mapsquare.
//
}
else
{
ASSERT(x1 < mx2);
//
// Make sure we only create the faces of the cube
// that are above this mapsquare.
//
clip = 0xffffffff;
if (z1 > mz1)
{
clip >>= z1 - mz1;
}
else
{
clip <<= mz1 - z1;
}
for (i = 0; i < qc->size_y; i++)
{
face_on[i] = clip;
}
//
// Which mapsquare do we search for cube to invalidate the faces?
//
look_x = map_x;
look_z = map_z;
if (x1 == mx1) {look_x -= 1;}
if (look_x < 0)
{
//
// All these faces are facing onto the edge of the world...
//
}
else
{
ASSERT(WITHIN(look_x, 0, QMAP_MAPSIZE - 1));
ASSERT(WITHIN(look_z, 0, QMAP_MAPSIZE - 1));
qm_look = &QMAP_map[look_x][look_z];
//
// Go through all the cubes on this square.
//
base = QMAP_ALL_INDEX_CUBES(qm_look);
for (i = 0; i < qm_look->num_cubes; i++)
{
ASSERT(WITHIN(base + i, 0, QMAP_all_upto - 1));
index = base + i;
cube_look = QMAP_all[index];
if (cube_look == cube)
{
//
// A cube can't cancel out its own faces!
//
}
else
{
ASSERT(WITHIN(cube_look, 0, QMAP_cube_upto - 1));
qc_look = &QMAP_cube[cube_look];
//
// The dimensions of the look cube.
//
look_x1 = qc_look->x;
look_z1 = qc_look->z;
look_x2 = look_x1 + qc_look->size_x;
look_z2 = look_z1 + qc_look->size_z;
//
// Is this cube going to invalidate our faces?
//
if ((look_x1 == x1 && cube_look > cube) ||
(look_x1 < x1 && look_x2 >= x1))
{
//
// Do they overlap in z?
//
if (look_z1 >= z2 ||
look_z2 <= z1)
{
//
// They don't overlap.
//
}
else
{
//
// Find the mask for the overlap in z.
//
width = look_z2 - look_z1;
ASSERT(width <= 32);
if (width == 32)
{
//
// 1 << 32 might not be 0...
//
mask = 0xffffffff;
}
else
{
mask = 1 << width;
mask -= 1;
}
if (look_z1 > z1)
{
mask <<= look_z1 - z1;
}
else
if (look_z1 < z1)
{
mask >>= z1 - look_z1;
}
//
// The overlap in y.
//
look_y1 = QMAP_calc_height_at((look_x1 + look_x2 << 15) & 0xffff0000, (look_z1 + look_z2 << 15) & 0xffff0000);
look_y1 >>= 16;
look_y2 = look_y1 + qc_look->size_y;
for (y = y1, j = 0; y < y2; y++, j++)
{
if (y >= look_y1)
{
if (y >= look_y2)
{
break;
}
else
{
face_on[j] &= ~mask;
}
}
}
}
}
}
}
}
#ifndef NDEBUG
memset(qd->hf, 255, sizeof(qd->hf));
#endif
//
// Create the points using the hf buffer in the QMAP_Draw structure.
//
for (z = lz1; z <= lz2; z++)
{
i = z - z1;
ASSERT(WITHIN(i, 0, 32));
if (i == 0)
{
mask = 0x1;
}
else
{
mask = 0x3 << (i - 1);
}
for (y = y1, j = 0; y <= y2; y++, j++)
{
ASSERT(WITHIN(j, 0, 32));
k1 = j;
k2 = j - 1;
if (k1 > 31) {k1 = 31;}
if (k2 < 0) {k2 = 0;}
if ((face_on[k1] | face_on[k2]) & mask)
{
//
// We need point (i,j)
//
if (QMAP_point_free == NULL)
{
MSG_add("No more points to create the cube.");
return;
}
else
{
ASSERT(WITHIN(QMAP_point_free, 1, QMAP_MAX_POINTS - 1));
qp = &QMAP_point[QMAP_point_free];
p_index = QMAP_point_free;
QMAP_point_free = qp->next;
qp->x = x1 - mx1 << 8;
qp->y = y << 8;
qp->z = z - mz1 << 8;
qp->red = 32;
qp->green = 32;
qp->blue = 32;
qp->normal = QMAP_POINT_NORMAL_XNEG;
qp->trans = 0;
//
// Put in the linked list of the QMAP_Draw structure.
//
qp->next = qd->next_point;
qd->next_point = p_index;
//
// Remember the index of this point.
//
qd->hf[i][j].texture = p_index;
}
}
}
}
//
// Create the faces.
//
for (z = lz1; z < lz2; z++)
{
i = z - z1;
ASSERT(WITHIN(i, 0, 31));
mask = 1 << i;
for (y = y1, j = 0; y < y2; y++, j++)
{
ASSERT(WITHIN(j, 0, 31));
if (face_on[j] & mask)
//
// Generate this face.
//
if (QMAP_face_free == NULL)
{
MSG_add("No more faces to create the cube.");
return;
}
else
{
ASSERT(WITHIN(QMAP_face_free, 1, QMAP_MAX_FACES - 1));
qf = &QMAP_face[QMAP_face_free];
f_index = QMAP_face_free;
QMAP_face_free = qf->next;
qf->point[0] = qd->hf[i + 0][j + 0].texture;
qf->point[1] = qd->hf[i + 1][j + 0].texture;
qf->point[2] = qd->hf[i + 0][j + 1].texture;
qf->point[3] = qd->hf[i + 1][j + 1].texture;
ASSERT(WITHIN(qf->point[0], 1, QMAP_MAX_POINTS - 1));
ASSERT(WITHIN(qf->point[1], 1, QMAP_MAX_POINTS - 1));
ASSERT(WITHIN(qf->point[2], 1, QMAP_MAX_POINTS - 1));
ASSERT(WITHIN(qf->point[3], 1, QMAP_MAX_POINTS - 1));
qf->texture = cube + 5;
qf->flag = 0;
#ifdef EDITOR
qf->cube = cube;
qf->edge = 0;
#endif
//
// Put in the linked list of the QMAP_Draw structure.
//
qf->next = qd->next_face;
qd->next_face = f_index;
}
}
}
}
}
void QMAP_create(QMAP_Draw *qd, SLONG map_x, SLONG map_z)
{
SLONG i;
SLONG j;
SLONG x;
SLONG z;
SLONG x1;
SLONG y1;
SLONG z1;
SLONG x2;
SLONG y2;
SLONG z2;
SLONG base;
SLONG index;
SLONG cube;
QMAP_Map *qm;
ASSERT(WITHIN(map_x, 0, QMAP_MAPSIZE - 1));
ASSERT(WITHIN(map_z, 0, QMAP_MAPSIZE - 1));
qm = &QMAP_map[map_x][map_z];
//
// Initialise.
//
for (x = 0; x < 32; x++)
for (z = 0; z < 32; z++)
{
qd->hf[x][z].texture = 2;
}
qd->map_x = map_x;
qd->map_z = map_z;
qd->next_point = 0;
qd->next_face = 0;
qd->trans = 0;
//
// Create the cube faces.
//
base = QMAP_ALL_INDEX_CUBES(qm);
for (i = 0; i < qm->num_cubes; i++)
{
index = base + i;
cube = QMAP_all[index];
QMAP_create_cube(qd, map_x, map_z, cube);
}
}
void QMAP_free(QMAP_Draw *qd)
{
UWORD point;
UWORD face;
UWORD next;
QMAP_Point *qp;
QMAP_Face *qf;
//
// Clear all the points and faces.
//
for (point = qd->next_point; point; point = next)
{
ASSERT(WITHIN(point, 1, QMAP_MAX_POINTS - 1));
qp = &QMAP_point[point];
next = qp->next;
qp->next = QMAP_point_free;
QMAP_point_free = point;
}
for (face = qd->next_face; face; face = next)
{
ASSERT(WITHIN(face, 1, QMAP_MAX_FACES - 1));
qf = &QMAP_face[face];
next = qf->next;
qf->next = QMAP_face_free;
QMAP_face_free = face;
}
qd->next_point = 0;
qd->next_face = 0;
}