diff --git a/include/QF/Makefile.am b/include/QF/Makefile.am index 366ce612f..031a50c31 100644 --- a/include/QF/Makefile.am +++ b/include/QF/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS = foreign SUBDIRS = plugin includedir = $(prefix)/include/QF -include_HEADERS = bspfile.h cdaudio.h checksum.h cmd.h \ +include_HEADERS = bspfile.h cdaudio.h checksum.h clip_hull.h cmd.h \ console.h crc.h cvar.h draw.h gcc_attr.h gib.h hash.h hl.h info.h \ input.h joystick.h keys.h link.h locs.h mathlib.h mdfour.h model.h \ modelgen.h msg.h pcx.h plugin.h pr_comp.h pr_debug.h progs.h qargs.h \ diff --git a/include/QF/clip_hull.h b/include/QF/clip_hull.h new file mode 100644 index 000000000..abc5bb431 --- /dev/null +++ b/include/QF/clip_hull.h @@ -0,0 +1,47 @@ +/* + clip_hull.h + + dynamic bsp clipping hull management + + Copyright (C) 2001 Bill Currie + + Author: Bill Currie + Date: 2001/7/28 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifndef __QF_clip_hull_h +#define __QF_clip_hull_h + +#include "QF/bspfile.h" + +typedef struct clip_hull_s { + vec3_t mins; + vec3_t maxs; + vec3_t axis[3]; + struct hull_s *hulls[MAX_MAP_HULLS]; +} clip_hull_t; + +clip_hull_t *MOD_Alloc_Hull (int nodes, int planes); +void MOD_Free_Hull (clip_hull_t *ch); + +#endif//__QF_clip_hull_h diff --git a/include/QF/model.h b/include/QF/model.h index 26b721ab7..65b0a213c 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -202,7 +202,7 @@ typedef struct mleaf_s } mleaf_t; // !!! if this is changed, it must be changed in asm_i386.h too !!! -typedef struct +typedef struct hull_s { dclipnode_t *clipnodes; mplane_t *planes; diff --git a/include/QF/progs.h b/include/QF/progs.h index ddc58a03f..d58e481f2 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -143,8 +143,8 @@ pr_type_t *PR_GetGlobalPointer (progs_t *pr, const char *name); func_t PR_GetFunctionIndex (progs_t *pr, const char *name); int PR_GetFieldOffset (progs_t *pr, const char *name); -void PR_Error (progs_t *pr, const char *error, ...) __attribute__((format(printf,2,3))); -void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(printf,2,3))); +void PR_Error (progs_t *pr, const char *error, ...) __attribute__((format(printf,2,3), noreturn)); +void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(printf,2,3), noreturn)); void ED_PrintEdicts (progs_t *pr, const char *fieldval); void ED_PrintNum (progs_t *pr, int ent); diff --git a/include/QF/sys.h b/include/QF/sys.h index 1738bbb83..08f56f1cb 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -45,7 +45,7 @@ typedef void (*sys_printf_t) (const char *fmt, va_list args); void Sys_SetPrintf (sys_printf_t func); void Sys_Printf (const char *fmt, ...) __attribute__((format(printf,1,2))); -void Sys_Error (const char *error, ...) __attribute__((format(printf,1,2))); +void Sys_Error (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); void Sys_Quit (void); double Sys_DoubleTime (void); diff --git a/libs/models/Makefile.am b/libs/models/Makefile.am index 52d6ce291..a2e930106 100644 --- a/libs/models/Makefile.am +++ b/libs/models/Makefile.am @@ -16,19 +16,21 @@ endif lib_LTLIBRARIES = libQFmodels.la $(MODELS_GL) $(MODELS_SW) +models_SOURCES = clip_hull.c model.c + libQFmodels_la_LDFLAGS = -version-info 1:0:0 libQFmodels_la_LIBADD = brush/libbrush.la -libQFmodels_la_SOURCES = model.c +libQFmodels_la_SOURCES = $(models_SOURCES) libQFmodels_la_DEPENDENCIES = brush/libbrush.la libQFmodels_gl_la_LDFLAGS = -version-info 1:0:0 libQFmodels_gl_la_LIBADD = alias/libalias_gl.la brush/libbrush_gl.la sprite/libsprite_gl.la -libQFmodels_gl_la_SOURCES = model.c gl_model_fullbright.c +libQFmodels_gl_la_SOURCES = $(models_SOURCES) gl_model_fullbright.c libQFmodels_gl_la_DEPENDENCIES = alias/libalias_gl.la brush/libbrush_gl.la sprite/libsprite_gl.la libQFmodels_sw_la_LDFLAGS = -version-info 1:0:0 libQFmodels_sw_la_LIBADD = alias/libalias_sw.la brush/libbrush_sw.la sprite/libsprite_sw.la -libQFmodels_sw_la_SOURCES = model.c +libQFmodels_sw_la_SOURCES = $(models_SOURCES) libQFmodels_sw_la_DEPENDENCIES = alias/libalias_sw.la brush/libbrush_sw.la sprite/libsprite_sw.la LIBLIST = libQFmodels.la libQFmodels_gl.la libQFmodels_sw.la diff --git a/libs/models/clip_hull.c b/libs/models/clip_hull.c new file mode 100644 index 000000000..f10567f29 --- /dev/null +++ b/libs/models/clip_hull.c @@ -0,0 +1,68 @@ +/* + clip_hull.c + + dynamic bsp clipping hull management + + Copyright (C) 2001 Bill Currie + + Author: Bill Currie + Date: 2001/7/28 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "QF/clip_hull.h" +#include "QF/model.h" + +clip_hull_t *MOD_Alloc_Hull (int nodes, int planes) +{ + clip_hull_t *ch; + int size; + int i; + + size = sizeof (hull_t); + size += sizeof (dclipnode_t) * nodes + sizeof (mplane_t) * planes; + size *= MAX_MAP_HULLS; + size += sizeof (clip_hull_t); + + ch = calloc (size, 1); + if (!ch) + return 0; + ch->hulls[0] = (hull_t*)&ch[1]; + for (i = 1; i < MAX_MAP_HULLS; i++) + ch->hulls[i] = &ch->hulls[i - 1][1]; + ch->hulls[0]->clipnodes = (dclipnode_t*)&ch->hulls[i - 1][1]; + ch->hulls[0]->planes = (mplane_t*)&ch->hulls[0]->clipnodes[nodes]; + for (i = 1; i < MAX_MAP_HULLS; i++) { + ch->hulls[i]->clipnodes = (dclipnode_t*)&ch->hulls[i - 1]->planes[planes]; + ch->hulls[i]->planes = (mplane_t*)&ch->hulls[i]->clipnodes[nodes]; + } + return ch; +} + +void MOD_Free_Hull (clip_hull_t *ch) +{ + free (ch); +} diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index b33d9519d..164ee9449 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -33,17 +33,18 @@ # include #endif +#include "QF/clip_hull.h" #include "QF/cmd.h" -#include "compat.h" #include "QF/cvar.h" #include "QF/msg.h" #include "QF/va.h" +#include "compat.h" +#include "crudefile.h" #include "server.h" #include "sv_pr_cmds.h" #include "sv_progs.h" #include "world.h" -#include "crudefile.h" #define RETURN_EDICT(p, e) ((p)->pr_globals[OFS_RETURN].integer_var = EDICT_TO_PROG(p, e)) #define RETURN_STRING(p, s) ((p)->pr_globals[OFS_RETURN].integer_var = PR_SetString((p), s)) @@ -1815,11 +1816,7 @@ PF_testentitypos (progs_t *pr) #define MAX_PF_HULLS 64 // FIXME make dynamic? -static int pf_hull_list_inited; -static hull_t *pf_free_hulls; -static dclipnode_t pf_clipnodes[MAX_PF_HULLS][6]; -static mplane_t pf_planes[MAX_PF_HULLS][6]; -hull_t pf_hull_list[MAX_PF_HULLS]; +clip_hull_t *pf_hull_list[MAX_PF_HULLS]; static void PF_hullpointcontents (progs_t *pr) @@ -1840,40 +1837,37 @@ static void PF_getboxbounds (progs_t *pr) { int h = G_INT (pr, OFS_PARM0) - 1; - hull_t *hull = &pf_hull_list[h]; + clip_hull_t *ch; - if (h < 0 || h > MAX_PF_HULLS - 1 - || hull->clipnodes != pf_clipnodes[h] - || hull->planes != pf_planes[h]) + if (h < 0 || h > MAX_PF_HULLS - 1 || !(ch = pf_hull_list[h])) PR_RunError (pr, "PF_freeboxhull: invalid box hull handle\n"); if (G_INT (pr, OFS_PARM1)) { - VectorCopy (hull->clip_maxs, G_VECTOR (pr, OFS_RETURN)); + VectorCopy (ch->maxs, G_VECTOR (pr, OFS_RETURN)); } else { - VectorCopy (hull->clip_mins, G_VECTOR (pr, OFS_RETURN)); + VectorCopy (ch->mins, G_VECTOR (pr, OFS_RETURN)); } } static void PF_getboxhull (progs_t *pr) { - hull_t *hull; + clip_hull_t *ch = 0; + int i; - if (!pf_hull_list_inited) { - int i; - pf_hull_list_inited = 1; - for (i = 0; i < MAX_PF_HULLS - 1; i++) - pf_hull_list[i].clipnodes = (dclipnode_t*)&pf_hull_list[i + 1]; - pf_hull_list[i].clipnodes = 0; - pf_free_hulls = pf_hull_list; + for (i = 0; i < MAX_PF_HULLS; i++) { + if (!pf_hull_list[i]) { + ch = MOD_Alloc_Hull (6, 6); + break; + } } - hull = pf_free_hulls; - if (hull) { - pf_free_hulls = (hull_t*)hull->clipnodes; - SV_InitHull (hull, pf_clipnodes[hull - pf_hull_list], - pf_planes[hull - pf_hull_list]); - G_INT (pr, OFS_RETURN) = (hull - pf_hull_list) + 1; + if (ch) { + pf_hull_list[i] = ch; + G_INT (pr, OFS_RETURN) = i + 1; + for (i = 0; i < MAX_MAP_HULLS; i++) + SV_InitHull (ch->hulls[i], ch->hulls[i]->clipnodes, + ch->hulls[i]->planes); } else { G_INT (pr, OFS_RETURN) = 0; } @@ -1883,15 +1877,12 @@ static void PF_freeboxhull (progs_t *pr) { int h = G_INT (pr, OFS_PARM0) - 1; - hull_t *hull = &pf_hull_list[h]; + clip_hull_t *ch; - if (h < 0 || h > MAX_PF_HULLS - 1 - || hull->clipnodes != pf_clipnodes[h] - || hull->planes != pf_planes[h]) + if (h < 0 || h > MAX_PF_HULLS - 1 || !(ch = pf_hull_list[h])) PR_RunError (pr, "PF_freeboxhull: invalid box hull handle\n"); - hull->clipnodes = (dclipnode_t*)pf_free_hulls; - hull->planes = 0; - pf_free_hulls = hull; + pf_hull_list[h] = 0; + MOD_Free_Hull (ch); } static void @@ -1905,25 +1896,36 @@ PF_rotate_bbox (progs_t *pr) }; float *mi = G_VECTOR (pr, OFS_PARM4); float *ma = G_VECTOR (pr, OFS_PARM5); - vec3_t m[3]; + vec3_t mins, maxs; float *verts[6] = {maxs, mins, maxs, mins, maxs, mins}; - hull_t *hull = &pf_hull_list[h]; - int i, j; + + vec3_t mins_offs = { -16, -16, -32 }; + vec3_t maxs_offs = { +16, +16, +32 }; vec3_t v[8], d; + hull_t *hull; + clip_hull_t *ch; + int i, j; float l; + if (h < 0 || h > MAX_PF_HULLS - 1 || !(ch = pf_hull_list[h])) + PR_RunError (pr, "PF_freeboxhull: invalid box hull handle\n"); + // set up the rotation matrix. the three orientation vectors form the // columns of the rotation matrix for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { - m[i][j] = dir[j][i]; + ch->axis[i][j] = dir[j][i]; } } // rotate the bounding box points for (i = 0; i < 3; i++) { - mins[i] = DotProduct (m[i], mi); - maxs[i] = DotProduct (m[i], ma); + mins[i] = DotProduct (ch->axis[i], mi); + maxs[i] = DotProduct (ch->axis[i], ma); + //if (mins[i] > maxs[i]) { + // mins_offs[i] *= -1; + // maxs_offs[i] *= -1; + //} } // find all 8 corners of the rotated box VectorCopy (mins, v[0]); @@ -1938,24 +1940,66 @@ PF_rotate_bbox (progs_t *pr) VectorSubtract (maxs, x, v[3 + i * 2]); } // now find the aligned bounding box - VectorCopy (v[0], hull->clip_mins); - VectorCopy (v[0], hull->clip_maxs); + VectorCopy (v[0], ch->mins); + VectorCopy (v[0], ch->maxs); for (i = 0; i < 8; i++) { //Con_Printf ("'%0.1f %0.1f %0.1f'\n", v[i][0], v[i][1], v[i][2]); for (j = 0; j < 3; j++) { - hull->clip_mins[j] = min (hull->clip_mins[j], v[i][j]); - hull->clip_maxs[j] = max (hull->clip_maxs[j], v[i][j]); + ch->mins[j] = min (ch->mins[j], v[i][j]); + ch->maxs[j] = max (ch->maxs[j], v[i][j]); } } - //Con_Printf ("---\n"); - //Con_Printf ("'%0.1f %0.1f %0.1f'\n", hull->clip_mins[0], hull->clip_mins[1], hull->clip_mins[2]); - //Con_Printf ("'%0.1f %0.1f %0.1f'\n", hull->clip_maxs[0], hull->clip_maxs[1], hull->clip_maxs[2]); + hull = ch->hulls[0]; // now set up the clip planes for (i = 0; i < 6; i++) { hull->planes[i].dist = DotProduct (dir[i / 2], verts[i]); hull->planes[i].type = 4; VectorCopy (dir[i / 2], hull->planes[i].normal); + //Con_Printf ("%f %f %f %f\n", + // hull->planes[i].dist, + // hull->planes[i].normal[0], hull->planes[i].normal[1], + // hull->planes[i].normal[2]); + } + + hull = ch->hulls[1]; + hull->clip_mins[0] = -16; + hull->clip_mins[1] = -16; + hull->clip_mins[2] = -24; + hull->clip_maxs[0] = 16; + hull->clip_maxs[1] = 16; + hull->clip_maxs[2] = 32; + VectorAdd (mins_offs, mins, mins); + VectorAdd (maxs_offs, maxs, maxs); + for (i = 0; i < 6; i++) { + hull->planes[i].dist = DotProduct (dir[i / 2], verts[i]); + hull->planes[i].type = 4; + VectorCopy (dir[i / 2], hull->planes[i].normal); + //Con_Printf ("%f %f %f %f\n", + // hull->planes[i].dist, + // hull->planes[i].normal[0], hull->planes[i].normal[1], + // hull->planes[i].normal[2]); + } + + hull = ch->hulls[2]; + hull->clip_mins[0] = -32; + hull->clip_mins[1] = -32; + hull->clip_mins[2] = -24; + hull->clip_maxs[0] = 32; + hull->clip_maxs[1] = 32; + hull->clip_maxs[2] = 64; + + maxs_offs[2] = 0; + VectorAdd (mins_offs, mins, mins); + VectorAdd (maxs_offs, maxs, maxs); + for (i = 0; i < 6; i++) { + hull->planes[i].dist = DotProduct (dir[i / 2], verts[i]); + hull->planes[i].type = 4; + VectorCopy (dir[i / 2], hull->planes[i].normal); + //Con_Printf ("%f %f %f %f\n", + // hull->planes[i].dist, + // hull->planes[i].normal[0], hull->planes[i].normal[1], + // hull->planes[i].normal[2]); } } diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 4ad25cdfb..eeb90bc73 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -42,13 +42,15 @@ #include #include "QF/checksum.h" +#include "QF/clip_hull.h" #include "QF/cmd.h" -#include "compat.h" #include "QF/cvar.h" #include "QF/msg.h" #include "QF/sys.h" #include "QF/va.h" #include "QF/vfs.h" + +#include "compat.h" #include "bothdefs.h" #include "msg_ucmd.h" #include "pmove.h" @@ -1311,9 +1313,9 @@ AddLinksToPmove (areanode_t *node) if (sv_fields.rotated_bbox != -1 && SVFIELD (check, rotated_bbox, integer)) { - int h = SVFIELD (check, rotated_bbox, integer); - extern hull_t pf_hull_list[]; - pe->hull = &pf_hull_list[h - 1]; + int h = SVFIELD (check, rotated_bbox, integer) - 1; + extern clip_hull_t *pf_hull_list[]; + pe->hull = pf_hull_list[h]->hulls[1]; } else { pe->hull = 0; if (SVFIELD (check, solid, float) == SOLID_BSP) { diff --git a/qw/source/world.c b/qw/source/world.c index 1943c32a2..cf9a2e906 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -38,6 +38,7 @@ #include +#include "QF/clip_hull.h" #include "QF/console.h" #include "QF/crc.h" @@ -152,17 +153,27 @@ SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset) model_t *model; vec3_t size; vec3_t hullmins, hullmaxs; - hull_t *hull; + hull_t *hull = 0; + int hull_index = 0; - if (sv_fields.rotated_bbox != -1 - && SVFIELD (ent, rotated_bbox, integer)) { - extern hull_t pf_hull_list[]; - hull = &pf_hull_list[SVFIELD (ent, rotated_bbox, integer) - 1]; - VectorCopy (SVFIELD (ent, origin, vector), offset); - return hull; + if ((sv_fields.rotated_bbox != -1 + && SVFIELD (ent, rotated_bbox, integer)) + || SVFIELD (ent, solid, float) == SOLID_BSP) { + VectorSubtract (maxs, mins, size); + if (size[0] < 3) + hull_index = 0; + else if (size[0] <= 32) + hull_index = 1; + else + hull_index = 2; } // decide which clipping hull to use, based on the size - if (SVFIELD (ent, solid, float) == SOLID_BSP) { + if (sv_fields.rotated_bbox != -1 + && SVFIELD (ent, rotated_bbox, integer)) { + extern clip_hull_t *pf_hull_list[]; + int h = SVFIELD (ent, rotated_bbox, integer) - 1; + hull = pf_hull_list[h]->hulls[hull_index]; + } if (SVFIELD (ent, solid, float) == SOLID_BSP) { // explicit hulls in the BSP model if (SVFIELD (ent, movetype, float) != MOVETYPE_PUSH) SV_Error ("SOLID_BSP without MOVETYPE_PUSH"); @@ -172,14 +183,10 @@ SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset) if (!model || model->type != mod_brush) SV_Error ("SOLID_BSP with a non bsp model"); - VectorSubtract (maxs, mins, size); - if (size[0] < 3) - hull = &model->hulls[0]; - else if (size[0] <= 32) - hull = &model->hulls[1]; - else - hull = &model->hulls[2]; + hull = &model->hulls[hull_index]; + } + if (hull) { // calculate an offset value to center the origin VectorSubtract (hull->clip_mins, mins, offset); VectorAdd (offset, SVFIELD (ent, origin, vector), offset);