2001-02-19 21:15:25 +00:00
|
|
|
/*
|
2001-02-21 23:45:49 +00:00
|
|
|
model_brush.c
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
model loading and caching
|
|
|
|
|
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
*/
|
|
|
|
// models are the only shared resource between a client and server running
|
|
|
|
// on the same machine.
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
2003-01-15 15:31:36 +00:00
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
# include <string.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
# include <strings.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
2001-03-27 20:33:07 +00:00
|
|
|
#include "QF/checksum.h"
|
|
|
|
#include "QF/cvar.h"
|
2018-08-19 15:05:00 +00:00
|
|
|
#include "QF/dstring.h"
|
2001-04-10 06:55:28 +00:00
|
|
|
#include "QF/model.h"
|
2001-03-27 20:33:07 +00:00
|
|
|
#include "QF/qendian.h"
|
2004-02-29 04:24:42 +00:00
|
|
|
#include "QF/quakefs.h"
|
2001-10-28 04:23:37 +00:00
|
|
|
#include "QF/render.h"
|
2021-07-26 02:15:51 +00:00
|
|
|
#include "QF/set.h"
|
2001-05-10 06:01:11 +00:00
|
|
|
#include "QF/sys.h"
|
2007-05-09 10:55:02 +00:00
|
|
|
#include "QF/va.h"
|
2001-05-10 06:01:11 +00:00
|
|
|
|
2012-02-14 12:25:19 +00:00
|
|
|
#include "QF/plugin/vid_render.h"
|
2022-05-22 02:18:32 +00:00
|
|
|
#include "QF/simd/vec4f.h"
|
2012-02-14 12:25:19 +00:00
|
|
|
|
2001-07-22 05:40:34 +00:00
|
|
|
#include "compat.h"
|
2021-02-01 05:39:00 +00:00
|
|
|
#include "mod_internal.h"
|
2001-07-22 05:40:34 +00:00
|
|
|
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
VISIBLE int mod_sky_divide; //FIXME visibility?
|
|
|
|
VISIBLE int mod_lightmap_bytes = 1; //FIXME should this be visible?
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2007-03-10 12:00:59 +00:00
|
|
|
VISIBLE mleaf_t *
|
2022-05-22 02:18:32 +00:00
|
|
|
Mod_PointInLeaf (vec4f_t p, model_t *model)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
|
|
|
float d;
|
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
if (!model || !model->brush.nodes)
|
2001-05-10 06:01:11 +00:00
|
|
|
Sys_Error ("Mod_PointInLeaf: bad model");
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-05-22 02:18:32 +00:00
|
|
|
int node_id = 0;
|
2001-02-19 21:15:25 +00:00
|
|
|
while (1) {
|
2022-05-22 02:18:32 +00:00
|
|
|
if (node_id < 0)
|
|
|
|
return model->brush.leafs + ~node_id;
|
|
|
|
mnode_t *node = model->brush.nodes + node_id;
|
|
|
|
d = dotf (p, node->plane)[0];
|
|
|
|
node_id = node->children[d < 0];
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL; // never reached
|
|
|
|
}
|
|
|
|
|
2021-03-20 03:00:40 +00:00
|
|
|
static inline void
|
2021-03-20 07:06:15 +00:00
|
|
|
Mod_DecompressVis_set (const byte *in, const mod_brush_t *brush, byte defvis,
|
2021-07-26 02:15:51 +00:00
|
|
|
set_t *pvs)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2021-07-26 02:15:51 +00:00
|
|
|
byte *out = (byte *) pvs->map;
|
2021-03-20 03:00:40 +00:00
|
|
|
byte *start = out;
|
2002-08-22 20:06:30 +00:00
|
|
|
int row, c;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-07-27 08:54:50 +00:00
|
|
|
// Ensure the set repesents visible leafs rather than invisible leafs.
|
|
|
|
pvs->inverted = 0;
|
2021-07-27 03:32:40 +00:00
|
|
|
row = (brush->visleafs + 7) >> 3;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
if (!in) { // no vis info, so make all visible
|
|
|
|
while (row) {
|
2021-03-20 03:00:40 +00:00
|
|
|
*out++ = defvis;
|
2001-02-19 21:15:25 +00:00
|
|
|
row--;
|
|
|
|
}
|
2021-03-20 03:00:40 +00:00
|
|
|
return;
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (*in) {
|
|
|
|
*out++ = *in++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = in[1];
|
|
|
|
in += 2;
|
|
|
|
while (c) {
|
|
|
|
*out++ = 0;
|
|
|
|
c--;
|
|
|
|
}
|
2021-03-20 03:00:40 +00:00
|
|
|
} while (out - start < row);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2021-03-20 07:06:15 +00:00
|
|
|
static inline void
|
|
|
|
Mod_DecompressVis_mix (const byte *in, const mod_brush_t *brush, byte defvis,
|
2021-07-26 02:15:51 +00:00
|
|
|
set_t *pvs)
|
2021-03-20 07:06:15 +00:00
|
|
|
{
|
2021-07-26 02:15:51 +00:00
|
|
|
byte *out = (byte *) pvs->map;
|
2021-03-20 07:06:15 +00:00
|
|
|
byte *start = out;
|
|
|
|
int row, c;
|
|
|
|
|
2021-07-27 08:54:50 +00:00
|
|
|
//FIXME should pvs->inverted be checked and the vis bits used to remove
|
|
|
|
// set bits?
|
2021-07-27 03:32:40 +00:00
|
|
|
row = (brush->visleafs + 7) >> 3;
|
2021-03-20 07:06:15 +00:00
|
|
|
|
|
|
|
if (!in) { // no vis info, so make all visible
|
|
|
|
while (row) {
|
|
|
|
*out++ |= defvis;
|
|
|
|
row--;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (*in) {
|
|
|
|
*out++ |= *in++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = in[1];
|
|
|
|
in += 2;
|
|
|
|
out += c;
|
|
|
|
} while (out - start < row);
|
|
|
|
}
|
|
|
|
|
2021-07-26 02:15:51 +00:00
|
|
|
VISIBLE set_t *
|
2021-03-20 03:00:40 +00:00
|
|
|
Mod_LeafPVS (const mleaf_t *leaf, const model_t *model)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2021-07-26 02:15:51 +00:00
|
|
|
static set_t *novis;
|
|
|
|
static set_t *decompressed;
|
2021-07-27 03:32:40 +00:00
|
|
|
unsigned numvis = model->brush.visleafs;
|
2021-07-26 02:15:51 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
if (leaf == model->brush.leafs) {
|
2021-07-26 02:15:51 +00:00
|
|
|
if (!novis) {
|
|
|
|
novis = set_new_size (numvis);
|
2021-02-01 05:39:00 +00:00
|
|
|
}
|
2021-07-26 02:15:51 +00:00
|
|
|
if (!novis->map[0] || SET_SIZE (numvis) > novis->size) {
|
|
|
|
unsigned excess = SET_SIZE (numvis) - numvis;
|
|
|
|
set_expand (novis, numvis);
|
|
|
|
memset (novis->map, 0xff,
|
|
|
|
SET_WORDS (novis) * sizeof (*novis->map));
|
|
|
|
novis->map[SET_WORDS (novis) - 1] &= (~SET_ZERO) >> excess;
|
|
|
|
}
|
|
|
|
return novis;
|
|
|
|
}
|
|
|
|
if (!decompressed) {
|
|
|
|
decompressed = set_new ();
|
2021-02-01 05:39:00 +00:00
|
|
|
}
|
2021-07-26 02:15:51 +00:00
|
|
|
set_expand (decompressed, numvis);
|
2021-03-20 07:06:15 +00:00
|
|
|
Mod_DecompressVis_set (leaf->compressed_vis, &model->brush, 0xff,
|
|
|
|
decompressed);
|
2021-03-20 03:00:40 +00:00
|
|
|
return decompressed;
|
|
|
|
}
|
|
|
|
|
|
|
|
VISIBLE void
|
2021-03-20 07:06:15 +00:00
|
|
|
Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis,
|
2021-07-26 02:15:51 +00:00
|
|
|
set_t *out)
|
2021-03-20 03:00:40 +00:00
|
|
|
{
|
2021-07-27 03:32:40 +00:00
|
|
|
unsigned numvis = model->brush.visleafs;
|
2021-07-26 02:15:51 +00:00
|
|
|
set_expand (out, numvis);
|
2021-03-20 03:00:40 +00:00
|
|
|
if (leaf == model->brush.leafs) {
|
2021-07-26 02:15:51 +00:00
|
|
|
unsigned excess = SET_SIZE (numvis) - numvis;
|
|
|
|
memset (out->map, defvis, SET_WORDS (out) * sizeof (*out->map));
|
|
|
|
out->map[SET_WORDS (out) - 1] &= (~SET_ZERO) >> excess;
|
2021-03-20 03:00:40 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-04-24 01:40:39 +00:00
|
|
|
Mod_DecompressVis_set (leaf->compressed_vis, &model->brush, defvis, out);
|
2021-03-20 07:06:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VISIBLE void
|
|
|
|
Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis,
|
2021-07-26 02:15:51 +00:00
|
|
|
set_t *out)
|
2021-03-20 07:06:15 +00:00
|
|
|
{
|
2021-07-27 03:32:40 +00:00
|
|
|
unsigned numvis = model->brush.visleafs;
|
2021-07-26 02:15:51 +00:00
|
|
|
set_expand (out, numvis);
|
2021-03-20 07:06:15 +00:00
|
|
|
if (leaf == model->brush.leafs) {
|
2021-07-26 02:15:51 +00:00
|
|
|
unsigned excess = SET_SIZE (numvis) - numvis;
|
|
|
|
byte *o = (byte *) out->map;
|
|
|
|
for (int i = SET_WORDS (out) * sizeof (*out->map); i-- > 0; ) {
|
|
|
|
*o++ |= defvis;
|
2021-03-20 07:06:15 +00:00
|
|
|
}
|
2021-07-26 02:15:51 +00:00
|
|
|
out->map[SET_WORDS (out) - 1] &= (~SET_ZERO) >> excess;
|
2021-03-20 07:06:15 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-04-24 01:40:39 +00:00
|
|
|
Mod_DecompressVis_mix (leaf->compressed_vis, &model->brush, defvis, out);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2002-08-20 00:48:59 +00:00
|
|
|
// BRUSHMODEL LOADING =========================================================
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2011-11-12 07:36:07 +00:00
|
|
|
//FIXME SLOW! However, it doesn't seem to be a big issue. Leave alone?
|
2007-05-09 10:55:02 +00:00
|
|
|
static void
|
|
|
|
mod_unique_miptex_name (texture_t **textures, texture_t *tx, int ind)
|
|
|
|
{
|
2022-05-12 14:40:52 +00:00
|
|
|
char name[17];
|
2007-05-09 10:55:02 +00:00
|
|
|
int num = 0, i;
|
2022-05-12 14:40:52 +00:00
|
|
|
const char *tag;
|
2007-05-09 10:55:02 +00:00
|
|
|
|
2022-05-12 14:40:52 +00:00
|
|
|
strncpy (name, tx->name, 16);
|
|
|
|
name[16] = 0;
|
2007-05-09 10:55:02 +00:00
|
|
|
do {
|
|
|
|
for (i = 0; i < ind; i++)
|
2007-05-16 09:23:54 +00:00
|
|
|
if (textures[i] && !strcmp (textures[i]->name, tx->name))
|
2007-05-09 10:55:02 +00:00
|
|
|
break;
|
|
|
|
if (i == ind)
|
|
|
|
break;
|
2022-05-12 14:40:52 +00:00
|
|
|
tag = va (0, "~%x", num++);
|
|
|
|
strncpy (tx->name, name, 16);
|
|
|
|
tx->name[15] = 0;
|
|
|
|
if (strlen (name) + strlen (tag) <= 15)
|
|
|
|
strcat (tx->name, tag);
|
|
|
|
else
|
|
|
|
strcpy (tx->name + 15 - strlen (tag), tag);
|
2007-05-09 10:55:02 +00:00
|
|
|
} while (1);
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadTextures (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2002-08-22 20:06:30 +00:00
|
|
|
dmiptexlump_t *m;
|
2021-08-01 12:54:05 +00:00
|
|
|
int pixels, num, max, altmax;
|
2002-08-22 20:06:30 +00:00
|
|
|
miptex_t *mt;
|
|
|
|
texture_t *tx, *tx2;
|
|
|
|
texture_t *anims[10], *altanims[10];
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &mod->brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
if (!bsp->texdatasize) {
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->textures = NULL;
|
2001-02-19 21:15:25 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-08-23 02:56:43 +00:00
|
|
|
m = (dmiptexlump_t *) bsp->texdata;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->numtextures = m->nummiptex;
|
2021-07-28 06:01:45 +00:00
|
|
|
brush->textures = Hunk_AllocName (0,
|
|
|
|
m->nummiptex * sizeof (*brush->textures),
|
2021-02-01 10:31:11 +00:00
|
|
|
mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-08-01 12:54:05 +00:00
|
|
|
for (uint32_t i = 0; i < m->nummiptex; i++) {
|
|
|
|
if (m->dataofs[i] == ~0u)
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
|
|
|
mt = (miptex_t *) ((byte *) m + m->dataofs[i]);
|
|
|
|
mt->width = LittleLong (mt->width);
|
|
|
|
mt->height = LittleLong (mt->height);
|
2021-08-01 12:54:05 +00:00
|
|
|
for (int j = 0; j < MIPLEVELS; j++)
|
2001-02-19 21:15:25 +00:00
|
|
|
mt->offsets[j] = LittleLong (mt->offsets[j]);
|
|
|
|
|
|
|
|
if ((mt->width & 15) || (mt->height & 15))
|
2001-05-10 06:01:11 +00:00
|
|
|
Sys_Error ("Texture %s is not 16 aligned", mt->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
pixels = mt->width * mt->height / 64 * 85;
|
2021-07-28 06:01:45 +00:00
|
|
|
tx = Hunk_AllocName (0, sizeof (texture_t) + pixels, mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->textures[i] = tx;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-05-12 14:40:52 +00:00
|
|
|
memcpy (tx->name, mt->name, sizeof (tx->name));
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_unique_miptex_name (brush->textures, tx, i);
|
2001-02-19 21:15:25 +00:00
|
|
|
tx->width = mt->width;
|
|
|
|
tx->height = mt->height;
|
2021-08-01 12:54:05 +00:00
|
|
|
for (int j = 0; j < MIPLEVELS; j++)
|
2001-02-19 21:15:25 +00:00
|
|
|
tx->offsets[j] =
|
|
|
|
mt->offsets[j] + sizeof (texture_t) - sizeof (miptex_t);
|
|
|
|
// the pixels immediately follow the structures
|
|
|
|
memcpy (tx + 1, mt + 1, pixels);
|
|
|
|
|
|
|
|
if (!strncmp (mt->name, "sky", 3))
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->skytexture = tx;
|
2021-01-19 04:05:39 +00:00
|
|
|
}
|
|
|
|
if (mod_funcs && mod_funcs->Mod_ProcessTexture) {
|
|
|
|
size_t render_size = mod_funcs->texture_render_size;
|
|
|
|
byte *render_data = 0;
|
|
|
|
if (render_size) {
|
2021-07-28 06:01:45 +00:00
|
|
|
render_data = Hunk_AllocName (0, m->nummiptex * render_size,
|
2021-02-01 05:39:00 +00:00
|
|
|
mod->name);
|
2021-01-19 04:05:39 +00:00
|
|
|
}
|
2021-08-01 12:54:05 +00:00
|
|
|
for (uint32_t i = 0; i < m->nummiptex; i++) {
|
2021-03-21 01:08:44 +00:00
|
|
|
if (!(tx = brush->textures[i])) {
|
|
|
|
continue;
|
|
|
|
}
|
2021-01-19 04:05:39 +00:00
|
|
|
tx->render = render_data;
|
|
|
|
render_data += render_size;
|
2021-02-01 05:39:00 +00:00
|
|
|
mod_funcs->Mod_ProcessTexture (mod, tx);
|
2021-01-19 04:05:39 +00:00
|
|
|
}
|
|
|
|
// signal the end of the textures
|
2021-02-01 05:39:00 +00:00
|
|
|
mod_funcs->Mod_ProcessTexture (mod, 0);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2001-07-22 05:40:34 +00:00
|
|
|
// sequence the animations
|
2021-08-01 12:54:05 +00:00
|
|
|
for (uint32_t i = 0; i < m->nummiptex; i++) {
|
2021-02-01 10:31:11 +00:00
|
|
|
tx = brush->textures[i];
|
2001-02-19 21:15:25 +00:00
|
|
|
if (!tx || tx->name[0] != '+')
|
|
|
|
continue;
|
|
|
|
if (tx->anim_next)
|
2001-02-21 23:45:49 +00:00
|
|
|
continue; // already sequenced
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// find the number of frames in the animation
|
|
|
|
memset (anims, 0, sizeof (anims));
|
|
|
|
memset (altanims, 0, sizeof (altanims));
|
|
|
|
|
2022-05-16 11:59:07 +00:00
|
|
|
// convert to uppercase, avoiding toupper (table lookup,
|
|
|
|
// localization issues, etc)
|
|
|
|
#define QTOUPPER(x) ((x) - ('a' - 'A'))
|
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
max = tx->name[1];
|
|
|
|
if (max >= 'a' && max <= 'z')
|
2022-05-16 11:59:07 +00:00
|
|
|
max = QTOUPPER (max);
|
2001-02-19 21:15:25 +00:00
|
|
|
if (max >= '0' && max <= '9') {
|
|
|
|
max -= '0';
|
|
|
|
altmax = 0;
|
|
|
|
anims[max] = tx;
|
|
|
|
max++;
|
|
|
|
} else if (max >= 'A' && max <= 'J') {
|
|
|
|
altmax = max - 'A';
|
|
|
|
max = 0;
|
|
|
|
altanims[altmax] = tx;
|
|
|
|
altmax++;
|
|
|
|
} else
|
2001-05-10 06:01:11 +00:00
|
|
|
Sys_Error ("Bad animating texture %s", tx->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-08-01 12:54:05 +00:00
|
|
|
for (uint32_t j = i + 1; j < m->nummiptex; j++) {
|
2021-02-01 10:31:11 +00:00
|
|
|
tx2 = brush->textures[j];
|
2001-02-19 21:15:25 +00:00
|
|
|
if (!tx2 || tx2->name[0] != '+')
|
|
|
|
continue;
|
|
|
|
if (strcmp (tx2->name + 2, tx->name + 2))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
num = tx2->name[1];
|
|
|
|
if (num >= 'a' && num <= 'z')
|
2022-05-16 11:59:07 +00:00
|
|
|
num = QTOUPPER (num);
|
2001-02-19 21:15:25 +00:00
|
|
|
if (num >= '0' && num <= '9') {
|
|
|
|
num -= '0';
|
|
|
|
anims[num] = tx2;
|
|
|
|
if (num + 1 > max)
|
|
|
|
max = num + 1;
|
|
|
|
} else if (num >= 'A' && num <= 'J') {
|
|
|
|
num = num - 'A';
|
|
|
|
altanims[num] = tx2;
|
|
|
|
if (num + 1 > altmax)
|
|
|
|
altmax = num + 1;
|
|
|
|
} else
|
2001-05-10 06:01:11 +00:00
|
|
|
Sys_Error ("Bad animating texture %s", tx->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// link them all together
|
2021-08-01 12:54:05 +00:00
|
|
|
for (int j = 0; j < max; j++) {
|
2001-02-19 21:15:25 +00:00
|
|
|
tx2 = anims[j];
|
|
|
|
if (!tx2)
|
2001-05-10 06:01:11 +00:00
|
|
|
Sys_Error ("Missing frame %i of %s", j, tx->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
tx2->anim_total = max * ANIM_CYCLE;
|
|
|
|
tx2->anim_min = j * ANIM_CYCLE;
|
|
|
|
tx2->anim_max = (j + 1) * ANIM_CYCLE;
|
|
|
|
tx2->anim_next = anims[(j + 1) % max];
|
|
|
|
if (altmax)
|
|
|
|
tx2->alternate_anims = altanims[0];
|
|
|
|
}
|
2021-08-01 12:54:05 +00:00
|
|
|
for (int j = 0; j < altmax; j++) {
|
2001-02-19 21:15:25 +00:00
|
|
|
tx2 = altanims[j];
|
|
|
|
if (!tx2)
|
2001-05-10 06:01:11 +00:00
|
|
|
Sys_Error ("Missing frame %i of %s", j, tx->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
tx2->anim_total = altmax * ANIM_CYCLE;
|
|
|
|
tx2->anim_min = j * ANIM_CYCLE;
|
|
|
|
tx2->anim_max = (j + 1) * ANIM_CYCLE;
|
|
|
|
tx2->anim_next = altanims[(j + 1) % altmax];
|
|
|
|
if (max)
|
|
|
|
tx2->alternate_anims = anims[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadVisibility (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2010-08-23 02:56:43 +00:00
|
|
|
if (!bsp->visdatasize) {
|
2021-02-01 10:31:11 +00:00
|
|
|
mod->brush.visdata = NULL;
|
2001-02-19 21:15:25 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-07-28 06:01:45 +00:00
|
|
|
mod->brush.visdata = Hunk_AllocName (0, bsp->visdatasize, mod->name);
|
2021-02-01 10:31:11 +00:00
|
|
|
memcpy (mod->brush.visdata, bsp->visdata, bsp->visdatasize);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadEntities (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2010-08-23 02:56:43 +00:00
|
|
|
if (!bsp->entdatasize) {
|
2021-02-01 10:31:11 +00:00
|
|
|
mod->brush.entities = NULL;
|
2001-02-19 21:15:25 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-07-28 06:01:45 +00:00
|
|
|
mod->brush.entities = Hunk_AllocName (0, bsp->entdatasize, mod->name);
|
2021-02-01 10:31:11 +00:00
|
|
|
memcpy (mod->brush.entities, bsp->entdata, bsp->entdatasize);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadVertexes (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
|
|
|
dvertex_t *in;
|
2002-08-22 20:06:30 +00:00
|
|
|
int count, i;
|
2001-02-19 21:15:25 +00:00
|
|
|
mvertex_t *out;
|
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
in = bsp->vertexes;
|
|
|
|
count = bsp->numvertexes;
|
2021-07-28 06:01:45 +00:00
|
|
|
out = Hunk_AllocName (0, count * sizeof (*out), mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
mod->brush.vertexes = out;
|
|
|
|
mod->brush.numvertexes = count;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2012-09-07 06:45:59 +00:00
|
|
|
for (i = 0; i < count; i++, in++, out++)
|
|
|
|
VectorCopy (in->point, out->position);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadSubmodels (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2002-08-22 20:06:30 +00:00
|
|
|
dmodel_t *in, *out;
|
|
|
|
int count, i, j;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &mod->brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
in = bsp->models;
|
|
|
|
count = bsp->nummodels;
|
2021-07-28 06:01:45 +00:00
|
|
|
out = Hunk_AllocName (0, count * sizeof (*out), mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->submodels = out;
|
|
|
|
brush->numsubmodels = count;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++, in++, out++) {
|
2012-09-07 06:45:59 +00:00
|
|
|
static vec3_t offset = {1, 1, 1};
|
|
|
|
// spread the mins / maxs by a pixel
|
|
|
|
VectorSubtract (in->mins, offset, out->mins);
|
|
|
|
VectorAdd (in->maxs, offset, out->maxs);
|
|
|
|
VectorCopy (in->origin, out->origin);
|
2001-02-19 21:15:25 +00:00
|
|
|
for (j = 0; j < MAX_MAP_HULLS; j++)
|
2012-09-07 06:45:59 +00:00
|
|
|
out->headnode[j] = in->headnode[j];
|
|
|
|
out->visleafs = in->visleafs;
|
|
|
|
out->firstface = in->firstface;
|
|
|
|
out->numfaces = in->numfaces;
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
2010-08-24 00:53:54 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
out = brush->submodels;
|
2010-08-24 00:53:54 +00:00
|
|
|
|
|
|
|
if (out->visleafs > 8192)
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_warn,
|
2010-08-24 00:53:54 +00:00
|
|
|
"%i visleafs exceeds standard limit of 8192.\n",
|
|
|
|
out->visleafs);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadEdges (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
|
|
|
dedge_t *in;
|
2002-08-22 20:06:30 +00:00
|
|
|
int count, i;
|
2001-02-19 21:15:25 +00:00
|
|
|
medge_t *out;
|
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
in = bsp->edges;
|
|
|
|
count = bsp->numedges;
|
2021-07-28 06:01:45 +00:00
|
|
|
out = Hunk_AllocName (0, (count + 1) * sizeof (*out), mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
mod->brush.edges = out;
|
|
|
|
mod->brush.numedges = count;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++, in++, out++) {
|
2012-09-07 06:45:59 +00:00
|
|
|
out->v[0] = in->v[0];
|
|
|
|
out->v[1] = in->v[1];
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadTexinfo (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
|
|
|
float len1, len2;
|
2021-08-01 12:54:05 +00:00
|
|
|
unsigned count, miptex, i, j;
|
2002-08-22 20:06:30 +00:00
|
|
|
mtexinfo_t *out;
|
|
|
|
texinfo_t *in;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
in = bsp->texinfo;
|
|
|
|
count = bsp->numtexinfo;
|
2021-07-28 06:01:45 +00:00
|
|
|
out = Hunk_AllocName (0, count * sizeof (*out), mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
mod->brush.texinfo = out;
|
|
|
|
mod->brush.numtexinfo = count;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++, in++, out++) {
|
|
|
|
for (j = 0; j < 4; j++) {
|
2012-09-07 06:45:59 +00:00
|
|
|
out->vecs[0][j] = in->vecs[0][j];
|
|
|
|
out->vecs[1][j] = in->vecs[1][j];
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
2002-08-20 02:22:40 +00:00
|
|
|
len1 = VectorLength (out->vecs[0]);
|
|
|
|
len2 = VectorLength (out->vecs[1]);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
len1 = (len1 + len2) / 2;
|
|
|
|
if (len1 < 0.32)
|
|
|
|
out->mipadjust = 4;
|
|
|
|
else if (len1 < 0.49)
|
|
|
|
out->mipadjust = 3;
|
|
|
|
else if (len1 < 0.99)
|
|
|
|
out->mipadjust = 2;
|
|
|
|
else
|
|
|
|
out->mipadjust = 1;
|
|
|
|
|
2012-09-07 06:45:59 +00:00
|
|
|
miptex = in->miptex;
|
|
|
|
out->flags = in->flags;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
if (!mod->brush.textures) {
|
2001-02-19 21:15:25 +00:00
|
|
|
out->texture = r_notexture_mip; // checkerboard texture
|
|
|
|
out->flags = 0;
|
|
|
|
} else {
|
2021-02-01 10:31:11 +00:00
|
|
|
if (miptex >= mod->brush.numtextures)
|
|
|
|
Sys_Error ("miptex >= mod->brush.numtextures");
|
|
|
|
out->texture = mod->brush.textures[miptex];
|
2001-02-19 21:15:25 +00:00
|
|
|
if (!out->texture) {
|
|
|
|
out->texture = r_notexture_mip; // texture not found
|
|
|
|
out->flags = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
CalcSurfaceExtents
|
|
|
|
|
|
|
|
Fills in s->texturemins[] and s->extents[]
|
|
|
|
*/
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
CalcSurfaceExtents (model_t *mod, msurface_t *s)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2002-08-22 20:06:30 +00:00
|
|
|
float mins[2], maxs[2], val;
|
|
|
|
int e, i, j;
|
|
|
|
int bmins[2], bmaxs[2];
|
2001-02-19 21:15:25 +00:00
|
|
|
mtexinfo_t *tex;
|
2002-08-22 20:06:30 +00:00
|
|
|
mvertex_t *v;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &mod->brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
mins[0] = mins[1] = 999999;
|
|
|
|
maxs[0] = maxs[1] = -99999;
|
|
|
|
|
|
|
|
tex = s->texinfo;
|
|
|
|
|
|
|
|
for (i = 0; i < s->numedges; i++) {
|
2021-02-01 10:31:11 +00:00
|
|
|
e = brush->surfedges[s->firstedge + i];
|
2001-02-19 21:15:25 +00:00
|
|
|
if (e >= 0)
|
2021-02-01 10:31:11 +00:00
|
|
|
v = &brush->vertexes[brush->edges[e].v[0]];
|
2001-02-19 21:15:25 +00:00
|
|
|
else
|
2021-02-01 10:31:11 +00:00
|
|
|
v = &brush->vertexes[brush->edges[-e].v[1]];
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
for (j = 0; j < 2; j++) {
|
|
|
|
val = v->position[0] * tex->vecs[j][0] +
|
|
|
|
v->position[1] * tex->vecs[j][1] +
|
|
|
|
v->position[2] * tex->vecs[j][2] + tex->vecs[j][3];
|
|
|
|
if (val < mins[j])
|
|
|
|
mins[j] = val;
|
|
|
|
if (val > maxs[j])
|
|
|
|
maxs[j] = val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
bmins[i] = floor (mins[i] / 16);
|
|
|
|
bmaxs[i] = ceil (maxs[i] / 16);
|
|
|
|
|
|
|
|
s->texturemins[i] = bmins[i] * 16;
|
|
|
|
s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
|
2010-08-24 00:53:54 +00:00
|
|
|
// FIXME even 2000 is really too small, need a saner test
|
|
|
|
if (!(tex->flags & TEX_SPECIAL) && s->extents[i] > 2000)
|
2002-08-27 16:01:51 +00:00
|
|
|
Sys_Error ("Bad surface extents: %d %x %d %d", i, tex->flags,
|
|
|
|
s->extents[i], LongSwap (s->extents[i]));
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadFaces (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
|
|
|
dface_t *in;
|
2002-08-22 20:06:30 +00:00
|
|
|
int count, planenum, side, surfnum, i;
|
2001-02-19 21:15:25 +00:00
|
|
|
msurface_t *out;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &mod->brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
in = bsp->faces;
|
|
|
|
count = bsp->numfaces;
|
2021-07-28 06:01:45 +00:00
|
|
|
out = Hunk_AllocName (0, count * sizeof (*out), mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-24 00:53:54 +00:00
|
|
|
if (count > 32767) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_warn,
|
2010-08-24 00:53:54 +00:00
|
|
|
"%i faces exceeds standard limit of 32767.\n", count);
|
|
|
|
}
|
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->surfaces = out;
|
|
|
|
brush->numsurfaces = count;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
for (surfnum = 0; surfnum < count; surfnum++, in++, out++) {
|
2012-09-07 06:45:59 +00:00
|
|
|
out->firstedge = in->firstedge;
|
|
|
|
out->numedges = in->numedges;
|
2001-02-19 21:15:25 +00:00
|
|
|
out->flags = 0;
|
|
|
|
|
2012-09-07 06:45:59 +00:00
|
|
|
planenum = in->planenum;
|
|
|
|
side = in->side;
|
2001-02-19 21:15:25 +00:00
|
|
|
if (side)
|
|
|
|
out->flags |= SURF_PLANEBACK;
|
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
out->plane = brush->planes + planenum;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
out->texinfo = brush->texinfo + in->texinfo;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 05:39:00 +00:00
|
|
|
CalcSurfaceExtents (mod, out);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// lighting info
|
|
|
|
|
|
|
|
for (i = 0; i < MAXLIGHTMAPS; i++)
|
|
|
|
out->styles[i] = in->styles[i];
|
2012-09-07 06:45:59 +00:00
|
|
|
i = in->lightofs;
|
2001-02-19 21:15:25 +00:00
|
|
|
if (i == -1)
|
|
|
|
out->samples = NULL;
|
|
|
|
else
|
2021-02-01 10:31:11 +00:00
|
|
|
out->samples = brush->lightdata + (i * mod_lightmap_bytes);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// set the drawing flags flag
|
2002-01-12 04:46:15 +00:00
|
|
|
if (!out->texinfo->texture || !out->texinfo->texture->name)
|
|
|
|
continue; // avoid crashing on null textures
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2002-01-12 04:46:15 +00:00
|
|
|
if (!strncmp (out->texinfo->texture->name, "sky", 3)) { // sky
|
2001-02-19 21:15:25 +00:00
|
|
|
out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
if (mod_sky_divide) {
|
|
|
|
if (mod_funcs && mod_funcs->Mod_SubdivideSurface) {
|
2021-02-01 05:39:00 +00:00
|
|
|
mod_funcs->Mod_SubdivideSurface (mod, out);
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
}
|
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2002-01-12 04:46:15 +00:00
|
|
|
if (out->texinfo->texture->name[0] == '*') { // turbulent
|
2001-08-05 05:59:15 +00:00
|
|
|
out->flags |= (SURF_DRAWTURB
|
|
|
|
| SURF_DRAWTILED
|
|
|
|
| SURF_LIGHTBOTHSIDES);
|
2001-02-19 21:15:25 +00:00
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
out->extents[i] = 16384;
|
|
|
|
out->texturemins[i] = -8192;
|
|
|
|
}
|
2021-01-18 23:26:53 +00:00
|
|
|
if (mod_funcs && mod_funcs->Mod_SubdivideSurface) {
|
|
|
|
// cut up polygon for warps
|
2021-02-01 05:39:00 +00:00
|
|
|
mod_funcs->Mod_SubdivideSurface (mod, out);
|
2021-01-18 23:26:53 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2022-05-22 02:18:32 +00:00
|
|
|
Mod_SetParent (mod_brush_t *brush, int node_id, int parent_id)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2022-05-22 02:18:32 +00:00
|
|
|
if (node_id < 0) {
|
|
|
|
brush->leaf_parents[~node_id] = parent_id;
|
2001-02-19 21:15:25 +00:00
|
|
|
return;
|
2021-02-03 02:41:38 +00:00
|
|
|
}
|
2022-05-22 02:18:32 +00:00
|
|
|
brush->node_parents[node_id] = parent_id;
|
|
|
|
mnode_t *node = brush->nodes + node_id;
|
|
|
|
Mod_SetParent (brush, node->children[0], node_id);
|
|
|
|
Mod_SetParent (brush, node->children[1], node_id);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2021-04-25 03:22:54 +00:00
|
|
|
static void
|
|
|
|
Mod_SetLeafFlags (mod_brush_t *brush)
|
|
|
|
{
|
2021-07-27 03:32:40 +00:00
|
|
|
for (unsigned i = 0; i < brush->modleafs; i++) {
|
2021-04-25 03:22:54 +00:00
|
|
|
int flags = 0;
|
|
|
|
mleaf_t *leaf = &brush->leafs[i];
|
2022-05-10 05:30:48 +00:00
|
|
|
msurface_t **msurf = brush->marksurfaces + leaf->firstmarksurface;
|
2021-04-25 03:22:54 +00:00
|
|
|
for (int j = 0; j < leaf->nummarksurfaces; j++) {
|
2022-05-10 05:30:48 +00:00
|
|
|
msurface_t *surf = *msurf++;
|
2021-04-25 03:22:54 +00:00
|
|
|
flags |= surf->flags;
|
|
|
|
}
|
|
|
|
brush->leaf_flags[i] = flags;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadNodes (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
|
|
|
dnode_t *in;
|
2002-08-22 20:06:30 +00:00
|
|
|
int count, i, j, p;
|
2001-02-19 21:15:25 +00:00
|
|
|
mnode_t *out;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &mod->brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
in = bsp->nodes;
|
|
|
|
count = bsp->numnodes;
|
2021-07-28 06:01:45 +00:00
|
|
|
out = Hunk_AllocName (0, count * sizeof (*out), mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-24 00:53:54 +00:00
|
|
|
if (count > 32767) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_warn,
|
2010-08-24 00:53:54 +00:00
|
|
|
"%i nodes exceeds standard limit of 32767.\n", count);
|
|
|
|
}
|
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->nodes = out;
|
|
|
|
brush->numnodes = count;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++, in++, out++) {
|
|
|
|
for (j = 0; j < 3; j++) {
|
2012-09-07 06:45:59 +00:00
|
|
|
out->minmaxs[j] = in->mins[j];
|
|
|
|
out->minmaxs[3 + j] = in->maxs[j];
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2022-05-22 02:18:32 +00:00
|
|
|
plane_t *plane = brush->planes + in->planenum;
|
|
|
|
out->plane = loadvec3f (plane->normal);
|
|
|
|
out->plane[3] = -plane->dist;
|
|
|
|
out->type = plane->type;
|
|
|
|
out->signbits = plane->signbits;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2012-09-07 06:45:59 +00:00
|
|
|
out->firstsurface = in->firstface;
|
|
|
|
out->numsurfaces = in->numfaces;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
for (j = 0; j < 2; j++) {
|
2012-09-07 07:09:24 +00:00
|
|
|
p = in->children[j];
|
|
|
|
// this check is for extended bsp 29 files
|
2012-12-30 02:42:31 +00:00
|
|
|
if (p >= 0) {
|
2022-05-22 02:18:32 +00:00
|
|
|
out->children[j] = p;
|
2010-08-24 00:53:54 +00:00
|
|
|
} else {
|
2022-05-22 02:18:32 +00:00
|
|
|
if ((unsigned) ~p < brush->modleafs) {
|
|
|
|
out->children[j] = p;
|
2010-08-24 00:53:54 +00:00
|
|
|
} else {
|
|
|
|
Sys_Printf ("Mod_LoadNodes: invalid leaf index %i "
|
2022-05-22 02:18:32 +00:00
|
|
|
"(file has only %i leafs)\n", ~p,
|
2021-07-27 03:32:40 +00:00
|
|
|
brush->modleafs);
|
2010-08-24 00:53:54 +00:00
|
|
|
//map it to the solid leaf
|
2022-05-22 02:18:32 +00:00
|
|
|
out->children[j] = ~0;
|
2010-08-24 00:53:54 +00:00
|
|
|
}
|
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-22 02:18:32 +00:00
|
|
|
size_t size = (brush->modleafs + brush->numnodes) * sizeof (int32_t);
|
2021-07-27 03:32:40 +00:00
|
|
|
size += brush->modleafs * sizeof (int);
|
2021-07-28 06:01:45 +00:00
|
|
|
brush->node_parents = Hunk_AllocName (0, size, mod->name);
|
2021-02-03 02:41:38 +00:00
|
|
|
brush->leaf_parents = brush->node_parents + brush->numnodes;
|
2021-07-27 03:32:40 +00:00
|
|
|
brush->leaf_flags = (int *) (brush->leaf_parents + brush->modleafs);
|
2022-05-22 02:18:32 +00:00
|
|
|
Mod_SetParent (brush, 0, -1); // sets nodes and leafs
|
2021-04-25 03:22:54 +00:00
|
|
|
Mod_SetLeafFlags (brush);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadLeafs (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
|
|
|
dleaf_t *in;
|
2002-08-22 20:06:30 +00:00
|
|
|
int count, i, j, p;
|
2001-02-19 21:15:25 +00:00
|
|
|
mleaf_t *out;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &mod->brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
in = bsp->leafs;
|
|
|
|
count = bsp->numleafs;
|
2021-07-28 06:01:45 +00:00
|
|
|
out = Hunk_AllocName (0, count * sizeof (*out), mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->leafs = out;
|
2021-07-27 03:32:40 +00:00
|
|
|
brush->modleafs = count;
|
2001-02-19 21:15:25 +00:00
|
|
|
for (i = 0; i < count; i++, in++, out++) {
|
|
|
|
for (j = 0; j < 3; j++) {
|
2012-09-07 06:45:59 +00:00
|
|
|
out->mins[j] = in->mins[j];
|
|
|
|
out->maxs[j] = in->maxs[j];
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2012-09-07 06:45:59 +00:00
|
|
|
p = in->contents;
|
2001-02-19 21:15:25 +00:00
|
|
|
out->contents = p;
|
|
|
|
|
2022-05-10 05:30:48 +00:00
|
|
|
out->firstmarksurface = in->firstmarksurface;
|
2012-09-07 06:45:59 +00:00
|
|
|
out->nummarksurfaces = in->nummarksurfaces;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2012-09-07 06:45:59 +00:00
|
|
|
p = in->visofs;
|
2001-02-19 21:15:25 +00:00
|
|
|
if (p == -1)
|
|
|
|
out->compressed_vis = NULL;
|
|
|
|
else
|
2021-02-01 10:31:11 +00:00
|
|
|
out->compressed_vis = brush->visdata + p;
|
2001-02-19 21:15:25 +00:00
|
|
|
out->efrags = NULL;
|
|
|
|
|
|
|
|
for (j = 0; j < 4; j++)
|
|
|
|
out->ambient_sound_level[j] = in->ambient_level[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadClipnodes (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2010-11-29 00:36:21 +00:00
|
|
|
dclipnode_t *in;
|
2022-05-19 06:13:07 +00:00
|
|
|
dclipnode_t *out;
|
2002-08-22 20:06:30 +00:00
|
|
|
hull_t *hull;
|
2021-08-01 12:54:05 +00:00
|
|
|
int count, i;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &mod->brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
in = bsp->clipnodes;
|
|
|
|
count = bsp->numclipnodes;
|
2021-07-28 06:01:45 +00:00
|
|
|
out = Hunk_AllocName (0, count * sizeof (*out), mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-24 00:53:54 +00:00
|
|
|
if (count > 32767) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_warn,
|
2010-08-24 00:53:54 +00:00
|
|
|
"%i clilpnodes exceeds standard limit of 32767.\n",
|
|
|
|
count);
|
|
|
|
}
|
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->clipnodes = out;
|
|
|
|
brush->numclipnodes = count;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
hull = &brush->hulls[1];
|
|
|
|
brush->hull_list[1] = hull;
|
2001-02-19 21:15:25 +00:00
|
|
|
hull->clipnodes = out;
|
|
|
|
hull->firstclipnode = 0;
|
|
|
|
hull->lastclipnode = count - 1;
|
2021-02-01 10:31:11 +00:00
|
|
|
hull->planes = brush->planes;
|
2001-02-19 21:15:25 +00:00
|
|
|
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;
|
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
hull = &brush->hulls[2];
|
|
|
|
brush->hull_list[2] = hull;
|
2001-02-19 21:15:25 +00:00
|
|
|
hull->clipnodes = out;
|
|
|
|
hull->firstclipnode = 0;
|
|
|
|
hull->lastclipnode = count - 1;
|
2021-02-01 10:31:11 +00:00
|
|
|
hull->planes = brush->planes;
|
2001-02-19 21:15:25 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++, out++, in++) {
|
2012-09-07 06:45:59 +00:00
|
|
|
out->planenum = in->planenum;
|
2021-08-01 12:54:05 +00:00
|
|
|
if (out->planenum >= brush->numplanes)
|
2010-08-24 00:53:54 +00:00
|
|
|
Sys_Error ("Mod_LoadClipnodes: planenum out of bounds");
|
2012-09-07 07:09:24 +00:00
|
|
|
out->children[0] = in->children[0];
|
|
|
|
out->children[1] = in->children[1];
|
|
|
|
// these checks are for extended bsp 29 files
|
2010-08-24 00:53:54 +00:00
|
|
|
if (out->children[0] >= count)
|
|
|
|
out->children[0] -= 65536;
|
|
|
|
if (out->children[1] >= count)
|
|
|
|
out->children[1] -= 65536;
|
2001-07-04 16:28:54 +00:00
|
|
|
if ((out->children[0] >= 0
|
|
|
|
&& (out->children[0] < hull->firstclipnode
|
|
|
|
|| out->children[0] > hull->lastclipnode))
|
|
|
|
|| (out->children[1] >= 0
|
|
|
|
&& (out->children[1] < hull->firstclipnode
|
|
|
|
|| out->children[1] > hull->lastclipnode)))
|
|
|
|
Sys_Error ("Mod_LoadClipnodes: bad node number");
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Mod_MakeHull0
|
|
|
|
|
2006-12-24 03:13:29 +00:00
|
|
|
Replicate the drawing hull structure as a clipping hull
|
2001-02-19 21:15:25 +00:00
|
|
|
*/
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2022-05-22 02:18:32 +00:00
|
|
|
Mod_MakeHull0 (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2022-05-19 06:13:07 +00:00
|
|
|
dclipnode_t *out;
|
2002-08-22 20:06:30 +00:00
|
|
|
hull_t *hull;
|
|
|
|
int count, i, j;
|
2022-05-22 02:18:32 +00:00
|
|
|
mnode_t *in;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &mod->brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
hull = &brush->hulls[0];
|
|
|
|
brush->hull_list[0] = hull;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
in = brush->nodes;
|
|
|
|
count = brush->numnodes;
|
2021-07-28 06:01:45 +00:00
|
|
|
out = Hunk_AllocName (0, count * sizeof (*out), mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
hull->clipnodes = out;
|
|
|
|
hull->firstclipnode = 0;
|
|
|
|
hull->lastclipnode = count - 1;
|
2021-02-01 10:31:11 +00:00
|
|
|
hull->planes = brush->planes;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++, out++, in++) {
|
2022-05-22 02:18:32 +00:00
|
|
|
out->planenum = bsp->nodes[i].planenum;
|
2001-02-19 21:15:25 +00:00
|
|
|
for (j = 0; j < 2; j++) {
|
2022-05-22 02:18:32 +00:00
|
|
|
int child_id = in->children[j];
|
|
|
|
if (child_id < 0) {
|
|
|
|
out->children[j] = bsp->leafs[~child_id].contents;
|
|
|
|
} else {
|
|
|
|
out->children[j] = child_id;
|
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadMarksurfaces (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2021-08-01 12:54:05 +00:00
|
|
|
unsigned count, i, j;
|
2001-02-19 21:15:25 +00:00
|
|
|
msurface_t **out;
|
2012-09-07 07:09:24 +00:00
|
|
|
uint32_t *in;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &mod->brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
in = bsp->marksurfaces;
|
|
|
|
count = bsp->nummarksurfaces;
|
2021-07-28 06:01:45 +00:00
|
|
|
out = Hunk_AllocName (0, count * sizeof (*out), mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-24 00:53:54 +00:00
|
|
|
if (count > 32767) {
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_warn,
|
2010-08-24 00:53:54 +00:00
|
|
|
"%i marksurfaces exceeds standard limit of 32767.\n",
|
|
|
|
count);
|
|
|
|
}
|
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->marksurfaces = out;
|
|
|
|
brush->nummarksurfaces = count;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
2012-09-07 06:45:59 +00:00
|
|
|
j = in[i];
|
2021-02-01 10:31:11 +00:00
|
|
|
if (j >= brush->numsurfaces)
|
2001-05-10 06:01:11 +00:00
|
|
|
Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
|
2021-02-01 10:31:11 +00:00
|
|
|
out[i] = brush->surfaces + j;
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadSurfedges (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2010-08-23 02:56:43 +00:00
|
|
|
int count, i;
|
|
|
|
int32_t *in;
|
|
|
|
int *out;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &mod->brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
in = bsp->surfedges;
|
|
|
|
count = bsp->numsurfedges;
|
2021-07-28 06:01:45 +00:00
|
|
|
out = Hunk_AllocName (0, count * sizeof (*out), mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->surfedges = out;
|
|
|
|
brush->numsurfedges = count;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
2012-09-07 06:45:59 +00:00
|
|
|
out[i] = in[i];
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadPlanes (model_t *mod, bsp_t *bsp)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
|
|
|
dplane_t *in;
|
2002-08-22 20:06:30 +00:00
|
|
|
int bits, count, i, j;
|
2011-11-14 02:18:22 +00:00
|
|
|
plane_t *out;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &mod->brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
in = bsp->planes;
|
|
|
|
count = bsp->numplanes;
|
2021-07-28 06:01:45 +00:00
|
|
|
out = Hunk_AllocName (0, count * 2 * sizeof (*out), mod->name);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->planes = out;
|
|
|
|
brush->numplanes = count;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++, in++, out++) {
|
|
|
|
bits = 0;
|
|
|
|
for (j = 0; j < 3; j++) {
|
2012-09-07 06:45:59 +00:00
|
|
|
out->normal[j] = in->normal[j];
|
2001-02-19 21:15:25 +00:00
|
|
|
if (out->normal[j] < 0)
|
|
|
|
bits |= 1 << j;
|
|
|
|
}
|
|
|
|
|
2012-09-07 06:45:59 +00:00
|
|
|
out->dist = in->dist;
|
|
|
|
out->type = in->type;
|
2001-02-19 21:15:25 +00:00
|
|
|
out->signbits = bits;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
static void
|
|
|
|
do_checksums (const bsp_t *bsp, void *_mod)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2010-08-23 02:56:43 +00:00
|
|
|
int i;
|
|
|
|
model_t *mod = (model_t *) _mod;
|
|
|
|
byte *base;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &mod->brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
base = (byte *) bsp->header;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// checksum all of the map, except for entities
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->checksum = 0;
|
|
|
|
brush->checksum2 = 0;
|
2001-02-19 21:15:25 +00:00
|
|
|
for (i = 0; i < HEADER_LUMPS; i++) {
|
2010-08-23 02:56:43 +00:00
|
|
|
lump_t *lump = bsp->header->lumps + i;
|
2004-02-29 04:24:42 +00:00
|
|
|
int csum;
|
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
if (i == LUMP_ENTITIES)
|
|
|
|
continue;
|
2010-08-23 02:56:43 +00:00
|
|
|
csum = Com_BlockChecksum (base + lump->fileofs, lump->filelen);
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->checksum ^= csum;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2004-02-29 04:24:42 +00:00
|
|
|
if (i != LUMP_VISIBILITY && i != LUMP_LEAFS && i != LUMP_NODES)
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->checksum2 ^= csum;
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
2010-08-23 02:56:43 +00:00
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2012-11-28 12:29:03 +00:00
|
|
|
static void
|
2022-05-22 02:18:32 +00:00
|
|
|
recurse_draw_tree (mod_brush_t *brush, int node_id, int depth)
|
2012-11-28 12:29:03 +00:00
|
|
|
{
|
2022-05-22 02:18:32 +00:00
|
|
|
if (node_id < 0) {
|
2021-02-01 10:31:11 +00:00
|
|
|
if (depth > brush->depth)
|
|
|
|
brush->depth = depth;
|
2012-11-28 12:29:03 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-05-22 02:18:32 +00:00
|
|
|
mnode_t *node = &brush->nodes[node_id];
|
2021-02-01 10:31:11 +00:00
|
|
|
recurse_draw_tree (brush, node->children[0], depth + 1);
|
|
|
|
recurse_draw_tree (brush, node->children[1], depth + 1);
|
2012-11-28 12:29:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-02-01 10:31:11 +00:00
|
|
|
Mod_FindDrawDepth (mod_brush_t *brush)
|
2012-11-28 12:29:03 +00:00
|
|
|
{
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->depth = 0;
|
2022-05-22 02:18:32 +00:00
|
|
|
recurse_draw_tree (brush, 0, 1);
|
2012-11-28 12:29:03 +00:00
|
|
|
}
|
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
void
|
|
|
|
Mod_LoadBrushModel (model_t *mod, void *buffer)
|
|
|
|
{
|
|
|
|
dmodel_t *bm;
|
2021-08-01 12:54:05 +00:00
|
|
|
unsigned i, j;
|
2010-08-23 02:56:43 +00:00
|
|
|
bsp_t *bsp;
|
|
|
|
|
2021-02-01 05:39:00 +00:00
|
|
|
mod->type = mod_brush;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2010-08-23 02:56:43 +00:00
|
|
|
bsp = LoadBSPMem (buffer, qfs_filesize, do_checksums, mod);
|
|
|
|
|
|
|
|
// load into heap
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadVertexes (mod, bsp);
|
|
|
|
Mod_LoadEdges (mod, bsp);
|
|
|
|
Mod_LoadSurfedges (mod, bsp);
|
|
|
|
Mod_LoadTextures (mod, bsp);
|
2021-01-18 23:26:53 +00:00
|
|
|
if (mod_funcs && mod_funcs->Mod_LoadLighting) {
|
2021-02-01 05:39:00 +00:00
|
|
|
mod_funcs->Mod_LoadLighting (mod, bsp);
|
2021-01-18 23:26:53 +00:00
|
|
|
}
|
2021-02-01 05:39:00 +00:00
|
|
|
Mod_LoadPlanes (mod, bsp);
|
|
|
|
Mod_LoadTexinfo (mod, bsp);
|
|
|
|
Mod_LoadFaces (mod, bsp);
|
|
|
|
Mod_LoadMarksurfaces (mod, bsp);
|
|
|
|
Mod_LoadVisibility (mod, bsp);
|
|
|
|
Mod_LoadLeafs (mod, bsp);
|
|
|
|
Mod_LoadNodes (mod, bsp);
|
|
|
|
Mod_LoadClipnodes (mod, bsp);
|
|
|
|
Mod_LoadEntities (mod, bsp);
|
|
|
|
Mod_LoadSubmodels (mod, bsp);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-05-22 02:18:32 +00:00
|
|
|
Mod_MakeHull0 (mod, bsp);
|
2012-01-29 13:32:35 +00:00
|
|
|
|
2022-05-22 02:18:32 +00:00
|
|
|
BSP_Free(bsp);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
Mod_FindDrawDepth (&mod->brush);
|
2012-11-28 12:29:03 +00:00
|
|
|
for (i = 0; i < MAX_MAP_HULLS; i++)
|
2021-02-01 10:31:11 +00:00
|
|
|
Mod_FindClipDepth (&mod->brush.hulls[i]);
|
2012-11-28 12:29:03 +00:00
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
mod->numframes = 2; // regular and alternate animation
|
|
|
|
|
2001-07-22 05:40:34 +00:00
|
|
|
// set up the submodels (FIXME: this is confusing)
|
2021-02-01 10:31:11 +00:00
|
|
|
for (i = 0; i < mod->brush.numsubmodels; i++) {
|
|
|
|
bm = &mod->brush.submodels[i];
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
mod->brush.hulls[0].firstclipnode = bm->headnode[0];
|
|
|
|
mod->brush.hull_list[0] = &mod->brush.hulls[0];
|
2001-02-19 21:15:25 +00:00
|
|
|
for (j = 1; j < MAX_MAP_HULLS; j++) {
|
2021-02-01 10:31:11 +00:00
|
|
|
mod->brush.hulls[j].firstclipnode = bm->headnode[j];
|
|
|
|
mod->brush.hulls[j].lastclipnode = mod->brush.numclipnodes - 1;
|
|
|
|
mod->brush.hull_list[j] = &mod->brush.hulls[j];
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
mod->brush.firstmodelsurface = bm->firstface;
|
|
|
|
mod->brush.nummodelsurfaces = bm->numfaces;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
VectorCopy (bm->maxs, mod->maxs);
|
|
|
|
VectorCopy (bm->mins, mod->mins);
|
|
|
|
|
|
|
|
mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
|
|
|
|
|
2021-07-27 03:32:40 +00:00
|
|
|
mod->brush.visleafs = bm->visleafs;
|
|
|
|
// The bsp file has leafs for all submodes and hulls, so update the
|
|
|
|
// leaf count for this model to be the correct number (which is one
|
|
|
|
// more than the number of visible leafs)
|
|
|
|
mod->brush.modleafs = bm->visleafs + 1;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
if (i < mod->brush.numsubmodels - 1) {
|
2002-01-12 04:46:15 +00:00
|
|
|
// duplicate the basic information
|
2020-02-06 08:38:51 +00:00
|
|
|
char name[12];
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
snprintf (name, sizeof (name), "*%i", i + 1);
|
2021-01-19 09:15:05 +00:00
|
|
|
model_t *m = Mod_FindName (name);
|
|
|
|
*m = *mod;
|
2021-02-01 05:39:00 +00:00
|
|
|
strcpy (m->path, name);
|
2021-01-19 09:15:05 +00:00
|
|
|
mod = m;
|
|
|
|
// make sure clear is called only for the main model
|
|
|
|
m->clear = 0;
|
|
|
|
m->data = 0;
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|