|
Title:
Node Generation System
Difficulty: Fairly Easy
By: Maj.Bitch
Email: peblair@frontier.net
Date: 09-27-99
Note: Please give credit where credit is due.
======================================================
This is some source I put together (derived from the previous
work of Warzone, and others). It will generate your node[]
array of valid nodes in a *.bsp file. I'm posting this because
it could use some tweaking (in terms of deleting extra nodes
that it generates) and to give people a head start on the
pathing stuff (so they won't have to reinvent this source again).
Create a new file called
grid.c and add it to your standard
Q2 source project.. You'll need to have this in your Q2 source
so you can take advantage of using the gi.pointcontents() function
of the gaming engine. ( Unless you have a better way )...
Use the node that are
generated with your new AStar.c stuff and
you'll be off and running pretty quickly..
===========================================================
#include < stdio.h>
#include < stdlib.h>
#include < stdarg.h>
#include < string.h>
#include < errno.h>
#include < math.h>
#include < float.h>
#include < malloc.h>
#include
"g_local.h"
#define INVALID -1
FILE *fp;
#define CONTENTS_NODE
0x00
typedef struct {
int nodenum; // node[]
int type; // type of node this is (pointcontents)
vec3_t origin; // location in [x,y,z]
} node_t;
node_t *node;
int numnodes;
// Q2 maps are
-4096,+4096 units along each axis
// 8192/256 = 32 units between nodes
// 8192/128 = 64 units between nodes
// 8192/64 =128 units between nodes.
// NOTE: you can vary
these number to 128, 64, etc
// to change the granularity of your slices of the world.
// HINT: Keep the zsize
256 else the nodes will be
// too high off the floor... (Your choice)
#define xsize 256 // 32
units
#define ysize 256 // 32 units
#define zsize 256 // 32 units
int
grid[xsize][ysize][zsize]; // Temp storage..
#define gridpt
grid[x][y][z]
float xevery =
8192/xsize;
float yevery = 8192/ysize;
float zevery = 8192/zsize;
#define MaxOf(x,y) ((x)
> (y)?(x):(y))
#define MinOf(x,y) ((x) < (y)?(x):(y))
//==================================================
// Converts a q2 vector into a position in the grid
//==================================================
void vec2grid(vec3_t in, int *x, int *y, int *z) {
*x=(int)MinOf(MaxOf((in[0]+4096)/xevery,0),xsize-1);
*y=(int)MinOf(MaxOf((in[1]+4096)/yevery,0),ysize-1);
*z=(int)MinOf(MaxOf((in[2]+4096)/zevery,0),zsize-1);
}
//==================================================
// Converts a position in the grid into a q2 vector
//==================================================
void grid2vec(int x, int y, int z, vec3_t out) {
out[0]=(float)MinOf(MaxOf(x*xevery-4096+(xevery/2),-4096),4096);
out[1]=(float)MinOf(MaxOf(y*yevery-4096+(yevery/2),-4096),4096);
out[2]=(float)MinOf(MaxOf(z*zevery-4096+(zevery/2),-4096),4096);
}
//===========================================================
void WriteGrid(void) {
int i=0,x,y,z;
char mappath[64];
fprintf(stderr,"Saving
Node File...");
sprintf(mappath,
"c:/quake2/baseq2/maps/%s.grd",level.mapname);
fp=fopen(mappath,"wb");
if (!fp) {
fprintf(stderr,"ERROR WRITING: %s\n",mappath);
return; }
// How many valid nodes
do we have?
numnodes=0;
for (z=0; z < zsize; z++)
for (x=0; x < xsize; x++)
for (y=0; y < ysize; y++)
if (gridpt != INVALID)
numnodes++;
// Write to file the
number of nodes
fwrite(&numnodes,sizeof(int),1,fp);
// Allocate a single node
for copying purposes
node=(node_t *)xmalloc(sizeof(node_t));
// Assign valid nodes to
node_t and write to file
for (z=0; z < zsize; z++)
for (x=0; x < xsize; x++)
for (y=0; y < ysize; y++)
if (gridpt != INVALID) {
node->type = gridpt; // pointcontents
node->nodenum = i++; // nodenum
grid2vec(x,y,z,node->origin); // node origin
fwrite(node,sizeof(node_t),1,fp); }
free(node);
fclose(fp);
fprintf(stderr,"Done\n%d
Nodes written to %s\n",numnodes,mappath);
}
//===========================================================
void ReadGrid(void) {
int i;
char mappath[64];
sprintf(mappath,
"c:/quake2/baseq2/maps/%s.grd",level.mapname);
fp=fopen(mappath,"rb");
if (!fp) {
fprintf(stderr,"ERROR READING: %s\n",mappath);
return; }
// How many nodes are in
this file?
fread(&numnodes,sizeof(int),1,fp);
// Allocate ALL the
node_t structs we'll need
node=(node_t *)xmalloc(numnodes*sizeof(node_t));
// Read these nodes from
file..
for (i=0;i < numnodes;i++)
fread(&node[i],sizeof(node_t),1,fp);
fclose(fp);
fprintf(stderr,"%d
Nodes Loaded\n",numnodes);
}
//========================================================
// Initialize all the cells in grid and delete any extras
//========================================================
void CreateGrid(void) {
int i,k,x,y,z;
int haslava=0;
vec3_t origin;
numnodes=xsize*ysize*zsize;
memset(&grid,0,xsize*ysize*zsize*sizeof(int));
fprintf(stderr,
"Wait.. Partitioning map into %d horizontal planes\n",zsize);
// Here, I'm getting the
point contents of EVERY node in the grid...
for (x=0; x < xsize;
x++)
for (y=0; y < ysize; y++)
for (z=0; z < zsize; z++) {
grid2vec(x,y,z,origin);
gridpt=gi.pointcontents(origin);
if (!haslava && gridpt & (CONTENTS_LAVA|CONTENTS_SLIME))
haslava=1; }
fprintf(stderr,"Deleting
nodes in Lava/Slime...");
// If map doesn't have
lava nodes then we can skip this part..
if (haslava)
for (z=0; z < zsize; z++)
for (x=0; x < xsize; x++)
for (y=0; y < ysize; y++)
for (i=z; i < zsize; i++)
if (grid[x][y][i] & (CONTENTS_LAVA|CONTENTS_SLIME))
while ((i < zsize) && !(grid[x][y][i] & (CONTENTS_SOLID|CONTENTS_LADDER)))
grid[x][y][i++] = INVALID;
fprintf(stderr,"Done\n");
fprintf(stderr,"Deleting
Nodes in mid-air...");
// What I'm trying to do
here is to delete any mid-air nodes (CONTENTS_NONE)
// while leaving the very first node directly above the ground. I'm also
// trying to leave ladder nodes intact.
for (z=0; z < zsize;
z++)
for (x=0; x < xsize; x++)
for (y=0; y < ysize; y++)
for (i=z; i < zsize; i++)
if (grid[x][y][i] == CONTENTS_NONE || grid[x][y][i] & CONTENTS_WATER) {
while ((++i < zsize) && !(grid[x][y][i] &
(CONTENTS_SOLID|CONTENTS_LADDER)))
grid[x][y][i] = INVALID;
fprintf(stderr,"Done\n");
fprintf(stderr,"Deleting
Nodes in Solids...");
// Lastly, I want to step thru all the nodes in the grid and remove any of
those
// nodes which are in solid but NOT ladder nodes.
//============================
// Now delete ALL solid nodes
//============================
for (z=0; z < zsize; z++)
for (x=0; x < xsize; x++)
for (y=0; y < ysize; y++)
if (gridpt & CONTENTS_SOLID && !(gridpt & CONTENTS_LADDER)))
gridpt = INVALID;
fprintf(stderr,"Done\n\n");
// In the end, I have a
layer of nodes covering ALL horizontal surfaces in the
// map with each node being zevery units above the floor or ground (any
solid)
// while keeping ladder nodes intact... Understand that?
WriteGrid();
}
|