DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
model_brush.c File Reference
#include "quakedef.h"
#include "image.h"
#include "r_shadow.h"
#include "polygon.h"
#include "curves.h"
#include "wad.h"
+ Include dependency graph for model_brush.c:

Go to the source code of this file.

Data Structures

struct  findnonsolidlocationinfo_t
 
struct  objvertex_t
 
struct  patchtess_t
 
struct  portal_t
 
struct  RecursiveHullCheckTraceInfo_t
 

Macros

#define DIST_EPSILON   (0.03125)
 
#define HULLCHECKSTATE_DONE   2
 
#define HULLCHECKSTATE_EMPTY   0
 
#define HULLCHECKSTATE_SOLID   1
 
#define MAX_PORTALPOINTS   64
 
#define PATCHTESS_SAME_LODGROUP(a, b)
 
#define PORTAL_DIST_EPSILON   (1.0 / 32.0)
 

Functions

static void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back)
 
void Collision_ClipTrace_Box (trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, int boxsupercontents, int boxq3surfaceflags, const texture_t *boxtexture)
 
void Collision_ClipTrace_Point (trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, int boxsupercontents, int boxq3surfaceflags, const texture_t *boxtexture)
 
void Mod_2PSB_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_BrushInit (void)
 
void Mod_BSP2_Load (model_t *mod, void *buffer, void *bufferend)
 
static int Mod_BSP_BoxTouchingLeafPVS (model_t *model, const unsigned char *pvs, const vec3_t mins, const vec3_t maxs)
 
static int Mod_BSP_BoxTouchingPVS (model_t *model, const unsigned char *pvs, const vec3_t mins, const vec3_t maxs)
 
static int Mod_BSP_BoxTouchingVisibleLeafs (model_t *model, const unsigned char *visibleleafs, const vec3_t mins, const vec3_t maxs)
 
static void Mod_BSP_DecompressVis (const unsigned char *in, const unsigned char *inend, unsigned char *out, unsigned char *outend)
 
static size_t Mod_BSP_FatPVS (model_t *model, const vec3_t org, vec_t radius, unsigned char **pvsbuffer, mempool_t *pool, qbool merge)
 
static void Mod_BSP_FatPVS_RecursiveBSPNode (model_t *model, const vec3_t org, vec_t radius, unsigned char *pvsbuffer, int pvsbytes, mnode_t *node)
 
static void Mod_BSP_FinalizePortals (void)
 
static int Mod_BSP_FindBoxClusters (model_t *model, const vec3_t mins, const vec3_t maxs, int maxclusters, int *clusterlist)
 
static void Mod_BSP_FindNonSolidLocation (model_t *model, const vec3_t in, vec3_t out, float radius)
 
static void Mod_BSP_FindNonSolidLocation_r (findnonsolidlocationinfo_t *info, mnode_t *node)
 
static void Mod_BSP_FindNonSolidLocation_r_Leaf (findnonsolidlocationinfo_t *info, mleaf_t *leaf)
 
static void Mod_BSP_FindNonSolidLocation_r_Triangle (findnonsolidlocationinfo_t *info, msurface_t *surface, int k)
 
static unsigned char * Mod_BSP_GetPVS (model_t *model, const vec3_t p)
 
static void Mod_BSP_LightPoint (model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
 
static int Mod_BSP_LightPoint_RecursiveBSPNode (model_t *model, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const mnode_t *node, float x, float y, float startz, float endz)
 
static void Mod_BSP_LoadNodes_RecursiveSetParent (mnode_t *node, mnode_t *parent)
 
static void Mod_BSP_LoadSubmodels (sizebuf_t *sb, hullinfo_t *hullinfo)
 
static void Mod_BSP_MakePortals (void)
 
static mleaf_tMod_BSP_PointInLeaf (model_t *model, const vec3_t p)
 
static void Mod_BSP_RecursiveNodePortals (mnode_t *node)
 
static void Mod_BSP_RecursiveRecalcNodeBBox (mnode_t *node)
 
int Mod_CollisionBIH_PointSuperContents (struct model_s *model, int frame, const vec3_t point)
 
int Mod_CollisionBIH_PointSuperContents_Mesh (struct model_s *model, int frame, const vec3_t start)
 
void Mod_CollisionBIH_TraceBox (model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
void Mod_CollisionBIH_TraceBrush (model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, colbrushf_t *thisbrush_start, colbrushf_t *thisbrush_end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
void Mod_CollisionBIH_TraceLine (model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
void Mod_CollisionBIH_TraceLineAgainstSurfaces (model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
qbool Mod_CollisionBIH_TraceLineOfSight (struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
 
static void Mod_CollisionBIH_TraceLineShared (model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, const bih_t *bih)
 
void Mod_CollisionBIH_TracePoint (model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
void Mod_CollisionBIH_TracePoint_Mesh (model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
void Mod_HLBSP_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_IBSP_Load (model_t *mod, void *buffer, void *bufferend)
 
bih_tMod_MakeCollisionBIH (model_t *model, qbool userendersurfaces, bih_t *out)
 
void Mod_MAP_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_OBJ_Load (model_t *mod, void *buffer, void *bufferend)
 
static void Mod_Q1BSP_AmbientSoundLevelsForPoint (model_t *model, const vec3_t p, unsigned char *out, int outsize)
 
static void Mod_Q1BSP_AssignNoShadowSkySurfaces (model_t *mod)
 
static qbool Mod_Q1BSP_CheckWaterAlphaSupport (void)
 
void Mod_Q1BSP_Load (model_t *mod, void *buffer, void *bufferend)
 
static void Mod_Q1BSP_LoadClipnodes (sizebuf_t *sb, hullinfo_t *hullinfo)
 
static void Mod_Q1BSP_LoadEdges (sizebuf_t *sb)
 
static void Mod_Q1BSP_LoadEntities (sizebuf_t *sb)
 
static void Mod_Q1BSP_LoadFaces (sizebuf_t *sb)
 
static void Mod_Q1BSP_LoadLeaffaces (sizebuf_t *sb)
 
static void Mod_Q1BSP_LoadLeafs (sizebuf_t *sb)
 
static void Mod_Q1BSP_LoadLighting (sizebuf_t *sb)
 
static void Mod_Q1BSP_LoadMapBrushes (void)
 
static void Mod_Q1BSP_LoadNodes (sizebuf_t *sb)
 
static void Mod_Q1BSP_LoadPlanes (sizebuf_t *sb)
 
static void Mod_Q1BSP_LoadSplitSky (unsigned char *src, int width, int height, int bytesperpixel)
 
static void Mod_Q1BSP_LoadSurfedges (sizebuf_t *sb)
 
static void Mod_Q1BSP_LoadTexinfo (sizebuf_t *sb)
 
static void Mod_Q1BSP_LoadTextures (sizebuf_t *sb)
 
static void Mod_Q1BSP_LoadVertexes (sizebuf_t *sb)
 
static void Mod_Q1BSP_LoadVisibility (sizebuf_t *sb)
 
static void Mod_Q1BSP_MakeHull0 (void)
 
int Mod_Q1BSP_NativeContentsFromSuperContents (int supercontents)
 
static void Mod_Q1BSP_ParseWadsFromEntityLump (const char *data)
 
static int Mod_Q1BSP_PointSuperContents (struct model_s *model, int frame, const vec3_t point)
 
static int Mod_Q1BSP_RecursiveHullCheck (RecursiveHullCheckTraceInfo_t *t, int num, double p1f, double p2f, double p1[3], double p2[3])
 
static int Mod_Q1BSP_RecursiveHullCheckPoint (RecursiveHullCheckTraceInfo_t *t, int num)
 
static void Mod_Q1BSP_RoundUpToHullSize (model_t *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs)
 
int Mod_Q1BSP_SuperContentsFromNativeContents (int nativecontents)
 
static void Mod_Q1BSP_TraceBox (struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
static void Mod_Q1BSP_TraceLine (struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
static void Mod_Q1BSP_TraceLineAgainstSurfaces (struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
static const texture_tMod_Q1BSP_TraceLineAgainstSurfacesFindTextureOnNode (RecursiveHullCheckTraceInfo_t *t, const model_t *model, const mnode_t *node, double mid[3])
 
static int Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode (RecursiveHullCheckTraceInfo_t *t, const model_t *model, const mnode_t *node, const double p1[3], const double p2[3])
 
static qbool Mod_Q1BSP_TraceLineOfSight (struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
 
static void Mod_Q1BSP_TracePoint (struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
static void Mod_Q2BSP_FindSubmodelBrushRange_r (model_t *mod, mnode_t *node, int *first, int *last)
 
static void Mod_Q2BSP_Load (model_t *mod, void *buffer, void *bufferend)
 
static void Mod_Q2BSP_LoadAreaPortals (sizebuf_t *sb)
 
static void Mod_Q2BSP_LoadAreas (sizebuf_t *sb)
 
static void Mod_Q2BSP_LoadBrushes (sizebuf_t *sb)
 
static void Mod_Q2BSP_LoadBrushSides (sizebuf_t *sb)
 
static void Mod_Q2BSP_LoadLeafBrushes (sizebuf_t *sb)
 
static void Mod_Q2BSP_LoadLeafs (sizebuf_t *sb)
 
static void Mod_Q2BSP_LoadLighting (sizebuf_t *sb)
 
static void Mod_Q2BSP_LoadNodes (sizebuf_t *sb)
 
static void Mod_Q2BSP_LoadPOP (sizebuf_t *sb)
 
static void Mod_Q2BSP_LoadTexinfo (sizebuf_t *sb)
 
static void Mod_Q2BSP_LoadVisibility (sizebuf_t *sb)
 
int Mod_Q2BSP_NativeContentsFromSuperContents (int supercontents)
 
int Mod_Q2BSP_SuperContentsFromNativeContents (int nativecontents)
 
static void Mod_Q3BSP_LightPoint (model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
 
static void Mod_Q3BSP_Load (model_t *mod, void *buffer, void *bufferend)
 
static void Mod_Q3BSP_LoadBrushes (lump_t *l)
 
static void Mod_Q3BSP_LoadBrushSides (lump_t *l)
 
static void Mod_Q3BSP_LoadBrushSides_IG (lump_t *l)
 
static void Mod_Q3BSP_LoadEffects (lump_t *l)
 
static void Mod_Q3BSP_LoadEntities (lump_t *l)
 
static void Mod_Q3BSP_LoadFaces (lump_t *l)
 
static void Mod_Q3BSP_LoadLeafBrushes (lump_t *l)
 
static void Mod_Q3BSP_LoadLeafFaces (lump_t *l)
 
static void Mod_Q3BSP_LoadLeafs (lump_t *l)
 
static void Mod_Q3BSP_LoadLightGrid (lump_t *l)
 
static void Mod_Q3BSP_LoadLightmaps (lump_t *l, lump_t *faceslump)
 
static void Mod_Q3BSP_LoadModels (lump_t *l)
 
static void Mod_Q3BSP_LoadNodes (lump_t *l)
 
static void Mod_Q3BSP_LoadPlanes (lump_t *l)
 
static void Mod_Q3BSP_LoadPVS (lump_t *l)
 
static void Mod_Q3BSP_LoadTextures (lump_t *l)
 
static void Mod_Q3BSP_LoadTriangles (lump_t *l)
 
static void Mod_Q3BSP_LoadVertices (lump_t *l)
 
static int Mod_Q3BSP_NativeContentsFromSuperContents (int supercontents)
 
static void Mod_Q3BSP_RecursiveFindNumLeafs (mnode_t *node)
 
static int Mod_Q3BSP_SuperContentsFromNativeContents (int nativecontents)
 
static qbool Mod_Q3BSP_TraceLineOfSight (struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
 
static int Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck (mnode_t *node, double p1[3], double p2[3], double endpos[3])
 
void Mod_VBSP_Load (model_t *mod, void *buffer, void *bufferend)
 
static void Mod_VBSP_LoadEdges (sizebuf_t *sb)
 
static void Mod_VBSP_LoadEntities (sizebuf_t *sb)
 
static void Mod_VBSP_LoadFaces (sizebuf_t *sb)
 
static void Mod_VBSP_LoadPlanes (sizebuf_t *sb)
 
static void Mod_VBSP_LoadSurfedges (sizebuf_t *sb)
 
static void Mod_VBSP_LoadTexinfo (sizebuf_t *sb)
 
static void Mod_VBSP_LoadTextures (sizebuf_t *sb)
 
static void Mod_VBSP_LoadVertexes (sizebuf_t *sb)
 
static void RemovePortalFromNodes (portal_t *portal)
 

Variables

cvar_t gl_max_lightmapsize
 
cvar_t mod_bsp_portalize = {CF_CLIENT, "mod_bsp_portalize", "0", "enables portal generation from BSP tree (takes a minute or more and GBs of memory when loading a complex map), used by r_drawportals, r_useportalculling, r_shadow_realtime_dlight_portalculling, r_shadow_realtime_world_compileportalculling"}
 
cvar_t mod_noshader_default_offsetmapping = {CF_CLIENT | CF_ARCHIVE, "mod_noshader_default_offsetmapping", "1", "use offsetmapping by default on all surfaces that are not using q3 shader files"}
 
cvar_t mod_obj_orientation = {CF_CLIENT | CF_SERVER, "mod_obj_orientation", "1", "fix orientation of OBJ models to the usual conventions (if zero, use coordinates as is)"}
 
cvar_t mod_q1bsp_polygoncollisions = {CF_CLIENT | CF_SERVER, "mod_q1bsp_polygoncollisions", "0", "disables use of precomputed cliphulls and instead collides with polygons (uses Bounding Interval Hierarchy optimizations)"}
 
static texture_t mod_q1bsp_texture_lava
 
static texture_t mod_q1bsp_texture_sky
 
static texture_t mod_q1bsp_texture_slime
 
static texture_t mod_q1bsp_texture_solid
 
static texture_t mod_q1bsp_texture_water
 
cvar_t mod_q1bsp_traceoutofsolid = {CF_SHARED, "mod_q1bsp_traceoutofsolid", "1", "enables tracebox to move an entity that's stuck in solid brushwork out to empty space, 1 matches FTEQW and QSS and is required by many community maps (items/monsters will be missing otherwise), 0 matches old versions of DP and the original Quake engine (if your map or QC needs 0 it's buggy)"}
 
cvar_t mod_q1bsp_zero_hullsize_cutoff = {CF_CLIENT | CF_SERVER, "mod_q1bsp_zero_hullsize_cutoff", "3", "bboxes with an X dimension smaller than this will use the smallest cliphull (0x0x0) instead of being rounded up to the player cliphull (32x32x56) in Q1BSP, or crouching player (32x32x36) in HLBSP"}
 
cvar_t mod_q2bsp_littransparentsurfaces = {CF_CLIENT, "mod_q2bsp_littransparentsurfaces", "0", "allows lighting on rain in 3v3gloom3 and other cases of transparent surfaces that have lightmaps that were ignored by quake2"}
 
cvar_t mod_q3bsp_curves_collisions = {CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_collisions", "1", "enables collisions with curves (SLOW)"}
 
cvar_t mod_q3bsp_curves_subdivisions_maxtess = {CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_subdivisions_maxtess", "1024", "maximum number of subdivisions for collision purposes (prevents curves beyond a certain detail level, limits smoothing)"}
 
cvar_t mod_q3bsp_curves_subdivisions_maxvertices = {CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_subdivisions_maxvertices", "4225", "maximum vertices allowed per subdivided curve for collision purposes"}
 
cvar_t mod_q3bsp_curves_subdivisions_mintess = {CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_subdivisions_mintess", "0", "minimum number of subdivisions for collision purposes (values above 0 will smooth curves that don't need it)"}
 
cvar_t mod_q3bsp_curves_subdivisions_tolerance = {CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_subdivisions_tolerance", "15", "maximum error tolerance on curve subdivision for collision purposes (usually a larger error tolerance than for rendering)"}
 
cvar_t mod_q3bsp_lightgrid_bsp_surfaces = {CF_CLIENT, "mod_q3bsp_lightgrid_bsp_surfaces", "0", "apply lightgrid lighting to bsp models other than the world rather than using their lightmaps (experimental/debug tool)"}
 
cvar_t mod_q3bsp_lightgrid_texture = {CF_CLIENT, "mod_q3bsp_lightgrid_texture", "1", "directly apply the lightgrid as a global texture rather than only reading it at the entity origin"}
 
cvar_t mod_q3bsp_lightgrid_world_surfaces = {CF_CLIENT, "mod_q3bsp_lightgrid_world_surfaces", "0", "apply lightgrid lighting to the world bsp geometry rather than using lightmaps (experimental/debug tool)"}
 
cvar_t mod_q3bsp_lightmapmergepower = {CF_CLIENT | CF_ARCHIVE, "mod_q3bsp_lightmapmergepower", "4", "merges the quake3 128x128 lightmap textures into larger lightmap group textures to speed up rendering, 1 = 256x256, 2 = 512x512, 3 = 1024x1024, 4 = 2048x2048, 5 = 4096x4096, ..."}
 
cvar_t mod_q3bsp_nolightmaps = {CF_CLIENT | CF_ARCHIVE, "mod_q3bsp_nolightmaps", "0", "do not load lightmaps in Q3BSP maps (to save video RAM, but be warned: it looks ugly)"}
 
cvar_t mod_q3bsp_optimizedtraceline = {CF_CLIENT | CF_SERVER, "mod_q3bsp_optimizedtraceline", "1", "whether to use optimized traceline code for line traces (as opposed to tracebox code)"}
 
cvar_t mod_q3bsp_sRGBlightmaps = {CF_CLIENT, "mod_q3bsp_sRGBlightmaps", "0", "treat lightmaps from Q3 maps as sRGB when vid_sRGB is active"}
 
cvar_t mod_q3bsp_tracelineofsight_brushes = {CF_CLIENT | CF_SERVER, "mod_q3bsp_tracelineofsight_brushes", "0", "enables culling of entities behind detail brushes, curves, etc"}
 
cvar_t mod_q3shader_default_offsetmapping = {CF_CLIENT | CF_ARCHIVE, "mod_q3shader_default_offsetmapping", "1", "use offsetmapping by default on all surfaces that are using q3 shader files"}
 
cvar_t mod_q3shader_default_offsetmapping_bias = {CF_CLIENT | CF_ARCHIVE, "mod_q3shader_default_offsetmapping_bias", "0", "default bias used for offsetmapping"}
 
cvar_t mod_q3shader_default_offsetmapping_scale = {CF_CLIENT | CF_ARCHIVE, "mod_q3shader_default_offsetmapping_scale", "1", "default scale used for offsetmapping"}
 
cvar_t mod_q3shader_default_polygonfactor = {CF_CLIENT, "mod_q3shader_default_polygonfactor", "0", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"}
 
cvar_t mod_q3shader_default_polygonoffset = {CF_CLIENT, "mod_q3shader_default_polygonoffset", "-2", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"}
 
cvar_t mod_q3shader_default_refractive_index = {CF_CLIENT, "mod_q3shader_default_refractive_index", "1.33", "angle of refraction specified as n to apply when a photon is refracted, example values are: 1.0003 = air, water = 1.333, crown glass = 1.517, flint glass = 1.655, diamond = 2.417"}
 
cvar_t mod_q3shader_force_addalpha = {CF_CLIENT, "mod_q3shader_force_addalpha", "0", "treat GL_ONE GL_ONE (or add) blendfunc as GL_SRC_ALPHA GL_ONE for compatibility with older DarkPlaces releases"}
 
cvar_t mod_q3shader_force_terrain_alphaflag = {CF_CLIENT, "mod_q3shader_force_terrain_alphaflag", "0", "for multilayered terrain shaders force TEXF_ALPHA flag on both layers"}
 
cvar_t mod_recalculatenodeboxes = {CF_CLIENT | CF_SERVER, "mod_recalculatenodeboxes", "1", "enables use of generated node bounding boxes based on BSP tree portal reconstruction, rather than the node boxes supplied by the map compiler"}
 
static unsigned char nobsp_pvs [1] = {1}
 
static memexpandablearray_t portalarray
 
static double * portalpointsbuffer
 
static int portalpointsbufferoffset
 
static int portalpointsbuffersize
 
cvar_t r_nosurftextures = {CF_CLIENT, "r_nosurftextures", "0", "pretends there was no texture lump found in the q1bsp/hlbsp loading (useful for debugging this rare case)"}
 
cvar_t r_novis = {CF_CLIENT, "r_novis", "0", "draws whole level, see also sv_cullentities_pvs 0"}
 
cvar_t r_subdivisions_maxtess = {CF_CLIENT, "r_subdivisions_maxtess", "1024", "maximum number of subdivisions (prevents curves beyond a certain detail level, limits smoothing)"}
 
cvar_t r_subdivisions_maxvertices = {CF_CLIENT, "r_subdivisions_maxvertices", "65536", "maximum vertices allowed per subdivided curve"}
 
cvar_t r_subdivisions_mintess = {CF_CLIENT, "r_subdivisions_mintess", "0", "minimum number of subdivisions (values above 0 will smooth curves that don't need it)"}
 
cvar_t r_subdivisions_tolerance = {CF_CLIENT, "r_subdivisions_tolerance", "4", "maximum error tolerance on curve subdivision for rendering purposes (in other words, the curves will be given as many polygons as necessary to represent curves at this quality)"}
 
cvar_t r_trippy = {CF_CLIENT, "r_trippy", "0", "easter egg"}
 

Macro Definition Documentation

◆ DIST_EPSILON

#define DIST_EPSILON   (0.03125)

Definition at line 681 of file model_brush.c.

◆ HULLCHECKSTATE_DONE

#define HULLCHECKSTATE_DONE   2

◆ HULLCHECKSTATE_EMPTY

#define HULLCHECKSTATE_EMPTY   0

◆ HULLCHECKSTATE_SOLID

#define HULLCHECKSTATE_SOLID   1

◆ MAX_PORTALPOINTS

#define MAX_PORTALPOINTS   64

Definition at line 3380 of file model_brush.c.

Referenced by Mod_BSP_MakePortals(), and Mod_BSP_RecursiveNodePortals().

◆ PATCHTESS_SAME_LODGROUP

#define PATCHTESS_SAME_LODGROUP ( a,
b )
Value:
( \
(a).lodgroup[0] == (b).lodgroup[0] && \
(a).lodgroup[1] == (b).lodgroup[1] && \
(a).lodgroup[2] == (b).lodgroup[2] && \
(a).lodgroup[3] == (b).lodgroup[3] && \
(a).lodgroup[4] == (b).lodgroup[4] && \
(a).lodgroup[5] == (b).lodgroup[5] \
)
dp_FragColor b
ret a

Definition at line 5796 of file model_brush.c.

5796#define PATCHTESS_SAME_LODGROUP(a,b) \
5797 ( \
5798 (a).lodgroup[0] == (b).lodgroup[0] && \
5799 (a).lodgroup[1] == (b).lodgroup[1] && \
5800 (a).lodgroup[2] == (b).lodgroup[2] && \
5801 (a).lodgroup[3] == (b).lodgroup[3] && \
5802 (a).lodgroup[4] == (b).lodgroup[4] && \
5803 (a).lodgroup[5] == (b).lodgroup[5] \
5804 )

Referenced by Mod_Q3BSP_LoadFaces().

◆ PORTAL_DIST_EPSILON

#define PORTAL_DIST_EPSILON   (1.0 / 32.0)

Definition at line 3613 of file model_brush.c.

Referenced by Mod_BSP_RecursiveNodePortals().

Function Documentation

◆ AddPortalToNodes()

static void AddPortalToNodes ( portal_t * p,
mnode_t * front,
mnode_t * back )
static

Definition at line 3545 of file model_brush.c.

3546{
3547 if (!front)
3548 Host_Error("AddPortalToNodes: NULL front node");
3549 if (!back)
3550 Host_Error("AddPortalToNodes: NULL back node");
3551 if (p->nodes[0] || p->nodes[1])
3552 Host_Error("AddPortalToNodes: already included");
3553 // note: front == back is handled gracefully, because leaf 0 is the shared solid leaf, it can often have portals with the same leaf on both sides
3554
3555 p->nodes[0] = front;
3556 p->next[0] = (portal_t *)front->portals;
3557 front->portals = (mportal_t *)p;
3558
3559 p->nodes[1] = back;
3560 p->next[1] = (portal_t *)back->portals;
3561 back->portals = (mportal_t *)p;
3562}
void Host_Error(const char *error,...)
Definition host.c:85
struct mportal_s * portals
mnode_t * nodes[2]
struct portal_s * next[2]

References Host_Error(), portal_t::next, portal_t::nodes, and mnode_t::portals.

Referenced by Mod_BSP_RecursiveNodePortals().

◆ Collision_ClipTrace_Box()

void Collision_ClipTrace_Box ( trace_t * trace,
const vec3_t cmins,
const vec3_t cmaxs,
const vec3_t start,
const vec3_t mins,
const vec3_t maxs,
const vec3_t end,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask,
int boxsupercontents,
int boxq3surfaceflags,
const texture_t * boxtexture )

Definition at line 1053 of file model_brush.c.

1054{
1055#if 1
1056 colbrushf_t cbox;
1057 colplanef_t cbox_planes[6];
1058 cbox.isaabb = true;
1059 cbox.hasaabbplanes = true;
1060 cbox.supercontents = boxsupercontents;
1061 cbox.numplanes = 6;
1062 cbox.numpoints = 0;
1063 cbox.numtriangles = 0;
1064 cbox.planes = cbox_planes;
1065 cbox.points = NULL;
1066 cbox.elements = NULL;
1067 cbox.markframe = 0;
1068 cbox.mins[0] = 0;
1069 cbox.mins[1] = 0;
1070 cbox.mins[2] = 0;
1071 cbox.maxs[0] = 0;
1072 cbox.maxs[1] = 0;
1073 cbox.maxs[2] = 0;
1074 cbox_planes[0].normal[0] = 1;cbox_planes[0].normal[1] = 0;cbox_planes[0].normal[2] = 0;cbox_planes[0].dist = cmaxs[0] - mins[0];
1075 cbox_planes[1].normal[0] = -1;cbox_planes[1].normal[1] = 0;cbox_planes[1].normal[2] = 0;cbox_planes[1].dist = maxs[0] - cmins[0];
1076 cbox_planes[2].normal[0] = 0;cbox_planes[2].normal[1] = 1;cbox_planes[2].normal[2] = 0;cbox_planes[2].dist = cmaxs[1] - mins[1];
1077 cbox_planes[3].normal[0] = 0;cbox_planes[3].normal[1] = -1;cbox_planes[3].normal[2] = 0;cbox_planes[3].dist = maxs[1] - cmins[1];
1078 cbox_planes[4].normal[0] = 0;cbox_planes[4].normal[1] = 0;cbox_planes[4].normal[2] = 1;cbox_planes[4].dist = cmaxs[2] - mins[2];
1079 cbox_planes[5].normal[0] = 0;cbox_planes[5].normal[1] = 0;cbox_planes[5].normal[2] = -1;cbox_planes[5].dist = maxs[2] - cmins[2];
1080 cbox_planes[0].q3surfaceflags = boxq3surfaceflags;cbox_planes[0].texture = boxtexture;
1081 cbox_planes[1].q3surfaceflags = boxq3surfaceflags;cbox_planes[1].texture = boxtexture;
1082 cbox_planes[2].q3surfaceflags = boxq3surfaceflags;cbox_planes[2].texture = boxtexture;
1083 cbox_planes[3].q3surfaceflags = boxq3surfaceflags;cbox_planes[3].texture = boxtexture;
1084 cbox_planes[4].q3surfaceflags = boxq3surfaceflags;cbox_planes[4].texture = boxtexture;
1085 cbox_planes[5].q3surfaceflags = boxq3surfaceflags;cbox_planes[5].texture = boxtexture;
1086 memset(trace, 0, sizeof(trace_t));
1087 trace->hitsupercontentsmask = hitsupercontentsmask;
1088 trace->skipsupercontentsmask = skipsupercontentsmask;
1089 trace->skipmaterialflagsmask = skipmaterialflagsmask;
1090 trace->fraction = 1;
1091 Collision_TraceLineBrushFloat(trace, start, end, &cbox, &cbox);
1092#else
1094 static hull_t box_hull;
1095 static mclipnode_t box_clipnodes[6];
1096 static mplane_t box_planes[6];
1097 // fill in a default trace
1098 memset(&rhc, 0, sizeof(rhc));
1099 memset(trace, 0, sizeof(trace_t));
1100 //To keep everything totally uniform, bounding boxes are turned into small
1101 //BSP trees instead of being compared directly.
1102 // create a temp hull from bounding box sizes
1103 box_planes[0].dist = cmaxs[0] - mins[0];
1104 box_planes[1].dist = cmins[0] - maxs[0];
1105 box_planes[2].dist = cmaxs[1] - mins[1];
1106 box_planes[3].dist = cmins[1] - maxs[1];
1107 box_planes[4].dist = cmaxs[2] - mins[2];
1108 box_planes[5].dist = cmins[2] - maxs[2];
1109#if COLLISIONPARANOID >= 3
1110 Con_Printf("box_planes %f:%f %f:%f %f:%f\ncbox %f %f %f:%f %f %f\nbox %f %f %f:%f %f %f\n", box_planes[0].dist, box_planes[1].dist, box_planes[2].dist, box_planes[3].dist, box_planes[4].dist, box_planes[5].dist, cmins[0], cmins[1], cmins[2], cmaxs[0], cmaxs[1], cmaxs[2], mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2]);
1111#endif
1112
1113 if (box_hull.clipnodes == NULL)
1114 {
1115 int i, side;
1116
1117 //Set up the planes and clipnodes so that the six floats of a bounding box
1118 //can just be stored out and get a proper hull_t structure.
1119
1120 box_hull.clipnodes = box_clipnodes;
1121 box_hull.planes = box_planes;
1122 box_hull.firstclipnode = 0;
1123 box_hull.lastclipnode = 5;
1124
1125 for (i = 0;i < 6;i++)
1126 {
1127 box_clipnodes[i].planenum = i;
1128
1129 side = i&1;
1130
1131 box_clipnodes[i].children[side] = CONTENTS_EMPTY;
1132 if (i != 5)
1133 box_clipnodes[i].children[side^1] = i + 1;
1134 else
1135 box_clipnodes[i].children[side^1] = CONTENTS_SOLID;
1136
1137 box_planes[i].type = i>>1;
1138 box_planes[i].normal[i>>1] = 1;
1139 }
1140 }
1141
1142 // trace a line through the generated clipping hull
1143 //rhc.boxsupercontents = boxsupercontents;
1144 rhc.hull = &box_hull;
1145 rhc.trace = trace;
1146 rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
1147 rhc.trace->skipsupercontentsmask = skipsupercontentsmask;
1148 rhc.trace->skipmaterialflagsmask = skipmaterialflagsmask;
1149 rhc.trace->fraction = 1;
1150 rhc.trace->allsolid = true;
1151 VectorCopy(start, rhc.start);
1152 VectorCopy(end, rhc.end);
1153 VectorSubtract(rhc.end, rhc.start, rhc.dist);
1154 Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
1155 //VectorMA(rhc.start, rhc.trace->fraction, rhc.dist, rhc.trace->endpos);
1156 if (rhc.trace->startsupercontents)
1157 rhc.trace->startsupercontents = boxsupercontents;
1158#endif
1159}
#define CONTENTS_SOLID
Definition bspfile.h:134
#define CONTENTS_EMPTY
Definition bspfile.h:133
void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const vec3_t lineend, const colbrushf_t *other_start, const colbrushf_t *other_end)
Definition collision.c:760
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
vector mins
vector maxs
#define VectorSubtract(a, b, out)
Definition mathlib.h:99
#define VectorCopy(in, out)
Definition mathlib.h:101
static int Mod_Q1BSP_RecursiveHullCheck(RecursiveHullCheckTraceInfo_t *t, int num, double p1f, double p2f, double p1[3], double p2[3])
int i
#define NULL
Definition qtypes.h:12
int hasaabbplanes
Definition collision.h:130
vec3_t mins
Definition collision.h:107
int numtriangles
Definition collision.h:123
int * elements
Definition collision.h:124
colpointf_t * points
Definition collision.h:121
colplanef_t * planes
Definition collision.h:115
int supercontents
Definition collision.h:112
vec3_t maxs
Definition collision.h:108
vec3_t normal
Definition collision.h:96
int q3surfaceflags
Definition collision.h:91
vec_t dist
Definition collision.h:97
const struct texture_s * texture
Definition collision.h:90
mclipnode_t * clipnodes
int firstclipnode
int lastclipnode
mplane_t * planes
int children[2]
vec3_t normal
Definition model_brush.h:59
vec_t dist
Definition model_brush.h:60
int hitsupercontentsmask
Definition collision.h:50
double fraction
Definition collision.h:40
int startsupercontents
Definition collision.h:56
qbool allsolid
Definition collision.h:24
int skipsupercontentsmask
Definition collision.h:52
int skipmaterialflagsmask
Definition collision.h:54

References trace_t::allsolid, mclipnode_t::children, hull_t::clipnodes, Collision_TraceLineBrushFloat(), Con_Printf(), CONTENTS_EMPTY, CONTENTS_SOLID, colplanef_t::dist, mplane_t::dist, RecursiveHullCheckTraceInfo_t::dist, colbrushf_t::elements, RecursiveHullCheckTraceInfo_t::end, hull_t::firstclipnode, trace_t::fraction, colbrushf_t::hasaabbplanes, trace_t::hitsupercontentsmask, RecursiveHullCheckTraceInfo_t::hull, i, colbrushf_t::isaabb, hull_t::lastclipnode, colbrushf_t::markframe, colbrushf_t::maxs, maxs, colbrushf_t::mins, mins, Mod_Q1BSP_RecursiveHullCheck(), colplanef_t::normal, mplane_t::normal, NULL, colbrushf_t::numplanes, colbrushf_t::numpoints, colbrushf_t::numtriangles, mclipnode_t::planenum, colbrushf_t::planes, hull_t::planes, colbrushf_t::points, colplanef_t::q3surfaceflags, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, RecursiveHullCheckTraceInfo_t::start, trace_t::startsupercontents, colbrushf_t::supercontents, colplanef_t::texture, RecursiveHullCheckTraceInfo_t::trace, mplane_t::type, VectorCopy, and VectorSubtract.

Referenced by CL_SelectTraceLine(), Collision_ClipLineToGenericEntity(), and Collision_ClipToGenericEntity().

◆ Collision_ClipTrace_Point()

void Collision_ClipTrace_Point ( trace_t * trace,
const vec3_t cmins,
const vec3_t cmaxs,
const vec3_t start,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask,
int boxsupercontents,
int boxq3surfaceflags,
const texture_t * boxtexture )

Definition at line 1161 of file model_brush.c.

1162{
1163 memset(trace, 0, sizeof(trace_t));
1164 trace->fraction = 1;
1165 trace->hitsupercontentsmask = hitsupercontentsmask;
1166 trace->skipsupercontentsmask = skipsupercontentsmask;
1167 trace->skipmaterialflagsmask = skipmaterialflagsmask;
1168 if (BoxesOverlap(start, start, cmins, cmaxs))
1169 {
1170 trace->startsupercontents |= boxsupercontents;
1171 if ((hitsupercontentsmask & boxsupercontents) && !(skipsupercontentsmask & boxsupercontents))
1172 {
1173 trace->startsolid = true;
1174 trace->allsolid = true;
1175 }
1176 }
1177}
#define BoxesOverlap(a, b, c, d)
Definition mathlib.h:122
qbool startsolid
Definition collision.h:26

References trace_t::allsolid, BoxesOverlap, trace_t::fraction, trace_t::hitsupercontentsmask, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, trace_t::startsolid, and trace_t::startsupercontents.

Referenced by Collision_ClipPointToGenericEntity().

◆ Mod_2PSB_Load()

void Mod_2PSB_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 3881 of file model_brush.c.

3882{
3883 mod->brush.isbsp2 = true;
3884 mod->brush.isbsp2rmqe = true; // like bsp2 except leaf/node bounds are 16bit (unexpanded)
3885 mod->modeldatatypestring = "Q1BSP2rmqe";
3886 Mod_Q1BSP_Load(mod, buffer, bufferend);
3887}
float mod(float dividend, float divisor)
GLuint buffer
Definition glquake.h:630
void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend)

References buffer, mod(), and Mod_Q1BSP_Load().

◆ Mod_BrushInit()

void Mod_BrushInit ( void )

Definition at line 80 of file model_brush.c.

81{
82// Cvar_RegisterVariable(&r_subdivide_size);
119
120 // these games were made for older DP engines and are no longer
121 // maintained; use this hack to show their textures properly
122 if(gamemode == GAME_NEXUIZ)
124
129
134
139
144
149}
#define SUPERCONTENTS_SKY
Definition bspfile.h:200
#define SUPERCONTENTS_LAVA
Definition bspfile.h:199
#define SUPERCONTENTS_SLIME
Definition bspfile.h:198
#define SUPERCONTENTS_SOLID
Definition bspfile.h:196
#define SUPERCONTENTS_NODROP
Definition bspfile.h:203
#define SUPERCONTENTS_WATER
Definition bspfile.h:197
gamemode_t gamemode
Definition com_game.c:26
@ GAME_NEXUIZ
Definition com_game.h:33
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
void Cvar_SetQuick(cvar_t *var, const char *value)
Definition cvar.c:436
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
Definition cvar.c:599
cvar_t mod_q3bsp_curves_subdivisions_maxtess
Definition model_brush.c:40
static texture_t mod_q1bsp_texture_sky
Definition model_brush.c:73
cvar_t mod_q3bsp_curves_subdivisions_maxvertices
Definition model_brush.c:41
cvar_t mod_q3shader_force_addalpha
Definition model_brush.c:58
cvar_t mod_bsp_portalize
Definition model_brush.c:67
static texture_t mod_q1bsp_texture_solid
Definition model_brush.c:72
cvar_t mod_q2bsp_littransparentsurfaces
Definition model_brush.c:61
cvar_t mod_q3bsp_lightgrid_world_surfaces
Definition model_brush.c:49
cvar_t mod_q3shader_default_polygonfactor
Definition model_brush.c:55
cvar_t mod_q3bsp_lightmapmergepower
Definition model_brush.c:44
cvar_t mod_noshader_default_offsetmapping
Definition model_brush.c:51
cvar_t mod_q3bsp_curves_subdivisions_mintess
Definition model_brush.c:39
cvar_t mod_q3bsp_nolightmaps
Definition model_brush.c:45
static texture_t mod_q1bsp_texture_lava
Definition model_brush.c:74
cvar_t mod_q3bsp_lightgrid_texture
Definition model_brush.c:48
cvar_t mod_q3bsp_curves_subdivisions_tolerance
Definition model_brush.c:38
cvar_t mod_q3shader_default_offsetmapping_scale
Definition model_brush.c:53
cvar_t mod_recalculatenodeboxes
Definition model_brush.c:68
cvar_t mod_q3bsp_sRGBlightmaps
Definition model_brush.c:47
cvar_t mod_q3bsp_tracelineofsight_brushes
Definition model_brush.c:46
static texture_t mod_q1bsp_texture_slime
Definition model_brush.c:75
cvar_t mod_q3shader_default_polygonoffset
Definition model_brush.c:56
cvar_t mod_q3shader_default_offsetmapping_bias
Definition model_brush.c:54
cvar_t mod_q3bsp_lightgrid_bsp_surfaces
Definition model_brush.c:50
cvar_t mod_q3shader_default_offsetmapping
Definition model_brush.c:52
cvar_t r_nosurftextures
Definition model_brush.c:32
cvar_t mod_q3bsp_curves_collisions
Definition model_brush.c:42
cvar_t r_novis
Definition model_brush.c:31
cvar_t mod_q1bsp_zero_hullsize_cutoff
Definition model_brush.c:65
cvar_t mod_q3bsp_optimizedtraceline
Definition model_brush.c:43
cvar_t r_trippy
Definition model_brush.c:29
cvar_t r_subdivisions_mintess
Definition model_brush.c:35
cvar_t mod_q1bsp_polygoncollisions
Definition model_brush.c:63
static texture_t mod_q1bsp_texture_water
Definition model_brush.c:76
cvar_t r_subdivisions_tolerance
Definition model_brush.c:34
cvar_t mod_q1bsp_traceoutofsolid
Definition model_brush.c:64
cvar_t mod_q3shader_force_terrain_alphaflag
Definition model_brush.c:59
cvar_t r_subdivisions_maxvertices
Definition model_brush.c:37
cvar_t r_subdivisions_maxtess
Definition model_brush.c:36
cvar_t mod_obj_orientation
Definition model_brush.c:70
cvar_t mod_q3shader_default_refractive_index
Definition model_brush.c:57
#define Q3SURFACEFLAG_SKY
#define Q3SURFACEFLAG_NOMARKS
#define Q3SURFACEFLAG_NOIMPACT
#define Q3SURFACEFLAG_NOLIGHTMAP
#define Q3SURFACEFLAG_NODLIGHT
char name[64]
int supercontents

References Cvar_RegisterVariable(), Cvar_SetQuick(), dp_strlcpy, GAME_NEXUIZ, gamemode, mod_bsp_portalize, mod_noshader_default_offsetmapping, mod_obj_orientation, mod_q1bsp_polygoncollisions, mod_q1bsp_texture_lava, mod_q1bsp_texture_sky, mod_q1bsp_texture_slime, mod_q1bsp_texture_solid, mod_q1bsp_texture_water, mod_q1bsp_traceoutofsolid, mod_q1bsp_zero_hullsize_cutoff, mod_q2bsp_littransparentsurfaces, mod_q3bsp_curves_collisions, mod_q3bsp_curves_subdivisions_maxtess, mod_q3bsp_curves_subdivisions_maxvertices, mod_q3bsp_curves_subdivisions_mintess, mod_q3bsp_curves_subdivisions_tolerance, mod_q3bsp_lightgrid_bsp_surfaces, mod_q3bsp_lightgrid_texture, mod_q3bsp_lightgrid_world_surfaces, mod_q3bsp_lightmapmergepower, mod_q3bsp_nolightmaps, mod_q3bsp_optimizedtraceline, mod_q3bsp_sRGBlightmaps, mod_q3bsp_tracelineofsight_brushes, mod_q3shader_default_offsetmapping, mod_q3shader_default_offsetmapping_bias, mod_q3shader_default_offsetmapping_scale, mod_q3shader_default_polygonfactor, mod_q3shader_default_polygonoffset, mod_q3shader_default_refractive_index, mod_q3shader_force_addalpha, mod_q3shader_force_terrain_alphaflag, mod_recalculatenodeboxes, texture_t::name, Q3SURFACEFLAG_NODLIGHT, Q3SURFACEFLAG_NOIMPACT, Q3SURFACEFLAG_NOLIGHTMAP, Q3SURFACEFLAG_NOMARKS, Q3SURFACEFLAG_SKY, r_nosurftextures, r_novis, r_subdivisions_maxtess, r_subdivisions_maxvertices, r_subdivisions_mintess, r_subdivisions_tolerance, r_trippy, texture_t::supercontents, SUPERCONTENTS_LAVA, SUPERCONTENTS_NODROP, SUPERCONTENTS_SKY, SUPERCONTENTS_SLIME, SUPERCONTENTS_SOLID, SUPERCONTENTS_WATER, and texture_t::surfaceflags.

Referenced by Mod_Init().

◆ Mod_BSP2_Load()

void Mod_BSP2_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 3889 of file model_brush.c.

3890{
3891 mod->brush.isbsp2 = true;
3892 mod->modeldatatypestring = "Q1BSP2";
3893 Mod_Q1BSP_Load(mod, buffer, bufferend);
3894}

References buffer, mod(), and Mod_Q1BSP_Load().

◆ Mod_BSP_BoxTouchingLeafPVS()

static int Mod_BSP_BoxTouchingLeafPVS ( model_t * model,
const unsigned char * pvs,
const vec3_t mins,
const vec3_t maxs )
static

Definition at line 323 of file model_brush.c.

324{
325 int nodestackindex = 0;
326 mnode_t *node, *nodestack[1024];
327 if (!model->brush.num_leafs)
328 return true;
329 node = model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode;
330 for (;;)
331 {
332#if 1
333 if (node->plane)
334 {
335 // node - recurse down the BSP tree
336 int sides = BoxOnPlaneSide(mins, maxs, node->plane);
337 if (sides < 3)
338 {
339 if (sides == 0)
340 return -1; // ERROR: NAN bounding box!
341 // box is on one side of plane, take that path
342 node = node->children[sides-1];
343 }
344 else
345 {
346 // box crosses plane, take one path and remember the other
347 if (nodestackindex < 1024)
348 nodestack[nodestackindex++] = node->children[0];
349 node = node->children[1];
350 }
351 continue;
352 }
353 else
354 {
355 // leaf - check cluster bit
356 int clusterindex = ((mleaf_t *)node) - model->brush.data_leafs;
357 if (CHECKPVSBIT(pvs, clusterindex))
358 {
359 // it is visible, return immediately with the news
360 return true;
361 }
362 }
363#else
364 if (BoxesOverlap(mins, maxs, node->mins, node->maxs))
365 {
366 if (node->plane)
367 {
368 if (nodestackindex < 1024)
369 nodestack[nodestackindex++] = node->children[0];
370 node = node->children[1];
371 continue;
372 }
373 else
374 {
375 // leaf - check cluster bit
376 int clusterindex = ((mleaf_t *)node) - model->brush.data_leafs;
377 if (CHECKPVSBIT(pvs, clusterindex))
378 {
379 // it is visible, return immediately with the news
380 return true;
381 }
382 }
383 }
384#endif
385 // nothing to see here, try another path we didn't take earlier
386 if (nodestackindex == 0)
387 break;
388 node = nodestack[--nodestackindex];
389 }
390 // it is not visible
391 return false;
392}
string model
int BoxOnPlaneSide(const vec3_t emins, const vec3_t emaxs, const mplane_t *p)
Definition mathlib.c:331
#define CHECKPVSBIT(pvs, b)
vec3_t maxs
vec3_t mins
struct mnode_s * children[2]
mplane_t * plane

References BoxesOverlap, BoxOnPlaneSide(), CHECKPVSBIT, mnode_t::children, maxs, mnode_t::maxs, mins, mnode_t::mins, model, and mnode_t::plane.

Referenced by Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_BSP_BoxTouchingPVS()

static int Mod_BSP_BoxTouchingPVS ( model_t * model,
const unsigned char * pvs,
const vec3_t mins,
const vec3_t maxs )
static

Definition at line 252 of file model_brush.c.

253{
254 int nodestackindex = 0;
255 mnode_t *node, *nodestack[1024];
256 if (!model->brush.num_pvsclusters)
257 return true;
258 node = model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode;
259 for (;;)
260 {
261#if 1
262 if (node->plane)
263 {
264 // node - recurse down the BSP tree
265 int sides = BoxOnPlaneSide(mins, maxs, node->plane);
266 if (sides < 3)
267 {
268 if (sides == 0)
269 return -1; // ERROR: NAN bounding box!
270 // box is on one side of plane, take that path
271 node = node->children[sides-1];
272 }
273 else
274 {
275 // box crosses plane, take one path and remember the other
276 if (nodestackindex < 1024)
277 nodestack[nodestackindex++] = node->children[0];
278 node = node->children[1];
279 }
280 continue;
281 }
282 else
283 {
284 // leaf - check cluster bit
285 int clusterindex = ((mleaf_t *)node)->clusterindex;
286 if (CHECKPVSBIT(pvs, clusterindex))
287 {
288 // it is visible, return immediately with the news
289 return true;
290 }
291 }
292#else
293 if (BoxesOverlap(mins, maxs, node->mins, node->maxs))
294 {
295 if (node->plane)
296 {
297 if (nodestackindex < 1024)
298 nodestack[nodestackindex++] = node->children[0];
299 node = node->children[1];
300 continue;
301 }
302 else
303 {
304 // leaf - check cluster bit
305 int clusterindex = ((mleaf_t *)node)->clusterindex;
306 if (CHECKPVSBIT(pvs, clusterindex))
307 {
308 // it is visible, return immediately with the news
309 return true;
310 }
311 }
312 }
313#endif
314 // nothing to see here, try another path we didn't take earlier
315 if (nodestackindex == 0)
316 break;
317 node = nodestack[--nodestackindex];
318 }
319 // it is not visible
320 return false;
321}

References BoxesOverlap, BoxOnPlaneSide(), CHECKPVSBIT, mnode_t::children, maxs, mnode_t::maxs, mins, mnode_t::mins, model, and mnode_t::plane.

Referenced by Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_BSP_BoxTouchingVisibleLeafs()

static int Mod_BSP_BoxTouchingVisibleLeafs ( model_t * model,
const unsigned char * visibleleafs,
const vec3_t mins,
const vec3_t maxs )
static

Definition at line 394 of file model_brush.c.

395{
396 int nodestackindex = 0;
397 mnode_t *node, *nodestack[1024];
398 if (!model->brush.num_leafs)
399 return true;
400 node = model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode;
401 for (;;)
402 {
403#if 1
404 if (node->plane)
405 {
406 // node - recurse down the BSP tree
407 int sides = BoxOnPlaneSide(mins, maxs, node->plane);
408 if (sides < 3)
409 {
410 if (sides == 0)
411 return -1; // ERROR: NAN bounding box!
412 // box is on one side of plane, take that path
413 node = node->children[sides-1];
414 }
415 else
416 {
417 // box crosses plane, take one path and remember the other
418 if (nodestackindex < 1024)
419 nodestack[nodestackindex++] = node->children[0];
420 node = node->children[1];
421 }
422 continue;
423 }
424 else
425 {
426 // leaf - check if it is visible
427 if (visibleleafs[(mleaf_t *)node - model->brush.data_leafs])
428 {
429 // it is visible, return immediately with the news
430 return true;
431 }
432 }
433#else
434 if (BoxesOverlap(mins, maxs, node->mins, node->maxs))
435 {
436 if (node->plane)
437 {
438 if (nodestackindex < 1024)
439 nodestack[nodestackindex++] = node->children[0];
440 node = node->children[1];
441 continue;
442 }
443 else
444 {
445 // leaf - check if it is visible
446 if (visibleleafs[(mleaf_t *)node - model->brush.data_leafs])
447 {
448 // it is visible, return immediately with the news
449 return true;
450 }
451 }
452 }
453#endif
454 // nothing to see here, try another path we didn't take earlier
455 if (nodestackindex == 0)
456 break;
457 node = nodestack[--nodestackindex];
458 }
459 // it is not visible
460 return false;
461}

References BoxesOverlap, BoxOnPlaneSide(), mnode_t::children, maxs, mnode_t::maxs, mins, mnode_t::mins, model, and mnode_t::plane.

Referenced by Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_BSP_DecompressVis()

static void Mod_BSP_DecompressVis ( const unsigned char * in,
const unsigned char * inend,
unsigned char * out,
unsigned char * outend )
static

Definition at line 1529 of file model_brush.c.

1530{
1531 int c;
1532 unsigned char *outstart = out;
1533 while (out < outend)
1534 {
1535 if (in == inend)
1536 {
1537 Con_Printf("Mod_BSP_DecompressVis: input underrun on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, (int)(out - outstart), (int)(outend - outstart));
1538 return;
1539 }
1540 c = *in++;
1541 if (c)
1542 *out++ = c;
1543 else
1544 {
1545 if (in == inend)
1546 {
1547 Con_Printf("Mod_BSP_DecompressVis: input underrun (during zero-run) on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, (int)(out - outstart), (int)(outend - outstart));
1548 return;
1549 }
1550 for (c = *in++;c > 0;c--)
1551 {
1552 if (out == outend)
1553 {
1554 Con_Printf("Mod_BSP_DecompressVis: output overrun on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, (int)(out - outstart), (int)(outend - outstart));
1555 return;
1556 }
1557 *out++ = 0;
1558 }
1559 }
1560 }
1561}
model_t * loadmodel
char name[MAX_QPATH]

References Con_Printf(), loadmodel, and model_t::name.

Referenced by Mod_Q1BSP_LoadLeafs(), and Mod_Q2BSP_LoadVisibility().

◆ Mod_BSP_FatPVS()

static size_t Mod_BSP_FatPVS ( model_t * model,
const vec3_t org,
vec_t radius,
unsigned char ** pvsbuffer,
mempool_t * pool,
qbool merge )
static

Definition at line 3825 of file model_brush.c.

3826{
3827 size_t bytes = model->brush.num_pvsclusterbytes;
3828
3829 if (!*pvsbuffer || bytes != Mem_Size(*pvsbuffer))
3830 {
3831// Con_Printf("^4FatPVS: allocating a%s ^4buffer in pool %s, old size %zu new size %zu\n", *pvsbuffer == NULL ? " ^5NEW" : "", pool->name, *pvsbuffer != NULL ? Mem_Size(*pvsbuffer) : 0, bytes);
3832 if (*pvsbuffer)
3833 Mem_Free(*pvsbuffer); // don't reuse stale data when the worldmodel changes
3834 *pvsbuffer = Mem_AllocType(pool, unsigned char, bytes);
3835 }
3836
3837 if (r_novis.integer || r_trippy.integer || !model->brush.num_pvsclusters || !Mod_BSP_GetPVS(model, org))
3838 {
3839 memset(*pvsbuffer, 0xFF, bytes);
3840 return bytes;
3841 }
3842 if (!merge)
3843 memset(*pvsbuffer, 0, bytes);
3844 Mod_BSP_FatPVS_RecursiveBSPNode(model, org, radius, *pvsbuffer, bytes, model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode);
3845 return bytes;
3846}
static unsigned char * Mod_BSP_GetPVS(model_t *model, const vec3_t p)
static void Mod_BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org, vec_t radius, unsigned char *pvsbuffer, int pvsbytes, mnode_t *node)
int integer
Definition cvar.h:73
#define Mem_Free(mem)
Definition zone.h:96
static size_t Mem_Size(void *data)
Returns the current size of an allocation.
Definition zone.h:122
#define Mem_AllocType(pool, type, size)
Definition zone.h:93

References cvar_t::integer, Mem_AllocType, Mem_Free, Mem_Size(), Mod_BSP_FatPVS_RecursiveBSPNode(), Mod_BSP_GetPVS(), model, r_novis, and r_trippy.

Referenced by Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_BSP_FatPVS_RecursiveBSPNode()

static void Mod_BSP_FatPVS_RecursiveBSPNode ( model_t * model,
const vec3_t org,
vec_t radius,
unsigned char * pvsbuffer,
int pvsbytes,
mnode_t * node )
static

Definition at line 3797 of file model_brush.c.

3798{
3799 while (node->plane)
3800 {
3801 float d = PlaneDiff(org, node->plane);
3802 if (d > radius)
3803 node = node->children[0];
3804 else if (d < -radius)
3805 node = node->children[1];
3806 else
3807 {
3808 // go down both sides
3809 Mod_BSP_FatPVS_RecursiveBSPNode(model, org, radius, pvsbuffer, pvsbytes, node->children[0]);
3810 node = node->children[1];
3811 }
3812 }
3813 // if this leaf is in a cluster, accumulate the pvs bits
3814 if (((mleaf_t *)node)->clusterindex >= 0)
3815 {
3816 int i;
3817 unsigned char *pvs = model->brush.data_pvsclusters + ((mleaf_t *)node)->clusterindex * model->brush.num_pvsclusterbytes;
3818 for (i = 0;i < pvsbytes;i++)
3819 pvsbuffer[i] |= pvs[i];
3820 }
3821}
#define PlaneDiff(point, plane)
Definition mathlib.h:257

References mnode_t::children, i, Mod_BSP_FatPVS_RecursiveBSPNode(), model, mnode_t::plane, and PlaneDiff.

Referenced by Mod_BSP_FatPVS(), and Mod_BSP_FatPVS_RecursiveBSPNode().

◆ Mod_BSP_FinalizePortals()

static void Mod_BSP_FinalizePortals ( void )
static

Definition at line 3414 of file model_brush.c.

3415{
3416 int i, j, numportals, numpoints, portalindex, portalrange = (int)Mem_ExpandableArray_IndexRange(&portalarray);
3417 portal_t *p;
3418 mportal_t *portal;
3419 mvertex_t *point;
3420 mleaf_t *leaf, *endleaf;
3421
3422 // tally up portal and point counts and recalculate bounding boxes for all
3423 // leafs (because qbsp is very sloppy)
3424 leaf = loadmodel->brush.data_leafs;
3425 endleaf = leaf + loadmodel->brush.num_leafs;
3427 {
3428 for (;leaf < endleaf;leaf++)
3429 {
3430 VectorSet(leaf->mins, 2000000000, 2000000000, 2000000000);
3431 VectorSet(leaf->maxs, -2000000000, -2000000000, -2000000000);
3432 }
3433 }
3434 numportals = 0;
3435 numpoints = 0;
3436 for (portalindex = 0;portalindex < portalrange;portalindex++)
3437 {
3439 if (!p)
3440 continue;
3441 // note: this check must match the one below or it will usually corrupt memory
3442 // the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides
3443 if (p->numpoints >= 3 && p->nodes[0] != p->nodes[1] && ((mleaf_t *)p->nodes[0])->clusterindex >= 0 && ((mleaf_t *)p->nodes[1])->clusterindex >= 0)
3444 {
3445 numportals += 2;
3446 numpoints += p->numpoints * 2;
3447 }
3448 }
3449 loadmodel->brush.data_portals = (mportal_t *)Mem_Alloc(loadmodel->mempool, numportals * sizeof(mportal_t) + numpoints * sizeof(mvertex_t));
3450 loadmodel->brush.num_portals = numportals;
3451 loadmodel->brush.data_portalpoints = (mvertex_t *)((unsigned char *) loadmodel->brush.data_portals + numportals * sizeof(mportal_t));
3452 loadmodel->brush.num_portalpoints = numpoints;
3453 // clear all leaf portal chains
3454 for (i = 0;i < loadmodel->brush.num_leafs;i++)
3456 // process all portals in the global portal chain, while freeing them
3457 portal = loadmodel->brush.data_portals;
3459 for (portalindex = 0;portalindex < portalrange;portalindex++)
3460 {
3462 if (!p)
3463 continue;
3464 if (p->numpoints >= 3 && p->nodes[0] != p->nodes[1])
3465 {
3466 // note: this check must match the one above or it will usually corrupt memory
3467 // the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides
3468 if (((mleaf_t *)p->nodes[0])->clusterindex >= 0 && ((mleaf_t *)p->nodes[1])->clusterindex >= 0)
3469 {
3470 // first make the back to front portal(forward portal)
3471 portal->points = point;
3472 portal->numpoints = p->numpoints;
3473 portal->plane.dist = p->plane.dist;
3474 VectorCopy(p->plane.normal, portal->plane.normal);
3475 portal->here = (mleaf_t *)p->nodes[1];
3476 portal->past = (mleaf_t *)p->nodes[0];
3477 // copy points
3478 for (j = 0;j < portal->numpoints;j++)
3479 {
3480 VectorCopy(p->points + j*3, point->position);
3481 point++;
3482 }
3483 BoxFromPoints(portal->mins, portal->maxs, portal->numpoints, portal->points->position);
3484 PlaneClassify(&portal->plane);
3485
3486 // link into leaf's portal chain
3487 portal->next = portal->here->portals;
3488 portal->here->portals = portal;
3489
3490 // advance to next portal
3491 portal++;
3492
3493 // then make the front to back portal(backward portal)
3494 portal->points = point;
3495 portal->numpoints = p->numpoints;
3496 portal->plane.dist = -p->plane.dist;
3497 VectorNegate(p->plane.normal, portal->plane.normal);
3498 portal->here = (mleaf_t *)p->nodes[0];
3499 portal->past = (mleaf_t *)p->nodes[1];
3500 // copy points
3501 for (j = portal->numpoints - 1;j >= 0;j--)
3502 {
3503 VectorCopy(p->points + j*3, point->position);
3504 point++;
3505 }
3506 BoxFromPoints(portal->mins, portal->maxs, portal->numpoints, portal->points->position);
3507 PlaneClassify(&portal->plane);
3508
3509 // link into leaf's portal chain
3510 portal->next = portal->here->portals;
3511 portal->here->portals = portal;
3512
3513 // advance to next portal
3514 portal++;
3515 }
3516 // add the portal's polygon points to the leaf bounding boxes
3518 {
3519 for (i = 0;i < 2;i++)
3520 {
3521 leaf = (mleaf_t *)p->nodes[i];
3522 for (j = 0;j < p->numpoints;j++)
3523 {
3524 if (leaf->mins[0] > p->points[j*3+0]) leaf->mins[0] = p->points[j*3+0];
3525 if (leaf->mins[1] > p->points[j*3+1]) leaf->mins[1] = p->points[j*3+1];
3526 if (leaf->mins[2] > p->points[j*3+2]) leaf->mins[2] = p->points[j*3+2];
3527 if (leaf->maxs[0] < p->points[j*3+0]) leaf->maxs[0] = p->points[j*3+0];
3528 if (leaf->maxs[1] < p->points[j*3+1]) leaf->maxs[1] = p->points[j*3+1];
3529 if (leaf->maxs[2] < p->points[j*3+2]) leaf->maxs[2] = p->points[j*3+2];
3530 }
3531 }
3532 }
3533 }
3534 }
3535 // now recalculate the node bounding boxes from the leafs
3538}
static int(ZEXPORT *qz_inflate)(z_stream *strm
void BoxFromPoints(vec3_t mins, vec3_t maxs, int numpoints, vec_t *point3f)
Definition mathlib.c:877
void PlaneClassify(mplane_t *p)
Definition mathlib.c:310
#define VectorNegate(a, b)
Definition mathlib.h:95
#define VectorSet(vec, x, y, z)
Definition mathlib.h:96
static memexpandablearray_t portalarray
static void Mod_BSP_RecursiveRecalcNodeBBox(mnode_t *node)
vec3_t mins
vec3_t maxs
struct mportal_s * portals
mportal_t * data_portals
mvertex_t * data_portalpoints
mleaf_t * data_leafs
mnode_t * data_nodes
hull_t hulls[MAX_MAP_HULLS]
Definition model_q1bsp.h:26
model_brush_t brush
model_brushq1_t brushq1
struct mempool_s * mempool
vec3_t mins
mleaf_t * here
mvertex_t * points
struct mportal_s * next
mleaf_t * past
mplane_t plane
vec3_t maxs
vec3_t position
Definition model_brush.h:43
double points[3 *MAX_PORTALPOINTS]
mplane_t plane
size_t Mem_ExpandableArray_IndexRange(const memexpandablearray_t *l)
Definition zone.c:763
void * Mem_ExpandableArray_RecordAtIndex(const memexpandablearray_t *l, size_t index)
Definition zone.c:780
#define Mem_Alloc(pool, size)
Definition zone.h:92

References BoxFromPoints(), model_t::brush, model_t::brushq1, model_brush_t::data_leafs, model_brush_t::data_nodes, model_brush_t::data_portalpoints, model_brush_t::data_portals, mplane_t::dist, hull_t::firstclipnode, mportal_t::here, model_brushq1_t::hulls, i, int(), cvar_t::integer, loadmodel, mleaf_t::maxs, mportal_t::maxs, Mem_Alloc, Mem_ExpandableArray_IndexRange(), Mem_ExpandableArray_RecordAtIndex(), model_t::mempool, mleaf_t::mins, mportal_t::mins, Mod_BSP_RecursiveRecalcNodeBBox(), mod_recalculatenodeboxes, mportal_t::next, portal_t::nodes, mplane_t::normal, NULL, model_brush_t::num_leafs, model_brush_t::num_portalpoints, model_brush_t::num_portals, mportal_t::numpoints, portal_t::numpoints, mportal_t::past, mportal_t::plane, portal_t::plane, PlaneClassify(), mportal_t::points, portal_t::points, portalarray, mleaf_t::portals, mvertex_t::position, VectorCopy, VectorNegate, and VectorSet.

Referenced by Mod_BSP_MakePortals().

◆ Mod_BSP_FindBoxClusters()

static int Mod_BSP_FindBoxClusters ( model_t * model,
const vec3_t mins,
const vec3_t maxs,
int maxclusters,
int * clusterlist )
static

Definition at line 186 of file model_brush.c.

187{
188 int numclusters = 0;
189 int nodestackindex = 0;
190 mnode_t *node, *nodestack[1024];
191 if (!model->brush.num_pvsclusters)
192 return -1;
193 node = model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode;
194 for (;;)
195 {
196#if 1
197 if (node->plane)
198 {
199 // node - recurse down the BSP tree
200 int sides = BoxOnPlaneSide(mins, maxs, node->plane);
201 if (sides < 3)
202 {
203 if (sides == 0)
204 return -1; // ERROR: NAN bounding box!
205 // box is on one side of plane, take that path
206 node = node->children[sides-1];
207 }
208 else
209 {
210 // box crosses plane, take one path and remember the other
211 if (nodestackindex < 1024)
212 nodestack[nodestackindex++] = node->children[0];
213 node = node->children[1];
214 }
215 continue;
216 }
217 else
218 {
219 // leaf - add clusterindex to list
220 if (numclusters < maxclusters)
221 clusterlist[numclusters] = ((mleaf_t *)node)->clusterindex;
222 numclusters++;
223 }
224#else
225 if (BoxesOverlap(mins, maxs, node->mins, node->maxs))
226 {
227 if (node->plane)
228 {
229 if (nodestackindex < 1024)
230 nodestack[nodestackindex++] = node->children[0];
231 node = node->children[1];
232 continue;
233 }
234 else
235 {
236 // leaf - add clusterindex to list
237 if (numclusters < maxclusters)
238 clusterlist[numclusters] = ((mleaf_t *)node)->clusterindex;
239 numclusters++;
240 }
241 }
242#endif
243 // try another path we didn't take earlier
244 if (nodestackindex == 0)
245 break;
246 node = nodestack[--nodestackindex];
247 }
248 // return number of clusters found (even if more than the maxclusters)
249 return numclusters;
250}

References BoxesOverlap, BoxOnPlaneSide(), mnode_t::children, maxs, mnode_t::maxs, mins, mnode_t::mins, model, and mnode_t::plane.

Referenced by Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_BSP_FindNonSolidLocation()

static void Mod_BSP_FindNonSolidLocation ( model_t * model,
const vec3_t in,
vec3_t out,
float radius )
static

Definition at line 598 of file model_brush.c.

599{
600 int i;
602 if (model == NULL)
603 {
604 VectorCopy(in, out);
605 return;
606 }
607 VectorCopy(in, info.center);
608 info.radius = radius;
609 info.model = model;
610 i = 0;
611 do
612 {
613 VectorClear(info.nudge);
614 info.bestdist = radius;
615 VectorCopy(info.center, info.absmin);
616 VectorCopy(info.center, info.absmax);
617 info.absmin[0] -= info.radius + 1;
618 info.absmin[1] -= info.radius + 1;
619 info.absmin[2] -= info.radius + 1;
620 info.absmax[0] += info.radius + 1;
621 info.absmax[1] += info.radius + 1;
622 info.absmax[2] += info.radius + 1;
623 Mod_BSP_FindNonSolidLocation_r(&info, model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode);
624 VectorAdd(info.center, info.nudge, info.center);
625 }
626 while (info.bestdist < radius && ++i < 10);
627 VectorCopy(info.center, out);
628}
#define VectorClear(a)
Definition mathlib.h:97
#define VectorAdd(a, b, out)
Definition mathlib.h:100
static void Mod_BSP_FindNonSolidLocation_r(findnonsolidlocationinfo_t *info, mnode_t *node)

References findnonsolidlocationinfo_t::absmax, findnonsolidlocationinfo_t::absmin, findnonsolidlocationinfo_t::bestdist, findnonsolidlocationinfo_t::center, i, Mod_BSP_FindNonSolidLocation_r(), findnonsolidlocationinfo_t::model, model, findnonsolidlocationinfo_t::nudge, NULL, findnonsolidlocationinfo_t::radius, VectorAdd, VectorClear, and VectorCopy.

Referenced by Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_BSP_FindNonSolidLocation_r()

static void Mod_BSP_FindNonSolidLocation_r ( findnonsolidlocationinfo_t * info,
mnode_t * node )
static

Definition at line 581 of file model_brush.c.

582{
583 if (node->plane)
584 {
585 float f = PlaneDiff(info->center, node->plane);
586 if (f >= -info->bestdist)
588 if (f <= info->bestdist)
590 }
591 else
592 {
593 if (((mleaf_t *)node)->numleafsurfaces)
595 }
596}
static void Mod_BSP_FindNonSolidLocation_r_Leaf(findnonsolidlocationinfo_t *info, mleaf_t *leaf)
float f

References findnonsolidlocationinfo_t::bestdist, findnonsolidlocationinfo_t::center, mnode_t::children, f, Mod_BSP_FindNonSolidLocation_r(), Mod_BSP_FindNonSolidLocation_r_Leaf(), mnode_t::plane, and PlaneDiff.

Referenced by Mod_BSP_FindNonSolidLocation(), and Mod_BSP_FindNonSolidLocation_r().

◆ Mod_BSP_FindNonSolidLocation_r_Leaf()

static void Mod_BSP_FindNonSolidLocation_r_Leaf ( findnonsolidlocationinfo_t * info,
mleaf_t * leaf )
static

Definition at line 562 of file model_brush.c.

563{
564 int surfacenum, k, *mark;
565 msurface_t *surface;
566 for (surfacenum = 0, mark = leaf->firstleafsurface;surfacenum < leaf->numleafsurfaces;surfacenum++, mark++)
567 {
568 surface = info->model->data_surfaces + *mark;
569 if(!surface->texture)
570 continue;
572 {
573 for (k = 0;k < surface->num_triangles;k++)
574 {
576 }
577 }
578 }
579}
static void Mod_BSP_FindNonSolidLocation_r_Triangle(findnonsolidlocationinfo_t *info, msurface_t *surface, int k)
int * firstleafsurface
msurface_t * data_surfaces
describes the textures to use on a range of triangles in the model, and mins/maxs (AABB) for culling.
int num_triangles
range of triangles and vertices in model->surfmesh
texture_t * texture
the texture to use on the surface

References model_t::data_surfaces, mleaf_t::firstleafsurface, Mod_BSP_FindNonSolidLocation_r_Triangle(), findnonsolidlocationinfo_t::model, msurface_t::num_triangles, texture_t::supercontents, SUPERCONTENTS_SOLID, and msurface_t::texture.

Referenced by Mod_BSP_FindNonSolidLocation_r().

◆ Mod_BSP_FindNonSolidLocation_r_Triangle()

static void Mod_BSP_FindNonSolidLocation_r_Triangle ( findnonsolidlocationinfo_t * info,
msurface_t * surface,
int k )
static

Definition at line 474 of file model_brush.c.

475{
476 int i, *tri;
477 float dist, f, vert[3][3], edge[3][3], facenormal[3], edgenormal[3][3], point[3];
478
479 tri = (info->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle) + k * 3;
480 VectorCopy((info->model->surfmesh.data_vertex3f + tri[0] * 3), vert[0]);
481 VectorCopy((info->model->surfmesh.data_vertex3f + tri[1] * 3), vert[1]);
482 VectorCopy((info->model->surfmesh.data_vertex3f + tri[2] * 3), vert[2]);
483 VectorSubtract(vert[1], vert[0], edge[0]);
484 VectorSubtract(vert[2], vert[1], edge[1]);
485 CrossProduct(edge[1], edge[0], facenormal);
486 if (facenormal[0] || facenormal[1] || facenormal[2])
487 {
488 VectorNormalize(facenormal);
489 f = DotProduct(info->center, facenormal) - DotProduct(vert[0], facenormal);
490 if (f <= info->bestdist && f >= -info->bestdist)
491 {
492 VectorSubtract(vert[0], vert[2], edge[2]);
493 VectorNormalize(edge[0]);
494 VectorNormalize(edge[1]);
495 VectorNormalize(edge[2]);
496 CrossProduct(facenormal, edge[0], edgenormal[0]);
497 CrossProduct(facenormal, edge[1], edgenormal[1]);
498 CrossProduct(facenormal, edge[2], edgenormal[2]);
499 // face distance
500 if (DotProduct(info->center, edgenormal[0]) < DotProduct(vert[0], edgenormal[0])
501 && DotProduct(info->center, edgenormal[1]) < DotProduct(vert[1], edgenormal[1])
502 && DotProduct(info->center, edgenormal[2]) < DotProduct(vert[2], edgenormal[2]))
503 {
504 // we got lucky, the center is within the face
505 dist = DotProduct(info->center, facenormal) - DotProduct(vert[0], facenormal);
506 if (dist < 0)
507 {
508 dist = -dist;
509 if (info->bestdist > dist)
510 {
511 info->bestdist = dist;
512 VectorScale(facenormal, (info->radius - -dist), info->nudge);
513 }
514 }
515 else
516 {
517 if (info->bestdist > dist)
518 {
519 info->bestdist = dist;
520 VectorScale(facenormal, (info->radius - dist), info->nudge);
521 }
522 }
523 }
524 else
525 {
526 // check which edge or vertex the center is nearest
527 for (i = 0;i < 3;i++)
528 {
529 f = DotProduct(info->center, edge[i]);
530 if (f >= DotProduct(vert[0], edge[i])
531 && f <= DotProduct(vert[1], edge[i]))
532 {
533 // on edge
534 VectorMA(info->center, -f, edge[i], point);
535 dist = sqrt(DotProduct(point, point));
536 if (info->bestdist > dist)
537 {
538 info->bestdist = dist;
539 VectorScale(point, (info->radius / dist), info->nudge);
540 }
541 // skip both vertex checks
542 // (both are further away than this edge)
543 i++;
544 }
545 else
546 {
547 // not on edge, check first vertex of edge
548 VectorSubtract(info->center, vert[i], point);
549 dist = sqrt(DotProduct(point, point));
550 if (info->bestdist > dist)
551 {
552 info->bestdist = dist;
553 VectorScale(point, (info->radius / dist), info->nudge);
554 }
555 }
556 }
557 }
558 }
559 }
560}
#define VectorNormalize(v)
Definition mathlib.h:104
#define CrossProduct(a, b, out)
Definition mathlib.h:103
#define DotProduct(a, b)
Definition mathlib.h:98
#define VectorScale(in, scale, out)
Definition mathlib.h:111
#define VectorMA(a, scale, b, out)
Definition mathlib.h:114
float sqrt(float f)
surfmesh_t surfmesh
int num_firsttriangle
int * data_element3i
float * data_vertex3f

References findnonsolidlocationinfo_t::bestdist, findnonsolidlocationinfo_t::center, CrossProduct, surfmesh_t::data_element3i, surfmesh_t::data_vertex3f, DotProduct, f, i, findnonsolidlocationinfo_t::model, findnonsolidlocationinfo_t::nudge, msurface_t::num_firsttriangle, findnonsolidlocationinfo_t::radius, sqrt(), model_t::surfmesh, VectorCopy, VectorMA, VectorNormalize, VectorScale, and VectorSubtract.

Referenced by Mod_BSP_FindNonSolidLocation_r_Leaf().

◆ Mod_BSP_GetPVS()

static unsigned char * Mod_BSP_GetPVS ( model_t * model,
const vec3_t p )
static

Definition at line 3785 of file model_brush.c.

3786{
3787 mnode_t *node;
3788 node = model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode;
3789 while (node->plane)
3790 node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p,node->plane->normal)) < node->plane->dist];
3791 if (((mleaf_t *)node)->clusterindex >= 0)
3792 return model->brush.data_pvsclusters + ((mleaf_t *)node)->clusterindex * model->brush.num_pvsclusterbytes;
3793 else
3794 return NULL;
3795}

References mnode_t::children, mplane_t::dist, DotProduct, model, mplane_t::normal, NULL, mnode_t::plane, and mplane_t::type.

Referenced by Mod_BSP_FatPVS(), Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_BSP_LightPoint()

static void Mod_BSP_LightPoint ( model_t * model,
const vec3_t p,
vec3_t ambientcolor,
vec3_t diffusecolor,
vec3_t diffusenormal )
static

Definition at line 1330 of file model_brush.c.

1331{
1332 // pretend lighting is coming down from above (due to lack of a lightgrid to know primary lighting direction)
1333 VectorSet(diffusenormal, 0, 0, 1);
1334
1335 if (!model->brushq1.lightdata)
1336 {
1337 VectorSet(ambientcolor, 1, 1, 1);
1338 VectorSet(diffusecolor, 0, 0, 0);
1339 return;
1340 }
1341
1342 Mod_BSP_LightPoint_RecursiveBSPNode(model, ambientcolor, diffusecolor, diffusenormal, model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode, p[0], p[1], p[2] + 0.125, p[2] - 65536);
1343}
static int Mod_BSP_LightPoint_RecursiveBSPNode(model_t *model, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const mnode_t *node, float x, float y, float startz, float endz)

References Mod_BSP_LightPoint_RecursiveBSPNode(), model, and VectorSet.

Referenced by Mod_Q1BSP_Load(), and Mod_Q2BSP_Load().

◆ Mod_BSP_LightPoint_RecursiveBSPNode()

static int Mod_BSP_LightPoint_RecursiveBSPNode ( model_t * model,
vec3_t ambientcolor,
vec3_t diffusecolor,
vec3_t diffusenormal,
const mnode_t * node,
float x,
float y,
float startz,
float endz )
static

Definition at line 1186 of file model_brush.c.

1187{
1188 int side;
1189 float front, back;
1190 float mid, distz = endz - startz;
1191
1192 while (node->plane)
1193 {
1194 switch (node->plane->type)
1195 {
1196 case PLANE_X:
1197 node = node->children[x < node->plane->dist];
1198 continue; // loop back and process the new node
1199 case PLANE_Y:
1200 node = node->children[y < node->plane->dist];
1201 continue; // loop back and process the new node
1202 case PLANE_Z:
1203 side = startz < node->plane->dist;
1204 if ((endz < node->plane->dist) == side)
1205 {
1206 node = node->children[side];
1207 continue; // loop back and process the new node
1208 }
1209 // found an intersection
1210 mid = node->plane->dist;
1211 break;
1212 default:
1213 back = front = x * node->plane->normal[0] + y * node->plane->normal[1];
1214 front += startz * node->plane->normal[2];
1215 back += endz * node->plane->normal[2];
1216 side = front < node->plane->dist;
1217 if ((back < node->plane->dist) == side)
1218 {
1219 node = node->children[side];
1220 continue; // loop back and process the new node
1221 }
1222 // found an intersection
1223 mid = startz + distz * (front - node->plane->dist) / (front - back);
1224 break;
1225 }
1226
1227 // go down front side
1228 if (node->children[side]->plane && Mod_BSP_LightPoint_RecursiveBSPNode(model, ambientcolor, diffusecolor, diffusenormal, node->children[side], x, y, startz, mid))
1229 return true; // hit something
1230
1231 // check for impact on this node
1232 if (node->numsurfaces)
1233 {
1234 unsigned int i;
1235 int dsi, dti, lmwidth, lmheight;
1236 float ds, dt;
1237 msurface_t *surface;
1238 unsigned char *lightmap;
1239 int maps, line3, size3;
1240 float dsfrac;
1241 float dtfrac;
1242 float scale, w, w00, w01, w10, w11;
1243
1244 surface = model->data_surfaces + node->firstsurface;
1245 for (i = 0;i < node->numsurfaces;i++, surface++)
1246 {
1247 if(!surface->texture)
1248 continue;
1249 if (!(surface->texture->basematerialflags & MATERIALFLAG_WALL) || !surface->lightmapinfo || !surface->lightmapinfo->samples)
1250 continue; // no lightmaps
1251
1252 // location we want to sample in the lightmap
1253 ds = ((x * surface->lightmapinfo->texinfo->vecs[0][0] + y * surface->lightmapinfo->texinfo->vecs[0][1] + mid * surface->lightmapinfo->texinfo->vecs[0][2] + surface->lightmapinfo->texinfo->vecs[0][3]) - surface->lightmapinfo->texturemins[0]) * 0.0625f;
1254 dt = ((x * surface->lightmapinfo->texinfo->vecs[1][0] + y * surface->lightmapinfo->texinfo->vecs[1][1] + mid * surface->lightmapinfo->texinfo->vecs[1][2] + surface->lightmapinfo->texinfo->vecs[1][3]) - surface->lightmapinfo->texturemins[1]) * 0.0625f;
1255
1256 // check the bounds
1257 // thanks to jitspoe for pointing out that this int cast was
1258 // rounding toward zero, so we floor it
1259 dsi = (int)floor(ds);
1260 dti = (int)floor(dt);
1261 lmwidth = ((surface->lightmapinfo->extents[0]>>4)+1);
1262 lmheight = ((surface->lightmapinfo->extents[1]>>4)+1);
1263
1264 // is it in bounds?
1265 // we have to tolerate a position of lmwidth-1 for some rare
1266 // cases - in which case the sampling position still gets
1267 // clamped but the color gets interpolated to that edge.
1268 if (dsi >= 0 && dsi < lmwidth && dti >= 0 && dti < lmheight)
1269 {
1270 // in the rare cases where we're sampling slightly off
1271 // the polygon, clamp the sampling position (we can still
1272 // interpolate outside it, where it becomes extrapolation)
1273 if (dsi < 0)
1274 dsi = 0;
1275 if (dti < 0)
1276 dti = 0;
1277 if (dsi > lmwidth-2)
1278 dsi = lmwidth-2;
1279 if (dti > lmheight-2)
1280 dti = lmheight-2;
1281
1282 // calculate bilinear interpolation factors
1283 // and also multiply by fixedpoint conversion factors to
1284 // compensate for lightmaps being 0-255 (as 0-2), we use
1285 // r_refdef.scene.rtlightstylevalue here which is already
1286 // 0.000-2.148 range
1287 // (if we used r_refdef.scene.lightstylevalue this
1288 // divisor would be 32768 rather than 128)
1289 dsfrac = ds - dsi;
1290 dtfrac = dt - dti;
1291 w00 = (1 - dsfrac) * (1 - dtfrac) * (1.0f / 128.0f);
1292 w01 = ( dsfrac) * (1 - dtfrac) * (1.0f / 128.0f);
1293 w10 = (1 - dsfrac) * ( dtfrac) * (1.0f / 128.0f);
1294 w11 = ( dsfrac) * ( dtfrac) * (1.0f / 128.0f);
1295
1296 // values for pointer math
1297 line3 = lmwidth * 3; // LadyHavoc: *3 for colored lighting
1298 size3 = lmwidth * lmheight * 3; // LadyHavoc: *3 for colored lighting
1299
1300 // look up the pixel
1301 lightmap = surface->lightmapinfo->samples + dti * line3 + dsi*3; // LadyHavoc: *3 for colored lighting
1302
1303 // bilinear filter each lightmap style, and sum them
1304 for (maps = 0;maps < MAXLIGHTMAPS && surface->lightmapinfo->styles[maps] != 255;maps++)
1305 {
1307 w = w00 * scale;VectorMA(ambientcolor, w, lightmap , ambientcolor);
1308 w = w01 * scale;VectorMA(ambientcolor, w, lightmap + 3 , ambientcolor);
1309 w = w10 * scale;VectorMA(ambientcolor, w, lightmap + line3 , ambientcolor);
1310 w = w11 * scale;VectorMA(ambientcolor, w, lightmap + line3 + 3, ambientcolor);
1311 lightmap += size3;
1312 }
1313
1314 return true; // success
1315 }
1316 }
1317 }
1318
1319 // go down back side
1320 node = node->children[side ^ 1];
1321 startz = mid;
1322 distz = endz - startz;
1323 // loop back and process the new node
1324 }
1325
1326 // did not hit anything
1327 return false;
1328}
#define PLANE_Y
Definition bspfile.h:114
#define MAXLIGHTMAPS
Definition bspfile.h:282
#define PLANE_X
Definition bspfile.h:113
#define PLANE_Z
Definition bspfile.h:115
float scale
r_refdef_t r_refdef
Definition gl_rmain.c:57
GLubyte GLubyte GLubyte GLubyte w
Definition glquake.h:782
GLint GLenum GLint GLint y
Definition glquake.h:651
GLint GLenum GLint x
Definition glquake.h:651
float floor(float f)
#define MATERIALFLAG_WALL
Definition model_brush.h:89
unsigned int numsurfaces
unsigned int firstsurface
unsigned char styles[MAXLIGHTMAPS]
unsigned char * samples
msurface_lightmapinfo_t * lightmapinfo
lightmaptexture rebuild information not used in q3bsp
float vecs[2][4]
float rtlightstylevalue[MAX_LIGHTSTYLES]
float fraction of base light value
Definition render.h:377
r_refdef_scene_t scene
Definition render.h:418
int basematerialflags

References texture_t::basematerialflags, mnode_t::children, mplane_t::dist, msurface_lightmapinfo_t::extents, mnode_t::firstsurface, floor(), i, int(), msurface_t::lightmapinfo, MATERIALFLAG_WALL, MAXLIGHTMAPS, Mod_BSP_LightPoint_RecursiveBSPNode(), model, mplane_t::normal, mnode_t::numsurfaces, mnode_t::plane, PLANE_X, PLANE_Y, PLANE_Z, r_refdef, r_refdef_scene_t::rtlightstylevalue, msurface_lightmapinfo_t::samples, scale, r_refdef_t::scene, msurface_lightmapinfo_t::styles, msurface_lightmapinfo_t::texinfo, msurface_t::texture, msurface_lightmapinfo_t::texturemins, mplane_t::type, mtexinfo_t::vecs, VectorMA, w, x, and y.

Referenced by Mod_BSP_LightPoint(), and Mod_BSP_LightPoint_RecursiveBSPNode().

◆ Mod_BSP_LoadNodes_RecursiveSetParent()

static void Mod_BSP_LoadNodes_RecursiveSetParent ( mnode_t * node,
mnode_t * parent )
static

Definition at line 2854 of file model_brush.c.

2855{
2856 //if (node->parent)
2857 // Host_Error("Mod_BSP_LoadNodes_RecursiveSetParent: runaway recursion");
2858 node->parent = parent;
2859 if (node->plane)
2860 {
2861 // this is a node, recurse to children
2864 // combine supercontents of children
2865 node->combinedsupercontents = node->children[0]->combinedsupercontents | node->children[1]->combinedsupercontents;
2866 }
2867 else
2868 {
2869 int j;
2870 mleaf_t *leaf = (mleaf_t *)node;
2871 // if this is a leaf, calculate supercontents mask from all collidable
2872 // primitives in the leaf (brushes and collision surfaces)
2873 // also flag if the leaf contains any collision surfaces
2874 leaf->combinedsupercontents = 0;
2875 // combine the supercontents values of all brushes in this leaf
2876 for (j = 0;j < leaf->numleafbrushes;j++)
2877 leaf->combinedsupercontents |= loadmodel->brush.data_brushes[leaf->firstleafbrush[j]].texture->supercontents;
2878 // check if this leaf contains any collision surfaces (q3 patches)
2879 for (j = 0;j < leaf->numleafsurfaces;j++)
2880 {
2881 msurface_t *surface = loadmodel->data_surfaces + leaf->firstleafsurface[j];
2882 if (surface->num_collisiontriangles)
2883 {
2884 leaf->containscollisionsurfaces = true;
2885 leaf->combinedsupercontents |= surface->texture->supercontents;
2886 }
2887 }
2888 }
2889}
static void Mod_BSP_LoadNodes_RecursiveSetParent(mnode_t *node, mnode_t *parent)
int numleafbrushes
int * firstleafbrush
int containscollisionsurfaces
int numleafsurfaces
int combinedsupercontents
int combinedsupercontents
struct mnode_s * parent
struct q3mbrush_s * data_brushes
int num_collisiontriangles

References model_t::brush, mnode_t::children, mleaf_t::combinedsupercontents, mnode_t::combinedsupercontents, mleaf_t::containscollisionsurfaces, model_brush_t::data_brushes, model_t::data_surfaces, mleaf_t::firstleafbrush, mleaf_t::firstleafsurface, loadmodel, Mod_BSP_LoadNodes_RecursiveSetParent(), msurface_t::num_collisiontriangles, mleaf_t::numleafbrushes, mleaf_t::numleafsurfaces, mnode_t::parent, mnode_t::plane, texture_t::supercontents, and msurface_t::texture.

Referenced by Mod_BSP_LoadNodes_RecursiveSetParent(), Mod_Q1BSP_Load(), Mod_Q1BSP_LoadNodes(), Mod_Q2BSP_Load(), Mod_Q2BSP_LoadNodes(), and Mod_Q3BSP_LoadNodes().

◆ Mod_BSP_LoadSubmodels()

static void Mod_BSP_LoadSubmodels ( sizebuf_t * sb,
hullinfo_t * hullinfo )
static

Definition at line 2298 of file model_brush.c.

2299{
2300 mmodel_t *out;
2301 int i, j, count;
2302 int structsize = hullinfo ? (48+4*hullinfo->filehulls) : 48;
2303
2304 if (sb->cursize % structsize)
2305 Host_Error ("Mod_BSP_LoadSubmodels: funny lump size in %s", loadmodel->name);
2306
2307 count = sb->cursize / structsize;
2308 out = (mmodel_t *)Mem_Alloc (loadmodel->mempool, count*sizeof(*out));
2309
2312
2313 for (i = 0; i < count; i++, out++)
2314 {
2315 // spread out the mins / maxs by a pixel
2316 out->mins[0] = MSG_ReadLittleFloat(sb) - 1;
2317 out->mins[1] = MSG_ReadLittleFloat(sb) - 1;
2318 out->mins[2] = MSG_ReadLittleFloat(sb) - 1;
2319 out->maxs[0] = MSG_ReadLittleFloat(sb) + 1;
2320 out->maxs[1] = MSG_ReadLittleFloat(sb) + 1;
2321 out->maxs[2] = MSG_ReadLittleFloat(sb) + 1;
2322 out->origin[0] = MSG_ReadLittleFloat(sb);
2323 out->origin[1] = MSG_ReadLittleFloat(sb);
2324 out->origin[2] = MSG_ReadLittleFloat(sb);
2325 if(hullinfo)
2326 {
2327 for (j = 0; j < hullinfo->filehulls; j++)
2328 out->headnode[j] = MSG_ReadLittleLong(sb);
2329 out->visleafs = MSG_ReadLittleLong(sb);
2330 }
2331 else // Quake 2 has only one hull
2332 out->headnode[0] = MSG_ReadLittleLong(sb);
2333
2334 out->firstface = MSG_ReadLittleLong(sb);
2335 out->numfaces = MSG_ReadLittleLong(sb);
2336 }
2337}
float MSG_ReadLittleFloat(sizebuf_t *sb)
Definition com_msg.c:307
int MSG_ReadLittleLong(sizebuf_t *sb)
Definition com_msg.c:285
GLenum GLenum GLsizei count
Definition glquake.h:656
int filehulls
Definition bspfile.h:58
float mins[3]
Definition bspfile.h:64
int headnode[MAX_MAP_HULLS]
Definition bspfile.h:66
int firstface
Definition bspfile.h:68
int numfaces
Definition bspfile.h:68
float maxs[3]
Definition bspfile.h:64
float origin[3]
Definition bspfile.h:65
int visleafs
Definition bspfile.h:67
mmodel_t * submodels
Definition model_q1bsp.h:9
int cursize
Definition common.h:54

References model_t::brush, model_t::brushq1, count, sizebuf_t::cursize, hullinfo_t::filehulls, mmodel_t::firstface, mmodel_t::headnode, Host_Error(), i, loadmodel, mmodel_t::maxs, Mem_Alloc, model_t::mempool, mmodel_t::mins, MSG_ReadLittleFloat(), MSG_ReadLittleLong(), model_t::name, mmodel_t::numfaces, model_brush_t::numsubmodels, mmodel_t::origin, model_brushq1_t::submodels, and mmodel_t::visleafs.

Referenced by Mod_Q1BSP_Load(), and Mod_Q2BSP_Load().

◆ Mod_BSP_MakePortals()

static void Mod_BSP_MakePortals ( void )
static

Definition at line 3768 of file model_brush.c.

3769{
3781}
#define MAX_PORTALPOINTS
static int portalpointsbufferoffset
static void Mod_BSP_FinalizePortals(void)
static int portalpointsbuffersize
static double * portalpointsbuffer
static void Mod_BSP_RecursiveNodePortals(mnode_t *node)
void Mem_ExpandableArray_NewArray(memexpandablearray_t *l, mempool_t *mempool, size_t recordsize, int numrecordsperarray)
Definition zone.c:675
void Mem_ExpandableArray_FreeArray(memexpandablearray_t *l)
Definition zone.c:683

References model_t::brush, model_t::brushq1, model_brush_t::data_nodes, hull_t::firstclipnode, model_brushq1_t::hulls, loadmodel, MAX_PORTALPOINTS, Mem_Alloc, Mem_ExpandableArray_FreeArray(), Mem_ExpandableArray_NewArray(), Mem_Free, model_t::mempool, Mod_BSP_FinalizePortals(), Mod_BSP_RecursiveNodePortals(), NULL, portalarray, portalpointsbuffer, portalpointsbufferoffset, and portalpointsbuffersize.

Referenced by Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), and Mod_Q3BSP_Load().

◆ Mod_BSP_PointInLeaf()

static mleaf_t * Mod_BSP_PointInLeaf ( model_t * model,
const vec3_t p )
static

Definition at line 151 of file model_brush.c.

152{
153 mnode_t *node;
154
155 if (model == NULL)
156 return NULL;
157
158 // LadyHavoc: modified to start at first clip node,
159 // in other words: first node of the (sub)model
160 node = model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode;
161 while (node->plane)
162 node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p,node->plane->normal)) < node->plane->dist];
163
164 return (mleaf_t *)node;
165}

References mnode_t::children, mplane_t::dist, DotProduct, model, mplane_t::normal, NULL, mnode_t::plane, and mplane_t::type.

Referenced by Mod_Q1BSP_AmbientSoundLevelsForPoint(), Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_BSP_RecursiveNodePortals()

static void Mod_BSP_RecursiveNodePortals ( mnode_t * node)
static

Definition at line 3617 of file model_brush.c.

3618{
3619 int i, side;
3620 mnode_t *front, *back, *other_node;
3621 mplane_t clipplane, *plane;
3622 portal_t *portal, *nextportal, *nodeportal, *splitportal, *temp;
3623 int numfrontpoints, numbackpoints;
3624 double *frontpoints, *backpoints;
3625
3626 // if a leaf, we're done
3627 if (!node->plane)
3628 return;
3629
3630 // get some space for our clipping operations to use
3632 {
3635 }
3640
3641 plane = node->plane;
3642
3643 front = node->children[0];
3644 back = node->children[1];
3645 if (front == back)
3646 Host_Error("Mod_BSP_RecursiveNodePortals: corrupt node hierarchy");
3647
3648 // create the new portal by generating a polygon for the node plane,
3649 // and clipping it by all of the other portals(which came from nodes above this one)
3651 nodeportal->plane = *plane;
3652
3653 // TODO: calculate node bounding boxes during recursion and calculate a maximum plane size accordingly to improve precision (as most maps do not need 1 billion unit plane polygons)
3654 PolygonD_QuadForPlane(nodeportal->points, nodeportal->plane.normal[0], nodeportal->plane.normal[1], nodeportal->plane.normal[2], nodeportal->plane.dist, 1024.0*1024.0*1024.0);
3655 nodeportal->numpoints = 4;
3656
3657 for (portal = (portal_t *)node->portals;portal;portal = portal->next[side])
3658 {
3659 clipplane = portal->plane;
3660 if (portal->nodes[0] == portal->nodes[1])
3661 Host_Error("Mod_BSP_RecursiveNodePortals: portal has same node on both sides(1)");
3662 if (portal->nodes[0] == node)
3663 side = 0;
3664 else if (portal->nodes[1] == node)
3665 {
3666 clipplane.dist = -clipplane.dist;
3667 VectorNegate(clipplane.normal, clipplane.normal);
3668 side = 1;
3669 }
3670 else
3671 {
3672 Host_Error("Mod_BSP_RecursiveNodePortals: mislinked portal");
3673 side = 0; // hush warning
3674 }
3675
3676 for (i = 0;i < nodeportal->numpoints*3;i++)
3677 frontpoints[i] = nodeportal->points[i];
3678 PolygonD_Divide(nodeportal->numpoints, frontpoints, clipplane.normal[0], clipplane.normal[1], clipplane.normal[2], clipplane.dist, PORTAL_DIST_EPSILON, MAX_PORTALPOINTS, nodeportal->points, &nodeportal->numpoints, 0, NULL, NULL, NULL);
3679 if (nodeportal->numpoints <= 0 || nodeportal->numpoints >= MAX_PORTALPOINTS)
3680 break;
3681 }
3682
3683 if (nodeportal->numpoints < 3)
3684 {
3685 Con_Print(CON_WARN "Mod_BSP_RecursiveNodePortals: WARNING: new portal was clipped away\n");
3686 nodeportal->numpoints = 0;
3687 }
3688 else if (nodeportal->numpoints >= MAX_PORTALPOINTS)
3689 {
3690 Con_Print(CON_WARN "Mod_BSP_RecursiveNodePortals: WARNING: new portal has too many points\n");
3691 nodeportal->numpoints = 0;
3692 }
3693
3694 AddPortalToNodes(nodeportal, front, back);
3695
3696 // split the portals of this node along this node's plane and assign them to the children of this node
3697 // (migrating the portals downward through the tree)
3698 for (portal = (portal_t *)node->portals;portal;portal = nextportal)
3699 {
3700 if (portal->nodes[0] == portal->nodes[1])
3701 Host_Error("Mod_BSP_RecursiveNodePortals: portal has same node on both sides(2)");
3702 if (portal->nodes[0] == node)
3703 side = 0;
3704 else if (portal->nodes[1] == node)
3705 side = 1;
3706 else
3707 {
3708 Host_Error("Mod_BSP_RecursiveNodePortals: mislinked portal");
3709 side = 0; // hush warning
3710 }
3711 nextportal = portal->next[side];
3712 if (!portal->numpoints)
3713 continue;
3714
3715 other_node = portal->nodes[!side];
3716 RemovePortalFromNodes(portal);
3717
3718 // cut the portal into two portals, one on each side of the node plane
3719 PolygonD_Divide(portal->numpoints, portal->points, plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, PORTAL_DIST_EPSILON, MAX_PORTALPOINTS, frontpoints, &numfrontpoints, MAX_PORTALPOINTS, backpoints, &numbackpoints, NULL);
3720
3721 if (!numfrontpoints)
3722 {
3723 if (side == 0)
3724 AddPortalToNodes(portal, back, other_node);
3725 else
3726 AddPortalToNodes(portal, other_node, back);
3727 continue;
3728 }
3729 if (!numbackpoints)
3730 {
3731 if (side == 0)
3732 AddPortalToNodes(portal, front, other_node);
3733 else
3734 AddPortalToNodes(portal, other_node, front);
3735 continue;
3736 }
3737
3738 // the portal is split
3740 temp = splitportal->chain;
3741 *splitportal = *portal;
3742 splitportal->chain = temp;
3743 for (i = 0;i < numbackpoints*3;i++)
3744 splitportal->points[i] = backpoints[i];
3745 splitportal->numpoints = numbackpoints;
3746 for (i = 0;i < numfrontpoints*3;i++)
3747 portal->points[i] = frontpoints[i];
3748 portal->numpoints = numfrontpoints;
3749
3750 if (side == 0)
3751 {
3752 AddPortalToNodes(portal, front, other_node);
3753 AddPortalToNodes(splitportal, back, other_node);
3754 }
3755 else
3756 {
3757 AddPortalToNodes(portal, other_node, front);
3758 AddPortalToNodes(splitportal, other_node, back);
3759 }
3760 }
3761
3764
3766}
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
#define CON_WARN
Definition console.h:101
#define PORTAL_DIST_EPSILON
static void AddPortalToNodes(portal_t *p, mnode_t *front, mnode_t *back)
static void RemovePortalFromNodes(portal_t *portal)
void PolygonD_QuadForPlane(double *outpoints, double planenormalx, double planenormaly, double planenormalz, double planedist, double quadsize)
Definition polygon.c:54
void PolygonD_Divide(int innumpoints, const double *inpoints, double planenormalx, double planenormaly, double planenormalz, double planedist, double epsilon, int outfrontmaxpoints, double *outfrontpoints, int *neededfrontpoints, int outbackmaxpoints, double *outbackpoints, int *neededbackpoints, int *oncountpointer)
Definition polygon.c:245
struct portal_s * chain
void * Mem_ExpandableArray_AllocRecord(memexpandablearray_t *l)
Definition zone.c:695
#define Mem_Realloc(pool, data, size)
Definition zone.h:94

References AddPortalToNodes(), portal_t::chain, mnode_t::children, Con_Print(), CON_WARN, mplane_t::dist, Host_Error(), i, loadmodel, MAX_PORTALPOINTS, Mem_ExpandableArray_AllocRecord(), Mem_Realloc, model_t::mempool, Mod_BSP_RecursiveNodePortals(), portal_t::next, portal_t::nodes, mplane_t::normal, NULL, portal_t::numpoints, mnode_t::plane, portal_t::plane, portal_t::points, PolygonD_Divide(), PolygonD_QuadForPlane(), PORTAL_DIST_EPSILON, portalarray, portalpointsbuffer, portalpointsbufferoffset, portalpointsbuffersize, mnode_t::portals, RemovePortalFromNodes(), and VectorNegate.

Referenced by Mod_BSP_MakePortals(), and Mod_BSP_RecursiveNodePortals().

◆ Mod_BSP_RecursiveRecalcNodeBBox()

static void Mod_BSP_RecursiveRecalcNodeBBox ( mnode_t * node)
static

Definition at line 3395 of file model_brush.c.

3396{
3397 // process only nodes (leafs already had their box calculated)
3398 if (!node->plane)
3399 return;
3400
3401 // calculate children first
3404
3405 // make combined bounding box from children
3406 node->mins[0] = min(node->children[0]->mins[0], node->children[1]->mins[0]);
3407 node->mins[1] = min(node->children[0]->mins[1], node->children[1]->mins[1]);
3408 node->mins[2] = min(node->children[0]->mins[2], node->children[1]->mins[2]);
3409 node->maxs[0] = max(node->children[0]->maxs[0], node->children[1]->maxs[0]);
3410 node->maxs[1] = max(node->children[0]->maxs[1], node->children[1]->maxs[1]);
3411 node->maxs[2] = max(node->children[0]->maxs[2], node->children[1]->maxs[2]);
3412}
#define max(A, B)
Definition mathlib.h:38
#define min(A, B)
Definition mathlib.h:37

References mnode_t::children, max, mnode_t::maxs, min, mnode_t::mins, Mod_BSP_RecursiveRecalcNodeBBox(), and mnode_t::plane.

Referenced by Mod_BSP_FinalizePortals(), and Mod_BSP_RecursiveRecalcNodeBBox().

◆ Mod_CollisionBIH_PointSuperContents()

int Mod_CollisionBIH_PointSuperContents ( struct model_s * model,
int frame,
const vec3_t point )

Definition at line 7348 of file model_brush.c.

7349{
7350 trace_t trace;
7351 Mod_CollisionBIH_TracePoint(model, NULL, NULL, &trace, point, 0, 0, 0);
7352 return trace.startsupercontents;
7353}
void Mod_CollisionBIH_TracePoint(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)

References Mod_CollisionBIH_TracePoint(), model, NULL, and trace_t::startsupercontents.

Referenced by Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_CollisionBIH_PointSuperContents_Mesh()

int Mod_CollisionBIH_PointSuperContents_Mesh ( struct model_s * model,
int frame,
const vec3_t start )

Definition at line 7387 of file model_brush.c.

7388{
7389#if 0
7390 // broken - needs to be modified to count front faces and backfaces to figure out if it is in solid
7391 trace_t trace;
7392 vec3_t end;
7393 VectorSet(end, start[0], start[1], model->normalmins[2]);
7394 memset(&trace, 0, sizeof(trace));
7395 trace.fraction = 1;
7396 trace.hitsupercontentsmask = hitsupercontentsmask;
7397 trace.skipsupercontentsmask = skipsupercontentsmask;
7398 trace.skipmaterialflagsmask = skipmaterialflagsmask;
7399 Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
7400 return trace.hitsupercontents;
7401#else
7402 return 0;
7403#endif
7404}
void Mod_CollisionBIH_TraceLine(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
vec_t vec3_t[3]
Definition qtypes.h:71
int hitsupercontents
Definition collision.h:58

References trace_t::fraction, trace_t::hitsupercontents, trace_t::hitsupercontentsmask, Mod_CollisionBIH_TraceLine(), model, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, and VectorSet.

Referenced by Mod_DARKPLACESMODEL_Load(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_IDP3_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_OBJ_Load(), Mod_PSKMODEL_Load(), and Mod_ZYMOTICMODEL_Load().

◆ Mod_CollisionBIH_TraceBox()

void Mod_CollisionBIH_TraceBox ( model_t * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
const vec3_t start,
const vec3_t boxmins,
const vec3_t boxmaxs,
const vec3_t end,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )

Definition at line 7332 of file model_brush.c.

7333{
7334 colboxbrushf_t thisbrush_start, thisbrush_end;
7335 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
7336
7337 // box trace, performed as brush trace
7338 VectorAdd(start, boxmins, boxstartmins);
7339 VectorAdd(start, boxmaxs, boxstartmaxs);
7340 VectorAdd(end, boxmins, boxendmins);
7341 VectorAdd(end, boxmaxs, boxendmaxs);
7342 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
7343 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
7344 Mod_CollisionBIH_TraceBrush(model, frameblend, skeleton, trace, &thisbrush_start.brush, &thisbrush_end.brush, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
7345}
void Collision_BrushForBox(colboxbrushf_t *boxbrush, const vec3_t mins, const vec3_t maxs, int supercontents, int q3surfaceflags, const texture_t *texture)
Definition collision.c:1141
void Mod_CollisionBIH_TraceBrush(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, colbrushf_t *thisbrush_start, colbrushf_t *thisbrush_end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
colbrushf_t brush
Definition collision.h:139

References colboxbrushf_t::brush, Collision_BrushForBox(), Mod_CollisionBIH_TraceBrush(), model, NULL, and VectorAdd.

Referenced by Mod_DARKPLACESMODEL_Load(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_IDP3_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_MDLMD2MD3_TraceBox(), Mod_OBJ_Load(), Mod_PSKMODEL_Load(), Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), Mod_VBSP_Load(), Mod_ZYMOTICMODEL_Load(), and PHYS_NudgeOutOfSolid().

◆ Mod_CollisionBIH_TraceBrush()

void Mod_CollisionBIH_TraceBrush ( model_t * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
colbrushf_t * thisbrush_start,
colbrushf_t * thisbrush_end,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )

Definition at line 7092 of file model_brush.c.

7093{
7094 const bih_t *bih;
7095 const bih_leaf_t *leaf;
7096 const bih_node_t *node;
7097 const colbrushf_t *brush;
7098 const int *e;
7099 const texture_t *texture;
7100 vec3_t start, end, startmins, startmaxs, endmins, endmaxs, mins, maxs;
7101 vec3_t nodebigmins, nodebigmaxs, nodestart, nodeend, sweepnodemins, sweepnodemaxs;
7102 vec_t d1, d2, d3, d4, f, nodestackline[1024][6];
7103 int axis, nodenum, nodestackpos = 0, nodestack[1024];
7104
7105 if (mod_q3bsp_optimizedtraceline.integer && VectorCompare(thisbrush_start->mins, thisbrush_start->maxs) && VectorCompare(thisbrush_end->mins, thisbrush_end->maxs))
7106 {
7107 if (VectorCompare(thisbrush_start->mins, thisbrush_end->mins))
7108 Mod_CollisionBIH_TracePoint(model, frameblend, skeleton, trace, thisbrush_start->mins, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
7109 else
7110 Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, thisbrush_start->mins, thisbrush_end->mins, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
7111 return;
7112 }
7113
7114 bih = &model->collision_bih;
7115 if(!bih->nodes)
7116 return;
7117 nodenum = bih->rootnode;
7118
7119 // box trace, performed as brush trace
7120 memset(trace, 0, sizeof(*trace));
7121 trace->fraction = 1;
7122 trace->hitsupercontentsmask = hitsupercontentsmask;
7123 trace->skipsupercontentsmask = skipsupercontentsmask;
7124 trace->skipmaterialflagsmask = skipmaterialflagsmask;
7125
7126 // calculate tracebox-like parameters for efficient culling
7127 VectorAdd(thisbrush_start->mins, thisbrush_start->maxs, start);
7128 VectorAdd(thisbrush_end->mins, thisbrush_end->maxs, end);
7129 VectorM(0.5f, start, start);
7130 VectorM(0.5f, end, end);
7131 VectorSubtract(thisbrush_start->mins, start, startmins);
7132 VectorSubtract(thisbrush_start->maxs, start, startmaxs);
7133 VectorSubtract(thisbrush_end->mins, end, endmins);
7134 VectorSubtract(thisbrush_end->maxs, end, endmaxs);
7135 mins[0] = min(startmins[0], endmins[0]);
7136 mins[1] = min(startmins[1], endmins[1]);
7137 mins[2] = min(startmins[2], endmins[2]);
7138 maxs[0] = max(startmaxs[0], endmaxs[0]);
7139 maxs[1] = max(startmaxs[1], endmaxs[1]);
7140 maxs[2] = max(startmaxs[2], endmaxs[2]);
7141
7142 // push first node
7143 nodestackline[nodestackpos][0] = start[0];
7144 nodestackline[nodestackpos][1] = start[1];
7145 nodestackline[nodestackpos][2] = start[2];
7146 nodestackline[nodestackpos][3] = end[0];
7147 nodestackline[nodestackpos][4] = end[1];
7148 nodestackline[nodestackpos][5] = end[2];
7149 nodestack[nodestackpos++] = nodenum;
7150 while (nodestackpos)
7151 {
7152 nodenum = nodestack[--nodestackpos];
7153 node = bih->nodes + nodenum;
7154 VectorCopy(nodestackline[nodestackpos], nodestart);
7155 VectorCopy(nodestackline[nodestackpos] + 3, nodeend);
7156 sweepnodemins[0] = min(nodestart[0], nodeend[0]) + mins[0] - 1;
7157 sweepnodemins[1] = min(nodestart[1], nodeend[1]) + mins[1] - 1;
7158 sweepnodemins[2] = min(nodestart[2], nodeend[2]) + mins[2] - 1;
7159 sweepnodemaxs[0] = max(nodestart[0], nodeend[0]) + maxs[0] + 1;
7160 sweepnodemaxs[1] = max(nodestart[1], nodeend[1]) + maxs[1] + 1;
7161 sweepnodemaxs[2] = max(nodestart[2], nodeend[2]) + maxs[2] + 1;
7162 if (!BoxesOverlap(sweepnodemins, sweepnodemaxs, node->mins, node->maxs))
7163 continue;
7164 assert(node->type <= BIH_UNORDERED);
7165 if (node->type != BIH_UNORDERED)
7166 {
7167 if(nodestackpos > 1024 - 2)
7168 //Out of stack
7169 continue;
7170 // recurse children of the split
7171 axis = node->type - BIH_SPLITX;
7172 d1 = node->backmax - mins[axis] - nodestart[axis];
7173 d2 = node->backmax - mins[axis] - nodeend[axis];
7174 d3 = nodestart[axis] - (node->frontmin - maxs[axis]);
7175 d4 = nodeend[axis] - (node->frontmin - maxs[axis]);
7176 f = 1.f / (nodeend[axis] - nodestart[axis]);
7177 switch((d1 < 0) | ((d2 < 0) << 1) | ((d3 < 0) << 2) | ((d4 < 0) << 3))
7178 {
7179 case 0: /* >>>> */
7180 VectorCopy(nodestart, nodestackline[nodestackpos]);
7181 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7182 nodestack[nodestackpos++] = node->back;
7183 VectorCopy(nodestart, nodestackline[nodestackpos]);
7184 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7185 nodestack[nodestackpos++] = node->front;
7186 break;
7187 case 1: /* <>>> */
7188 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos]);
7189 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7190 nodestack[nodestackpos++] = node->back;
7191 VectorCopy(nodestart, nodestackline[nodestackpos]);
7192 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7193 nodestack[nodestackpos++] = node->front;
7194 break;
7195 case 2: /* ><>> */
7196 VectorCopy(nodestart, nodestackline[nodestackpos]);
7197 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos] + 3);
7198 nodestack[nodestackpos++] = node->back;
7199 VectorCopy(nodestart, nodestackline[nodestackpos]);
7200 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7201 nodestack[nodestackpos++] = node->front;
7202 break;
7203 case 3: /* <<>> */
7204 VectorCopy(nodestart, nodestackline[nodestackpos]);
7205 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7206 nodestack[nodestackpos++] = node->front;
7207 break;
7208 case 4: /* >><> */
7209 VectorCopy(nodestart, nodestackline[nodestackpos]);
7210 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7211 nodestack[nodestackpos++] = node->back;
7212 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos]);
7213 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7214 nodestack[nodestackpos++] = node->front;
7215 break;
7216 case 5: /* <><> */
7217 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos]);
7218 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7219 nodestack[nodestackpos++] = node->back;
7220 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos]);
7221 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7222 nodestack[nodestackpos++] = node->front;
7223 break;
7224 case 6: /* ><<> */
7225 VectorCopy(nodestart, nodestackline[nodestackpos]);
7226 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos] + 3);
7227 nodestack[nodestackpos++] = node->back;
7228 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos]);
7229 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7230 nodestack[nodestackpos++] = node->front;
7231 break;
7232 case 7: /* <<<> */
7233 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos]);
7234 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7235 nodestack[nodestackpos++] = node->front;
7236 break;
7237 case 8: /* >>>< */
7238 VectorCopy(nodestart, nodestackline[nodestackpos]);
7239 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7240 nodestack[nodestackpos++] = node->back;
7241 VectorCopy(nodestart, nodestackline[nodestackpos]);
7242 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos] + 3);
7243 nodestack[nodestackpos++] = node->front;
7244 break;
7245 case 9: /* <>>< */
7246 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos]);
7247 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7248 nodestack[nodestackpos++] = node->back;
7249 VectorCopy(nodestart, nodestackline[nodestackpos]);
7250 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos] + 3);
7251 nodestack[nodestackpos++] = node->front;
7252 break;
7253 case 10: /* ><>< */
7254 VectorCopy(nodestart, nodestackline[nodestackpos]);
7255 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos] + 3);
7256 nodestack[nodestackpos++] = node->back;
7257 VectorCopy(nodestart, nodestackline[nodestackpos]);
7258 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos] + 3);
7259 nodestack[nodestackpos++] = node->front;
7260 break;
7261 case 11: /* <<>< */
7262 VectorCopy(nodestart, nodestackline[nodestackpos]);
7263 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos] + 3);
7264 nodestack[nodestackpos++] = node->front;
7265 break;
7266 case 12: /* >><< */
7267 VectorCopy(nodestart, nodestackline[nodestackpos]);
7268 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7269 nodestack[nodestackpos++] = node->back;
7270 break;
7271 case 13: /* <><< */
7272 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos]);
7273 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7274 nodestack[nodestackpos++] = node->back;
7275 break;
7276 case 14: /* ><<< */
7277 VectorCopy(nodestart, nodestackline[nodestackpos]);
7278 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos] + 3);
7279 nodestack[nodestackpos++] = node->back;
7280 break;
7281 case 15: /* <<<< */
7282 break;
7283 }
7284 }
7285 else
7286 {
7287 // calculate sweep bounds for this node
7288 // copy node bounds into local variables and expand to get Minkowski Sum of the two shapes
7289 VectorSubtract(node->mins, maxs, nodebigmins);
7290 VectorSubtract(node->maxs, mins, nodebigmaxs);
7291 // clip line to this node bounds
7292 axis = 0; d1 = nodestart[axis] - nodebigmins[axis]; d2 = nodeend[axis] - nodebigmins[axis]; if (d1 < 0) { if (d2 < 0) continue; f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodestart); } else if (d2 < 0) { f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodeend); } d1 = nodebigmaxs[axis] - nodestart[axis]; d2 = nodebigmaxs[axis] - nodeend[axis]; if (d1 < 0) { if (d2 < 0) continue; f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodestart); } else if (d2 < 0) { f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodeend); }
7293 axis = 1; d1 = nodestart[axis] - nodebigmins[axis]; d2 = nodeend[axis] - nodebigmins[axis]; if (d1 < 0) { if (d2 < 0) continue; f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodestart); } else if (d2 < 0) { f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodeend); } d1 = nodebigmaxs[axis] - nodestart[axis]; d2 = nodebigmaxs[axis] - nodeend[axis]; if (d1 < 0) { if (d2 < 0) continue; f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodestart); } else if (d2 < 0) { f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodeend); }
7294 axis = 2; d1 = nodestart[axis] - nodebigmins[axis]; d2 = nodeend[axis] - nodebigmins[axis]; if (d1 < 0) { if (d2 < 0) continue; f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodestart); } else if (d2 < 0) { f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodeend); } d1 = nodebigmaxs[axis] - nodestart[axis]; d2 = nodebigmaxs[axis] - nodeend[axis]; if (d1 < 0) { if (d2 < 0) continue; f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodestart); } else if (d2 < 0) { f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodeend); }
7295 // some of the line intersected the enlarged node box
7296 // calculate sweep bounds for this node
7297 sweepnodemins[0] = min(nodestart[0], nodeend[0]) + mins[0] - 1;
7298 sweepnodemins[1] = min(nodestart[1], nodeend[1]) + mins[1] - 1;
7299 sweepnodemins[2] = min(nodestart[2], nodeend[2]) + mins[2] - 1;
7300 sweepnodemaxs[0] = max(nodestart[0], nodeend[0]) + maxs[0] + 1;
7301 sweepnodemaxs[1] = max(nodestart[1], nodeend[1]) + maxs[1] + 1;
7302 sweepnodemaxs[2] = max(nodestart[2], nodeend[2]) + maxs[2] + 1;
7303 for (axis = 0;axis < BIH_MAXUNORDEREDCHILDREN && node->children[axis] >= 0;axis++)
7304 {
7305 leaf = bih->leafs + node->children[axis];
7306 if (!BoxesOverlap(sweepnodemins, sweepnodemaxs, leaf->mins, leaf->maxs))
7307 continue;
7308 switch(leaf->type)
7309 {
7310 case BIH_BRUSH:
7311 brush = model->brush.data_brushes[leaf->itemindex].colbrushf;
7312 Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, brush, brush);
7313 break;
7316 continue;
7317 e = model->brush.data_collisionelement3i + 3*leaf->itemindex;
7318 texture = model->data_textures + leaf->textureindex;
7319 Collision_TraceBrushTriangleFloat(trace, thisbrush_start, thisbrush_end, model->brush.data_collisionvertex3f + e[0] * 3, model->brush.data_collisionvertex3f + e[1] * 3, model->brush.data_collisionvertex3f + e[2] * 3, texture->supercontents, texture->surfaceflags, texture);
7320 break;
7321 case BIH_RENDERTRIANGLE:
7322 e = model->surfmesh.data_element3i + 3*leaf->itemindex;
7323 texture = model->data_textures + leaf->textureindex;
7324 Collision_TraceBrushTriangleFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.data_vertex3f + e[0] * 3, model->surfmesh.data_vertex3f + e[1] * 3, model->surfmesh.data_vertex3f + e[2] * 3, texture->supercontents, texture->surfaceflags, texture);
7325 break;
7326 }
7327 }
7328 }
7329 }
7330}
@ BIH_COLLISIONTRIANGLE
Definition bih.h:30
@ BIH_RENDERTRIANGLE
Definition bih.h:31
@ BIH_BRUSH
Definition bih.h:29
#define BIH_MAXUNORDEREDCHILDREN
Definition bih.h:9
@ BIH_UNORDERED
Definition bih.h:23
@ BIH_SPLITX
Definition bih.h:20
void Collision_TraceBrushTriangleFloat(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, const float *v0, const float *v1, const float *v2, int supercontents, int q3surfaceflags, const texture_t *texture)
Definition collision.c:1107
void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *trace_start, const colbrushf_t *trace_end, const colbrushf_t *other_start, const colbrushf_t *other_end)
Definition collision.c:559
GLenum GLenum GLuint texture
Definition glquake.h:613
#define VectorLerp(v1, lerp, v2, out)
Definition mathlib.h:120
#define VectorCompare(a, b)
Definition mathlib.h:113
#define VectorM(scale1, b1, out)
Definition mathlib.h:115
float vec_t
Definition qtypes.h:68
int textureindex
Definition bih.h:63
float maxs[3]
Definition bih.h:61
bih_leaftype_t type
Definition bih.h:59
int itemindex
Definition bih.h:65
float mins[3]
Definition bih.h:60
float maxs[3]
Definition bih.h:41
float mins[3]
Definition bih.h:40
float backmax
Definition bih.h:49
int children[BIH_MAXUNORDEREDCHILDREN]
Definition bih.h:52
int front
Definition bih.h:45
bih_nodetype_t type
Definition bih.h:37
int back
Definition bih.h:46
float frontmin
Definition bih.h:48
Definition bih.h:70
bih_node_t * nodes
Definition bih.h:77
bih_leaf_t * leafs
Definition bih.h:74
int rootnode
Definition bih.h:78

References bih_node_t::back, bih_node_t::backmax, BIH_BRUSH, BIH_COLLISIONTRIANGLE, BIH_MAXUNORDEREDCHILDREN, BIH_RENDERTRIANGLE, BIH_SPLITX, BIH_UNORDERED, BoxesOverlap, bih_node_t::children, Collision_TraceBrushBrushFloat(), Collision_TraceBrushTriangleFloat(), f, trace_t::fraction, bih_node_t::front, bih_node_t::frontmin, trace_t::hitsupercontentsmask, cvar_t::integer, bih_leaf_t::itemindex, bih_t::leafs, max, bih_leaf_t::maxs, bih_node_t::maxs, colbrushf_t::maxs, maxs, min, bih_leaf_t::mins, bih_node_t::mins, colbrushf_t::mins, mins, Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint(), mod_q3bsp_curves_collisions, mod_q3bsp_optimizedtraceline, model, bih_t::nodes, bih_t::rootnode, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, texture, bih_leaf_t::textureindex, bih_leaf_t::type, bih_node_t::type, VectorAdd, VectorCompare, VectorCopy, VectorLerp, VectorM, and VectorSubtract.

Referenced by Mod_CollisionBIH_TraceBox(), Mod_DARKPLACESMODEL_Load(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_IDP3_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_OBJ_Load(), Mod_PSKMODEL_Load(), Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), Mod_VBSP_Load(), and Mod_ZYMOTICMODEL_Load().

◆ Mod_CollisionBIH_TraceLine()

void Mod_CollisionBIH_TraceLine ( model_t * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
const vec3_t start,
const vec3_t end,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )

Definition at line 7082 of file model_brush.c.

7083{
7084 if (VectorCompare(start, end))
7085 {
7086 Mod_CollisionBIH_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
7087 return;
7088 }
7089 Mod_CollisionBIH_TraceLineShared(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, &model->collision_bih);
7090}
static void Mod_CollisionBIH_TraceLineShared(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, const bih_t *bih)

References Mod_CollisionBIH_TraceLineShared(), Mod_CollisionBIH_TracePoint(), model, and VectorCompare.

Referenced by Mod_CollisionBIH_PointSuperContents_Mesh(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLineOfSight(), Mod_CollisionBIH_TracePoint_Mesh(), Mod_DARKPLACESMODEL_Load(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_IDP3_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_MDLMD2MD3_TraceLine(), Mod_OBJ_Load(), Mod_PSKMODEL_Load(), Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), Mod_VBSP_Load(), and Mod_ZYMOTICMODEL_Load().

◆ Mod_CollisionBIH_TraceLineAgainstSurfaces()

void Mod_CollisionBIH_TraceLineAgainstSurfaces ( model_t * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
const vec3_t start,
const vec3_t end,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )

Definition at line 7406 of file model_brush.c.

7407{
7408 Mod_CollisionBIH_TraceLineShared(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask, &model->render_bih);
7409}

References Mod_CollisionBIH_TraceLineShared(), and model.

Referenced by Mod_Q1BSP_Load().

◆ Mod_CollisionBIH_TraceLineOfSight()

qbool Mod_CollisionBIH_TraceLineOfSight ( struct model_s * model,
const vec3_t start,
const vec3_t end,
const vec3_t acceptmins,
const vec3_t acceptmaxs )

Definition at line 7355 of file model_brush.c.

7356{
7357 trace_t trace;
7359 return trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, acceptmins, acceptmaxs);
7360}
#define SUPERCONTENTS_VISBLOCKERMASK
Definition bspfile.h:219
#define MATERIALFLAGMASK_TRANSLUCENT
double endpos[3]
Definition collision.h:42

References BoxesOverlap, trace_t::endpos, trace_t::fraction, MATERIALFLAGMASK_TRANSLUCENT, Mod_CollisionBIH_TraceLine(), model, NULL, and SUPERCONTENTS_VISBLOCKERMASK.

◆ Mod_CollisionBIH_TraceLineShared()

static void Mod_CollisionBIH_TraceLineShared ( model_t * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
const vec3_t start,
const vec3_t end,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask,
const bih_t * bih )
static

Definition at line 6861 of file model_brush.c.

6862{
6863 const bih_leaf_t *leaf;
6864 const bih_node_t *node;
6865 const colbrushf_t *brush;
6866 const int *e;
6867 const texture_t *texture;
6868 vec3_t nodebigmins, nodebigmaxs, nodestart, nodeend, sweepnodemins, sweepnodemaxs;
6869 vec_t d1, d2, d3, d4, f, nodestackline[1024][6];
6870 int axis, nodenum, nodestackpos = 0, nodestack[1024];
6871
6872 if(!bih->nodes)
6873 return;
6874
6875 if (VectorCompare(start, end))
6876 {
6877 Mod_CollisionBIH_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
6878 return;
6879 }
6880
6881 nodenum = bih->rootnode;
6882
6883 memset(trace, 0, sizeof(*trace));
6884 trace->fraction = 1;
6885 trace->hitsupercontentsmask = hitsupercontentsmask;
6886 trace->skipsupercontentsmask = skipsupercontentsmask;
6887 trace->skipmaterialflagsmask = skipmaterialflagsmask;
6888
6889 // push first node
6890 nodestackline[nodestackpos][0] = start[0];
6891 nodestackline[nodestackpos][1] = start[1];
6892 nodestackline[nodestackpos][2] = start[2];
6893 nodestackline[nodestackpos][3] = end[0];
6894 nodestackline[nodestackpos][4] = end[1];
6895 nodestackline[nodestackpos][5] = end[2];
6896 nodestack[nodestackpos++] = nodenum;
6897 while (nodestackpos)
6898 {
6899 nodenum = nodestack[--nodestackpos];
6900 node = bih->nodes + nodenum;
6901 VectorCopy(nodestackline[nodestackpos], nodestart);
6902 VectorCopy(nodestackline[nodestackpos] + 3, nodeend);
6903 sweepnodemins[0] = min(nodestart[0], nodeend[0]) - 1;
6904 sweepnodemins[1] = min(nodestart[1], nodeend[1]) - 1;
6905 sweepnodemins[2] = min(nodestart[2], nodeend[2]) - 1;
6906 sweepnodemaxs[0] = max(nodestart[0], nodeend[0]) + 1;
6907 sweepnodemaxs[1] = max(nodestart[1], nodeend[1]) + 1;
6908 sweepnodemaxs[2] = max(nodestart[2], nodeend[2]) + 1;
6909 if (!BoxesOverlap(sweepnodemins, sweepnodemaxs, node->mins, node->maxs) && !collision_bih_fullrecursion.integer)
6910 continue;
6911 assert(node->type <= BIH_UNORDERED);
6912 if (node->type != BIH_UNORDERED)
6913 {
6914 if(nodestackpos > 1024 - 2)
6915 //Out of stack
6916 continue;
6917 // recurse children of the split
6918 axis = node->type - BIH_SPLITX;
6919 d1 = node->backmax - nodestart[axis];
6920 d2 = node->backmax - nodeend[axis];
6921 d3 = nodestart[axis] - node->frontmin;
6922 d4 = nodeend[axis] - node->frontmin;
6923 f = 1.f / (nodeend[axis] - nodestart[axis]);
6925 d1 = d2 = d3 = d4 = 1; // force full recursion
6926 switch((d1 < 0) | ((d2 < 0) << 1) | ((d3 < 0) << 2) | ((d4 < 0) << 3))
6927 {
6928 case 0: /* >>>> */
6929 VectorCopy(nodestart, nodestackline[nodestackpos]);
6930 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6931 nodestack[nodestackpos++] = node->back;
6932 VectorCopy(nodestart, nodestackline[nodestackpos]);
6933 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6934 nodestack[nodestackpos++] = node->front;
6935 break;
6936 case 1: /* <>>> */
6937 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos]);
6938 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6939 nodestack[nodestackpos++] = node->back;
6940 VectorCopy(nodestart, nodestackline[nodestackpos]);
6941 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6942 nodestack[nodestackpos++] = node->front;
6943 break;
6944 case 2: /* ><>> */
6945 VectorCopy(nodestart, nodestackline[nodestackpos]);
6946 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos] + 3);
6947 nodestack[nodestackpos++] = node->back;
6948 VectorCopy(nodestart, nodestackline[nodestackpos]);
6949 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6950 nodestack[nodestackpos++] = node->front;
6951 break;
6952 case 3: /* <<>> */
6953 VectorCopy(nodestart, nodestackline[nodestackpos]);
6954 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6955 nodestack[nodestackpos++] = node->front;
6956 break;
6957 case 4: /* >><> */
6958 VectorCopy(nodestart, nodestackline[nodestackpos]);
6959 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6960 nodestack[nodestackpos++] = node->back;
6961 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos]);
6962 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6963 nodestack[nodestackpos++] = node->front;
6964 break;
6965 case 5: /* <><> */
6966 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos]);
6967 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6968 nodestack[nodestackpos++] = node->back;
6969 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos]);
6970 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6971 nodestack[nodestackpos++] = node->front;
6972 break;
6973 case 6: /* ><<> */
6974 VectorCopy(nodestart, nodestackline[nodestackpos]);
6975 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos] + 3);
6976 nodestack[nodestackpos++] = node->back;
6977 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos]);
6978 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6979 nodestack[nodestackpos++] = node->front;
6980 break;
6981 case 7: /* <<<> */
6982 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos]);
6983 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6984 nodestack[nodestackpos++] = node->front;
6985 break;
6986 case 8: /* >>>< */
6987 VectorCopy(nodestart, nodestackline[nodestackpos]);
6988 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6989 nodestack[nodestackpos++] = node->back;
6990 VectorCopy(nodestart, nodestackline[nodestackpos]);
6991 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos] + 3);
6992 nodestack[nodestackpos++] = node->front;
6993 break;
6994 case 9: /* <>>< */
6995 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos]);
6996 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
6997 nodestack[nodestackpos++] = node->back;
6998 VectorCopy(nodestart, nodestackline[nodestackpos]);
6999 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos] + 3);
7000 nodestack[nodestackpos++] = node->front;
7001 break;
7002 case 10: /* ><>< */
7003 VectorCopy(nodestart, nodestackline[nodestackpos]);
7004 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos] + 3);
7005 nodestack[nodestackpos++] = node->back;
7006 VectorCopy(nodestart, nodestackline[nodestackpos]);
7007 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos] + 3);
7008 nodestack[nodestackpos++] = node->front;
7009 break;
7010 case 11: /* <<>< */
7011 VectorCopy(nodestart, nodestackline[nodestackpos]);
7012 VectorLerp(nodestart, -d3 * f, nodeend, nodestackline[nodestackpos] + 3);
7013 nodestack[nodestackpos++] = node->front;
7014 break;
7015 case 12: /* >><< */
7016 VectorCopy(nodestart, nodestackline[nodestackpos]);
7017 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7018 nodestack[nodestackpos++] = node->back;
7019 break;
7020 case 13: /* <><< */
7021 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos]);
7022 VectorCopy(nodeend, nodestackline[nodestackpos] + 3);
7023 nodestack[nodestackpos++] = node->back;
7024 break;
7025 case 14: /* ><<< */
7026 VectorCopy(nodestart, nodestackline[nodestackpos]);
7027 VectorLerp(nodestart, d1 * f, nodeend, nodestackline[nodestackpos] + 3);
7028 nodestack[nodestackpos++] = node->back;
7029 break;
7030 case 15: /* <<<< */
7031 break;
7032 }
7033 }
7034 else
7035 {
7036 // calculate sweep bounds for this node
7037 // copy node bounds into local variables
7038 VectorCopy(node->mins, nodebigmins);
7039 VectorCopy(node->maxs, nodebigmaxs);
7040 // clip line to this node bounds
7041 axis = 0; d1 = nodestart[axis] - nodebigmins[axis]; d2 = nodeend[axis] - nodebigmins[axis]; if (d1 < 0) { if (d2 < 0) continue; f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodestart); } else if (d2 < 0) { f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodeend); } d1 = nodebigmaxs[axis] - nodestart[axis]; d2 = nodebigmaxs[axis] - nodeend[axis]; if (d1 < 0) { if (d2 < 0) continue; f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodestart); } else if (d2 < 0) { f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodeend); }
7042 axis = 1; d1 = nodestart[axis] - nodebigmins[axis]; d2 = nodeend[axis] - nodebigmins[axis]; if (d1 < 0) { if (d2 < 0) continue; f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodestart); } else if (d2 < 0) { f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodeend); } d1 = nodebigmaxs[axis] - nodestart[axis]; d2 = nodebigmaxs[axis] - nodeend[axis]; if (d1 < 0) { if (d2 < 0) continue; f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodestart); } else if (d2 < 0) { f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodeend); }
7043 axis = 2; d1 = nodestart[axis] - nodebigmins[axis]; d2 = nodeend[axis] - nodebigmins[axis]; if (d1 < 0) { if (d2 < 0) continue; f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodestart); } else if (d2 < 0) { f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodeend); } d1 = nodebigmaxs[axis] - nodestart[axis]; d2 = nodebigmaxs[axis] - nodeend[axis]; if (d1 < 0) { if (d2 < 0) continue; f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodestart); } else if (d2 < 0) { f = d1 / (d1 - d2); VectorLerp(nodestart, f, nodeend, nodeend); }
7044 // some of the line intersected the enlarged node box
7045 // calculate sweep bounds for this node
7046 sweepnodemins[0] = min(nodestart[0], nodeend[0]) - 1;
7047 sweepnodemins[1] = min(nodestart[1], nodeend[1]) - 1;
7048 sweepnodemins[2] = min(nodestart[2], nodeend[2]) - 1;
7049 sweepnodemaxs[0] = max(nodestart[0], nodeend[0]) + 1;
7050 sweepnodemaxs[1] = max(nodestart[1], nodeend[1]) + 1;
7051 sweepnodemaxs[2] = max(nodestart[2], nodeend[2]) + 1;
7052 for (axis = 0;axis < BIH_MAXUNORDEREDCHILDREN && node->children[axis] >= 0;axis++)
7053 {
7054 leaf = bih->leafs + node->children[axis];
7055 // TODO: This is very expensive in Steel Storm. Framerate halved during even light combat.
7056 if (!BoxesOverlap(sweepnodemins, sweepnodemaxs, leaf->mins, leaf->maxs))
7057 continue;
7058 switch(leaf->type)
7059 {
7060 case BIH_BRUSH:
7061 brush = model->brush.data_brushes[leaf->itemindex].colbrushf;
7062 Collision_TraceLineBrushFloat(trace, start, end, brush, brush);
7063 break;
7066 continue;
7067 e = model->brush.data_collisionelement3i + 3*leaf->itemindex;
7068 texture = model->data_textures + leaf->textureindex;
7069 Collision_TraceLineTriangleFloat(trace, start, end, model->brush.data_collisionvertex3f + e[0] * 3, model->brush.data_collisionvertex3f + e[1] * 3, model->brush.data_collisionvertex3f + e[2] * 3, texture->supercontents, texture->surfaceflags, texture);
7070 break;
7071 case BIH_RENDERTRIANGLE:
7072 e = model->surfmesh.data_element3i + 3*leaf->itemindex;
7073 texture = model->data_textures + leaf->textureindex;
7074 Collision_TraceLineTriangleFloat(trace, start, end, model->surfmesh.data_vertex3f + e[0] * 3, model->surfmesh.data_vertex3f + e[1] * 3, model->surfmesh.data_vertex3f + e[2] * 3, texture->supercontents, texture->surfaceflags, texture);
7075 break;
7076 }
7077 }
7078 }
7079 }
7080}
void Collision_TraceLineTriangleFloat(trace_t *trace, const vec3_t linestart, const vec3_t lineend, const float *point0, const float *point1, const float *point2, int supercontents, int q3surfaceflags, const texture_t *texture)
Definition collision.c:1251
cvar_t collision_bih_fullrecursion
Definition collision.c:21

References bih_node_t::back, bih_node_t::backmax, BIH_BRUSH, BIH_COLLISIONTRIANGLE, BIH_MAXUNORDEREDCHILDREN, BIH_RENDERTRIANGLE, BIH_SPLITX, BIH_UNORDERED, BoxesOverlap, bih_node_t::children, collision_bih_fullrecursion, Collision_TraceLineBrushFloat(), Collision_TraceLineTriangleFloat(), f, trace_t::fraction, bih_node_t::front, bih_node_t::frontmin, trace_t::hitsupercontentsmask, cvar_t::integer, bih_leaf_t::itemindex, bih_t::leafs, max, bih_leaf_t::maxs, bih_node_t::maxs, min, bih_leaf_t::mins, bih_node_t::mins, Mod_CollisionBIH_TracePoint(), mod_q3bsp_curves_collisions, model, bih_t::nodes, bih_t::rootnode, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, texture, bih_leaf_t::textureindex, bih_leaf_t::type, bih_node_t::type, VectorCompare, VectorCopy, and VectorLerp.

Referenced by Mod_CollisionBIH_TraceLine(), and Mod_CollisionBIH_TraceLineAgainstSurfaces().

◆ Mod_CollisionBIH_TracePoint()

void Mod_CollisionBIH_TracePoint ( model_t * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
const vec3_t start,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )

Definition at line 6791 of file model_brush.c.

6792{
6793 const bih_t *bih;
6794 const bih_leaf_t *leaf;
6795 const bih_node_t *node;
6796 const colbrushf_t *brush;
6797 int axis;
6798 int nodenum;
6799 int nodestackpos = 0;
6800 int nodestack[1024];
6801
6802 memset(trace, 0, sizeof(*trace));
6803 trace->fraction = 1;
6804 trace->hitsupercontentsmask = hitsupercontentsmask;
6805 trace->skipsupercontentsmask = skipsupercontentsmask;
6806 trace->skipmaterialflagsmask = skipmaterialflagsmask;
6807
6808 bih = &model->collision_bih;
6809 if(!bih->nodes)
6810 return;
6811
6812 nodenum = bih->rootnode;
6813 nodestack[nodestackpos++] = nodenum;
6814 while (nodestackpos)
6815 {
6816 nodenum = nodestack[--nodestackpos];
6817 node = bih->nodes + nodenum;
6818 assert(node->type <= BIH_UNORDERED);
6819#if 1
6820 if (!BoxesOverlap(start, start, node->mins, node->maxs))
6821 continue;
6822#endif
6823 if (node->type != BIH_UNORDERED)
6824 {
6825 if(nodestackpos > 1024 - 2)
6826 //Out of stack
6827 continue;
6828 axis = node->type - BIH_SPLITX;
6829 if (start[axis] >= node->frontmin)
6830 nodestack[nodestackpos++] = node->front;
6831 if (start[axis] <= node->backmax)
6832 nodestack[nodestackpos++] = node->back;
6833 }
6834 else
6835 {
6836 for (axis = 0;axis < BIH_MAXUNORDEREDCHILDREN && node->children[axis] >= 0;axis++)
6837 {
6838 leaf = bih->leafs + node->children[axis];
6839#if 1
6840 if (!BoxesOverlap(start, start, leaf->mins, leaf->maxs))
6841 continue;
6842#endif
6843 switch(leaf->type)
6844 {
6845 case BIH_BRUSH:
6846 brush = model->brush.data_brushes[leaf->itemindex].colbrushf;
6847 Collision_TracePointBrushFloat(trace, start, brush);
6848 break;
6850 // collision triangle - skipped because they have no volume
6851 break;
6852 case BIH_RENDERTRIANGLE:
6853 // render triangle - skipped because they have no volume
6854 break;
6855 }
6856 }
6857 }
6858 }
6859}
void Collision_TracePointBrushFloat(trace_t *trace, const vec3_t linestart, const colbrushf_t *other_start)
Definition collision.c:923

References bih_node_t::back, bih_node_t::backmax, BIH_BRUSH, BIH_COLLISIONTRIANGLE, BIH_MAXUNORDEREDCHILDREN, BIH_RENDERTRIANGLE, BIH_SPLITX, BIH_UNORDERED, BoxesOverlap, bih_node_t::children, Collision_TracePointBrushFloat(), trace_t::fraction, bih_node_t::front, bih_node_t::frontmin, trace_t::hitsupercontentsmask, bih_leaf_t::itemindex, bih_t::leafs, bih_leaf_t::maxs, bih_node_t::maxs, bih_leaf_t::mins, bih_node_t::mins, model, bih_t::nodes, bih_t::rootnode, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, bih_leaf_t::type, and bih_node_t::type.

Referenced by Mod_CollisionBIH_PointSuperContents(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TraceLineShared(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_CollisionBIH_TracePoint_Mesh()

void Mod_CollisionBIH_TracePoint_Mesh ( model_t * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
const vec3_t start,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )

Definition at line 7362 of file model_brush.c.

7363{
7364#if 0
7365 // broken - needs to be modified to count front faces and backfaces to figure out if it is in solid
7366 vec3_t end;
7367 int hitsupercontents;
7368 VectorSet(end, start[0], start[1], model->normalmins[2]);
7369#endif
7370 memset(trace, 0, sizeof(*trace));
7371 trace->fraction = 1;
7372 trace->hitsupercontentsmask = hitsupercontentsmask;
7373 trace->skipsupercontentsmask = skipsupercontentsmask;
7374 trace->skipmaterialflagsmask = skipmaterialflagsmask;
7375#if 0
7376 Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
7377 hitsupercontents = trace->hitsupercontents;
7378 memset(trace, 0, sizeof(*trace));
7379 trace->fraction = 1;
7380 trace->hitsupercontentsmask = hitsupercontentsmask;
7381 trace->skipsupercontentsmask = skipsupercontentsmask;
7382 trace->skipmaterialflagsmask = skipmaterialflagsmask;
7383 trace->startsupercontents = hitsupercontents;
7384#endif
7385}

References trace_t::fraction, trace_t::hitsupercontents, trace_t::hitsupercontentsmask, Mod_CollisionBIH_TraceLine(), model, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, trace_t::startsupercontents, and VectorSet.

Referenced by Mod_DARKPLACESMODEL_Load(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_IDP3_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_OBJ_Load(), Mod_PSKMODEL_Load(), and Mod_ZYMOTICMODEL_Load().

◆ Mod_HLBSP_Load()

void Mod_HLBSP_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 3896 of file model_brush.c.

3897{
3898 mod->brush.ishlbsp = true;
3899 mod->modeldatatypestring = "HLBSP";
3900 Mod_Q1BSP_Load(mod, buffer, bufferend);
3901}

References buffer, mod(), and Mod_Q1BSP_Load().

◆ Mod_IBSP_Load()

void Mod_IBSP_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 7876 of file model_brush.c.

7877{
7878 int i = LittleLong(((int *)buffer)[1]);
7880 Mod_Q3BSP_Load(mod,buffer, bufferend);
7881 else if (i == Q2BSPVERSION)
7882 Mod_Q2BSP_Load(mod,buffer, bufferend);
7883 else
7884 Host_Error("Mod_IBSP_Load: unknown/unsupported version %i", i);
7885}
#define LittleLong(l)
Definition common.h:92
static void Mod_Q2BSP_Load(model_t *mod, void *buffer, void *bufferend)
static void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend)
#define Q2BSPVERSION
Definition model_q2bsp.h:7
#define Q3BSPVERSION_IG
Definition model_q3bsp.h:13
#define Q3BSPVERSION_LIVE
Definition model_q3bsp.h:12
#define Q3BSPVERSION
Definition model_q3bsp.h:11

References buffer, Host_Error(), i, LittleLong, mod(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), Q2BSPVERSION, Q3BSPVERSION, Q3BSPVERSION_IG, and Q3BSPVERSION_LIVE.

◆ Mod_MakeCollisionBIH()

bih_t * Mod_MakeCollisionBIH ( model_t * model,
qbool userendersurfaces,
bih_t * out )

Definition at line 7412 of file model_brush.c.

7413{
7414 int j;
7415 int bihnumleafs;
7416 int bihmaxnodes;
7417 int brushindex;
7418 int triangleindex;
7419 int bihleafindex;
7420 int nummodelbrushes = model->nummodelbrushes;
7421 const int *e;
7422 const int *collisionelement3i;
7423 const float *collisionvertex3f;
7424 const int *renderelement3i;
7425 const float *rendervertex3f;
7426 bih_leaf_t *bihleafs;
7427 bih_node_t *bihnodes;
7428 int *temp_leafsort;
7429 int *temp_leafsortscratch;
7430 const msurface_t *surface;
7431 const q3mbrush_t *brush;
7432
7433 // find out how many BIH leaf nodes we need
7434 bihnumleafs = 0;
7435 if (userendersurfaces)
7436 {
7437 for (j = model->submodelsurfaces_start;j < model->submodelsurfaces_end;j++)
7438 bihnumleafs += model->data_surfaces[j].num_triangles;
7439 }
7440 else
7441 {
7442 for (brushindex = 0, brush = model->brush.data_brushes + brushindex+model->firstmodelbrush;brushindex < nummodelbrushes;brushindex++, brush++)
7443 if (brush->colbrushf)
7444 bihnumleafs++;
7445 for (j = model->submodelsurfaces_start;j < model->submodelsurfaces_end;j++)
7446 {
7447 if (model->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_MESHCOLLISIONS)
7448 bihnumleafs += model->data_surfaces[j].num_triangles + model->data_surfaces[j].num_collisiontriangles;
7449 else
7450 bihnumleafs += model->data_surfaces[j].num_collisiontriangles;
7451 }
7452 }
7453
7454 if (!bihnumleafs)
7455 return NULL;
7456
7457 // allocate the memory for the BIH leaf nodes
7458 bihleafs = (bih_leaf_t *)Mem_Alloc(loadmodel->mempool, sizeof(bih_leaf_t) * bihnumleafs);
7459
7460 // now populate the BIH leaf nodes
7461 bihleafindex = 0;
7462
7463 // add render surfaces
7464 renderelement3i = model->surfmesh.data_element3i;
7465 rendervertex3f = model->surfmesh.data_vertex3f;
7466 for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++)
7467 {
7468 surface = model->data_surfaces + j;
7469 for (triangleindex = 0, e = renderelement3i + 3*surface->num_firsttriangle;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7470 {
7471 if (!userendersurfaces && !(surface->texture->basematerialflags & MATERIALFLAG_MESHCOLLISIONS))
7472 continue;
7473 bihleafs[bihleafindex].type = BIH_RENDERTRIANGLE;
7474 bihleafs[bihleafindex].textureindex = surface->texture - model->data_textures;
7475 bihleafs[bihleafindex].surfaceindex = surface - model->data_surfaces;
7476 bihleafs[bihleafindex].itemindex = triangleindex+surface->num_firsttriangle;
7477 bihleafs[bihleafindex].mins[0] = min(rendervertex3f[3*e[0]+0], min(rendervertex3f[3*e[1]+0], rendervertex3f[3*e[2]+0])) - 1;
7478 bihleafs[bihleafindex].mins[1] = min(rendervertex3f[3*e[0]+1], min(rendervertex3f[3*e[1]+1], rendervertex3f[3*e[2]+1])) - 1;
7479 bihleafs[bihleafindex].mins[2] = min(rendervertex3f[3*e[0]+2], min(rendervertex3f[3*e[1]+2], rendervertex3f[3*e[2]+2])) - 1;
7480 bihleafs[bihleafindex].maxs[0] = max(rendervertex3f[3*e[0]+0], max(rendervertex3f[3*e[1]+0], rendervertex3f[3*e[2]+0])) + 1;
7481 bihleafs[bihleafindex].maxs[1] = max(rendervertex3f[3*e[0]+1], max(rendervertex3f[3*e[1]+1], rendervertex3f[3*e[2]+1])) + 1;
7482 bihleafs[bihleafindex].maxs[2] = max(rendervertex3f[3*e[0]+2], max(rendervertex3f[3*e[1]+2], rendervertex3f[3*e[2]+2])) + 1;
7483 bihleafindex++;
7484 }
7485 }
7486
7487 if (!userendersurfaces)
7488 {
7489 // add collision brushes
7490 for (brushindex = 0, brush = model->brush.data_brushes + brushindex+model->firstmodelbrush;brushindex < nummodelbrushes;brushindex++, brush++)
7491 {
7492 if (!brush->colbrushf)
7493 continue;
7494 bihleafs[bihleafindex].type = BIH_BRUSH;
7495 bihleafs[bihleafindex].textureindex = brush->texture - model->data_textures;
7496 bihleafs[bihleafindex].surfaceindex = -1;
7497 bihleafs[bihleafindex].itemindex = brushindex+model->firstmodelbrush;
7498 VectorCopy(brush->colbrushf->mins, bihleafs[bihleafindex].mins);
7499 VectorCopy(brush->colbrushf->maxs, bihleafs[bihleafindex].maxs);
7500 bihleafindex++;
7501 }
7502
7503 // add collision surfaces
7504 collisionelement3i = model->brush.data_collisionelement3i;
7505 collisionvertex3f = model->brush.data_collisionvertex3f;
7506 for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++)
7507 {
7508 surface = model->data_surfaces + j;
7509 for (triangleindex = 0, e = collisionelement3i + 3*surface->num_firstcollisiontriangle;triangleindex < surface->num_collisiontriangles;triangleindex++, e += 3)
7510 {
7511 bihleafs[bihleafindex].type = BIH_COLLISIONTRIANGLE;
7512 bihleafs[bihleafindex].textureindex = surface->texture - model->data_textures;
7513 bihleafs[bihleafindex].surfaceindex = surface - model->data_surfaces;
7514 bihleafs[bihleafindex].itemindex = triangleindex+surface->num_firstcollisiontriangle;
7515 bihleafs[bihleafindex].mins[0] = min(collisionvertex3f[3*e[0]+0], min(collisionvertex3f[3*e[1]+0], collisionvertex3f[3*e[2]+0])) - 1;
7516 bihleafs[bihleafindex].mins[1] = min(collisionvertex3f[3*e[0]+1], min(collisionvertex3f[3*e[1]+1], collisionvertex3f[3*e[2]+1])) - 1;
7517 bihleafs[bihleafindex].mins[2] = min(collisionvertex3f[3*e[0]+2], min(collisionvertex3f[3*e[1]+2], collisionvertex3f[3*e[2]+2])) - 1;
7518 bihleafs[bihleafindex].maxs[0] = max(collisionvertex3f[3*e[0]+0], max(collisionvertex3f[3*e[1]+0], collisionvertex3f[3*e[2]+0])) + 1;
7519 bihleafs[bihleafindex].maxs[1] = max(collisionvertex3f[3*e[0]+1], max(collisionvertex3f[3*e[1]+1], collisionvertex3f[3*e[2]+1])) + 1;
7520 bihleafs[bihleafindex].maxs[2] = max(collisionvertex3f[3*e[0]+2], max(collisionvertex3f[3*e[1]+2], collisionvertex3f[3*e[2]+2])) + 1;
7521 bihleafindex++;
7522 }
7523 }
7524 }
7525
7526 // allocate buffers for the produced and temporary data
7527 bihmaxnodes = bihnumleafs + 1;
7528 bihnodes = (bih_node_t *)Mem_Alloc(loadmodel->mempool, sizeof(bih_node_t) * bihmaxnodes);
7529 temp_leafsort = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int) * bihnumleafs * 2);
7530 temp_leafsortscratch = temp_leafsort + bihnumleafs;
7531
7532 // now build it
7533 BIH_Build(out, bihnumleafs, bihleafs, bihmaxnodes, bihnodes, temp_leafsort, temp_leafsortscratch);
7534
7535 // we're done with the temporary data
7536 Mem_Free(temp_leafsort);
7537
7538 // resize the BIH nodes array if it over-allocated
7539 if (out->maxnodes > out->numnodes)
7540 {
7541 out->maxnodes = out->numnodes;
7542 out->nodes = (bih_node_t *)Mem_Realloc(loadmodel->mempool, out->nodes, out->numnodes * sizeof(bih_node_t));
7543 }
7544
7545 return out;
7546}
int BIH_Build(bih_t *bih, int numleafs, bih_leaf_t *leafs, int maxnodes, bih_node_t *nodes, int *temp_leafsort, int *temp_leafsortscratch)
Definition bih.c:133
#define MATERIALFLAG_MESHCOLLISIONS
Definition model_brush.h:77
int surfaceindex
Definition bih.h:64
int maxnodes
Definition bih.h:84
int numnodes
Definition bih.h:76
int num_firstcollisiontriangle
mesh information for collisions (only used by q3bsp curves)
struct colbrushf_s * colbrushf
struct texture_s * texture

References texture_t::basematerialflags, BIH_BRUSH, BIH_Build(), BIH_COLLISIONTRIANGLE, BIH_RENDERTRIANGLE, q3mbrush_t::colbrushf, bih_leaf_t::itemindex, loadmodel, MATERIALFLAG_MESHCOLLISIONS, max, bih_t::maxnodes, bih_leaf_t::maxs, Mem_Alloc, Mem_Free, Mem_Realloc, model_t::mempool, min, bih_leaf_t::mins, model, bih_t::nodes, NULL, msurface_t::num_firstcollisiontriangle, msurface_t::num_firsttriangle, bih_t::numnodes, bih_leaf_t::surfaceindex, msurface_t::texture, q3mbrush_t::texture, bih_leaf_t::textureindex, bih_leaf_t::type, and VectorCopy.

Referenced by Mod_DARKPLACESMODEL_Load(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_IDP3_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_OBJ_Load(), Mod_PSKMODEL_Load(), Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_ZYMOTICMODEL_Load().

◆ Mod_MAP_Load()

void Mod_MAP_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 8399 of file model_brush.c.

8400{
8401 Host_Error("Mod_MAP_Load: not yet implemented");
8402}

References Host_Error().

◆ Mod_OBJ_Load()

void Mod_OBJ_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 8417 of file model_brush.c.

8418{
8419 const char *textbase = (char *)buffer, *text = textbase;
8420 char *s;
8421 char *argv[512];
8422 char line[1024];
8423 char materialname[MAX_QPATH];
8424 int i, j, l, numvertices, firstvertex, firsttriangle, elementindex, vertexindex, surfacevertices, surfacetriangles, surfaceelements, submodelindex = 0;
8425 int index1, index2, index3;
8426 objvertex_t vfirst, vprev, vcurrent;
8427 int argc;
8428 int linelen;
8429 int numtriangles = 0;
8430 int maxtriangles = 0;
8431 objvertex_t *vertices = NULL;
8432 int linenumber = 0;
8433 int maxtextures = 0, numtextures = 0, textureindex = 0;
8434 int maxv = 0, numv = 1;
8435 int maxvt = 0, numvt = 1;
8436 int maxvn = 0, numvn = 1;
8437 char *texturenames = NULL;
8438 float dist, modelradius, modelyawradius, yawradius;
8439 float *obj_v = NULL;
8440 float *obj_vt = NULL;
8441 float *obj_vn = NULL;
8442 float mins[3];
8443 float maxs[3];
8444 float corner[3];
8445 objvertex_t *thisvertex = NULL;
8446 int vertexhashindex;
8447 int *vertexhashtable = NULL;
8448 objvertex_t *vertexhashdata = NULL;
8449 objvertex_t *vdata = NULL;
8450 int vertexhashsize = 0;
8451 int vertexhashcount = 0;
8452 skinfile_t *skinfiles = NULL;
8453 unsigned char *data = NULL;
8454 int *submodelfirstsurface;
8455 msurface_t *tempsurface;
8456 msurface_t *tempsurfaces;
8457
8458 memset(&vfirst, 0, sizeof(vfirst));
8459 memset(&vprev, 0, sizeof(vprev));
8460 memset(&vcurrent, 0, sizeof(vcurrent));
8461
8462 dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
8463
8465
8467 loadmodel->soundfromcenter = true;
8496
8497 skinfiles = Mod_LoadSkinFiles();
8498 if (loadmodel->numskins < 1)
8499 loadmodel->numskins = 1;
8500
8501 // make skinscenes for the skins (no groups)
8503 for (i = 0;i < loadmodel->numskins;i++)
8504 {
8507 loadmodel->skinscenes[i].loop = true;
8509 }
8510
8513
8514 // we always have model 0, i.e. the first "submodel"
8516
8517 // parse the OBJ text now
8518 for(;;)
8519 {
8520 static char emptyarg[1] = "";
8521 if (!*text)
8522 break;
8523 linenumber++;
8524 linelen = 0;
8525 for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
8526 line[linelen] = text[linelen];
8527 line[linelen] = 0;
8528 for (argc = 0;argc < 4;argc++)
8529 argv[argc] = emptyarg;
8530 argc = 0;
8531 s = line;
8532 while (*s == ' ' || *s == '\t')
8533 s++;
8534 while (*s)
8535 {
8536 argv[argc++] = s;
8537 while (*s > ' ')
8538 s++;
8539 if (!*s)
8540 break;
8541 *s++ = 0;
8542 while (*s == ' ' || *s == '\t')
8543 s++;
8544 }
8545 text += linelen;
8546 if (*text == '\r')
8547 text++;
8548 if (*text == '\n')
8549 text++;
8550 if (!argc)
8551 continue;
8552 if (argv[0][0] == '#')
8553 continue;
8554 if (!strcmp(argv[0], "v"))
8555 {
8556 if (maxv <= numv)
8557 {
8558 maxv = max(maxv * 2, 1024);
8559 obj_v = (float *)Mem_Realloc(tempmempool, obj_v, maxv * sizeof(float[3]));
8560 }
8562 {
8563 obj_v[numv*3+0] = atof(argv[1]);
8564 obj_v[numv*3+2] = atof(argv[2]);
8565 obj_v[numv*3+1] = atof(argv[3]);
8566 }
8567 else
8568 {
8569 obj_v[numv*3+0] = atof(argv[1]);
8570 obj_v[numv*3+1] = atof(argv[2]);
8571 obj_v[numv*3+2] = atof(argv[3]);
8572 }
8573 numv++;
8574 }
8575 else if (!strcmp(argv[0], "vt"))
8576 {
8577 if (maxvt <= numvt)
8578 {
8579 maxvt = max(maxvt * 2, 1024);
8580 obj_vt = (float *)Mem_Realloc(tempmempool, obj_vt, maxvt * sizeof(float[2]));
8581 }
8582 obj_vt[numvt*2+0] = atof(argv[1]);
8583 obj_vt[numvt*2+1] = 1-atof(argv[2]);
8584 numvt++;
8585 }
8586 else if (!strcmp(argv[0], "vn"))
8587 {
8588 if (maxvn <= numvn)
8589 {
8590 maxvn = max(maxvn * 2, 1024);
8591 obj_vn = (float *)Mem_Realloc(tempmempool, obj_vn, maxvn * sizeof(float[3]));
8592 }
8594 {
8595 obj_vn[numvn*3+0] = atof(argv[1]);
8596 obj_vn[numvn*3+2] = atof(argv[2]);
8597 obj_vn[numvn*3+1] = atof(argv[3]);
8598 }
8599 else
8600 {
8601 obj_vn[numvn*3+0] = atof(argv[1]);
8602 obj_vn[numvn*3+1] = atof(argv[2]);
8603 obj_vn[numvn*3+2] = atof(argv[3]);
8604 }
8605 numvn++;
8606 }
8607 else if (!strcmp(argv[0], "f"))
8608 {
8609 if (!numtextures)
8610 {
8611 if (maxtextures <= numtextures)
8612 {
8613 maxtextures = max(maxtextures * 2, 256);
8614 texturenames = (char *)Mem_Realloc(loadmodel->mempool, texturenames, maxtextures * MAX_QPATH);
8615 }
8616 textureindex = numtextures++;
8617 dp_strlcpy(texturenames + textureindex*MAX_QPATH, loadmodel->name, MAX_QPATH);
8618 }
8619 for (j = 1;j < argc;j++)
8620 {
8621 index1 = atoi(argv[j]);
8622 while(argv[j][0] && argv[j][0] != '/')
8623 argv[j]++;
8624 if (argv[j][0])
8625 argv[j]++;
8626 index2 = atoi(argv[j]);
8627 while(argv[j][0] && argv[j][0] != '/')
8628 argv[j]++;
8629 if (argv[j][0])
8630 argv[j]++;
8631 index3 = atoi(argv[j]);
8632 // negative refers to a recent vertex
8633 // zero means not specified
8634 // positive means an absolute vertex index
8635 if (index1 < 0)
8636 index1 = numv - index1;
8637 if (index2 < 0)
8638 index2 = numvt - index2;
8639 if (index3 < 0)
8640 index3 = numvn - index3;
8641 vcurrent.nextindex = -1;
8642 vcurrent.textureindex = textureindex;
8643 vcurrent.submodelindex = submodelindex;
8644 if (obj_v && index1 >= 0 && index1 < numv)
8645 VectorCopy(obj_v + 3*index1, vcurrent.v);
8646 if (obj_vt && index2 >= 0 && index2 < numvt)
8647 Vector2Copy(obj_vt + 2*index2, vcurrent.vt);
8648 if (obj_vn && index3 >= 0 && index3 < numvn)
8649 VectorCopy(obj_vn + 3*index3, vcurrent.vn);
8650 if (numtriangles == 0)
8651 {
8652 VectorCopy(vcurrent.v, mins);
8653 VectorCopy(vcurrent.v, maxs);
8654 }
8655 else
8656 {
8657 mins[0] = min(mins[0], vcurrent.v[0]);
8658 mins[1] = min(mins[1], vcurrent.v[1]);
8659 mins[2] = min(mins[2], vcurrent.v[2]);
8660 maxs[0] = max(maxs[0], vcurrent.v[0]);
8661 maxs[1] = max(maxs[1], vcurrent.v[1]);
8662 maxs[2] = max(maxs[2], vcurrent.v[2]);
8663 }
8664 if (j == 1)
8665 vfirst = vcurrent;
8666 else if (j >= 3)
8667 {
8668 if (maxtriangles <= numtriangles)
8669 {
8670 maxtriangles = max(maxtriangles * 2, 32768);
8671 vertices = (objvertex_t*)Mem_Realloc(loadmodel->mempool, vertices, maxtriangles * sizeof(objvertex_t[3]));
8672 }
8674 {
8675 vertices[numtriangles*3+0] = vfirst;
8676 vertices[numtriangles*3+1] = vprev;
8677 vertices[numtriangles*3+2] = vcurrent;
8678 }
8679 else
8680 {
8681 vertices[numtriangles*3+0] = vfirst;
8682 vertices[numtriangles*3+2] = vprev;
8683 vertices[numtriangles*3+1] = vcurrent;
8684 }
8685 numtriangles++;
8686 }
8687 vprev = vcurrent;
8688 }
8689 }
8690 else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
8691 {
8692 submodelindex = atof(argv[1]);
8693 loadmodel->brush.numsubmodels = max(submodelindex + 1, loadmodel->brush.numsubmodels);
8694 }
8695 else if (!strcmp(argv[0], "usemtl"))
8696 {
8697 for (i = 0;i < numtextures;i++)
8698 if (!strcmp(texturenames+i*MAX_QPATH, argv[1]))
8699 break;
8700 if (i < numtextures)
8701 textureindex = i;
8702 else
8703 {
8704 if (maxtextures <= numtextures)
8705 {
8706 maxtextures = max(maxtextures * 2, 256);
8707 texturenames = (char *)Mem_Realloc(loadmodel->mempool, texturenames, maxtextures * MAX_QPATH);
8708 }
8709 textureindex = numtextures++;
8710 dp_strlcpy(texturenames + textureindex*MAX_QPATH, argv[1], MAX_QPATH);
8711 }
8712 }
8713 }
8714
8715 // now that we have the OBJ data loaded as-is, we can convert it
8716
8717 // copy the model bounds, then enlarge the yaw and rotated bounds according to radius
8721 modelyawradius = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
8722 modelyawradius = dist*dist+modelyawradius*modelyawradius;
8723 modelradius = max(fabs(loadmodel->normalmins[2]), fabs(loadmodel->normalmaxs[2]));
8724 modelradius = modelyawradius + modelradius * modelradius;
8725 modelyawradius = sqrt(modelyawradius);
8726 modelradius = sqrt(modelradius);
8727 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -modelyawradius;
8729 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelyawradius;
8731 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -modelradius;
8732 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = modelradius;
8733 loadmodel->radius = modelradius;
8734 loadmodel->radius2 = modelradius * modelradius;
8735
8736 // allocate storage for triangles
8737 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, numtriangles * sizeof(int[3]));
8738 // allocate vertex hash structures to build an optimal vertex subset
8739 vertexhashsize = numtriangles*2;
8740 vertexhashtable = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int) * vertexhashsize);
8741 memset(vertexhashtable, 0xFF, sizeof(int) * vertexhashsize);
8742 vertexhashdata = (objvertex_t *)Mem_Alloc(loadmodel->mempool, sizeof(*vertexhashdata) * numtriangles*3);
8743 vertexhashcount = 0;
8744
8745 // gather surface stats for assigning vertex/triangle ranges
8746 firstvertex = 0;
8747 firsttriangle = 0;
8748 elementindex = 0;
8750 // allocate storage for the worst case number of surfaces, later we resize
8751 tempsurfaces = (msurface_t *)Mem_Alloc(loadmodel->mempool, numtextures * loadmodel->brush.numsubmodels * sizeof(msurface_t));
8752 submodelfirstsurface = (int *)Mem_Alloc(loadmodel->mempool, (loadmodel->brush.numsubmodels+1) * sizeof(int));
8753 tempsurface = tempsurfaces;
8754 for (submodelindex = 0;submodelindex < loadmodel->brush.numsubmodels;submodelindex++)
8755 {
8756 submodelfirstsurface[submodelindex] = loadmodel->num_surfaces;
8757 for (textureindex = 0;textureindex < numtextures;textureindex++)
8758 {
8759 for (vertexindex = 0;vertexindex < numtriangles*3;vertexindex++)
8760 {
8761 thisvertex = vertices + vertexindex;
8762 if (thisvertex->submodelindex == submodelindex && thisvertex->textureindex == textureindex)
8763 break;
8764 }
8765 // skip the surface creation if there are no triangles for it
8766 if (vertexindex == numtriangles*3)
8767 continue;
8768 // create a surface for these vertices
8769 surfacevertices = 0;
8770 surfaceelements = 0;
8771 // we hack in a texture index in the surface to be fixed up later...
8772 tempsurface->texture = (texture_t *)((size_t)textureindex);
8773 // calculate bounds as we go
8774 VectorCopy(thisvertex->v, tempsurface->mins);
8775 VectorCopy(thisvertex->v, tempsurface->maxs);
8776 for (;vertexindex < numtriangles*3;vertexindex++)
8777 {
8778 thisvertex = vertices + vertexindex;
8779 if (thisvertex->submodelindex != submodelindex)
8780 continue;
8781 if (thisvertex->textureindex != textureindex)
8782 continue;
8783 // add vertex to surface bounds
8784 tempsurface->mins[0] = min(tempsurface->mins[0], thisvertex->v[0]);
8785 tempsurface->mins[1] = min(tempsurface->mins[1], thisvertex->v[1]);
8786 tempsurface->mins[2] = min(tempsurface->mins[2], thisvertex->v[2]);
8787 tempsurface->maxs[0] = max(tempsurface->maxs[0], thisvertex->v[0]);
8788 tempsurface->maxs[1] = max(tempsurface->maxs[1], thisvertex->v[1]);
8789 tempsurface->maxs[2] = max(tempsurface->maxs[2], thisvertex->v[2]);
8790 // add the vertex if it is not found in the merged set, and
8791 // get its index (triangle element) for the surface
8792 vertexhashindex = (unsigned int)(thisvertex->v[0] * 3571 + thisvertex->v[0] * 1777 + thisvertex->v[0] * 457) % (unsigned int)vertexhashsize;
8793 for (i = vertexhashtable[vertexhashindex];i >= 0;i = vertexhashdata[i].nextindex)
8794 {
8795 vdata = vertexhashdata + i;
8796 if (vdata->submodelindex == thisvertex->submodelindex && vdata->textureindex == thisvertex->textureindex && VectorCompare(thisvertex->v, vdata->v) && VectorCompare(thisvertex->vn, vdata->vn) && Vector2Compare(thisvertex->vt, vdata->vt))
8797 break;
8798 }
8799 if (i < 0)
8800 {
8801 i = vertexhashcount++;
8802 vdata = vertexhashdata + i;
8803 *vdata = *thisvertex;
8804 vdata->nextindex = vertexhashtable[vertexhashindex];
8805 vertexhashtable[vertexhashindex] = i;
8806 surfacevertices++;
8807 }
8808 loadmodel->surfmesh.data_element3i[elementindex++] = i;
8809 surfaceelements++;
8810 }
8811 surfacetriangles = surfaceelements / 3;
8812 tempsurface->num_vertices = surfacevertices;
8813 tempsurface->num_triangles = surfacetriangles;
8814 tempsurface->num_firstvertex = firstvertex;
8815 tempsurface->num_firsttriangle = firsttriangle;
8816 firstvertex += tempsurface->num_vertices;
8817 firsttriangle += tempsurface->num_triangles;
8818 tempsurface++;
8820 }
8821 }
8822 submodelfirstsurface[submodelindex] = loadmodel->num_surfaces;
8823 numvertices = firstvertex;
8825 tempsurfaces = NULL;
8826
8827 // allocate storage for final mesh data
8828 loadmodel->num_textures = numtextures * loadmodel->numskins;
8829 loadmodel->num_texturesperskin = numtextures;
8830 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + numtriangles * sizeof(int[3]) + (numvertices <= 65536 ? numtriangles * sizeof(unsigned short[3]) : 0) + numvertices * sizeof(float[14]) + loadmodel->brush.numsubmodels * sizeof(model_t *));
8834 loadmodel->surfmesh.num_vertices = numvertices;
8835 loadmodel->surfmesh.num_triangles = numtriangles;
8836 loadmodel->surfmesh.data_vertex3f = (float *)data;data += numvertices * sizeof(float[3]);
8837 loadmodel->surfmesh.data_svector3f = (float *)data;data += numvertices * sizeof(float[3]);
8838 loadmodel->surfmesh.data_tvector3f = (float *)data;data += numvertices * sizeof(float[3]);
8839 loadmodel->surfmesh.data_normal3f = (float *)data;data += numvertices * sizeof(float[3]);
8840 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += numvertices * sizeof(float[2]);
8841
8842 if (loadmodel->surfmesh.num_vertices <= 65536) {
8843 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
8844 }
8845
8846 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
8847 {
8848 VectorCopy(vertexhashdata[j].v, loadmodel->surfmesh.data_vertex3f + 3*j);
8849 VectorCopy(vertexhashdata[j].vn, loadmodel->surfmesh.data_normal3f + 3*j);
8850 Vector2Copy(vertexhashdata[j].vt, loadmodel->surfmesh.data_texcoordtexture2f + 2*j);
8851 }
8852
8853 // load the textures
8854 for (textureindex = 0;textureindex < numtextures;textureindex++)
8855 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + textureindex, skinfiles, texturenames + textureindex*MAX_QPATH, texturenames + textureindex*MAX_QPATH);
8856 Mod_FreeSkinFiles(skinfiles);
8857
8858 // set the surface textures to their real values now that we loaded them...
8859 for (i = 0;i < loadmodel->num_surfaces;i++)
8861
8862 // free data
8863 Mem_Free(vertices);
8864 Mem_Free(texturenames);
8865 Mem_Free(obj_v);
8866 Mem_Free(obj_vt);
8867 Mem_Free(obj_vn);
8868 Mem_Free(vertexhashtable);
8869 Mem_Free(vertexhashdata);
8870
8871 // compute all the mesh information that was not loaded from the file
8873 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
8876 // generate normals if the file did not have them
8880
8881 // if this is a worldmodel and has no BSP tree, create a fake one for the purpose
8891 //if (loadmodel->num_nodes) loadmodel->data_nodes = (mnode_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_nodes * sizeof(mnode_t));
8892 //loadmodel->data_leafsurfaces = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->num_leafsurfaces * sizeof(int));
8904
8907
8908 mod = loadmodel;
8909 for (i = 0;i < loadmodel->brush.numsubmodels;i++)
8910 {
8911 if (i > 0)
8912 {
8913 char name[10];
8914 // duplicate the basic information
8915 dpsnprintf(name, sizeof(name), "*%i", i);
8917 // copy the base model to this one
8918 *mod = *loadmodel;
8919 // rename the clone back to its proper name
8920 dp_strlcpy(mod->name, name, sizeof(mod->name));
8921 mod->brush.parentmodel = loadmodel;
8922 // textures and memory belong to the main model
8923 mod->texturepool = NULL;
8924 mod->mempool = NULL;
8925 mod->brush.GetPVS = NULL;
8926 mod->brush.FatPVS = NULL;
8927 mod->brush.BoxTouchingPVS = NULL;
8928 mod->brush.BoxTouchingLeafPVS = NULL;
8929 mod->brush.BoxTouchingVisibleLeafs = NULL;
8930 mod->brush.FindBoxClusters = NULL;
8931 mod->brush.LightPoint = NULL;
8932 mod->brush.AmbientSoundLevelsForPoint = NULL;
8933 }
8934 mod->brush.submodel = i;
8937
8938 // make the model surface list (used by shadowing/lighting)
8939 mod->submodelsurfaces_start = submodelfirstsurface[i];
8940 mod->submodelsurfaces_end = submodelfirstsurface[i+1];
8941 mod->firstmodelbrush = 0;
8942 mod->nummodelbrushes = 0;
8943
8944 VectorClear(mod->normalmins);
8945 VectorClear(mod->normalmaxs);
8946 l = false;
8947 for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
8948 {
8949 const msurface_t *surface = mod->data_surfaces + j;
8950 const float *v3f = mod->surfmesh.data_vertex3f + 3 * surface->num_firstvertex;
8951 int k;
8952 if (!surface->num_vertices)
8953 continue;
8954 if (!l)
8955 {
8956 l = true;
8957 VectorCopy(v3f, mod->normalmins);
8958 VectorCopy(v3f, mod->normalmaxs);
8959 }
8960 for (k = 0;k < surface->num_vertices;k++, v3f += 3)
8961 {
8962 mod->normalmins[0] = min(mod->normalmins[0], v3f[0]);
8963 mod->normalmins[1] = min(mod->normalmins[1], v3f[1]);
8964 mod->normalmins[2] = min(mod->normalmins[2], v3f[2]);
8965 mod->normalmaxs[0] = max(mod->normalmaxs[0], v3f[0]);
8966 mod->normalmaxs[1] = max(mod->normalmaxs[1], v3f[1]);
8967 mod->normalmaxs[2] = max(mod->normalmaxs[2], v3f[2]);
8968 }
8969 }
8970 corner[0] = max(fabs(mod->normalmins[0]), fabs(mod->normalmaxs[0]));
8971 corner[1] = max(fabs(mod->normalmins[1]), fabs(mod->normalmaxs[1]));
8972 corner[2] = max(fabs(mod->normalmins[2]), fabs(mod->normalmaxs[2]));
8973 modelradius = sqrt(corner[0]*corner[0]+corner[1]*corner[1]+corner[2]*corner[2]);
8974 yawradius = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
8975 mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius;
8976 mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
8977 mod->yawmaxs[0] = mod->yawmaxs[1] = yawradius;
8978 mod->yawmins[0] = mod->yawmins[1] = -yawradius;
8979 mod->yawmins[2] = mod->normalmins[2];
8980 mod->yawmaxs[2] = mod->normalmaxs[2];
8981 mod->radius = modelradius;
8982 mod->radius2 = modelradius * modelradius;
8983
8985
8986 Mod_MakeCollisionBIH(mod, true, &mod->collision_bih);
8987 mod->render_bih = mod->collision_bih;
8988
8989 // generate VBOs and other shared data before cloning submodels
8990 if (i == 0)
8991 Mod_BuildVBOs();
8992 }
8993 mod = loadmodel;
8994 Mem_Free(submodelfirstsurface);
8995
8996 // make the model surface list (used by shadowing/lighting)
8998
8999 Con_DPrintf("Stats for obj model \"%s\": %i faces, %i nodes, %i leafs, %i clusters, %i clusterportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces);
9000}
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:997
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
cvar_t r_smoothnormals_areaweighting
Definition gl_rmain.c:229
void R_Mod_CompileShadowMap(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativelightdirection, float lightradius, int numsurfaces, const int *surfacelist)
Definition gl_rsurf.c:1286
void R_Mod_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs, unsigned char *visitingleafpvs, int numfrustumplanes, const mplane_t *frustumplanes, qbool noocclusion)
Definition gl_rsurf.c:1202
void R_Mod_DrawDebug(entity_render_t *ent)
Definition gl_rsurf.c:660
void R_Mod_DrawLight(entity_render_t *ent, int numsurfaces, const int *surfacelist, const unsigned char *lighttrispvs)
Definition gl_rsurf.c:1399
void R_Mod_Draw(entity_render_t *ent)
Definition gl_rsurf.c:637
void R_Mod_DrawShadowMap(int side, entity_render_t *ent, const vec3_t relativelightorigin, const vec3_t relativelightdirection, float lightradius, int modelnumsurfaces, const int *modelsurfacelist, const unsigned char *surfacesides, const vec3_t lightmins, const vec3_t lightmaxs)
Definition gl_rsurf.c:1320
void R_Mod_DrawDepth(entity_render_t *ent)
Definition gl_rsurf.c:645
void R_Mod_DrawPrepass(entity_render_t *ent)
Definition gl_rsurf.c:667
const GLdouble * v
Definition glquake.h:762
GLsizeiptr const GLvoid * data
Definition glquake.h:639
const GLchar * name
Definition glquake.h:601
#define Vector2Copy(in, out)
Definition mathlib.h:74
#define VectorLength2(a)
Definition mathlib.h:110
#define Vector2Compare(a, b)
Definition mathlib.h:73
float fabs(float f)
string argv(float n)
void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
int Mod_CollisionBIH_PointSuperContents_Mesh(struct model_s *model, int frame, const vec3_t start)
void Mod_CollisionBIH_TracePoint_Mesh(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
void Mod_CollisionBIH_TraceBox(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
static unsigned char nobsp_pvs[1]
bih_t * Mod_MakeCollisionBIH(model_t *model, qbool userendersurfaces, bih_t *out)
skinfile_t * Mod_LoadSkinFiles(void)
void Mod_BuildNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f, qbool areaweighting)
void Mod_BuildVBOs(void)
model_t * Mod_FindName(const char *name, const char *parentname)
void Mod_BuildTextureVectorsFromNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const float *texcoord2f, const float *normal3f, const int *elements, float *svector3f, float *tvector3f, qbool areaweighting)
void Mod_FreeSkinFiles(skinfile_t *skinfile)
void Mod_MakeSortedSurfaces(model_t *mod)
qbool Mod_ValidateElements(int *element3i, unsigned short *element3s, int numtriangles, int firstvertex, int numvertices, const char *filename, int fileline)
void Mod_SetDrawSkyAndWater(model_t *mod)
Sets the mod->DrawSky and mod->DrawAddWaterPlanes pointers conditionally based on whether surfaces in...
@ mod_obj
#define MAX_QPATH
max length of a quake game pathname
Definition qdefs.h:169
float framerate
int areaindex
int clusterindex
int(* BoxTouchingVisibleLeafs)(struct model_s *model, const unsigned char *visibleleafs, const vec3_t mins, const vec3_t maxs)
unsigned char * data_pvsclusters
int(* NativeContentsFromSuperContents)(int supercontents)
qbool(* TraceLineOfSight)(struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
qbool supportwateralpha
void(* RoundUpToHullSize)(struct model_s *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs)
size_t(* FatPVS)(struct model_s *model, const vec3_t org, vec_t radius, unsigned char **pvsbuffer, mempool_t *pool, qbool merge)
int(* SuperContentsFromNativeContents)(int nativecontents)
struct model_s ** submodels
unsigned char *(* GetPVS)(struct model_s *model, const vec3_t p)
int(* FindBoxClusters)(struct model_s *model, const vec3_t mins, const vec3_t maxs, int maxclusters, int *clusterlist)
mleaf_t *(* PointInLeaf)(struct model_s *model, const vec3_t p)
int num_pvsclusterbytes
void(* LightPoint)(struct model_s *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
void(* FindNonSolidLocation)(struct model_s *model, const vec3_t in, vec3_t out, vec_t radius)
void(* AmbientSoundLevelsForPoint)(struct model_s *model, const vec3_t p, unsigned char *out, int outsize)
int * data_leafsurfaces
int(* BoxTouchingPVS)(struct model_s *model, const unsigned char *pvs, const vec3_t mins, const vec3_t maxs)
int(* BoxTouchingLeafPVS)(struct model_s *model, const unsigned char *pvs, const vec3_t mins, const vec3_t maxs)
float radius2
void(* DrawDepth)(struct entity_render_s *ent)
modtype_t type
int(* PointSuperContents)(struct model_s *model, int frame, const vec3_t point)
vec3_t rotatedmins
vec3_t yawmaxs
int * modelsurfaces_sorted
surface indices of model in an optimal draw order (submodelindex -> texture -> lightmap -> index)
vec3_t rotatedmaxs
void(* Draw)(struct entity_render_s *ent)
float radius
void(* DrawPrepass)(struct entity_render_s *ent)
void(* TraceBox)(struct model_s *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, struct trace_s *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
vec3_t normalmaxs
void(* DrawShadowMap)(int side, struct entity_render_s *ent, const vec3_t relativelightorigin, const vec3_t relativelightdirection, float lightradius, int numsurfaces, const int *surfacelist, const unsigned char *surfacesides, const vec3_t lightmins, const vec3_t lightmaxs)
void(* TracePoint)(struct model_s *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, struct trace_s *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
void(* GetLightInfo)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs, unsigned char *visitingleafpvs, int numfrustumplanes, const mplane_t *frustumplanes, qbool noocclusion)
void(* DrawDebug)(struct entity_render_s *ent)
void(* TraceBrush)(struct model_s *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, struct trace_s *trace, struct colbrushf_s *start, struct colbrushf_s *end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
vec3_t yawmins
void(* CompileShadowMap)(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativelightdirection, float lightradius, int numsurfaces, const int *surfacelist)
void(* TraceLineAgainstSurfaces)(struct model_s *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, struct trace_s *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
vec3_t normalmins
int soundfromcenter
int num_surfaces
int num_textures
const char * modeldatatypestring
texture_t * data_textures
animscene_t * skinscenes
void(* DrawLight)(struct entity_render_s *ent, int numsurfaces, const int *surfacelist, const unsigned char *trispvs)
int num_texturesperskin
void(* TraceLine)(struct model_s *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, struct trace_s *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
int num_firstvertex
vec3_t mins
bounding box for onscreen checks
float vn[3]
float vt[2]
float * data_svector3f
unsigned short * data_element3s
float * data_tvector3f
int num_triangles
float * data_texcoordtexture2f
float * data_normal3f
mempool_t * tempmempool
Definition zone.c:794

References model_brush_t::AmbientSoundLevelsForPoint, mleaf_t::areaindex, argv(), model_brush_t::BoxTouchingLeafPVS, model_brush_t::BoxTouchingPVS, model_brush_t::BoxTouchingVisibleLeafs, model_t::brush, buffer, mleaf_t::clusterindex, mleaf_t::combinedsupercontents, model_t::CompileShadowMap, Con_DPrintf(), data, surfmesh_t::data_element3i, surfmesh_t::data_element3s, model_brush_t::data_leafs, model_brush_t::data_leafsurfaces, model_brush_t::data_nodes, surfmesh_t::data_normal3f, model_brush_t::data_pvsclusters, model_t::data_surfaces, surfmesh_t::data_svector3f, surfmesh_t::data_texcoordtexture2f, model_t::data_textures, surfmesh_t::data_tvector3f, surfmesh_t::data_vertex3f, dp_strlcpy, dpsnprintf(), model_t::Draw, model_t::DrawDebug, model_t::DrawDepth, model_t::DrawLight, model_t::DrawPrepass, model_t::DrawShadowMap, fabs(), model_brush_t::FatPVS, model_brush_t::FindBoxClusters, model_brush_t::FindNonSolidLocation, animscene_t::firstframe, mleaf_t::firstleafbrush, mleaf_t::firstleafsurface, animscene_t::framecount, animscene_t::framerate, model_t::GetLightInfo, model_brush_t::GetPVS, i, int(), cvar_t::integer, model_brush_t::LightPoint, loadmodel, animscene_t::loop, max, MAX_QPATH, maxs, mleaf_t::maxs, msurface_t::maxs, Mem_Alloc, Mem_Free, Mem_Realloc, model_t::mempool, min, mins, mleaf_t::mins, msurface_t::mins, mod(), Mod_BuildAliasSkinsFromSkinFiles(), Mod_BuildNormals(), Mod_BuildTextureVectorsFromNormals(), Mod_BuildVBOs(), Mod_CollisionBIH_PointSuperContents_Mesh(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint_Mesh(), Mod_FindName(), Mod_FreeSkinFiles(), Mod_LoadSkinFiles(), Mod_MakeCollisionBIH(), Mod_MakeSortedSurfaces(), mod_obj, mod_obj_orientation, Mod_SetDrawSkyAndWater(), Mod_ValidateElements(), model_t::modeldatatypestring, model_t::modelsurfaces_sorted, model_t::name, name, model_brush_t::NativeContentsFromSuperContents, objvertex_t::nextindex, nobsp_pvs, model_t::normalmaxs, model_t::normalmins, NULL, msurface_t::num_firsttriangle, msurface_t::num_firstvertex, model_brush_t::num_leafs, model_brush_t::num_leafsurfaces, model_brush_t::num_nodes, model_brush_t::num_portals, model_brush_t::num_pvsclusterbytes, model_brush_t::num_pvsclusters, model_t::num_surfaces, model_t::num_textures, model_t::num_texturesperskin, msurface_t::num_triangles, surfmesh_t::num_triangles, msurface_t::num_vertices, surfmesh_t::num_vertices, model_brush_t::num_visleafs, mleaf_t::numleafbrushes, mleaf_t::numleafsurfaces, model_t::numskins, model_brush_t::numsubmodels, model_brush_t::PointInLeaf, model_t::PointSuperContents, R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), R_Mod_GetLightInfo(), r_smoothnormals_areaweighting, model_t::radius, model_t::radius2, model_t::rotatedmaxs, model_t::rotatedmins, model_brush_t::RoundUpToHullSize, model_t::skinscenes, model_t::soundfromcenter, sqrt(), objvertex_t::submodelindex, model_brush_t::submodels, model_brush_t::SuperContentsFromNativeContents, model_brush_t::supportwateralpha, model_t::surfmesh, tempmempool, msurface_t::texture, objvertex_t::textureindex, model_t::TraceBox, model_t::TraceBrush, model_t::TraceLine, model_t::TraceLineAgainstSurfaces, model_brush_t::TraceLineOfSight, model_t::TracePoint, model_t::type, objvertex_t::v, v, Vector2Compare, Vector2Copy, VectorClear, VectorCompare, VectorCopy, VectorLength2, objvertex_t::vn, objvertex_t::vt, model_t::yawmaxs, and model_t::yawmins.

◆ Mod_Q1BSP_AmbientSoundLevelsForPoint()

static void Mod_Q1BSP_AmbientSoundLevelsForPoint ( model_t * model,
const vec3_t p,
unsigned char * out,
int outsize )
static

Definition at line 167 of file model_brush.c.

168{
169 int i;
170 mleaf_t *leaf;
171 leaf = Mod_BSP_PointInLeaf(model, p);
172 if (leaf)
173 {
174 i = min(outsize, (int)sizeof(leaf->ambient_sound_level));
175 if (i)
176 {
177 memcpy(out, leaf->ambient_sound_level, i);
178 out += i;
179 outsize -= i;
180 }
181 }
182 if (outsize)
183 memset(out, 0, outsize);
184}
static mleaf_t * Mod_BSP_PointInLeaf(model_t *model, const vec3_t p)
unsigned char ambient_sound_level[NUM_AMBIENTS]

References mleaf_t::ambient_sound_level, i, min, Mod_BSP_PointInLeaf(), and model.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_AssignNoShadowSkySurfaces()

static void Mod_Q1BSP_AssignNoShadowSkySurfaces ( model_t * mod)
static

Definition at line 3264 of file model_brush.c.

3265{
3266 int surfaceindex;
3267 msurface_t *surface;
3268 vec3_t center;
3269 int contents;
3270 for (surfaceindex = mod->submodelsurfaces_start; surfaceindex < mod->submodelsurfaces_end;surfaceindex++)
3271 {
3272 surface = mod->data_surfaces + surfaceindex;
3274 {
3275 // check if the point behind the surface polygon is SOLID or SKY contents
3276 VectorMAMAM(0.5f, surface->mins, 0.5f, surface->maxs, -0.25f, mod->surfmesh.data_normal3f + 3*surface->num_firstvertex, center);
3277 contents = Mod_Q1BSP_PointSuperContents(mod, 0, center);
3278 if (!(contents & SUPERCONTENTS_SOLID))
3279 surface->texture = surface->texture->skynoshadowtexture;
3280 }
3281 }
3282}
#define VectorMAMAM(scale1, b1, scale2, b2, scale3, b3, out)
Definition mathlib.h:117
static int Mod_Q1BSP_PointSuperContents(struct model_s *model, int frame, const vec3_t point)
#define MATERIALFLAG_SKY
Definition model_brush.h:92
struct texture_s * skynoshadowtexture
this points to a variant of the sky texture that has MATERIALFLAG_NOSHADOW, for the e1m5 logo shadow ...

References texture_t::basematerialflags, MATERIALFLAG_SKY, msurface_t::maxs, msurface_t::mins, mod(), Mod_Q1BSP_PointSuperContents(), msurface_t::num_firstvertex, texture_t::skynoshadowtexture, SUPERCONTENTS_SOLID, msurface_t::texture, and VectorMAMAM.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_CheckWaterAlphaSupport()

static qbool Mod_Q1BSP_CheckWaterAlphaSupport ( void )
static

Definition at line 3087 of file model_brush.c.

3088{
3089 int i, j;
3090 mleaf_t *leaf;
3091 const unsigned char *pvs;
3092 // if there's no vis data, assume supported (because everything is visible all the time)
3094 return true;
3095 // check all liquid leafs to see if they can see into empty leafs, if any
3096 // can we can assume this map supports r_wateralpha
3097 for (i = 0, leaf = loadmodel->brush.data_leafs;i < loadmodel->brush.num_leafs;i++, leaf++)
3098 {
3099 if ((leaf->contents == CONTENTS_WATER || leaf->contents == CONTENTS_SLIME) && leaf->clusterindex >= 0)
3100 {
3102 for (j = 0;j < loadmodel->brush.num_leafs;j++)
3104 return true;
3105 }
3106 }
3107 return false;
3108}
#define CONTENTS_SLIME
Definition bspfile.h:136
#define CONTENTS_WATER
Definition bspfile.h:135
int contents

References model_t::brush, CHECKPVSBIT, mleaf_t::clusterindex, mleaf_t::contents, CONTENTS_EMPTY, CONTENTS_SLIME, CONTENTS_WATER, model_brush_t::data_leafs, model_brush_t::data_pvsclusters, i, loadmodel, model_brush_t::num_leafs, and model_brush_t::num_pvsclusterbytes.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_Load()

void Mod_Q1BSP_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 3903 of file model_brush.c.

3904{
3905 int i, j, k;
3906 sizebuf_t lumpsb[HEADER_LUMPS];
3907 mmodel_t *bm;
3908 float dist, modelyawradius, modelradius;
3909 msurface_t *surface;
3910 hullinfo_t hullinfo;
3911 int totalstylesurfaces, totalstyles, stylecounts[256], remapstyles[256];
3912 model_brush_lightstyleinfo_t styleinfo[256];
3913 int *datapointer;
3914 model_brush_lightstyleinfo_t *lsidatapointer;
3915 sizebuf_t sb;
3916
3917 MSG_InitReadBuffer(&sb, (unsigned char *)buffer, (unsigned char *)bufferend - (unsigned char *)buffer);
3918
3919 mod->type = mod_brushq1;
3920
3921 mod->brush.skymasking = true;
3922 i = MSG_ReadLittleLong(&sb);
3923
3924 if(!mod->modeldatatypestring)
3925 mod->modeldatatypestring = "Q1BSP";
3926
3927// fill in hull info
3928 VectorClear (hullinfo.hullsizes[0][0]);
3929 VectorClear (hullinfo.hullsizes[0][1]);
3930 if (mod->brush.ishlbsp)
3931 {
3932 hullinfo.filehulls = 4;
3933 VectorSet (hullinfo.hullsizes[1][0], -16, -16, -36);
3934 VectorSet (hullinfo.hullsizes[1][1], 16, 16, 36);
3935 VectorSet (hullinfo.hullsizes[2][0], -32, -32, -32);
3936 VectorSet (hullinfo.hullsizes[2][1], 32, 32, 32);
3937 VectorSet (hullinfo.hullsizes[3][0], -16, -16, -18);
3938 VectorSet (hullinfo.hullsizes[3][1], 16, 16, 18);
3939 }
3940 else
3941 {
3942 hullinfo.filehulls = 4;
3943 VectorSet (hullinfo.hullsizes[1][0], -16, -16, -24);
3944 VectorSet (hullinfo.hullsizes[1][1], 16, 16, 32);
3945 VectorSet (hullinfo.hullsizes[2][0], -32, -32, -24);
3946 VectorSet (hullinfo.hullsizes[2][1], 32, 32, 64);
3947 }
3948
3949// read lumps
3950 for (i = 0; i < HEADER_LUMPS; i++)
3951 {
3952 int offset = MSG_ReadLittleLong(&sb);
3953 int size = MSG_ReadLittleLong(&sb);
3955 Host_Error("Mod_Q1BSP_Load: %s has invalid lump %i (offset %i, size %i, file size %i)\n", mod->name, i, offset, size, (int)sb.cursize);
3956 MSG_InitReadBuffer(&lumpsb[i], sb.data + offset, size);
3957 }
3958
3959 mod->soundfromcenter = true;
3960 mod->TraceBox = Mod_Q1BSP_TraceBox;
3961 mod->TraceLine = Mod_Q1BSP_TraceLine;
3962 mod->TracePoint = Mod_Q1BSP_TracePoint;
3963 mod->PointSuperContents = Mod_Q1BSP_PointSuperContents;
3964 mod->TraceLineAgainstSurfaces = Mod_Q1BSP_TraceLineAgainstSurfaces;
3965 mod->brush.TraceLineOfSight = Mod_Q1BSP_TraceLineOfSight;
3966 mod->brush.SuperContentsFromNativeContents = Mod_Q1BSP_SuperContentsFromNativeContents;
3967 mod->brush.NativeContentsFromSuperContents = Mod_Q1BSP_NativeContentsFromSuperContents;
3968 mod->brush.GetPVS = Mod_BSP_GetPVS;
3969 mod->brush.FatPVS = Mod_BSP_FatPVS;
3970 mod->brush.BoxTouchingPVS = Mod_BSP_BoxTouchingPVS;
3971 mod->brush.BoxTouchingLeafPVS = Mod_BSP_BoxTouchingLeafPVS;
3972 mod->brush.BoxTouchingVisibleLeafs = Mod_BSP_BoxTouchingVisibleLeafs;
3973 mod->brush.FindBoxClusters = Mod_BSP_FindBoxClusters;
3974 mod->brush.LightPoint = Mod_BSP_LightPoint;
3975 mod->brush.FindNonSolidLocation = Mod_BSP_FindNonSolidLocation;
3976 mod->brush.AmbientSoundLevelsForPoint = Mod_Q1BSP_AmbientSoundLevelsForPoint;
3977 mod->brush.RoundUpToHullSize = Mod_Q1BSP_RoundUpToHullSize;
3978 mod->brush.PointInLeaf = Mod_BSP_PointInLeaf;
3979 mod->Draw = R_Mod_Draw;
3980 mod->DrawDepth = R_Mod_DrawDepth;
3981 mod->DrawDebug = R_Mod_DrawDebug;
3982 mod->DrawPrepass = R_Mod_DrawPrepass;
3983 mod->GetLightInfo = R_Mod_GetLightInfo;
3984 mod->CompileShadowMap = R_Mod_CompileShadowMap;
3985 mod->DrawShadowMap = R_Mod_DrawShadowMap;
3986 mod->DrawLight = R_Mod_DrawLight;
3987
3988// load into heap
3989
3990 mod->brush.qw_md4sum = 0;
3991 mod->brush.qw_md4sum2 = 0;
3992 for (i = 0;i < HEADER_LUMPS;i++)
3993 {
3994 int temp;
3995 if (i == LUMP_ENTITIES)
3996 continue;
3997 temp = Com_BlockChecksum(lumpsb[i].data, lumpsb[i].cursize);
3998 mod->brush.qw_md4sum ^= LittleLong(temp);
3999 if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
4000 continue;
4001 mod->brush.qw_md4sum2 ^= LittleLong(temp);
4002 }
4003
4015 // load submodels before leafs because they contain the number of vis leafs
4016 Mod_BSP_LoadSubmodels(&lumpsb[LUMP_MODELS], &hullinfo);
4019 Mod_Q1BSP_LoadClipnodes(&lumpsb[LUMP_CLIPNODES], &hullinfo);
4020
4021 for (i = 0; i < HEADER_LUMPS; i++)
4022 if (lumpsb[i].readcount != lumpsb[i].cursize && i != LUMP_TEXTURES && i != LUMP_LIGHTING)
4023 Host_Error("Lump %i incorrectly loaded (readcount %i, size %i)\n", i, lumpsb[i].readcount, lumpsb[i].cursize);
4024
4025 // check if the map supports transparent water rendering
4027
4028 // we don't need the compressed pvs data anymore
4029 if (mod->brushq1.data_compressedpvs)
4030 Mem_Free(mod->brushq1.data_compressedpvs);
4031 mod->brushq1.data_compressedpvs = NULL;
4032 mod->brushq1.num_compressedpvs = 0;
4033
4037
4038 mod->numframes = 2; // regular and alternate animation
4039 mod->numskins = 1;
4040
4043
4044 // LadyHavoc: to clear the fog around the original quake submodel code, I
4045 // will explain:
4046 // first of all, some background info on the submodels:
4047 // model 0 is the map model (the world, named maps/e1m1.bsp for example)
4048 // model 1 and higher are submodels (doors and the like, named *1, *2, etc)
4049 // now the weird for loop itself:
4050 // the loop functions in an odd way, on each iteration it sets up the
4051 // current 'mod' model (which despite the confusing code IS the model of
4052 // the number i), at the end of the loop it duplicates the model to become
4053 // the next submodel, and loops back to set up the new submodel.
4054
4055 // LadyHavoc: now the explanation of my sane way (which works identically):
4056 // set up the world model, then on each submodel copy from the world model
4057 // and set up the submodel with the respective model info.
4058 totalstylesurfaces = 0;
4059 totalstyles = 0;
4060 for (i = 0;i < mod->brush.numsubmodels;i++)
4061 {
4062 memset(stylecounts, 0, sizeof(stylecounts));
4063 for (k = 0;k < mod->brushq1.submodels[i].numfaces;k++)
4064 {
4065 surface = mod->data_surfaces + mod->brushq1.submodels[i].firstface + k;
4066 for (j = 0;j < MAXLIGHTMAPS;j++)
4067 stylecounts[surface->lightmapinfo->styles[j]]++;
4068 }
4069 for (k = 0;k < 255;k++)
4070 {
4071 totalstyles++;
4072 if (stylecounts[k])
4073 totalstylesurfaces += stylecounts[k];
4074 }
4075 }
4076 // bones_was_here: using a separate allocation for model_brush_lightstyleinfo_t
4077 // because on a 64-bit machine it no longer has the same alignment requirement as int.
4078 lsidatapointer = Mem_AllocType(mod->mempool, model_brush_lightstyleinfo_t, totalstyles * sizeof(model_brush_lightstyleinfo_t));
4079 datapointer = Mem_AllocType(mod->mempool, int, mod->num_surfaces * sizeof(int) + totalstylesurfaces * sizeof(int));
4080 mod->modelsurfaces_sorted = datapointer;datapointer += mod->num_surfaces;
4081 for (i = 0;i < mod->brush.numsubmodels;i++)
4082 {
4083 // LadyHavoc: this code was originally at the end of this loop, but
4084 // has been transformed to something more readable at the start here.
4085
4086 if (i > 0)
4087 {
4088 char name[10];
4089 // duplicate the basic information
4090 dpsnprintf(name, sizeof(name), "*%i", i);
4092 // copy the base model to this one
4093 *mod = *loadmodel;
4094 // rename the clone back to its proper name
4095 dp_strlcpy(mod->name, name, sizeof(mod->name));
4096 mod->brush.parentmodel = loadmodel;
4097 // textures and memory belong to the main model
4098 mod->texturepool = NULL;
4099 mod->mempool = NULL;
4100 mod->brush.GetPVS = NULL;
4101 mod->brush.FatPVS = NULL;
4102 mod->brush.BoxTouchingPVS = NULL;
4103 mod->brush.BoxTouchingLeafPVS = NULL;
4104 mod->brush.BoxTouchingVisibleLeafs = NULL;
4105 mod->brush.FindBoxClusters = NULL;
4106 mod->brush.LightPoint = NULL;
4107 mod->brush.AmbientSoundLevelsForPoint = NULL;
4108 }
4109
4110 mod->brush.submodel = i;
4111
4114
4115 bm = &mod->brushq1.submodels[i];
4116
4117 mod->brushq1.hulls[0].firstclipnode = bm->headnode[0];
4118 for (j=1 ; j<MAX_MAP_HULLS ; j++)
4119 {
4120 mod->brushq1.hulls[j].firstclipnode = bm->headnode[j];
4121 mod->brushq1.hulls[j].lastclipnode = mod->brushq1.numclipnodes - 1;
4122 }
4123
4124 mod->submodelsurfaces_start = bm->firstface;
4125 mod->submodelsurfaces_end = bm->firstface + bm->numfaces;
4126
4127 // set node/leaf parents for this submodel
4128 Mod_BSP_LoadNodes_RecursiveSetParent(mod->brush.data_nodes + mod->brushq1.hulls[0].firstclipnode, NULL);
4129
4130 // this has to occur after hull info has been set, as it uses Mod_Q1BSP_PointSuperContents
4132
4133 // copy the submodel bounds, then enlarge the yaw and rotated bounds according to radius
4134 // (previously this code measured the radius of the vertices of surfaces in the submodel, but that broke submodels that contain only CLIP brushes, which do not produce surfaces)
4135 VectorCopy(bm->mins, mod->normalmins);
4136 VectorCopy(bm->maxs, mod->normalmaxs);
4137 dist = max(fabs(mod->normalmins[0]), fabs(mod->normalmaxs[0]));
4138 modelyawradius = max(fabs(mod->normalmins[1]), fabs(mod->normalmaxs[1]));
4139 modelyawradius = dist*dist+modelyawradius*modelyawradius;
4140 modelradius = max(fabs(mod->normalmins[2]), fabs(mod->normalmaxs[2]));
4141 modelradius = modelyawradius + modelradius * modelradius;
4142 modelyawradius = sqrt(modelyawradius);
4143 modelradius = sqrt(modelradius);
4144 mod->yawmins[0] = mod->yawmins[1] = -modelyawradius;
4145 mod->yawmins[2] = mod->normalmins[2];
4146 mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius;
4147 mod->yawmaxs[2] = mod->normalmaxs[2];
4148 mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius;
4149 mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
4150 mod->radius = modelradius;
4151 mod->radius2 = modelradius * modelradius;
4152
4154
4155 if (mod->submodelsurfaces_start < mod->submodelsurfaces_end)
4156 {
4157 // build lightstyle update chains
4158 // (used to rapidly mark lightmapupdateflags on many surfaces
4159 // when d_lightstylevalue changes)
4160 memset(stylecounts, 0, sizeof(stylecounts));
4161 for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
4162 for (j = 0;j < MAXLIGHTMAPS;j++)
4163 stylecounts[mod->data_surfaces[k].lightmapinfo->styles[j]]++;
4164 mod->brushq1.num_lightstyles = 0;
4165 for (k = 0;k < 255;k++)
4166 {
4167 if (stylecounts[k])
4168 {
4169 styleinfo[mod->brushq1.num_lightstyles].style = k;
4170 styleinfo[mod->brushq1.num_lightstyles].value = 0;
4171 styleinfo[mod->brushq1.num_lightstyles].numsurfaces = 0;
4172 styleinfo[mod->brushq1.num_lightstyles].surfacelist = datapointer;datapointer += stylecounts[k];
4173 remapstyles[k] = mod->brushq1.num_lightstyles;
4174 mod->brushq1.num_lightstyles++;
4175 }
4176 }
4177 for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
4178 {
4179 surface = mod->data_surfaces + k;
4180 for (j = 0;j < MAXLIGHTMAPS;j++)
4181 {
4182 if (surface->lightmapinfo->styles[j] != 255)
4183 {
4184 int r = remapstyles[surface->lightmapinfo->styles[j]];
4185 styleinfo[r].surfacelist[styleinfo[r].numsurfaces++] = k;
4186 }
4187 }
4188 }
4189 mod->brushq1.data_lightstyleinfo = lsidatapointer;lsidatapointer += mod->brushq1.num_lightstyles;
4190 memcpy(mod->brushq1.data_lightstyleinfo, styleinfo, mod->brushq1.num_lightstyles * sizeof(model_brush_lightstyleinfo_t));
4191 }
4192 else
4193 {
4194 // LadyHavoc: empty submodel(lacrima.bsp has such a glitch)
4195 Con_Printf(CON_WARN "warning: empty submodel *%i in %s\n", i+1, loadmodel->name);
4196 }
4197 //mod->brushq1.num_visleafs = bm->visleafs;
4198
4199 // build a Bounding Interval Hierarchy for culling triangles in light rendering
4200 Mod_MakeCollisionBIH(mod, true, &mod->render_bih);
4201
4203 {
4204 mod->collision_bih = mod->render_bih;
4205 // point traces and contents checks still use the bsp tree
4206 mod->TraceLine = Mod_CollisionBIH_TraceLine;
4207 mod->TraceBox = Mod_CollisionBIH_TraceBox;
4208 mod->TraceBrush = Mod_CollisionBIH_TraceBrush;
4209 mod->TraceLineAgainstSurfaces = Mod_CollisionBIH_TraceLineAgainstSurfaces;
4210 }
4211
4212 // generate VBOs and other shared data before cloning submodels
4213 if (i == 0)
4214 {
4215 Mod_BuildVBOs();
4217 //Mod_Q1BSP_ProcessLightList();
4218 }
4219 }
4220 mod = loadmodel;
4221
4222 // make the model surface list (used by shadowing/lighting)
4224
4225 Con_DPrintf("Stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces);
4226}
#define LUMP_LIGHTING
Definition bspfile.h:47
#define LUMP_EDGES
Definition bspfile.h:51
#define LUMP_SURFEDGES
Definition bspfile.h:52
#define LUMP_LEAFS
Definition bspfile.h:49
#define LUMP_VERTEXES
Definition bspfile.h:42
#define LUMP_CLIPNODES
Definition bspfile.h:48
#define HEADER_LUMPS
Definition bspfile.h:54
#define MAX_MAP_HULLS
Definition bspfile.h:24
#define LUMP_PLANES
Definition bspfile.h:40
#define LUMP_TEXINFO
Definition bspfile.h:45
#define LUMP_MODELS
Definition bspfile.h:53
#define LUMP_MARKSURFACES
Definition bspfile.h:50
#define LUMP_TEXTURES
Definition bspfile.h:41
#define LUMP_VISIBILITY
Definition bspfile.h:43
#define LUMP_FACES
Definition bspfile.h:46
#define LUMP_NODES
Definition bspfile.h:44
#define LUMP_ENTITIES
Definition bspfile.h:39
client_static_t cls
Definition cl_main.c:116
@ ca_dedicated
Definition client.h:530
void MSG_InitReadBuffer(sizebuf_t *buf, unsigned char *data, int size)
Definition com_msg.c:249
unsigned Com_BlockChecksum(void *buffer, int length)
Definition mdfour.c:198
vector size
GLuint GLuint GLintptr offset
Definition glquake.h:632
static void Mod_Q1BSP_LoadVertexes(sizebuf_t *sb)
static void Mod_BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
static void Mod_Q1BSP_LoadTextures(sizebuf_t *sb)
int Mod_Q1BSP_SuperContentsFromNativeContents(int nativecontents)
static void Mod_Q1BSP_LoadLeafs(sizebuf_t *sb)
static void Mod_Q1BSP_LoadClipnodes(sizebuf_t *sb, hullinfo_t *hullinfo)
static void Mod_Q1BSP_LoadPlanes(sizebuf_t *sb)
int Mod_Q1BSP_NativeContentsFromSuperContents(int supercontents)
static qbool Mod_Q1BSP_CheckWaterAlphaSupport(void)
static void Mod_Q1BSP_LoadTexinfo(sizebuf_t *sb)
static int Mod_BSP_BoxTouchingLeafPVS(model_t *model, const unsigned char *pvs, const vec3_t mins, const vec3_t maxs)
static void Mod_Q1BSP_LoadLighting(sizebuf_t *sb)
void Mod_CollisionBIH_TraceLineAgainstSurfaces(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
static void Mod_Q1BSP_TraceLineAgainstSurfaces(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
static size_t Mod_BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, unsigned char **pvsbuffer, mempool_t *pool, qbool merge)
static void Mod_Q1BSP_LoadEntities(sizebuf_t *sb)
static void Mod_Q1BSP_RoundUpToHullSize(model_t *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs)
static int Mod_BSP_FindBoxClusters(model_t *model, const vec3_t mins, const vec3_t maxs, int maxclusters, int *clusterlist)
static void Mod_Q1BSP_TraceLine(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
static void Mod_Q1BSP_LoadFaces(sizebuf_t *sb)
static void Mod_Q1BSP_TracePoint(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
static void Mod_BSP_FindNonSolidLocation(model_t *model, const vec3_t in, vec3_t out, float radius)
static void Mod_Q1BSP_AssignNoShadowSkySurfaces(model_t *mod)
static int Mod_BSP_BoxTouchingPVS(model_t *model, const unsigned char *pvs, const vec3_t mins, const vec3_t maxs)
static void Mod_Q1BSP_LoadSurfedges(sizebuf_t *sb)
static void Mod_Q1BSP_LoadLeaffaces(sizebuf_t *sb)
static void Mod_Q1BSP_LoadEdges(sizebuf_t *sb)
static void Mod_Q1BSP_LoadNodes(sizebuf_t *sb)
static void Mod_Q1BSP_AmbientSoundLevelsForPoint(model_t *model, const vec3_t p, unsigned char *out, int outsize)
static int Mod_BSP_BoxTouchingVisibleLeafs(model_t *model, const unsigned char *visibleleafs, const vec3_t mins, const vec3_t maxs)
static void Mod_Q1BSP_MakeHull0(void)
static void Mod_Q1BSP_LoadVisibility(sizebuf_t *sb)
static qbool Mod_Q1BSP_TraceLineOfSight(struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
static void Mod_Q1BSP_LoadMapBrushes(void)
static void Mod_BSP_MakePortals(void)
static void Mod_BSP_LoadSubmodels(sizebuf_t *sb, hullinfo_t *hullinfo)
static void Mod_Q1BSP_TraceBox(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
@ mod_brushq1
dp_FragColor r
cactive_t state
Definition client.h:568
float hullsizes[MAX_MAP_HULLS][2][3]
Definition bspfile.h:59
unsigned char * data
Definition common.h:52

References model_t::brush, buffer, ca_dedicated, cls, Com_BlockChecksum(), Con_DPrintf(), Con_Printf(), CON_WARN, sizebuf_t::cursize, data, sizebuf_t::data, dp_strlcpy, dpsnprintf(), fabs(), hullinfo_t::filehulls, mmodel_t::firstface, HEADER_LUMPS, mmodel_t::headnode, Host_Error(), hullinfo_t::hullsizes, i, cvar_t::integer, msurface_t::lightmapinfo, LittleLong, loadmodel, LUMP_CLIPNODES, LUMP_EDGES, LUMP_ENTITIES, LUMP_FACES, LUMP_LEAFS, LUMP_LIGHTING, LUMP_MARKSURFACES, LUMP_MODELS, LUMP_NODES, LUMP_PLANES, LUMP_SURFEDGES, LUMP_TEXINFO, LUMP_TEXTURES, LUMP_VERTEXES, LUMP_VISIBILITY, max, MAX_MAP_HULLS, MAXLIGHTMAPS, mmodel_t::maxs, Mem_Alloc, Mem_AllocType, Mem_Free, model_t::mempool, mmodel_t::mins, mod(), mod_brushq1, Mod_BSP_BoxTouchingLeafPVS(), Mod_BSP_BoxTouchingPVS(), Mod_BSP_BoxTouchingVisibleLeafs(), Mod_BSP_FatPVS(), Mod_BSP_FindBoxClusters(), Mod_BSP_FindNonSolidLocation(), Mod_BSP_GetPVS(), Mod_BSP_LightPoint(), Mod_BSP_LoadNodes_RecursiveSetParent(), Mod_BSP_LoadSubmodels(), Mod_BSP_MakePortals(), Mod_BSP_PointInLeaf(), mod_bsp_portalize, Mod_BuildVBOs(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TraceLineAgainstSurfaces(), Mod_FindName(), Mod_MakeCollisionBIH(), Mod_MakeSortedSurfaces(), Mod_Q1BSP_AmbientSoundLevelsForPoint(), Mod_Q1BSP_AssignNoShadowSkySurfaces(), Mod_Q1BSP_CheckWaterAlphaSupport(), Mod_Q1BSP_LoadClipnodes(), Mod_Q1BSP_LoadEdges(), Mod_Q1BSP_LoadEntities(), Mod_Q1BSP_LoadFaces(), Mod_Q1BSP_LoadLeaffaces(), Mod_Q1BSP_LoadLeafs(), Mod_Q1BSP_LoadLighting(), Mod_Q1BSP_LoadMapBrushes(), Mod_Q1BSP_LoadNodes(), Mod_Q1BSP_LoadPlanes(), Mod_Q1BSP_LoadSurfedges(), Mod_Q1BSP_LoadTexinfo(), Mod_Q1BSP_LoadTextures(), Mod_Q1BSP_LoadVertexes(), Mod_Q1BSP_LoadVisibility(), Mod_Q1BSP_MakeHull0(), Mod_Q1BSP_NativeContentsFromSuperContents(), Mod_Q1BSP_PointSuperContents(), mod_q1bsp_polygoncollisions, Mod_Q1BSP_RoundUpToHullSize(), Mod_Q1BSP_SuperContentsFromNativeContents(), Mod_Q1BSP_TraceBox(), Mod_Q1BSP_TraceLine(), Mod_Q1BSP_TraceLineAgainstSurfaces(), Mod_Q1BSP_TraceLineOfSight(), Mod_Q1BSP_TracePoint(), Mod_SetDrawSkyAndWater(), MSG_InitReadBuffer(), MSG_ReadLittleLong(), model_t::name, name, NULL, model_brush_t::num_leafs, model_brush_t::num_nodes, model_brush_t::num_portals, model_t::num_surfaces, surfmesh_t::num_triangles, surfmesh_t::num_vertices, mmodel_t::numfaces, model_brush_t::numsubmodels, model_brush_lightstyleinfo_t::numsurfaces, offset, r, R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), R_Mod_GetLightInfo(), size, sqrt(), client_static_t::state, model_brush_lightstyleinfo_t::style, msurface_lightmapinfo_t::styles, model_brush_t::submodels, model_brush_t::supportwateralpha, model_brush_lightstyleinfo_t::surfacelist, model_t::surfmesh, model_brush_lightstyleinfo_t::value, VectorClear, VectorCopy, and VectorSet.

Referenced by Mod_2PSB_Load(), Mod_BSP2_Load(), and Mod_HLBSP_Load().

◆ Mod_Q1BSP_LoadClipnodes()

static void Mod_Q1BSP_LoadClipnodes ( sizebuf_t * sb,
hullinfo_t * hullinfo )
static

Definition at line 3110 of file model_brush.c.

3111{
3112 mclipnode_t *out;
3113 int i, count;
3114 hull_t *hull;
3115 int structsize = loadmodel->brush.isbsp2 ? 12 : 8;
3116
3117 if (sb->cursize % structsize)
3118 Host_Error("Mod_Q1BSP_LoadClipnodes: funny lump size in %s",loadmodel->name);
3119 count = sb->cursize / structsize;
3120 out = (mclipnode_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
3121
3124
3125 for (i = 1; i < MAX_MAP_HULLS; i++)
3126 {
3127 hull = &loadmodel->brushq1.hulls[i];
3128 hull->clipnodes = out;
3129 hull->firstclipnode = 0;
3130 hull->lastclipnode = count-1;
3132 hull->clip_mins[0] = hullinfo->hullsizes[i][0][0];
3133 hull->clip_mins[1] = hullinfo->hullsizes[i][0][1];
3134 hull->clip_mins[2] = hullinfo->hullsizes[i][0][2];
3135 hull->clip_maxs[0] = hullinfo->hullsizes[i][1][0];
3136 hull->clip_maxs[1] = hullinfo->hullsizes[i][1][1];
3137 hull->clip_maxs[2] = hullinfo->hullsizes[i][1][2];
3138 VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size);
3139 }
3140
3141 for (i=0 ; i<count ; i++, out++)
3142 {
3143 out->planenum = MSG_ReadLittleLong(sb);
3144 if (out->planenum < 0 || out->planenum >= loadmodel->brush.num_planes)
3145 Host_Error("%s: Corrupt clipping hull(out of range planenum)", loadmodel->name);
3146 if (loadmodel->brush.isbsp2)
3147 {
3148 out->children[0] = MSG_ReadLittleLong(sb);
3149 out->children[1] = MSG_ReadLittleLong(sb);
3150 if (out->children[0] >= count)
3151 Host_Error("%s: Corrupt clipping hull (invalid child index)", loadmodel->name);
3152 if (out->children[1] >= count)
3153 Host_Error("%s: Corrupt clipping hull (invalid child index)", loadmodel->name);
3154 }
3155 else
3156 {
3157 // LadyHavoc: this code supports arguire qbsp's broken clipnodes indices (more than 32768 clipnodes), values above count are assumed to be contents values
3158 out->children[0] = (unsigned short)MSG_ReadLittleShort(sb);
3159 out->children[1] = (unsigned short)MSG_ReadLittleShort(sb);
3160 if (out->children[0] >= count)
3161 out->children[0] -= 65536;
3162 if (out->children[1] >= count)
3163 out->children[1] -= 65536;
3164 }
3165 }
3166}
int MSG_ReadLittleShort(sizebuf_t *sb)
Definition com_msg.c:263
vec3_t clip_size
vec3_t clip_maxs
vec3_t clip_mins
mplane_t * data_planes
mclipnode_t * clipnodes
Definition model_q1bsp.h:24

References model_t::brush, model_t::brushq1, mclipnode_t::children, hull_t::clip_maxs, hull_t::clip_mins, hull_t::clip_size, hull_t::clipnodes, model_brushq1_t::clipnodes, count, sizebuf_t::cursize, model_brush_t::data_planes, hull_t::firstclipnode, Host_Error(), model_brushq1_t::hulls, hullinfo_t::hullsizes, i, model_brush_t::isbsp2, hull_t::lastclipnode, loadmodel, MAX_MAP_HULLS, Mem_Alloc, model_t::mempool, MSG_ReadLittleLong(), MSG_ReadLittleShort(), model_t::name, model_brush_t::num_planes, model_brushq1_t::numclipnodes, mclipnode_t::planenum, hull_t::planes, and VectorSubtract.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_LoadEdges()

static void Mod_Q1BSP_LoadEdges ( sizebuf_t * sb)
static

Definition at line 2339 of file model_brush.c.

2340{
2341 medge_t *out;
2342 int i, count;
2343 int structsize = loadmodel->brush.isbsp2 ? 8 : 4;
2344
2345 if (sb->cursize % structsize)
2346 Host_Error("Mod_Q1BSP_LoadEdges: funny lump size in %s",loadmodel->name);
2347 count = sb->cursize / structsize;
2348 out = (medge_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
2349
2350 loadmodel->brushq1.edges = out;
2352
2353 for ( i=0 ; i<count ; i++, out++)
2354 {
2355 if (loadmodel->brush.isbsp2)
2356 {
2357 out->v[0] = (unsigned int)MSG_ReadLittleLong(sb);
2358 out->v[1] = (unsigned int)MSG_ReadLittleLong(sb);
2359 }
2360 else
2361 {
2362 out->v[0] = (unsigned short)MSG_ReadLittleShort(sb);
2363 out->v[1] = (unsigned short)MSG_ReadLittleShort(sb);
2364 }
2365 if ((int)out->v[0] >= loadmodel->brushq1.numvertexes || (int)out->v[1] >= loadmodel->brushq1.numvertexes)
2366 {
2367 Con_Printf("Mod_Q1BSP_LoadEdges: %s has invalid vertex indices in edge %i (vertices %i %i >= numvertices %i)\n", loadmodel->name, i, out->v[0], out->v[1], loadmodel->brushq1.numvertexes);
2369 Host_Error("Mod_Q1BSP_LoadEdges: %s has edges but no vertexes, cannot fix\n", loadmodel->name);
2370
2371 out->v[0] = 0;
2372 out->v[1] = 0;
2373 }
2374 }
2375}
unsigned int v[2]
medge_t * edges
Definition model_q1bsp.h:15

References model_t::brush, model_t::brushq1, Con_Printf(), count, sizebuf_t::cursize, model_brushq1_t::edges, Host_Error(), i, int(), model_brush_t::isbsp2, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadLittleLong(), MSG_ReadLittleShort(), model_t::name, model_brushq1_t::numedges, model_brushq1_t::numvertexes, and medge_t::v.

Referenced by Mod_Q1BSP_Load(), and Mod_Q2BSP_Load().

◆ Mod_Q1BSP_LoadEntities()

static void Mod_Q1BSP_LoadEntities ( sizebuf_t * sb)
static

Definition at line 2263 of file model_brush.c.

2264{
2266 if (!sb->cursize)
2267 return;
2269 MSG_ReadBytes(sb, sb->cursize, (unsigned char *)loadmodel->brush.entities);
2270 loadmodel->brush.entities[sb->cursize] = 0;
2271 if (loadmodel->brush.ishlbsp)
2273}
size_t MSG_ReadBytes(sizebuf_t *sb, size_t numbytes, unsigned char *out)
Definition com_msg.c:364
static void Mod_Q1BSP_ParseWadsFromEntityLump(const char *data)

References model_t::brush, sizebuf_t::cursize, model_brush_t::entities, model_brush_t::ishlbsp, loadmodel, Mem_Alloc, model_t::mempool, Mod_Q1BSP_ParseWadsFromEntityLump(), MSG_ReadBytes(), and NULL.

Referenced by Mod_Q1BSP_Load(), and Mod_Q2BSP_Load().

◆ Mod_Q1BSP_LoadFaces()

static void Mod_Q1BSP_LoadFaces ( sizebuf_t * sb)
static

Definition at line 2575 of file model_brush.c.

2576{
2577 msurface_t *surface;
2578 int i, j, count, surfacenum, planenum, smax, tmax, ssize, tsize, firstedge, numedges, totalverts, totaltris, lightmapnumber, lightmapsize, totallightmapsamples, lightmapoffset, texinfoindex;
2579 float texmins[2], texmaxs[2], val;
2580 rtexture_t *lightmaptexture, *deluxemaptexture;
2581 char vabuf[1024];
2582 int structsize = loadmodel->brush.isbsp2 ? 28 : 20;
2583
2584 if (sb->cursize % structsize)
2585 Host_Error("Mod_Q1BSP_LoadFaces: funny lump size in %s",loadmodel->name);
2586 count = sb->cursize / structsize;
2589
2591
2593 loadmodel->brushq1.lightmapupdateflags = (unsigned char *)Mem_Alloc(loadmodel->mempool, count*sizeof(unsigned char));
2594
2595 totalverts = 0;
2596 totaltris = 0;
2597 for (surfacenum = 0;surfacenum < count;surfacenum++)
2598 {
2599 if (loadmodel->brush.isbsp2)
2600 numedges = BuffLittleLong(sb->data + structsize * surfacenum + 12);
2601 else
2602 numedges = BuffLittleShort(sb->data + structsize * surfacenum + 8);
2603 totalverts += numedges;
2604 totaltris += numedges - 2;
2605 }
2606
2607 Mod_AllocSurfMesh(loadmodel->mempool, totalverts, totaltris, true, false);
2608
2609 lightmaptexture = NULL;
2610 deluxemaptexture = r_texture_blanknormalmap;
2611 lightmapnumber = 0;
2612 lightmapsize = bound(256, gl_max_lightmapsize.integer, (int)vid.maxtexturesize_2d);
2613 totallightmapsamples = 0;
2614
2615 totalverts = 0;
2616 totaltris = 0;
2617 for (surfacenum = 0, surface = loadmodel->data_surfaces;surfacenum < count;surfacenum++, surface++)
2618 {
2619 surface->lightmapinfo = loadmodel->data_surfaces_lightmapinfo + surfacenum;
2620 // the struct on disk is the same in BSP29 (Q1), BSP30 (HL1), and IBSP38 (Q2)
2621 planenum = loadmodel->brush.isbsp2 ? MSG_ReadLittleLong(sb) : (unsigned short)MSG_ReadLittleShort(sb);
2622 /*side = */loadmodel->brush.isbsp2 ? MSG_ReadLittleLong(sb) : (unsigned short)MSG_ReadLittleShort(sb);
2623 firstedge = MSG_ReadLittleLong(sb);
2624 numedges = loadmodel->brush.isbsp2 ? MSG_ReadLittleLong(sb) : (unsigned short)MSG_ReadLittleShort(sb);
2625 texinfoindex = loadmodel->brush.isbsp2 ? MSG_ReadLittleLong(sb) : (unsigned short)MSG_ReadLittleShort(sb);
2626 for (i = 0;i < MAXLIGHTMAPS;i++)
2627 surface->lightmapinfo->styles[i] = MSG_ReadByte(sb);
2628 lightmapoffset = MSG_ReadLittleLong(sb);
2629
2630 // FIXME: validate edges, texinfo, etc?
2631 if ((unsigned int) firstedge > (unsigned int) loadmodel->brushq1.numsurfedges || (unsigned int) numedges > (unsigned int) loadmodel->brushq1.numsurfedges || (unsigned int) firstedge + (unsigned int) numedges > (unsigned int) loadmodel->brushq1.numsurfedges)
2632 Host_Error("Mod_Q1BSP_LoadFaces: invalid edge range (firstedge %i, numedges %i, model edges %i)", firstedge, numedges, loadmodel->brushq1.numsurfedges);
2633 if ((unsigned int) texinfoindex >= (unsigned int) loadmodel->brushq1.numtexinfo)
2634 Host_Error("Mod_Q1BSP_LoadFaces: invalid texinfo index %i(model has %i texinfos)", texinfoindex, loadmodel->brushq1.numtexinfo);
2635 if ((unsigned int) planenum >= (unsigned int) loadmodel->brush.num_planes)
2636 Host_Error("Mod_Q1BSP_LoadFaces: invalid plane index %i (model has %i planes)", planenum, loadmodel->brush.num_planes);
2637
2638 surface->lightmapinfo->texinfo = loadmodel->brushq1.texinfo + texinfoindex;
2640
2641 // Q2BSP doesn't use lightmaps on sky or warped surfaces (water), but still has a lightofs of 0
2642 if (lightmapoffset == 0 && (surface->texture->q2flags & (Q2SURF_SKY | Q2SURF_WARP)))
2643 lightmapoffset = -1;
2644
2645 //surface->flags = surface->texture->flags;
2646 //if (LittleShort(in->side))
2647 // surface->flags |= SURF_PLANEBACK;
2648 //surface->plane = loadmodel->brush.data_planes + planenum;
2649
2650 surface->num_firstvertex = totalverts;
2651 surface->num_vertices = numedges;
2652 surface->num_firsttriangle = totaltris;
2653 surface->num_triangles = numedges - 2;
2654 totalverts += numedges;
2655 totaltris += numedges - 2;
2656
2657 // convert edges back to a normal polygon
2658 for (i = 0;i < surface->num_vertices;i++)
2659 {
2660 int lindex = loadmodel->brushq1.surfedges[firstedge + i];
2661 float s, t;
2662 // note: the q1bsp format does not allow a 0 surfedge (it would have no negative counterpart)
2663 if (lindex >= 0)
2665 else
2667 s = DotProduct(((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3), surface->lightmapinfo->texinfo->vecs[0]) + surface->lightmapinfo->texinfo->vecs[0][3];
2668 t = DotProduct(((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3), surface->lightmapinfo->texinfo->vecs[1]) + surface->lightmapinfo->texinfo->vecs[1][3];
2669 (loadmodel->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[i * 2 + 0] = s / surface->texture->width;
2670 (loadmodel->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[i * 2 + 1] = t / surface->texture->height;
2671 (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[i * 2 + 0] = 0;
2672 (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[i * 2 + 1] = 0;
2674 }
2675
2676 for (i = 0;i < surface->num_triangles;i++)
2677 {
2678 (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle)[i * 3 + 0] = 0 + surface->num_firstvertex;
2679 (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle)[i * 3 + 1] = i + 1 + surface->num_firstvertex;
2680 (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle)[i * 3 + 2] = i + 2 + surface->num_firstvertex;
2681 }
2682
2683 // compile additional data about the surface geometry
2686 BoxFromPoints(surface->mins, surface->maxs, surface->num_vertices, (loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex));
2687
2688 // generate surface extents information
2689 texmins[0] = texmaxs[0] = DotProduct((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex), surface->lightmapinfo->texinfo->vecs[0]) + surface->lightmapinfo->texinfo->vecs[0][3];
2690 texmins[1] = texmaxs[1] = DotProduct((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex), surface->lightmapinfo->texinfo->vecs[1]) + surface->lightmapinfo->texinfo->vecs[1][3];
2691 for (i = 1;i < surface->num_vertices;i++)
2692 {
2693 for (j = 0;j < 2;j++)
2694 {
2695 val = DotProduct((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3, surface->lightmapinfo->texinfo->vecs[j]) + surface->lightmapinfo->texinfo->vecs[j][3];
2696 texmins[j] = min(texmins[j], val);
2697 texmaxs[j] = max(texmaxs[j], val);
2698 }
2699 }
2700 for (i = 0;i < 2;i++)
2701 {
2702 surface->lightmapinfo->texturemins[i] = (int) floor(texmins[i] / 16.0) * 16;
2703 surface->lightmapinfo->extents[i] = (int) ceil(texmaxs[i] / 16.0) * 16 - surface->lightmapinfo->texturemins[i];
2704 }
2705
2706 smax = surface->lightmapinfo->extents[0] >> 4;
2707 tmax = surface->lightmapinfo->extents[1] >> 4;
2708 ssize = (surface->lightmapinfo->extents[0] >> 4) + 1;
2709 tsize = (surface->lightmapinfo->extents[1] >> 4) + 1;
2710
2711 // lighting info
2712 surface->lightmaptexture = NULL;
2714 if (lightmapoffset == -1)
2715 {
2716 surface->lightmapinfo->samples = NULL;
2717#if 1
2718 // give non-lightmapped water a 1x white lightmap
2719 if (!loadmodel->brush.isq2bsp && surface->texture->name[0] == '*' && (surface->lightmapinfo->texinfo->q1flags & TEX_SPECIAL) && ssize <= 256 && tsize <= 256)
2720 {
2721 surface->lightmapinfo->samples = (unsigned char *)Mem_Alloc(loadmodel->mempool, ssize * tsize * 3);
2722 surface->lightmapinfo->styles[0] = 0;
2723 memset(surface->lightmapinfo->samples, 128, ssize * tsize * 3);
2724 }
2725#endif
2726 }
2727 else if (loadmodel->brush.ishlbsp || loadmodel->brush.isq2bsp) // LadyHavoc: HalfLife map (bsp version 30)
2728 surface->lightmapinfo->samples = loadmodel->brushq1.lightdata + lightmapoffset;
2729 else // LadyHavoc: white lighting (bsp version 29)
2730 {
2731 surface->lightmapinfo->samples = loadmodel->brushq1.lightdata + (lightmapoffset * 3);
2733 surface->lightmapinfo->nmapsamples = loadmodel->brushq1.nmaplightdata + (lightmapoffset * 3);
2734 }
2735
2736 // check if we should apply a lightmap to this
2737 if (!(surface->lightmapinfo->texinfo->q1flags & TEX_SPECIAL) || surface->lightmapinfo->samples)
2738 {
2739 if (ssize > 256 || tsize > 256)
2740 Host_Error("Bad surface extents");
2741
2742 if (lightmapsize < ssize)
2743 lightmapsize = ssize;
2744 if (lightmapsize < tsize)
2745 lightmapsize = tsize;
2746
2747 totallightmapsamples += ssize*tsize;
2748
2749 // force lightmap upload on first time seeing the surface
2750 //
2751 // additionally this is used by the later code to see if a
2752 // lightmap is needed on this surface (rather than duplicating the
2753 // logic above)
2754 loadmodel->brushq1.lightmapupdateflags[surfacenum] = true;
2755 loadmodel->lit = true;
2756 }
2757 }
2758
2759 // small maps (such as ammo boxes especially) don't need big lightmap
2760 // textures, so this code tries to guess a good size based on
2761 // totallightmapsamples (size of the lightmaps lump basically), as well as
2762 // trying to max out the size if there is a lot of lightmap data to store
2763 // additionally, never choose a lightmapsize that is smaller than the
2764 // largest surface encountered (as it would fail)
2765 i = lightmapsize;
2766 for (lightmapsize = 64; (lightmapsize < i) && (lightmapsize < bound(128, gl_max_lightmapsize.integer, (int)vid.maxtexturesize_2d)) && (totallightmapsamples > lightmapsize*lightmapsize); lightmapsize*=2)
2767 ;
2768
2769 // now that we've decided the lightmap texture size, we can do the rest
2770 if (cls.state != ca_dedicated)
2771 {
2772 int stainmapsize = 0;
2773 mod_alloclightmap_state_t allocState;
2774
2775 Mod_AllocLightmap_Init(&allocState, loadmodel->mempool, lightmapsize, lightmapsize);
2776 for (surfacenum = 0, surface = loadmodel->data_surfaces;surfacenum < count;surfacenum++, surface++)
2777 {
2778 int iu, iv, lightmapx = 0, lightmapy = 0;
2779 float u, v, ubase, vbase, uscale, vscale;
2780
2781 if (!loadmodel->brushq1.lightmapupdateflags[surfacenum])
2782 continue;
2783
2784 smax = surface->lightmapinfo->extents[0] >> 4;
2785 tmax = surface->lightmapinfo->extents[1] >> 4;
2786 ssize = (surface->lightmapinfo->extents[0] >> 4) + 1;
2787 tsize = (surface->lightmapinfo->extents[1] >> 4) + 1;
2788 stainmapsize += ssize * tsize * 3;
2789
2790 if (!lightmaptexture || !Mod_AllocLightmap_Block(&allocState, ssize, tsize, &lightmapx, &lightmapy))
2791 {
2792 // allocate a texture pool if we need it
2793 if (loadmodel->texturepool == NULL)
2795 // could not find room, make a new lightmap
2796 loadmodel->brushq3.num_mergedlightmaps = lightmapnumber + 1;
2799 loadmodel->brushq3.data_lightmaps[lightmapnumber] = lightmaptexture = R_LoadTexture2D(loadmodel->texturepool, va(vabuf, sizeof(vabuf), "lightmap%i", lightmapnumber), lightmapsize, lightmapsize, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_ALLOWUPDATES, -1, NULL);
2801 loadmodel->brushq3.data_deluxemaps[lightmapnumber] = deluxemaptexture = R_LoadTexture2D(loadmodel->texturepool, va(vabuf, sizeof(vabuf), "deluxemap%i", lightmapnumber), lightmapsize, lightmapsize, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_ALLOWUPDATES, -1, NULL);
2802 lightmapnumber++;
2803 Mod_AllocLightmap_Reset(&allocState);
2804 Mod_AllocLightmap_Block(&allocState, ssize, tsize, &lightmapx, &lightmapy);
2805 }
2806 surface->lightmaptexture = lightmaptexture;
2807 surface->deluxemaptexture = deluxemaptexture;
2808 surface->lightmapinfo->lightmaporigin[0] = lightmapx;
2809 surface->lightmapinfo->lightmaporigin[1] = lightmapy;
2810
2811 uscale = 1.0f / (float)lightmapsize;
2812 vscale = 1.0f / (float)lightmapsize;
2813 ubase = lightmapx * uscale;
2814 vbase = lightmapy * vscale;
2815
2816 for (i = 0;i < surface->num_vertices;i++)
2817 {
2818 u = ((DotProduct(((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3), surface->lightmapinfo->texinfo->vecs[0]) + surface->lightmapinfo->texinfo->vecs[0][3]) + 8 - surface->lightmapinfo->texturemins[0]) * (1.0 / 16.0);
2819 v = ((DotProduct(((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3), surface->lightmapinfo->texinfo->vecs[1]) + surface->lightmapinfo->texinfo->vecs[1][3]) + 8 - surface->lightmapinfo->texturemins[1]) * (1.0 / 16.0);
2820 (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[i * 2 + 0] = u * uscale + ubase;
2821 (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[i * 2 + 1] = v * vscale + vbase;
2822 // LadyHavoc: calc lightmap data offset for vertex lighting to use
2823 iu = (int) u;
2824 iv = (int) v;
2825 (loadmodel->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i] = (bound(0, iv, tmax) * ssize + bound(0, iu, smax)) * 3;
2826 }
2827 }
2828
2830 {
2831 // allocate stainmaps for permanent marks on walls and clear white
2832 unsigned char *stainsamples = NULL;
2833 stainsamples = (unsigned char *)Mem_Alloc(loadmodel->mempool, stainmapsize);
2834 memset(stainsamples, 255, stainmapsize);
2835 // assign pointers
2836 for (surfacenum = 0, surface = loadmodel->data_surfaces;surfacenum < count;surfacenum++, surface++)
2837 {
2838 if (!loadmodel->brushq1.lightmapupdateflags[surfacenum])
2839 continue;
2840 ssize = (surface->lightmapinfo->extents[0] >> 4) + 1;
2841 tsize = (surface->lightmapinfo->extents[1] >> 4) + 1;
2842 surface->lightmapinfo->stainsamples = stainsamples;
2843 stainsamples += ssize * tsize * 3;
2844 }
2845 }
2846 }
2847
2848 // generate ushort elements array if possible
2850 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2852}
#define TEX_SPECIAL
Definition bspfile.h:271
cvar_t cl_stainmaps
Definition cl_main.c:75
short BuffLittleShort(const unsigned char *buffer)
Extract a little endian 16bit short from the given buffer.
Definition com_msg.c:76
int BuffLittleLong(const unsigned char *buffer)
Extract a little endian 32bit int from the given buffer.
Definition com_msg.c:71
char * va(char *buf, size_t buflen, const char *format,...)
Definition common.c:972
#define MSG_ReadByte(sb)
Definition common.h:188
rtexture_t * r_texture_blanknormalmap
Definition gl_rmain.c:272
rtexturepool_t * R_AllocTexturePool(void)
rtexture_t * R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette)
#define bound(min, num, max)
Definition mathlib.h:34
float ceil(float f)
cvar_t gl_max_lightmapsize
Definition gl_textures.c:28
#define Q2SURF_WARP
Definition model_q2bsp.h:99
#define Q2SURF_SKY
Definition model_q2bsp.h:98
void Mod_AllocLightmap_Reset(mod_alloclightmap_state_t *state)
void Mod_AllocLightmap_Init(mod_alloclightmap_state_t *state, mempool_t *mempool, int width, int height)
void Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qbool lightmapoffsets, qbool vertexcolors)
qbool Mod_AllocLightmap_Block(mod_alloclightmap_state_t *state, int blockwidth, int blockheight, int *outx, int *outy)
#define TEXF_ALLOWUPDATES
Definition r_textures.h:31
#define TEXF_FORCELINEAR
Definition r_textures.h:19
@ TEXTYPE_BGRA
Definition r_textures.h:53
precision highp float
Definition shader_glsl.h:53
mvertex_t * vertexes
Definition model_q1bsp.h:12
unsigned char * lightmapupdateflags
Definition model_q1bsp.h:40
unsigned char * nmaplightdata
Definition model_q1bsp.h:33
unsigned char * lightdata
Definition model_q1bsp.h:32
struct mtexinfo_s * texinfo
Definition model_q1bsp.h:18
rtexture_t ** data_lightmaps
rtexture_t ** data_deluxemaps
qbool lit
msurface_lightmapinfo_t * data_surfaces_lightmapinfo
model_brushq3_t brushq3
rtexturepool_t * texturepool
unsigned char * stainsamples
unsigned char * nmapsamples
struct rtexture_s * deluxemaptexture
the lighting direction texture fragment to use on the rendering mesh
struct rtexture_s * lightmaptexture
the lightmap texture fragment to use on the rendering mesh
int * data_lightmapoffsets
float * data_texcoordlightmap2f
unsigned int width
unsigned int height
unsigned int maxtexturesize_2d
Definition vid.h:83
viddef_t vid
global video state
Definition vid_shared.c:64

References bound, BoxFromPoints(), model_t::brush, model_t::brushq1, model_t::brushq3, BuffLittleLong(), BuffLittleShort(), ca_dedicated, ceil(), cl_stainmaps, cls, count, sizebuf_t::cursize, sizebuf_t::data, model_brushq3_t::data_deluxemaps, surfmesh_t::data_element3i, surfmesh_t::data_element3s, surfmesh_t::data_lightmapoffsets, model_brushq3_t::data_lightmaps, surfmesh_t::data_normal3f, model_t::data_surfaces, model_t::data_surfaces_lightmapinfo, surfmesh_t::data_svector3f, surfmesh_t::data_texcoordlightmap2f, surfmesh_t::data_texcoordtexture2f, model_t::data_textures, surfmesh_t::data_tvector3f, surfmesh_t::data_vertex3f, msurface_t::deluxemaptexture, DotProduct, model_brushq1_t::edges, msurface_lightmapinfo_t::extents, model_brushq1_t::firstrender, float, floor(), gl_max_lightmapsize, texture_t::height, Host_Error(), i, int(), cvar_t::integer, model_brush_t::isbsp2, model_brush_t::ishlbsp, model_brush_t::isq2bsp, model_brushq1_t::lightdata, msurface_t::lightmapinfo, msurface_lightmapinfo_t::lightmaporigin, msurface_t::lightmaptexture, model_brushq1_t::lightmapupdateflags, model_t::lit, loadmodel, max, MAXLIGHTMAPS, msurface_t::maxs, viddef_t::maxtexturesize_2d, Mem_Alloc, Mem_Realloc, model_t::mempool, min, msurface_t::mins, Mod_AllocLightmap_Block(), Mod_AllocLightmap_Init(), Mod_AllocLightmap_Reset(), Mod_AllocSurfMesh(), Mod_BuildNormals(), Mod_BuildTextureVectorsFromNormals(), MSG_ReadByte, MSG_ReadLittleLong(), MSG_ReadLittleShort(), model_t::name, texture_t::name, model_brushq1_t::nmaplightdata, msurface_lightmapinfo_t::nmapsamples, NULL, msurface_t::num_firsttriangle, msurface_t::num_firstvertex, model_brushq3_t::num_mergedlightmaps, model_brush_t::num_planes, model_t::num_surfaces, msurface_t::num_triangles, surfmesh_t::num_triangles, msurface_t::num_vertices, model_brushq1_t::numsurfedges, model_brushq1_t::numtexinfo, mvertex_t::position, mtexinfo_t::q1flags, texture_t::q2flags, Q2SURF_SKY, Q2SURF_WARP, R_AllocTexturePool(), R_LoadTexture2D(), r_smoothnormals_areaweighting, r_texture_blanknormalmap, msurface_lightmapinfo_t::samples, msurface_lightmapinfo_t::stainsamples, client_static_t::state, msurface_lightmapinfo_t::styles, model_brushq1_t::surfedges, model_t::surfmesh, TEX_SPECIAL, TEXF_ALLOWUPDATES, TEXF_FORCELINEAR, model_brushq1_t::texinfo, msurface_lightmapinfo_t::texinfo, msurface_t::texture, mtexinfo_t::textureindex, msurface_lightmapinfo_t::texturemins, model_t::texturepool, TEXTYPE_BGRA, medge_t::v, v, va(), mtexinfo_t::vecs, VectorCopy, model_brushq1_t::vertexes, vid, and texture_t::width.

Referenced by Mod_Q1BSP_Load(), and Mod_Q2BSP_Load().

◆ Mod_Q1BSP_LoadLeaffaces()

static void Mod_Q1BSP_LoadLeaffaces ( sizebuf_t * sb)
static

Definition at line 3194 of file model_brush.c.

3195{
3196 int i, j;
3197 int structsize = loadmodel->brush.isbsp2 ? 4 : 2;
3198
3199 if (sb->cursize % structsize)
3200 Host_Error("Mod_Q1BSP_LoadLeaffaces: funny lump size in %s",loadmodel->name);
3201 loadmodel->brush.num_leafsurfaces = sb->cursize / structsize;
3203
3204 if (loadmodel->brush.isbsp2)
3205 {
3206 for (i = 0;i < loadmodel->brush.num_leafsurfaces;i++)
3207 {
3208 j = MSG_ReadLittleLong(sb);
3209 if (j < 0 || j >= loadmodel->num_surfaces)
3210 Host_Error("Mod_Q1BSP_LoadLeaffaces: bad surface number");
3212 }
3213 }
3214 else
3215 {
3216 for (i = 0;i < loadmodel->brush.num_leafsurfaces;i++)
3217 {
3218 j = (unsigned short) MSG_ReadLittleShort(sb);
3219 if (j >= loadmodel->num_surfaces)
3220 Host_Error("Mod_Q1BSP_LoadLeaffaces: bad surface number");
3222 }
3223 }
3224}

References model_t::brush, sizebuf_t::cursize, model_brush_t::data_leafsurfaces, Host_Error(), i, model_brush_t::isbsp2, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadLittleLong(), MSG_ReadLittleShort(), model_t::name, model_brush_t::num_leafsurfaces, and model_t::num_surfaces.

Referenced by Mod_Q1BSP_Load(), and Mod_Q2BSP_Load().

◆ Mod_Q1BSP_LoadLeafs()

static void Mod_Q1BSP_LoadLeafs ( sizebuf_t * sb)
static

Definition at line 2995 of file model_brush.c.

2996{
2997 mleaf_t *out;
2998 int i, j, count, p, firstmarksurface, nummarksurfaces;
2999 int structsize = loadmodel->brush.isbsp2rmqe ? 32 : (loadmodel->brush.isbsp2 ? 44 : 28);
3000
3001 if (sb->cursize % structsize)
3002 Host_Error("Mod_Q1BSP_LoadLeafs: funny lump size in %s",loadmodel->name);
3003 count = sb->cursize / structsize;
3004 out = (mleaf_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
3005
3006 loadmodel->brush.data_leafs = out;
3008 // get visleafs from the submodel data
3013
3014 // FIXME: this function could really benefit from some error checking
3015 for ( i=0 ; i<count ; i++, out++)
3016 {
3017 out->contents = MSG_ReadLittleLong(sb);
3018
3019 out->clusterindex = i - 1;
3021 out->clusterindex = -1;
3022
3023 p = MSG_ReadLittleLong(sb);
3024 // ignore visofs errors on leaf 0 (solid)
3025 if (p >= 0 && out->clusterindex >= 0)
3026 {
3028 Con_Print("Mod_Q1BSP_LoadLeafs: invalid visofs\n");
3029 else
3031 }
3032
3034 {
3035 out->mins[0] = MSG_ReadLittleShort(sb);
3036 out->mins[1] = MSG_ReadLittleShort(sb);
3037 out->mins[2] = MSG_ReadLittleShort(sb);
3038 out->maxs[0] = MSG_ReadLittleShort(sb);
3039 out->maxs[1] = MSG_ReadLittleShort(sb);
3040 out->maxs[2] = MSG_ReadLittleShort(sb);
3041
3042 firstmarksurface = MSG_ReadLittleLong(sb);
3043 nummarksurfaces = MSG_ReadLittleLong(sb);
3044 }
3045 else if (loadmodel->brush.isbsp2)
3046 {
3047 out->mins[0] = MSG_ReadLittleFloat(sb);
3048 out->mins[1] = MSG_ReadLittleFloat(sb);
3049 out->mins[2] = MSG_ReadLittleFloat(sb);
3050 out->maxs[0] = MSG_ReadLittleFloat(sb);
3051 out->maxs[1] = MSG_ReadLittleFloat(sb);
3052 out->maxs[2] = MSG_ReadLittleFloat(sb);
3053
3054 firstmarksurface = MSG_ReadLittleLong(sb);
3055 nummarksurfaces = MSG_ReadLittleLong(sb);
3056 }
3057 else
3058 {
3059 out->mins[0] = MSG_ReadLittleShort(sb);
3060 out->mins[1] = MSG_ReadLittleShort(sb);
3061 out->mins[2] = MSG_ReadLittleShort(sb);
3062 out->maxs[0] = MSG_ReadLittleShort(sb);
3063 out->maxs[1] = MSG_ReadLittleShort(sb);
3064 out->maxs[2] = MSG_ReadLittleShort(sb);
3065
3066 firstmarksurface = (unsigned short)MSG_ReadLittleShort(sb);
3067 nummarksurfaces = (unsigned short)MSG_ReadLittleShort(sb);
3068 }
3069
3070 if (firstmarksurface >= 0 && firstmarksurface + nummarksurfaces <= loadmodel->brush.num_leafsurfaces)
3071 {
3072 out->firstleafsurface = loadmodel->brush.data_leafsurfaces + firstmarksurface;
3073 out->numleafsurfaces = nummarksurfaces;
3074 }
3075 else
3076 {
3077 Con_Printf("Mod_Q1BSP_LoadLeafs: invalid leafsurface range %i:%i outside range %i:%i\n", firstmarksurface, firstmarksurface+nummarksurfaces, 0, loadmodel->brush.num_leafsurfaces);
3078 out->firstleafsurface = NULL;
3079 out->numleafsurfaces = 0;
3080 }
3081
3082 for (j = 0;j < 4;j++)
3083 out->ambient_sound_level[j] = MSG_ReadByte(sb);
3084 }
3085}
static void Mod_BSP_DecompressVis(const unsigned char *in, const unsigned char *inend, unsigned char *out, unsigned char *outend)
unsigned char * data_compressedpvs
Definition model_q1bsp.h:29

References mleaf_t::ambient_sound_level, model_t::brush, model_t::brushq1, mleaf_t::clusterindex, Con_Print(), Con_Printf(), mleaf_t::contents, count, sizebuf_t::cursize, model_brushq1_t::data_compressedpvs, model_brush_t::data_leafs, model_brush_t::data_leafsurfaces, model_brush_t::data_pvsclusters, mleaf_t::firstleafsurface, Host_Error(), i, model_brush_t::isbsp2, model_brush_t::isbsp2rmqe, loadmodel, mleaf_t::maxs, Mem_Alloc, model_t::mempool, mleaf_t::mins, Mod_BSP_DecompressVis(), MSG_ReadByte, MSG_ReadLittleFloat(), MSG_ReadLittleLong(), MSG_ReadLittleShort(), model_t::name, NULL, model_brushq1_t::num_compressedpvs, model_brush_t::num_leafs, model_brush_t::num_leafsurfaces, model_brush_t::num_pvsclusterbytes, model_brush_t::num_pvsclusters, mleaf_t::numleafsurfaces, model_brushq1_t::submodels, and mmodel_t::visleafs.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_LoadLighting()

static void Mod_Q1BSP_LoadLighting ( sizebuf_t * sb)
static

Definition at line 2111 of file model_brush.c.

2112{
2113 int i;
2114 unsigned char *in, *out, *data, d;
2115 char litfilename[MAX_QPATH];
2116 char dlitfilename[MAX_QPATH];
2117 fs_offset_t filesize;
2118 if (loadmodel->brush.ishlbsp) // LadyHavoc: load the colored lighting data straight
2119 {
2120 loadmodel->brushq1.lightdata = (unsigned char *)Mem_Alloc(loadmodel->mempool, sb->cursize);
2121 for (i = 0;i < sb->cursize;i++)
2122 loadmodel->brushq1.lightdata[i] = sb->data[i] >>= 1;
2123 }
2124 else // LadyHavoc: bsp version 29 (normal white lighting)
2125 {
2126 // LadyHavoc: hope is not lost yet, check for a .lit file to load
2127 dp_strlcpy (litfilename, loadmodel->name, sizeof (litfilename));
2128 FS_StripExtension (litfilename, litfilename, sizeof (litfilename));
2129 dp_strlcpy (dlitfilename, litfilename, sizeof (dlitfilename));
2130 dp_strlcat (litfilename, ".lit", sizeof (litfilename));
2131 dp_strlcat (dlitfilename, ".dlit", sizeof (dlitfilename));
2132 data = (unsigned char*) FS_LoadFile(litfilename, tempmempool, false, &filesize);
2133 if (data)
2134 {
2135 if (filesize == (fs_offset_t)(8 + sb->cursize * 3) && data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' && data[3] == 'T')
2136 {
2137 i = LittleLong(((int *)data)[1]);
2138 if (i == 1)
2139 {
2141 Con_Printf("loaded %s\n", litfilename);
2142 loadmodel->brushq1.lightdata = (unsigned char *)Mem_Alloc(loadmodel->mempool, filesize - 8);
2143 memcpy(loadmodel->brushq1.lightdata, data + 8, filesize - 8);
2144 Mem_Free(data);
2145 data = (unsigned char*) FS_LoadFile(dlitfilename, tempmempool, false, &filesize);
2146 if (data)
2147 {
2148 if (filesize == (fs_offset_t)(8 + sb->cursize * 3) && data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' && data[3] == 'T')
2149 {
2150 i = LittleLong(((int *)data)[1]);
2151 if (i == 1)
2152 {
2154 Con_Printf("loaded %s\n", dlitfilename);
2155 loadmodel->brushq1.nmaplightdata = (unsigned char *)Mem_Alloc(loadmodel->mempool, filesize - 8);
2156 memcpy(loadmodel->brushq1.nmaplightdata, data + 8, filesize - 8);
2159 }
2160 }
2161 Mem_Free(data);
2162 data = NULL;
2163 }
2164 return;
2165 }
2166 else
2167 Con_Printf("Unknown .lit file version (%d)\n", i);
2168 }
2169 else if (filesize == 8)
2170 Con_Print("Empty .lit file, ignoring\n");
2171 else
2172 Con_Printf("Corrupt .lit file (file size %i bytes, should be %i bytes), ignoring\n", (int) filesize, (int) (8 + sb->cursize * 3));
2173 if (data)
2174 {
2175 Mem_Free(data);
2176 data = NULL;
2177 }
2178 }
2179 // LadyHavoc: oh well, expand the white lighting data
2180 if (!sb->cursize)
2181 return;
2182 loadmodel->brushq1.lightdata = (unsigned char *)Mem_Alloc(loadmodel->mempool, sb->cursize*3);
2183 in = sb->data;
2185 for (i = 0;i < sb->cursize;i++)
2186 {
2187 d = *in++;
2188 *out++ = d;
2189 *out++ = d;
2190 *out++ = d;
2191 }
2192 }
2193}
#define dp_strlcat(dst, src, dsize)
Definition common.h:304
unsigned char * FS_LoadFile(const char *path, mempool_t *pool, qbool quiet, fs_offset_t *filesizepointer)
Definition fs.c:3540
void FS_StripExtension(const char *in, char *out, size_t size_out)
Definition fs.c:3611
int64_t fs_offset_t
Definition fs.h:37
cvar_t developer_loading
Definition host.c:52
qbool deluxemapping_modelspace

References model_t::brush, model_t::brushq1, model_t::brushq3, Con_Print(), Con_Printf(), sizebuf_t::cursize, data, sizebuf_t::data, model_brushq3_t::deluxemapping, model_brushq3_t::deluxemapping_modelspace, developer_loading, dp_strlcat, dp_strlcpy, FS_LoadFile(), FS_StripExtension(), i, cvar_t::integer, model_brush_t::ishlbsp, model_brushq1_t::lightdata, LittleLong, loadmodel, MAX_QPATH, Mem_Alloc, Mem_Free, model_t::mempool, model_t::name, model_brushq1_t::nmaplightdata, NULL, and tempmempool.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_LoadMapBrushes()

static void Mod_Q1BSP_LoadMapBrushes ( void )
static

Definition at line 3284 of file model_brush.c.

3285{
3286#if 0
3287// unfinished
3288 int submodel, numbrushes;
3289 qbool firstbrush;
3290 char *text, *maptext;
3291 char mapfilename[MAX_QPATH];
3292 FS_StripExtension (loadmodel->name, mapfilename, sizeof (mapfilename));
3293 strlcat (mapfilename, ".map", sizeof (mapfilename));
3294 maptext = (unsigned char*) FS_LoadFile(mapfilename, tempmempool, false, NULL);
3295 if (!maptext)
3296 return;
3297 text = maptext;
3298 if (!COM_ParseToken_Simple(&data, false, false, true))
3299 return; // error
3300 submodel = 0;
3301 for (;;)
3302 {
3303 if (!COM_ParseToken_Simple(&data, false, false, true))
3304 break;
3305 if (com_token[0] != '{')
3306 return; // error
3307 // entity
3308 firstbrush = true;
3309 numbrushes = 0;
3310 maxbrushes = 256;
3311 brushes = Mem_Alloc(loadmodel->mempool, maxbrushes * sizeof(mbrush_t));
3312 for (;;)
3313 {
3314 if (!COM_ParseToken_Simple(&data, false, false, true))
3315 return; // error
3316 if (com_token[0] == '}')
3317 break; // end of entity
3318 if (com_token[0] == '{')
3319 {
3320 // brush
3321 if (firstbrush)
3322 {
3323 if (submodel)
3324 {
3325 if (submodel > loadmodel->brush.numsubmodels)
3326 {
3327 Con_Printf("Mod_Q1BSP_LoadMapBrushes: .map has more submodels than .bsp!\n");
3328 model = NULL;
3329 }
3330 else
3331 model = loadmodel->brush.submodels[submodel];
3332 }
3333 else
3334 model = loadmodel;
3335 }
3336 for (;;)
3337 {
3338 if (!COM_ParseToken_Simple(&data, false, false, true))
3339 return; // error
3340 if (com_token[0] == '}')
3341 break; // end of brush
3342 // each brush face should be this format:
3343 // ( x y z ) ( x y z ) ( x y z ) texture scroll_s scroll_t rotateangle scale_s scale_t
3344 // FIXME: support hl .map format
3345 for (pointnum = 0;pointnum < 3;pointnum++)
3346 {
3347 COM_ParseToken_Simple(&data, false, false, true);
3348 for (componentnum = 0;componentnum < 3;componentnum++)
3349 {
3350 COM_ParseToken_Simple(&data, false, false, true);
3351 point[pointnum][componentnum] = atof(com_token);
3352 }
3353 COM_ParseToken_Simple(&data, false, false, true);
3354 }
3355 COM_ParseToken_Simple(&data, false, false, true);
3356 strlcpy(facetexture, com_token, sizeof(facetexture));
3357 COM_ParseToken_Simple(&data, false, false, true);
3358 //scroll_s = atof(com_token);
3359 COM_ParseToken_Simple(&data, false, false, true);
3360 //scroll_t = atof(com_token);
3361 COM_ParseToken_Simple(&data, false, false, true);
3362 //rotate = atof(com_token);
3363 COM_ParseToken_Simple(&data, false, false, true);
3364 //scale_s = atof(com_token);
3365 COM_ParseToken_Simple(&data, false, false, true);
3366 //scale_t = atof(com_token);
3367 TriangleNormal(point[0], point[1], point[2], planenormal);
3368 VectorNormalizeDouble(planenormal);
3369 planedist = DotProduct(point[0], planenormal);
3370 //ChooseTexturePlane(planenormal, texturevector[0], texturevector[1]);
3371 }
3372 continue;
3373 }
3374 }
3375 }
3376#endif
3377}
char com_token[MAX_INPUTLINE]
Definition common.c:39
qbool COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool parsebackslash, qbool parsecomments)
Definition common.c:463
#define strlcpy
Definition common.h:272
#define strlcat
Definition common.h:274
#define TriangleNormal(a, b, c, n)
Definition mathlib.h:126
#define VectorNormalizeDouble(v)
Definition mathlib.h:106
bool qbool
Definition qtypes.h:9

References model_t::brush, COM_ParseToken_Simple(), com_token, Con_Printf(), data, DotProduct, FS_LoadFile(), FS_StripExtension(), loadmodel, MAX_QPATH, Mem_Alloc, model_t::mempool, model, model_t::name, NULL, model_brush_t::numsubmodels, strlcat, strlcpy, model_brush_t::submodels, tempmempool, TriangleNormal, and VectorNormalizeDouble.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_LoadNodes()

static void Mod_Q1BSP_LoadNodes ( sizebuf_t * sb)
static

Definition at line 2891 of file model_brush.c.

2892{
2893 int i, j, count, p, child[2];
2894 mnode_t *out;
2895 int structsize = loadmodel->brush.isbsp2rmqe ? 32 : (loadmodel->brush.isbsp2 ? 44 : 24);
2896
2897 if (sb->cursize % structsize)
2898 Host_Error("Mod_Q1BSP_LoadNodes: funny lump size in %s",loadmodel->name);
2899 count = sb->cursize / structsize;
2900 if (count == 0)
2901 Host_Error("Mod_Q1BSP_LoadNodes: missing BSP tree in %s",loadmodel->name);
2902 out = (mnode_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
2903
2904 loadmodel->brush.data_nodes = out;
2906
2907 for ( i=0 ; i<count ; i++, out++)
2908 {
2909 p = MSG_ReadLittleLong(sb);
2910 out->plane = loadmodel->brush.data_planes + p;
2911
2913 {
2914 child[0] = MSG_ReadLittleLong(sb);
2915 child[1] = MSG_ReadLittleLong(sb);
2916 out->mins[0] = MSG_ReadLittleShort(sb);
2917 out->mins[1] = MSG_ReadLittleShort(sb);
2918 out->mins[2] = MSG_ReadLittleShort(sb);
2919 out->maxs[0] = MSG_ReadLittleShort(sb);
2920 out->maxs[1] = MSG_ReadLittleShort(sb);
2921 out->maxs[2] = MSG_ReadLittleShort(sb);
2924 }
2925 else if (loadmodel->brush.isbsp2)
2926 {
2927 child[0] = MSG_ReadLittleLong(sb);
2928 child[1] = MSG_ReadLittleLong(sb);
2929 out->mins[0] = MSG_ReadLittleFloat(sb);
2930 out->mins[1] = MSG_ReadLittleFloat(sb);
2931 out->mins[2] = MSG_ReadLittleFloat(sb);
2932 out->maxs[0] = MSG_ReadLittleFloat(sb);
2933 out->maxs[1] = MSG_ReadLittleFloat(sb);
2934 out->maxs[2] = MSG_ReadLittleFloat(sb);
2937 }
2938 else
2939 {
2940 child[0] = (unsigned short)MSG_ReadLittleShort(sb);
2941 child[1] = (unsigned short)MSG_ReadLittleShort(sb);
2942 if (child[0] >= count)
2943 child[0] -= 65536;
2944 if (child[1] >= count)
2945 child[1] -= 65536;
2946
2947 out->mins[0] = MSG_ReadLittleShort(sb);
2948 out->mins[1] = MSG_ReadLittleShort(sb);
2949 out->mins[2] = MSG_ReadLittleShort(sb);
2950 out->maxs[0] = MSG_ReadLittleShort(sb);
2951 out->maxs[1] = MSG_ReadLittleShort(sb);
2952 out->maxs[2] = MSG_ReadLittleShort(sb);
2953
2954 out->firstsurface = (unsigned short)MSG_ReadLittleShort(sb);
2955 out->numsurfaces = (unsigned short)MSG_ReadLittleShort(sb);
2956 }
2957
2958 for (j=0 ; j<2 ; j++)
2959 {
2960 // LadyHavoc: this code supports broken bsp files produced by
2961 // arguire qbsp which can produce more than 32768 nodes, any value
2962 // below count is assumed to be a node number, any other value is
2963 // assumed to be a leaf number
2964 p = child[j];
2965 if (p >= 0)
2966 {
2967 if (p < loadmodel->brush.num_nodes)
2968 out->children[j] = loadmodel->brush.data_nodes + p;
2969 else
2970 {
2971 Con_Printf("Mod_Q1BSP_LoadNodes: invalid node index %i (file has only %i nodes)\n", p, loadmodel->brush.num_nodes);
2972 // map it to the solid leaf
2974 }
2975 }
2976 else
2977 {
2978 // get leaf index as a positive value starting at 0 (-1 becomes 0, -2 becomes 1, etc)
2979 p = -(p+1);
2980 if (p < loadmodel->brush.num_leafs)
2981 out->children[j] = (mnode_t *)(loadmodel->brush.data_leafs + p);
2982 else
2983 {
2984 Con_Printf("Mod_Q1BSP_LoadNodes: invalid leaf index %i (file has only %i leafs)\n", p, loadmodel->brush.num_leafs);
2985 // map it to the solid leaf
2987 }
2988 }
2989 }
2990 }
2991
2993}

References model_t::brush, mnode_t::children, Con_Printf(), count, sizebuf_t::cursize, model_brush_t::data_leafs, model_brush_t::data_nodes, model_brush_t::data_planes, mnode_t::firstsurface, Host_Error(), i, model_brush_t::isbsp2, model_brush_t::isbsp2rmqe, loadmodel, mnode_t::maxs, Mem_Alloc, model_t::mempool, mnode_t::mins, Mod_BSP_LoadNodes_RecursiveSetParent(), MSG_ReadLittleFloat(), MSG_ReadLittleLong(), MSG_ReadLittleShort(), model_t::name, NULL, model_brush_t::num_leafs, model_brush_t::num_nodes, mnode_t::numsurfaces, and mnode_t::plane.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_LoadPlanes()

static void Mod_Q1BSP_LoadPlanes ( sizebuf_t * sb)
static

Definition at line 3241 of file model_brush.c.

3242{
3243 int i;
3244 mplane_t *out;
3245 int structsize = 20;
3246
3247 if (sb->cursize % structsize)
3248 Host_Error("Mod_Q1BSP_LoadPlanes: funny lump size in %s", loadmodel->name);
3249 loadmodel->brush.num_planes = sb->cursize / structsize;
3251
3252 for (i = 0;i < loadmodel->brush.num_planes;i++, out++)
3253 {
3254 out->normal[0] = MSG_ReadLittleFloat(sb);
3255 out->normal[1] = MSG_ReadLittleFloat(sb);
3256 out->normal[2] = MSG_ReadLittleFloat(sb);
3257 out->dist = MSG_ReadLittleFloat(sb);
3258 MSG_ReadLittleLong(sb); // type is not used, we use PlaneClassify
3259 PlaneClassify(out);
3260 }
3261}

References model_t::brush, sizebuf_t::cursize, model_brush_t::data_planes, mplane_t::dist, Host_Error(), i, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadLittleFloat(), MSG_ReadLittleLong(), model_t::name, mplane_t::normal, model_brush_t::num_planes, and PlaneClassify().

Referenced by Mod_Q1BSP_Load(), and Mod_Q2BSP_Load().

◆ Mod_Q1BSP_LoadSplitSky()

static void Mod_Q1BSP_LoadSplitSky ( unsigned char * src,
int width,
int height,
int bytesperpixel )
static

Definition at line 1570 of file model_brush.c.

1571{
1572 int x, y;
1573 int w = width/2;
1574 int h = height;
1575 unsigned int *solidpixels = (unsigned int *)Mem_Alloc(tempmempool, w*h*sizeof(unsigned char[4]));
1576 unsigned int *alphapixels = (unsigned int *)Mem_Alloc(tempmempool, w*h*sizeof(unsigned char[4]));
1577
1578 // allocate a texture pool if we need it
1581
1582 if (bytesperpixel == 4)
1583 {
1584 for (y = 0;y < h;y++)
1585 {
1586 for (x = 0;x < w;x++)
1587 {
1588 solidpixels[y*w+x] = ((unsigned *)src)[y*width+x+w];
1589 alphapixels[y*w+x] = ((unsigned *)src)[y*width+x];
1590 }
1591 }
1592 }
1593 else
1594 {
1595 // make an average value for the back to avoid
1596 // a fringe on the top level
1597 int p, r, g, b;
1598 union
1599 {
1600 unsigned int i;
1601 unsigned char b[4];
1602 }
1603 bgra;
1604 r = g = b = 0;
1605 for (y = 0;y < h;y++)
1606 {
1607 for (x = 0;x < w;x++)
1608 {
1609 p = src[x*width+y+w];
1610 r += palette_rgb[p][0];
1611 g += palette_rgb[p][1];
1612 b += palette_rgb[p][2];
1613 }
1614 }
1615 bgra.b[2] = r/(w*h);
1616 bgra.b[1] = g/(w*h);
1617 bgra.b[0] = b/(w*h);
1618 bgra.b[3] = 0;
1619 for (y = 0;y < h;y++)
1620 {
1621 for (x = 0;x < w;x++)
1622 {
1623 solidpixels[y*w+x] = palette_bgra_complete[src[y*width+x+w]];
1624 p = src[y*width+x];
1625 alphapixels[y*w+x] = p ? palette_bgra_complete[p] : bgra.i;
1626 }
1627 }
1628 }
1629
1630 // Load the solid and alpha parts of the sky texture as separate textures
1632 "sky_solidtexture",
1633 0,
1634 (unsigned char *) solidpixels,
1635 w, h, w, h,
1636 CRC_Block((unsigned char *) solidpixels, w*h*4),
1637 vid.sRGB3D);
1639 "sky_alphatexture",
1640 TEXF_ALPHA,
1641 (unsigned char *) alphapixels,
1642 w, h, w, h,
1643 CRC_Block((unsigned char *) alphapixels, w*h*4),
1644 vid.sRGB3D);
1645 Mem_Free(solidpixels);
1646 Mem_Free(alphapixels);
1647}
unsigned short CRC_Block(const unsigned char *data, size_t size)
Definition com_crc16.c:75
skinframe_t * R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, int comparewidth, int compareheight, int comparecrc, qbool sRGB)
Definition gl_rmain.c:2546
GLenum GLsizei width
Definition glquake.h:622
GLenum GLsizei GLsizei height
Definition glquake.h:622
unsigned char palette_rgb[256][3]
Definition palette.c:7
unsigned int palette_bgra_complete[256]
Definition palette.c:13
prvm_eval_t * src
#define TEXF_ALPHA
Definition r_textures.h:9
dp_FragColor g
struct skinframe_s * alphaskyskinframe
struct skinframe_s * solidskyskinframe
qbool sRGB3D
whether 3D rendering is sRGB corrected (based on sRGBcapable3D)
Definition vid.h:76

References model_brush_t::alphaskyskinframe, b, model_t::brush, ca_dedicated, cls, CRC_Block(), g, height, i, loadmodel, Mem_Alloc, Mem_Free, NULL, palette_bgra_complete, palette_rgb, r, R_AllocTexturePool(), R_SkinFrame_LoadInternalBGRA(), model_brush_t::solidskyskinframe, src, viddef_t::sRGB3D, client_static_t::state, tempmempool, TEXF_ALPHA, model_t::texturepool, vid, w, width, x, and y.

Referenced by Mod_Q1BSP_LoadTextures().

◆ Mod_Q1BSP_LoadSurfedges()

static void Mod_Q1BSP_LoadSurfedges ( sizebuf_t * sb)
static

Definition at line 3226 of file model_brush.c.

3227{
3228 int i;
3229 int structsize = 4;
3230
3231 if (sb->cursize % structsize)
3232 Host_Error("Mod_Q1BSP_LoadSurfedges: funny lump size in %s",loadmodel->name);
3233 loadmodel->brushq1.numsurfedges = sb->cursize / structsize;
3235
3236 for (i = 0;i < loadmodel->brushq1.numsurfedges;i++)
3238}

References model_t::brushq1, sizebuf_t::cursize, Host_Error(), i, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadLittleLong(), model_t::name, model_brushq1_t::numsurfedges, and model_brushq1_t::surfedges.

Referenced by Mod_Q1BSP_Load(), and Mod_Q2BSP_Load().

◆ Mod_Q1BSP_LoadTexinfo()

static void Mod_Q1BSP_LoadTexinfo ( sizebuf_t * sb)
static

Definition at line 2377 of file model_brush.c.

2378{
2379 mtexinfo_t *out;
2380 int i, j, k, count, miptex;
2381 int structsize = 40;
2382
2383 if (sb->cursize % structsize)
2384 Host_Error("Mod_Q1BSP_LoadTexinfo: funny lump size in %s",loadmodel->name);
2385 count = sb->cursize / structsize;
2386 out = (mtexinfo_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
2387
2388 loadmodel->brushq1.texinfo = out;
2390
2391 for (i = 0;i < count;i++, out++)
2392 {
2393 for (k = 0;k < 2;k++)
2394 for (j = 0;j < 4;j++)
2395 out->vecs[k][j] = MSG_ReadLittleFloat(sb);
2396
2397 miptex = MSG_ReadLittleLong(sb);
2398 out->q1flags = MSG_ReadLittleLong(sb);
2399
2400 if (out->q1flags & TEX_SPECIAL)
2401 {
2402 // if texture chosen is NULL or the shader needs a lightmap,
2403 // force to notexture water shader
2405 }
2406 else
2407 {
2408 // if texture chosen is NULL, force to notexture
2410 }
2411 // see if the specified miptex is valid and try to use it instead
2413 {
2414 if ((unsigned int) miptex >= (unsigned int) loadmodel->num_textures)
2415 Con_Printf("error in model \"%s\": invalid miptex index %i(of %i)\n", loadmodel->name, miptex, loadmodel->num_textures);
2416 else
2417 out->textureindex = miptex;
2418 }
2419 }
2420}

References model_t::brushq1, Con_Printf(), count, sizebuf_t::cursize, model_t::data_textures, Host_Error(), i, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadLittleFloat(), MSG_ReadLittleLong(), model_t::name, model_t::num_textures, model_brushq1_t::numtexinfo, mtexinfo_t::q1flags, TEX_SPECIAL, model_brushq1_t::texinfo, mtexinfo_t::textureindex, and mtexinfo_t::vecs.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_LoadTextures()

static void Mod_Q1BSP_LoadTextures ( sizebuf_t * sb)
static

Definition at line 1649 of file model_brush.c.

1650{
1651 int i, j, k, num, max, altmax, mtwidth, mtheight, doffset, incomplete, nummiptex = 0, firstskynoshadowtexture = 0;
1652 skinframe_t *skinframemissing;
1653 texture_t *tx, *tx2, *anims[10], *altanims[10], *currentskynoshadowtexture;
1654 texture_t backuptex;
1655 unsigned char *data, *mtdata;
1656 const char *s;
1658 unsigned char zeroopaque[4], zerotrans[4];
1659 sizebuf_t miptexsb;
1660 char vabuf[1024];
1661 Vector4Set(zeroopaque, 0, 0, 0, 255);
1662 Vector4Set(zerotrans, 0, 0, 0, 128);
1663
1665
1666 // add two slots for notexture walls and notexture liquids, and duplicate
1667 // all sky textures; sky surfaces can be shadow-casting or not, the surface
1668 // loading will choose according to the contents behind the surface
1669 // (necessary to support e1m5 logo shadow which has a SKY contents brush,
1670 // while correctly treating sky textures as occluders in other situations).
1671 if (sb->cursize)
1672 {
1673 int numsky = 0;
1674 size_t watermark;
1675 nummiptex = MSG_ReadLittleLong(sb);
1676 loadmodel->num_textures = nummiptex + 2;
1677 // save the position so we can go back to it
1678 watermark = sb->readcount;
1679 for (i = 0; i < nummiptex; i++)
1680 {
1681 doffset = MSG_ReadLittleLong(sb);
1683 continue;
1684 if (doffset == -1)
1685 {
1686 Con_DPrintf("%s: miptex #%i missing\n", loadmodel->name, i);
1687 continue;
1688 }
1689
1690 MSG_InitReadBuffer(&miptexsb, sb->data + doffset, sb->cursize - doffset);
1691
1692 // copy name, but only up to 16 characters
1693 // (the output buffer can hold more than this, but the input buffer is
1694 // only 16)
1695 for (j = 0; j < 16; j++)
1696 name[j] = MSG_ReadByte(&miptexsb);
1697 name[j] = 0;
1698 // pretty up the buffer (replacing any trailing garbage with 0)
1699 for (j = (int)strlen(name); j < 16; j++)
1700 name[j] = 0;
1701 // bones_was_here: force all names to lowercase (matching code below) so we don't crash on e2m9
1702 for (j = 0;name[j];j++)
1703 if (name[j] >= 'A' && name[j] <= 'Z')
1704 name[j] += 'a' - 'A';
1705
1706 if (!strncmp(name, "sky", 3))
1707 numsky++;
1708 }
1709
1710 // bump it back to where we started parsing
1711 sb->readcount = (int)watermark;
1712
1713 firstskynoshadowtexture = loadmodel->num_textures;
1714 loadmodel->num_textures += numsky;
1715 }
1716 else
1717 {
1719 firstskynoshadowtexture = loadmodel->num_textures;
1720 }
1722
1724
1725 // we'll be writing to these in parallel for sky textures
1726 currentskynoshadowtexture = loadmodel->data_textures + firstskynoshadowtexture;
1727
1728 // fill out all slots with notexture
1729 skinframemissing = R_SkinFrame_LoadMissing();
1730 for (i = 0, tx = loadmodel->data_textures;i < loadmodel->num_textures;i++, tx++)
1731 {
1732 dp_strlcpy(tx->name, "NO TEXTURE FOUND", sizeof(tx->name));
1733 tx->width = 16;
1734 tx->height = 16;
1735 tx->basealpha = 1.0f;
1736 tx->materialshaderpass = tx->shaderpasses[0] = Mod_CreateShaderPass(loadmodel->mempool, skinframemissing);
1737 tx->materialshaderpass->skinframes[0] = skinframemissing;
1738 tx->currentskinframe = skinframemissing;
1740 if (i == loadmodel->num_textures - 1)
1741 {
1745 }
1746 else
1747 {
1750 }
1751 tx->currentframe = tx;
1752
1753 // clear water settings
1754 tx->reflectmin = 0;
1755 tx->reflectmax = 1;
1757 tx->refractfactor = 1;
1758 Vector4Set(tx->refractcolor4f, 1, 1, 1, 1);
1759 tx->reflectfactor = 1;
1760 Vector4Set(tx->reflectcolor4f, 1, 1, 1, 1);
1761 tx->r_water_wateralpha = 1;
1763 tx->offsetscale = 1;
1764 tx->offsetbias = 0;
1765 tx->specularscalemod = 1;
1766 tx->specularpowermod = 1;
1768 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
1769 // JUST GREP FOR "specularscalemod = 1".
1770 }
1771
1772 if (!sb->cursize)
1773 {
1774 Con_Printf("%s: no miptex lump to load textures from\n", loadmodel->name);
1775 return;
1776 }
1777
1778 s = loadmodel->name;
1779 if (!strncasecmp(s, "maps/", 5))
1780 s += 5;
1781 FS_StripExtension(s, mapname, sizeof(mapname));
1782
1783 // LadyHavoc: mostly rewritten map texture loader
1784 for (i = 0;i < nummiptex;i++)
1785 {
1786 doffset = MSG_ReadLittleLong(sb);
1788 continue;
1789 if (doffset == -1)
1790 {
1791 Con_DPrintf("%s: miptex #%i missing\n", loadmodel->name, i);
1792 continue;
1793 }
1794
1795 MSG_InitReadBuffer(&miptexsb, sb->data + doffset, sb->cursize - doffset);
1796
1797 // copy name, but only up to 16 characters
1798 // (the output buffer can hold more than this, but the input buffer is
1799 // only 16)
1800 for (j = 0;j < 16;j++)
1801 name[j] = MSG_ReadByte(&miptexsb);
1802 name[j] = 0;
1803 // pretty up the buffer (replacing any trailing garbage with 0)
1804 for (j = (int)strlen(name);j < 16;j++)
1805 name[j] = 0;
1806
1807 if (!name[0])
1808 {
1809 dpsnprintf(name, sizeof(name), "unnamed%i", i);
1810 Con_DPrintf("%s: warning: renaming unnamed texture to %s\n", loadmodel->name, name);
1811 }
1812
1813 mtwidth = MSG_ReadLittleLong(&miptexsb);
1814 mtheight = MSG_ReadLittleLong(&miptexsb);
1815 mtdata = NULL;
1816 j = MSG_ReadLittleLong(&miptexsb);
1817 if (j)
1818 {
1819 // texture included
1820 if (j < 40 || j + mtwidth * mtheight > miptexsb.cursize)
1821 {
1822 Con_Printf("%s: Texture \"%s\" is corrupt or incomplete\n", loadmodel->name, name);
1823 continue;
1824 }
1825 mtdata = miptexsb.data + j;
1826 }
1827
1828 if ((mtwidth & 15) || (mtheight & 15))
1829 Con_DPrintf("%s: warning: texture \"%s\" is not 16 aligned\n", loadmodel->name, name);
1830
1831 // LadyHavoc: force all names to lowercase
1832 for (j = 0;name[j];j++)
1833 if (name[j] >= 'A' && name[j] <= 'Z')
1834 name[j] += 'a' - 'A';
1835
1836 tx = loadmodel->data_textures + i;
1837 // try to load shader or external textures, but first we have to backup the texture_t because shader loading overwrites it even if it fails
1838 backuptex = loadmodel->data_textures[i];
1839 if (name[0] && /* HACK */ strncmp(name, "sky", 3) /* END HACK */ && (Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + i, va(vabuf, sizeof(vabuf), "%s/%s", mapname, name), false, false, TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL) ||
1841 {
1842 // set the width/height fields which are used for parsing texcoords in this bsp format
1843 tx->width = mtwidth;
1844 tx->height = mtheight;
1845 continue;
1846 }
1847 // no luck with loading shaders or external textures - restore the in-progress texture loading
1848 loadmodel->data_textures[i] = backuptex;
1849
1850 dp_strlcpy(tx->name, name, sizeof(tx->name));
1851 tx->width = mtwidth;
1852 tx->height = mtheight;
1853 tx->basealpha = 1.0f;
1854
1855 // start out with no animation
1856 tx->currentframe = tx;
1858
1859 if (tx->name[0] == '*')
1860 {
1861 if (!strncmp(tx->name, "*lava", 5))
1862 {
1865 }
1866 else if (!strncmp(tx->name, "*slime", 6))
1867 {
1870 }
1871 else
1872 {
1875 }
1876 }
1877 else if (!strncmp(tx->name, "sky", 3))
1878 {
1881 // for the surface traceline we need to hit this surface as a solid...
1883 }
1884 else
1885 {
1888 }
1889
1890 if (cls.state != ca_dedicated)
1891 {
1892 skinframe_t *skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s/%s", mapname, tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false, false);
1893 if ((!skinframe &&
1894 !(skinframe = R_SkinFrame_LoadExternal(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s", tx->name), TEXF_ALPHA | TEXF_MIPMAP | TEXF_ISWORLD | TEXF_PICMIP | TEXF_COMPRESS, false, false)))
1895 // HACK: It loads custom skybox textures as a wall if loaded as a skinframe.
1896 || !strncmp(tx->name, "sky", 3))
1897 {
1898 // did not find external texture via shader loading, load it from the bsp or wad3
1899 if (loadmodel->brush.ishlbsp)
1900 {
1901 // internal texture overrides wad
1902 unsigned char* pixels, * freepixels;
1903 pixels = freepixels = NULL;
1904 if (mtdata)
1905 pixels = W_ConvertWAD3TextureBGRA(&miptexsb);
1906 if (pixels == NULL)
1907 pixels = freepixels = W_GetTextureBGRA(tx->name);
1908 if (pixels != NULL)
1909 {
1910 tx->width = image_width;
1911 tx->height = image_height;
1913 }
1914 if (freepixels)
1915 Mem_Free(freepixels);
1916 }
1917 else if (!strncmp(tx->name, "sky", 3) && mtwidth == mtheight * 2)
1918 {
1919 data = loadimagepixelsbgra(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s/%s", mapname, tx->name), false, false, false, NULL);
1920 if (!data)
1921 data = loadimagepixelsbgra(gamemode == GAME_TENEBRAE ? tx->name : va(vabuf, sizeof(vabuf), "textures/%s", tx->name), false, false, false, NULL);
1922 if (data && image_width == image_height * 2)
1923 {
1925 Mem_Free(data);
1926 }
1927 else if (mtdata != NULL)
1928 Mod_Q1BSP_LoadSplitSky(mtdata, mtwidth, mtheight, 1);
1929 }
1930 else if (mtdata) // texture included
1932 // if mtdata is NULL, the "missing" texture has already been assigned to this
1933 // LadyHavoc: some Tenebrae textures get replaced by black
1934 if (!strncmp(tx->name, "*glassmirror", 12)) // Tenebrae
1935 tx->materialshaderpass->skinframes[0] = R_SkinFrame_LoadInternalBGRA(tx->name, TEXF_MIPMAP | TEXF_ALPHA, zerotrans, 1, 1, 0, 0, 0, false);
1936 else if (!strncmp(tx->name, "mirror", 6)) // Tenebrae
1937 tx->materialshaderpass->skinframes[0] = R_SkinFrame_LoadInternalBGRA(tx->name, 0, zeroopaque, 1, 1, 0, 0, 0, false);
1938 }
1939 else
1940 tx->materialshaderpass->skinframes[0] = skinframe;
1942 }
1943
1945 if (tx->name[0] == '*')
1946 {
1947 // LadyHavoc: some turbulent textures should not be affected by wateralpha
1948 if (!strncmp(tx->name, "*glassmirror", 12)) // Tenebrae
1950 else if (!strncmp(tx->name,"*lava",5)
1951 || !strncmp(tx->name,"*teleport",9)
1952 || !strncmp(tx->name,"*rift",5)) // Scourge of Armagon texture
1954 else
1956 if (tx->currentskinframe != NULL && tx->currentskinframe->hasalpha)
1958 }
1959 else if (tx->name[0] == '{') // fence textures
1960 {
1962 }
1963 else if (!strncmp(tx->name, "mirror", 6)) // Tenebrae
1964 {
1965 // replace the texture with black
1967 }
1968 else if (!strncmp(tx->name, "sky", 3))
1970 else if (!strcmp(tx->name, "caulk"))
1972 else if (tx->currentskinframe != NULL && tx->currentskinframe->hasalpha)
1975
1976 // duplicate of sky with NOSHADOW
1978 {
1979 *currentskynoshadowtexture = *tx;
1980 currentskynoshadowtexture->basematerialflags |= MATERIALFLAG_NOSHADOW;
1981 tx->skynoshadowtexture = currentskynoshadowtexture;
1982 currentskynoshadowtexture++;
1983 }
1984 }
1985
1986 // sequence the animations
1987 for (i = 0;i < nummiptex;i++)
1988 {
1989 tx = loadmodel->data_textures + i;
1990 if (!tx || tx->name[0] != '+' || tx->name[1] == 0 || tx->name[2] == 0)
1991 continue;
1992 num = tx->name[1];
1993 if ((num < '0' || num > '9') && (num < 'a' || num > 'j'))
1994 {
1995 Con_Printf("Bad animating texture %s\n", tx->name);
1996 continue;
1997 }
1998 if (tx->anim_total[0] || tx->anim_total[1])
1999 continue; // already sequenced
2000
2001 // find the number of frames in the animation
2002 memset(anims, 0, sizeof(anims));
2003 memset(altanims, 0, sizeof(altanims));
2004
2005 for (j = i;j < nummiptex;j++)
2006 {
2007 tx2 = loadmodel->data_textures + j;
2008 if (!tx2 || tx2->name[0] != '+' || strcmp(tx2->name+2, tx->name+2))
2009 continue;
2010
2011 num = tx2->name[1];
2012 if (num >= '0' && num <= '9')
2013 anims[num - '0'] = tx2;
2014 else if (num >= 'a' && num <= 'j')
2015 altanims[num - 'a'] = tx2;
2016 // No need to warn otherwise - we already did above.
2017 }
2018
2019 max = altmax = 0;
2020 for (j = 0;j < 10;j++)
2021 {
2022 if (anims[j])
2023 max = j + 1;
2024 if (altanims[j])
2025 altmax = j + 1;
2026 }
2027 //Con_Printf("linking animation %s (%i:%i frames)\n\n", tx->name, max, altmax);
2028
2029 incomplete = false;
2030 for (j = 0;j < max;j++)
2031 {
2032 if (!anims[j])
2033 {
2034 Con_Printf("Missing frame %i of %s\n", j, tx->name);
2035 incomplete = true;
2036 }
2037 }
2038 for (j = 0;j < altmax;j++)
2039 {
2040 if (!altanims[j])
2041 {
2042 Con_Printf("Missing altframe %i of %s\n", j, tx->name);
2043 incomplete = true;
2044 }
2045 }
2046 if (incomplete)
2047 continue;
2048
2049 // If we have exactly one frame, something's wrong.
2050 if (max + altmax <= 1)
2051 {
2052 Con_Printf("Texture %s is animated (leading +) but has only one frame\n", tx->name);
2053 }
2054
2055 if (altmax < 1)
2056 {
2057 // if there is no alternate animation, duplicate the primary
2058 // animation into the alternate
2059 altmax = max;
2060 for (k = 0;k < 10;k++)
2061 altanims[k] = anims[k];
2062 }
2063
2064 if (max < 1)
2065 {
2066 // Warn.
2067 Con_Printf("Missing frame 0 of %s\n", tx->name);
2068
2069 // however, we can handle this by duplicating the alternate animation into the primary
2070 max = altmax;
2071 for (k = 0;k < 10;k++)
2072 anims[k] = altanims[k];
2073 }
2074
2075
2076 // link together the primary animation
2077 for (j = 0;j < max;j++)
2078 {
2079 tx2 = anims[j];
2080 tx2->animated = 1; // q1bsp
2081 tx2->anim_total[0] = max;
2082 tx2->anim_total[1] = altmax;
2083 for (k = 0;k < 10;k++)
2084 {
2085 tx2->anim_frames[0][k] = anims[k];
2086 tx2->anim_frames[1][k] = altanims[k];
2087 }
2088 }
2089
2090 // if there really is an alternate anim...
2091 if (anims[0] != altanims[0])
2092 {
2093 // link together the alternate animation
2094 for (j = 0;j < altmax;j++)
2095 {
2096 tx2 = altanims[j];
2097 tx2->animated = 1; // q1bsp
2098 // the primary/alternate are reversed here
2099 tx2->anim_total[0] = altmax;
2100 tx2->anim_total[1] = max;
2101 for (k = 0;k < 10;k++)
2102 {
2103 tx2->anim_frames[0][k] = altanims[k];
2104 tx2->anim_frames[1][k] = anims[k];
2105 }
2106 }
2107 }
2108 }
2109}
@ GAME_TENEBRAE
full of evil hackery
Definition com_game.h:41
string mapname
skinframe_t * R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
Definition gl_rmain.c:2616
cvar_t r_fullbrights
Definition gl_rmain.c:122
skinframe_t * R_SkinFrame_LoadExternal(const char *name, int textureflags, qbool complain, qbool fallbacknotexture)
Definition gl_rmain.c:2314
skinframe_t * R_SkinFrame_LoadMissing(void)
Definition gl_rmain.c:2804
GLint GLenum GLenum GLvoid * pixels
Definition glquake.h:706
int image_height
Definition image.c:10
unsigned char * loadimagepixelsbgra(const char *filename, qbool complain, qbool allowFixtrans, qbool convertsRGB, int *miplevel)
Definition image.c:1043
int image_width
Definition image.c:9
#define Vector4Set(vec, r, g, b, a)
Definition mathlib.h:86
float strlen(string s)
static void Mod_Q1BSP_LoadSplitSky(unsigned char *src, int width, int height, int bytesperpixel)
#define MATERIALFLAG_ADD
Definition model_brush.h:81
#define MATERIALFLAG_ALPHA
Definition model_brush.h:79
#define MATERIALFLAG_NODRAW
Definition model_brush.h:96
#define MATERIALFLAG_ALPHATEST
#define MATERIALFLAG_BLENDED
#define MATERIALFLAG_WATERALPHA
Definition model_brush.h:85
#define MATERIALFLAG_WATERSHADER
#define MATERIALFLAG_NOSHADOW
#define MATERIALFLAG_REFLECTION
#define MATERIALFLAG_LIGHTBOTHSIDES
Definition model_brush.h:98
#define MATERIALFLAG_WATERSCROLL
Definition model_brush.h:94
qbool Mod_LoadTextureFromQ3Shader(mempool_t *mempool, const char *modelname, texture_t *texture, const char *name, qbool warnmissing, qbool fallback, int defaulttexflags, int defaultmaterialflags)
texture_shaderpass_t * Mod_CreateShaderPass(mempool_t *mempool, skinframe_t *skinframe)
@ TRANSPARENTSORT_DISTANCE
Definition r_qshader.h:194
@ OFFSETMAPPING_DEFAULT
Definition r_qshader.h:186
#define TEXF_PICMIP
Definition r_textures.h:21
#define TEXF_MIPMAP
Definition r_textures.h:11
#define TEXF_ISWORLD
Definition r_textures.h:33
#define TEXF_COMPRESS
Definition r_textures.h:23
float value
Definition cvar.h:74
int readcount
Definition common.h:55
struct skinframe_s * skinframes[TEXTURE_MAXFRAMES]
Definition r_qshader.h:265
texture_shaderpass_t * shaderpasses[Q3SHADER_MAXLAYERS]
float refractfactor
dptransparentsortcategory_t transparentsort
int anim_total[2]
dpoffsetmapping_technique_t offsetmapping
int currentmaterialflags
float basealpha
float specularpowermod
struct texture_s * currentframe
float reflectmin
vec4_t refractcolor4f
float reflectmax
float offsetscale
float refractive_index
texture_shaderpass_t * materialshaderpass
float r_water_wateralpha
float specularscalemod
float reflectfactor
float offsetbias
struct skinframe_s * currentskinframe
struct texture_s * anim_frames[2][10]
vec4_t reflectcolor4f
unsigned char * W_GetTextureBGRA(char *name)
Definition wad.c:277
unsigned char * W_ConvertWAD3TextureBGRA(sizebuf_t *sb)
Definition wad.c:226

References texture_t::anim_frames, texture_t::anim_total, texture_t::animated, texture_t::basealpha, texture_t::basematerialflags, model_t::brush, ca_dedicated, cls, Con_DPrintf(), Con_Printf(), CRC_Block(), texture_t::currentframe, texture_t::currentmaterialflags, texture_t::currentskinframe, sizebuf_t::cursize, data, sizebuf_t::data, model_t::data_textures, dp_strlcpy, dpsnprintf(), FS_StripExtension(), GAME_TENEBRAE, gamemode, texture_t::height, i, image_height, image_width, int(), cvar_t::integer, model_brush_t::ishlbsp, loadimagepixelsbgra(), loadmodel, mapname, MATERIALFLAG_ADD, MATERIALFLAG_ALPHA, MATERIALFLAG_ALPHATEST, MATERIALFLAG_BLENDED, MATERIALFLAG_LIGHTBOTHSIDES, MATERIALFLAG_NODRAW, MATERIALFLAG_NOSHADOW, MATERIALFLAG_REFLECTION, MATERIALFLAG_SKY, MATERIALFLAG_WALL, MATERIALFLAG_WATERALPHA, MATERIALFLAG_WATERSCROLL, MATERIALFLAG_WATERSHADER, texture_t::materialshaderpass, max, MAX_QPATH, Mem_Alloc, Mem_Free, model_t::mempool, Mod_CreateShaderPass(), Mod_LoadTextureFromQ3Shader(), Mod_Q1BSP_LoadSplitSky(), mod_q1bsp_texture_lava, mod_q1bsp_texture_sky, mod_q1bsp_texture_slime, mod_q1bsp_texture_solid, mod_q1bsp_texture_water, mod_q3shader_default_refractive_index, MSG_InitReadBuffer(), MSG_ReadByte, MSG_ReadLittleLong(), model_t::name, name, texture_t::name, NULL, model_t::num_textures, model_t::num_texturesperskin, texture_t::offsetbias, texture_t::offsetmapping, OFFSETMAPPING_DEFAULT, texture_t::offsetscale, pixels, r_fullbrights, r_nosurftextures, R_SkinFrame_LoadExternal(), R_SkinFrame_LoadInternalBGRA(), R_SkinFrame_LoadInternalQuake(), R_SkinFrame_LoadMissing(), texture_t::r_water_wateralpha, sizebuf_t::readcount, texture_t::reflectcolor4f, texture_t::reflectfactor, texture_t::reflectmax, texture_t::reflectmin, texture_t::refractcolor4f, texture_t::refractfactor, texture_t::refractive_index, texture_t::shaderpasses, texture_shaderpass_t::skinframes, texture_t::skynoshadowtexture, texture_t::specularpowermod, texture_t::specularscalemod, client_static_t::state, strlen(), texture_t::supercontents, SUPERCONTENTS_SOLID, texture_t::surfaceflags, TEXF_ALPHA, TEXF_COMPRESS, TEXF_ISWORLD, TEXF_MIPMAP, TEXF_PICMIP, texture_t::transparentsort, TRANSPARENTSORT_DISTANCE, va(), cvar_t::value, Vector4Set, W_ConvertWAD3TextureBGRA(), W_GetTextureBGRA(), and texture_t::width.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_LoadVertexes()

static void Mod_Q1BSP_LoadVertexes ( sizebuf_t * sb)
static

Definition at line 2276 of file model_brush.c.

2277{
2278 mvertex_t *out;
2279 int i, count;
2280 int structsize = 12;
2281
2282 if (sb->cursize % structsize)
2283 Host_Error("Mod_Q1BSP_LoadVertexes: funny lump size in %s",loadmodel->name);
2284 count = sb->cursize / structsize;
2285 out = (mvertex_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
2286
2287 loadmodel->brushq1.vertexes = out;
2289
2290 for ( i=0 ; i<count ; i++, out++)
2291 {
2292 out->position[0] = MSG_ReadLittleFloat(sb);
2293 out->position[1] = MSG_ReadLittleFloat(sb);
2294 out->position[2] = MSG_ReadLittleFloat(sb);
2295 }
2296}

References model_t::brushq1, count, sizebuf_t::cursize, Host_Error(), i, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadLittleFloat(), model_t::name, model_brushq1_t::numvertexes, mvertex_t::position, and model_brushq1_t::vertexes.

Referenced by Mod_Q1BSP_Load(), and Mod_Q2BSP_Load().

◆ Mod_Q1BSP_LoadVisibility()

◆ Mod_Q1BSP_MakeHull0()

static void Mod_Q1BSP_MakeHull0 ( void )
static

Definition at line 3169 of file model_brush.c.

3170{
3171 mnode_t *in;
3172 mclipnode_t *out;
3173 int i;
3174 hull_t *hull;
3175
3176 hull = &loadmodel->brushq1.hulls[0];
3177
3179 out = (mclipnode_t *)Mem_Alloc(loadmodel->mempool, loadmodel->brush.num_nodes * sizeof(*out));
3180
3181 hull->clipnodes = out;
3182 hull->firstclipnode = 0;
3185
3186 for (i = 0;i < loadmodel->brush.num_nodes;i++, out++, in++)
3187 {
3188 out->planenum = in->plane - loadmodel->brush.data_planes;
3189 out->children[0] = in->children[0]->plane ? in->children[0] - loadmodel->brush.data_nodes : ((mleaf_t *)in->children[0])->contents;
3190 out->children[1] = in->children[1]->plane ? in->children[1] - loadmodel->brush.data_nodes : ((mleaf_t *)in->children[1])->contents;
3191 }
3192}

References model_t::brush, model_t::brushq1, mclipnode_t::children, mnode_t::children, hull_t::clipnodes, model_brush_t::data_nodes, model_brush_t::data_planes, hull_t::firstclipnode, model_brushq1_t::hulls, i, hull_t::lastclipnode, loadmodel, Mem_Alloc, model_t::mempool, model_brush_t::num_nodes, mnode_t::plane, mclipnode_t::planenum, and hull_t::planes.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_NativeContentsFromSuperContents()

int Mod_Q1BSP_NativeContentsFromSuperContents ( int supercontents)

Definition at line 650 of file model_brush.c.

651{
652 if (supercontents & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY))
653 return CONTENTS_SOLID;
654 if (supercontents & SUPERCONTENTS_SKY)
655 return CONTENTS_SKY;
656 if (supercontents & SUPERCONTENTS_LAVA)
657 return CONTENTS_LAVA;
658 if (supercontents & SUPERCONTENTS_SLIME)
659 return CONTENTS_SLIME;
660 if (supercontents & SUPERCONTENTS_WATER)
661 return CONTENTS_WATER;
662 return CONTENTS_EMPTY;
663}
#define SUPERCONTENTS_BODY
Definition bspfile.h:201
#define CONTENTS_LAVA
Definition bspfile.h:137
#define CONTENTS_SKY
Definition bspfile.h:138

References CONTENTS_EMPTY, CONTENTS_LAVA, CONTENTS_SKY, CONTENTS_SLIME, CONTENTS_SOLID, CONTENTS_WATER, SUPERCONTENTS_BODY, SUPERCONTENTS_LAVA, SUPERCONTENTS_SKY, SUPERCONTENTS_SLIME, SUPERCONTENTS_SOLID, and SUPERCONTENTS_WATER.

Referenced by Mod_Q1BSP_Load(), SV_CheckWater(), SV_CheckWaterTransition(), VM_CL_pointcontents(), and VM_SV_pointcontents().

◆ Mod_Q1BSP_ParseWadsFromEntityLump()

static void Mod_Q1BSP_ParseWadsFromEntityLump ( const char * data)
static

Definition at line 2207 of file model_brush.c.

2208{
2209 char key[128], value[4096];
2210 int i, j, k;
2211 if (!data)
2212 return;
2213 if (!COM_ParseToken_Simple(&data, false, false, true))
2214 return; // error
2215 if (com_token[0] != '{')
2216 return; // error
2217 while (1)
2218 {
2219 if (!COM_ParseToken_Simple(&data, false, false, true))
2220 return; // error
2221 if (com_token[0] == '}')
2222 break; // end of worldspawn
2223 if (com_token[0] == '_')
2224 dp_strlcpy(key, com_token + 1, sizeof(key));
2225 else
2226 dp_strlcpy(key, com_token, sizeof(key));
2227 while (key[strlen(key)-1] == ' ') // remove trailing spaces
2228 key[strlen(key)-1] = 0;
2229 if (!COM_ParseToken_Simple(&data, false, false, true))
2230 return; // error
2231 dpsnprintf(value, sizeof(value), "%s", com_token);
2232 if (!strcmp("wad", key)) // for HalfLife maps
2233 {
2234 if (loadmodel->brush.ishlbsp)
2235 {
2236 j = 0;
2237 for (i = 0;i < (int)sizeof(value);i++)
2238 if (value[i] != ';' && value[i] != '\\' && value[i] != '/' && value[i] != ':')
2239 break;
2240 if (i < (int)sizeof(value) && value[i])
2241 {
2242 for (;i < (int)sizeof(value);i++)
2243 {
2244 // ignore path - the \\ check is for HalfLife... stupid windoze 'programmers'...
2245 if (value[i] == '\\' || value[i] == '/' || value[i] == ':')
2246 j = i+1;
2247 else if (value[i] == ';' || value[i] == 0)
2248 {
2249 k = value[i];
2250 value[i] = 0;
2251 W_LoadTextureWadFile(&value[j], false);
2252 j = i+1;
2253 if (!k)
2254 break;
2255 }
2256 }
2257 }
2258 }
2259 }
2260 }
2261}
GLsizei const GLfloat * value
Definition glquake.h:740
void W_LoadTextureWadFile(char *filename, int complain)
Definition wad.c:165

References model_t::brush, COM_ParseToken_Simple(), com_token, data, dp_strlcpy, dpsnprintf(), i, int(), model_brush_t::ishlbsp, loadmodel, strlen(), value, and W_LoadTextureWadFile().

Referenced by Mod_Q1BSP_LoadEntities().

◆ Mod_Q1BSP_PointSuperContents()

static int Mod_Q1BSP_PointSuperContents ( struct model_s * model,
int frame,
const vec3_t point )
static

Definition at line 1039 of file model_brush.c.

1040{
1041 int num = model->brushq1.hulls[0].firstclipnode;
1042 mplane_t *plane;
1043 mclipnode_t *nodes = model->brushq1.hulls[0].clipnodes;
1044 mplane_t *planes = model->brushq1.hulls[0].planes;
1045 while (num >= 0)
1046 {
1047 plane = planes + nodes[num].planenum;
1048 num = nodes[num].children[(plane->type < 3 ? point[plane->type] : DotProduct(plane->normal, point)) < plane->dist];
1049 }
1051}

References mclipnode_t::children, mplane_t::dist, DotProduct, Mod_Q1BSP_SuperContentsFromNativeContents(), model, mplane_t::normal, mclipnode_t::planenum, and mplane_t::type.

Referenced by Mod_Q1BSP_AssignNoShadowSkySurfaces(), and Mod_Q1BSP_Load().

◆ Mod_Q1BSP_RecursiveHullCheck()

static int Mod_Q1BSP_RecursiveHullCheck ( RecursiveHullCheckTraceInfo_t * t,
int num,
double p1f,
double p2f,
double p1[3],
double p2[3] )
static

Definition at line 687 of file model_brush.c.

688{
689 // status variables, these don't need to be saved on the stack when
690 // recursing... but are because this should be thread-safe
691 // (note: tracing against a bbox is not thread-safe, yet)
692 int ret;
693 mplane_t *plane;
694 double t1, t2;
695
696 // variables that need to be stored on the stack when recursing
697 mclipnode_t *node;
698 int p1side, p2side;
699 double midf, mid[3];
700
701 // keep looping until we hit a leaf
702 while (num >= 0)
703 {
704 // find the point distances
705 node = t->hull->clipnodes + num;
706 plane = t->hull->planes + node->planenum;
707
708 // axial planes can be calculated more quickly without the DotProduct
709 if (plane->type < 3)
710 {
711 t1 = p1[plane->type] - plane->dist;
712 t2 = p2[plane->type] - plane->dist;
713 }
714 else
715 {
716 t1 = DotProduct (plane->normal, p1) - plane->dist;
717 t2 = DotProduct (plane->normal, p2) - plane->dist;
718 }
719
720 // negative plane distances indicate children[1] (behind plane)
721 p1side = t1 < 0;
722 p2side = t2 < 0;
723
724 // if the line starts and ends on the same side of the plane, recurse
725 // into that child instantly
726 if (p1side == p2side)
727 {
728#if COLLISIONPARANOID >= 3
729 if (p1side)
730 Con_Print("<");
731 else
732 Con_Print(">");
733#endif
734 // loop back and process the start child
735 num = node->children[p1side];
736 }
737 else
738 {
739 // find the midpoint where the line crosses the plane, use the
740 // original line for best accuracy
741#if COLLISIONPARANOID >= 3
742 Con_Print("M");
743#endif
744 if (plane->type < 3)
745 {
746 t1 = t->start[plane->type] - plane->dist;
747 t2 = t->end[plane->type] - plane->dist;
748 }
749 else
750 {
751 t1 = DotProduct (plane->normal, t->start) - plane->dist;
752 t2 = DotProduct (plane->normal, t->end) - plane->dist;
753 }
754 midf = t1 / (t1 - t2);
755 midf = bound(p1f, midf, p2f);
756 VectorMA(t->start, midf, t->dist, mid);
757
758 // we now have a mid point, essentially splitting the line into
759 // the segments in the near child and the far child, we can now
760 // recurse those in order and get their results
761
762 // recurse both sides, front side first
763 ret = Mod_Q1BSP_RecursiveHullCheck(t, node->children[p1side], p1f, midf, p1, mid);
764 // if this side is not empty, return what it is (solid or done)
766 return ret;
767
768 ret = Mod_Q1BSP_RecursiveHullCheck(t, node->children[p2side], midf, p2f, mid, p2);
769 // if other side is not solid, return what it is (empty or done)
771 return ret;
772
773 // front is air and back is solid, this is the impact point...
774
775 // copy the plane information, flipping it if needed
776 if (p1side)
777 {
778 t->trace->plane.dist = -plane->dist;
779 VectorNegate (plane->normal, t->trace->plane.normal);
780 }
781 else
782 {
783 t->trace->plane.dist = plane->dist;
784 VectorCopy (plane->normal, t->trace->plane.normal);
785 }
786
787 // calculate the return fraction which is nudged off the surface a bit
788 t1 = DotProduct(t->trace->plane.normal, t->start) - t->trace->plane.dist;
789 t2 = DotProduct(t->trace->plane.normal, t->end) - t->trace->plane.dist;
790 midf = (t1 - collision_impactnudge.value) / (t1 - t2);
791 t->trace->fraction = bound(0, midf, 1);
792
793#if COLLISIONPARANOID >= 3
794 Con_Print("D");
795#endif
796 return HULLCHECKSTATE_DONE;
797 }
798 }
799
800 // we reached a leaf contents
801
802 // check for empty
804 if (!t->trace->startfound)
805 {
806 t->trace->startfound = true;
807 t->trace->startsupercontents |= num;
808 }
810 t->trace->inwater = true;
811 if (num == 0)
812 t->trace->inopen = true;
813 if (num & SUPERCONTENTS_SOLID)
815 else if (num & SUPERCONTENTS_SKY)
817 else if (num & SUPERCONTENTS_LAVA)
819 else if (num & SUPERCONTENTS_SLIME)
821 else
823 t->trace->hitq3surfaceflags = t->trace->hittexture->surfaceflags;
824 t->trace->hitsupercontents = num;
825 if (num & t->trace->hitsupercontentsmask)
826 {
827 // if the first leaf is solid, set startsolid
828 if (t->trace->allsolid)
829 t->trace->startsolid = true;
830#if COLLISIONPARANOID >= 3
831 Con_Print("S");
832#endif
834 }
835 else
836 {
837 t->trace->allsolid = false;
838#if COLLISIONPARANOID >= 3
839 Con_Print("E");
840#endif
842 }
843}
#define SUPERCONTENTS_LIQUIDSMASK
Definition bspfile.h:218
cvar_t collision_impactnudge
Definition collision.c:13
#define HULLCHECKSTATE_SOLID
#define HULLCHECKSTATE_EMPTY
#define HULLCHECKSTATE_DONE
return ret
const struct texture_s * hittexture
Definition collision.h:62
int hitq3surfaceflags
Definition collision.h:60
qbool inopen
Definition collision.h:33
plane_t plane
Definition collision.h:44
qbool inwater
Definition collision.h:36
qbool startfound
Definition collision.h:65
vec_t dist
Definition collision.h:14
vec3_t normal
Definition collision.h:13

References trace_t::allsolid, bound, mclipnode_t::children, hull_t::clipnodes, collision_impactnudge, Con_Print(), mplane_t::dist, plane_t::dist, RecursiveHullCheckTraceInfo_t::dist, DotProduct, RecursiveHullCheckTraceInfo_t::end, trace_t::fraction, trace_t::hitq3surfaceflags, trace_t::hitsupercontents, trace_t::hitsupercontentsmask, trace_t::hittexture, RecursiveHullCheckTraceInfo_t::hull, HULLCHECKSTATE_DONE, HULLCHECKSTATE_EMPTY, HULLCHECKSTATE_SOLID, trace_t::inopen, cvar_t::integer, trace_t::inwater, Mod_Q1BSP_RecursiveHullCheck(), Mod_Q1BSP_SuperContentsFromNativeContents(), mod_q1bsp_texture_lava, mod_q1bsp_texture_sky, mod_q1bsp_texture_slime, mod_q1bsp_texture_solid, mod_q1bsp_texture_water, mod_q1bsp_traceoutofsolid, mplane_t::normal, plane_t::normal, trace_t::plane, mclipnode_t::planenum, hull_t::planes, ret, RecursiveHullCheckTraceInfo_t::start, trace_t::startfound, trace_t::startsolid, trace_t::startsupercontents, SUPERCONTENTS_LAVA, SUPERCONTENTS_LIQUIDSMASK, SUPERCONTENTS_SKY, SUPERCONTENTS_SLIME, SUPERCONTENTS_SOLID, RecursiveHullCheckTraceInfo_t::trace, mplane_t::type, cvar_t::value, VectorCopy, VectorMA, and VectorNegate.

Referenced by Collision_ClipTrace_Box(), Mod_Q1BSP_RecursiveHullCheck(), Mod_Q1BSP_TraceBox(), and Mod_Q1BSP_TraceLine().

◆ Mod_Q1BSP_RecursiveHullCheckPoint()

static int Mod_Q1BSP_RecursiveHullCheckPoint ( RecursiveHullCheckTraceInfo_t * t,
int num )
static

Definition at line 846 of file model_brush.c.

847{
848 mplane_t *plane;
849 mclipnode_t *nodes = t->hull->clipnodes;
850 mplane_t *planes = t->hull->planes;
851 vec3_t point;
852 VectorCopy(t->start, point);
853 while (num >= 0)
854 {
855 plane = planes + nodes[num].planenum;
856 num = nodes[num].children[(plane->type < 3 ? point[plane->type] : DotProduct(plane->normal, point)) < plane->dist];
857 }
859 t->trace->startsupercontents |= num;
861 t->trace->inwater = true;
862 if (num == 0)
863 t->trace->inopen = true;
864 if (num & t->trace->hitsupercontentsmask)
865 {
866 t->trace->allsolid = t->trace->startsolid = true;
868 }
869 else
870 {
871 t->trace->allsolid = t->trace->startsolid = false;
873 }
874}

References trace_t::allsolid, mclipnode_t::children, hull_t::clipnodes, mplane_t::dist, DotProduct, trace_t::hitsupercontentsmask, RecursiveHullCheckTraceInfo_t::hull, HULLCHECKSTATE_EMPTY, HULLCHECKSTATE_SOLID, trace_t::inopen, trace_t::inwater, Mod_Q1BSP_SuperContentsFromNativeContents(), mplane_t::normal, mclipnode_t::planenum, hull_t::planes, RecursiveHullCheckTraceInfo_t::start, trace_t::startsolid, trace_t::startsupercontents, SUPERCONTENTS_LIQUIDSMASK, RecursiveHullCheckTraceInfo_t::trace, mplane_t::type, and VectorCopy.

Referenced by Mod_Q1BSP_TraceBox(), Mod_Q1BSP_TraceLine(), and Mod_Q1BSP_TracePoint().

◆ Mod_Q1BSP_RoundUpToHullSize()

static void Mod_Q1BSP_RoundUpToHullSize ( model_t * cmodel,
const vec3_t inmins,
const vec3_t inmaxs,
vec3_t outmins,
vec3_t outmaxs )
static

Definition at line 3848 of file model_brush.c.

3849{
3850 vec3_t size;
3851 const hull_t *hull;
3852
3853 VectorSubtract(inmaxs, inmins, size);
3855 hull = &cmodel->brushq1.hulls[0]; // 0x0x0
3856 else if (cmodel->brush.ishlbsp)
3857 {
3858 if (size[0] <= 32)
3859 {
3860 if (size[2] < 54) // pick the nearest of 36 or 72
3861 hull = &cmodel->brushq1.hulls[3]; // 32x32x36
3862 else
3863 hull = &cmodel->brushq1.hulls[1]; // 32x32x72
3864 }
3865 else
3866 hull = &cmodel->brushq1.hulls[2]; // 64x64x64
3867 }
3868 else
3869 {
3870 if (size[0] <= 32)
3871 hull = &cmodel->brushq1.hulls[1]; // 32x32x56
3872 else
3873 hull = &cmodel->brushq1.hulls[2]; // 64x64x88
3874 }
3875 VectorCopy(inmins, outmins);
3876 VectorAdd(inmins, hull->clip_size, outmaxs);
3877}

References model_t::brush, model_t::brushq1, hull_t::clip_size, model_brushq1_t::hulls, model_brush_t::ishlbsp, mod_q1bsp_zero_hullsize_cutoff, size, cvar_t::value, VectorAdd, VectorCopy, and VectorSubtract.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_SuperContentsFromNativeContents()

int Mod_Q1BSP_SuperContentsFromNativeContents ( int nativecontents)

◆ Mod_Q1BSP_TraceBox()

static void Mod_Q1BSP_TraceBox ( struct model_s * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
const vec3_t start,
const vec3_t boxmins,
const vec3_t boxmaxs,
const vec3_t end,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )
static

Definition at line 955 of file model_brush.c.

956{
957 // this function currently only supports same size start and end
958 double boxsize[3];
960
961 if (VectorCompare(boxmins, boxmaxs))
962 {
963 if (VectorCompare(start, end))
964 Mod_Q1BSP_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
965 else
966 Mod_Q1BSP_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
967 return;
968 }
969
970 memset(&rhc, 0, sizeof(rhc));
971 memset(trace, 0, sizeof(trace_t));
972 rhc.trace = trace;
973 rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
974 rhc.trace->skipsupercontentsmask = skipsupercontentsmask;
975 rhc.trace->skipmaterialflagsmask = skipmaterialflagsmask;
976 rhc.trace->fraction = 1;
977 rhc.trace->allsolid = true;
978 VectorSubtract(boxmaxs, boxmins, boxsize);
979 if (boxsize[0] < mod_q1bsp_zero_hullsize_cutoff.value)
980 rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
981 else if (model->brush.ishlbsp)
982 {
983 // LadyHavoc: this has to have a minor tolerance (the .1) because of
984 // minor float precision errors from the box being transformed around
985 if (boxsize[0] < 32.1)
986 {
987 if (boxsize[2] < 54) // pick the nearest of 36 or 72
988 rhc.hull = &model->brushq1.hulls[3]; // 32x32x36
989 else
990 rhc.hull = &model->brushq1.hulls[1]; // 32x32x72
991 }
992 else
993 rhc.hull = &model->brushq1.hulls[2]; // 64x64x64
994 }
995 else
996 {
997 // LadyHavoc: this has to have a minor tolerance (the .1) because of
998 // minor float precision errors from the box being transformed around
999 if (boxsize[0] < 32.1)
1000 rhc.hull = &model->brushq1.hulls[1]; // 32x32x56
1001 else
1002 rhc.hull = &model->brushq1.hulls[2]; // 64x64x88
1003 }
1004 VectorMAMAM(1, start, 1, boxmins, -1, rhc.hull->clip_mins, rhc.start);
1005 VectorMAMAM(1, end, 1, boxmins, -1, rhc.hull->clip_mins, rhc.end);
1006 VectorSubtract(rhc.end, rhc.start, rhc.dist);
1007#if COLLISIONPARANOID >= 2
1008 Con_Printf("t(%f %f %f,%f %f %f,%li %f %f %f)", rhc.start[0], rhc.start[1], rhc.start[2], rhc.end[0], rhc.end[1], rhc.end[2], rhc.hull - model->brushq1.hulls, rhc.hull->clip_mins[0], rhc.hull->clip_mins[1], rhc.hull->clip_mins[2]);
1009 Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
1010 {
1011
1012 double test[3];
1013 trace_t testtrace;
1014 VectorLerp(rhc.start, rhc.trace->fraction, rhc.end, test);
1015 memset(&testtrace, 0, sizeof(trace_t));
1016 rhc.trace = &testtrace;
1017 rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
1018 rhc.trace->skipsupercontentsmask = skipsupercontentsmask;
1019 rhc.trace->skipmaterialflagsmask = skipmaterialflagsmask;
1020 rhc.trace->fraction = 1;
1021 rhc.trace->allsolid = true;
1022 VectorCopy(test, rhc.start);
1023 VectorCopy(test, rhc.end);
1024 VectorClear(rhc.dist);
1026 //Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, test, test);
1027 if (!trace->startsolid && testtrace.startsolid)
1028 Con_Printf(" - ended in solid!\n");
1029 }
1030 Con_Print("\n");
1031#else
1032 if (VectorLength2(rhc.dist))
1033 Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
1034 else
1036#endif
1037}
static int Mod_Q1BSP_RecursiveHullCheckPoint(RecursiveHullCheckTraceInfo_t *t, int num)

References trace_t::allsolid, hull_t::clip_mins, Con_Print(), Con_Printf(), RecursiveHullCheckTraceInfo_t::dist, RecursiveHullCheckTraceInfo_t::end, hull_t::firstclipnode, trace_t::fraction, trace_t::hitsupercontentsmask, RecursiveHullCheckTraceInfo_t::hull, Mod_Q1BSP_RecursiveHullCheck(), Mod_Q1BSP_RecursiveHullCheckPoint(), Mod_Q1BSP_TraceLine(), Mod_Q1BSP_TracePoint(), mod_q1bsp_zero_hullsize_cutoff, model, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, RecursiveHullCheckTraceInfo_t::start, trace_t::startsolid, RecursiveHullCheckTraceInfo_t::trace, cvar_t::value, VectorClear, VectorCompare, VectorCopy, VectorLength2, VectorLerp, VectorMAMAM, and VectorSubtract.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_TraceLine()

static void Mod_Q1BSP_TraceLine ( struct model_s * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
const vec3_t start,
const vec3_t end,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )
static

Definition at line 894 of file model_brush.c.

895{
897
898 if (VectorCompare(start, end))
899 {
900 Mod_Q1BSP_TracePoint(model, frameblend, skeleton, trace, start, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
901 return;
902 }
903
904 // sometimes we want to traceline against polygons so we can report the texture that was hit rather than merely a contents, but using this method breaks one of negke's maps so it must be a cvar check...
906 {
907 Mod_Q1BSP_TraceLineAgainstSurfaces(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
908 return;
909 }
910
911 memset(&rhc, 0, sizeof(rhc));
912 memset(trace, 0, sizeof(trace_t));
913 rhc.trace = trace;
914 rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
915 rhc.trace->skipsupercontentsmask = skipsupercontentsmask;
916 rhc.trace->skipmaterialflagsmask = skipmaterialflagsmask;
917 rhc.trace->fraction = 1;
918 rhc.trace->allsolid = true;
919 rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
920 VectorCopy(start, rhc.start);
921 VectorCopy(end, rhc.end);
922 VectorSubtract(rhc.end, rhc.start, rhc.dist);
923#if COLLISIONPARANOID >= 2
924 Con_Printf("t(%f %f %f,%f %f %f)", rhc.start[0], rhc.start[1], rhc.start[2], rhc.end[0], rhc.end[1], rhc.end[2]);
925 Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
926 {
927
928 double test[3];
929 trace_t testtrace;
930 VectorLerp(rhc.start, rhc.trace->fraction, rhc.end, test);
931 memset(&testtrace, 0, sizeof(trace_t));
932 rhc.trace = &testtrace;
933 rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
934 rhc.trace->skipsupercontentsmask = skipsupercontentsmask;
935 rhc.trace->skipmaterialflagsmask = skipmaterialflagsmask;
936 rhc.trace->fraction = 1;
937 rhc.trace->allsolid = true;
938 VectorCopy(test, rhc.start);
939 VectorCopy(test, rhc.end);
940 VectorClear(rhc.dist);
942 //Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, test, test);
943 if (!trace->startsolid && testtrace.startsolid)
944 Con_Printf(" - ended in solid!\n");
945 }
946 Con_Print("\n");
947#else
948 if (VectorLength2(rhc.dist))
949 Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
950 else
952#endif
953}
cvar_t sv_gameplayfix_q1bsptracelinereportstexture
Definition sv_main.c:129

References trace_t::allsolid, Con_Print(), Con_Printf(), RecursiveHullCheckTraceInfo_t::dist, RecursiveHullCheckTraceInfo_t::end, hull_t::firstclipnode, trace_t::fraction, trace_t::hitsupercontentsmask, RecursiveHullCheckTraceInfo_t::hull, cvar_t::integer, Mod_Q1BSP_RecursiveHullCheck(), Mod_Q1BSP_RecursiveHullCheckPoint(), Mod_Q1BSP_TraceLineAgainstSurfaces(), Mod_Q1BSP_TracePoint(), model, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, RecursiveHullCheckTraceInfo_t::start, trace_t::startsolid, sv_gameplayfix_q1bsptracelinereportstexture, RecursiveHullCheckTraceInfo_t::trace, VectorClear, VectorCompare, VectorCopy, VectorLength2, VectorLerp, and VectorSubtract.

Referenced by Mod_Q1BSP_Load(), Mod_Q1BSP_TraceBox(), and Mod_Q1BSP_TraceLineOfSight().

◆ Mod_Q1BSP_TraceLineAgainstSurfaces()

static void Mod_Q1BSP_TraceLineAgainstSurfaces ( struct model_s * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
const vec3_t start,
const vec3_t end,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )
static

Definition at line 1509 of file model_brush.c.

1510{
1512
1513 memset(&rhc, 0, sizeof(rhc));
1514 memset(trace, 0, sizeof(trace_t));
1515 rhc.trace = trace;
1516 rhc.trace->hitsupercontentsmask = hitsupercontentsmask;
1517 rhc.trace->skipsupercontentsmask = skipsupercontentsmask;
1518 rhc.trace->skipmaterialflagsmask = skipmaterialflagsmask;
1519 rhc.trace->fraction = 1;
1520 rhc.trace->allsolid = true;
1521 rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
1522 VectorCopy(start, rhc.start);
1523 VectorCopy(end, rhc.end);
1524 VectorSubtract(rhc.end, rhc.start, rhc.dist);
1526 VectorMA(rhc.start, rhc.trace->fraction, rhc.dist, rhc.trace->endpos);
1527}
static int Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode(RecursiveHullCheckTraceInfo_t *t, const model_t *model, const mnode_t *node, const double p1[3], const double p2[3])

References trace_t::allsolid, RecursiveHullCheckTraceInfo_t::dist, RecursiveHullCheckTraceInfo_t::end, trace_t::endpos, hull_t::firstclipnode, trace_t::fraction, trace_t::hitsupercontentsmask, RecursiveHullCheckTraceInfo_t::hull, Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode(), model, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, RecursiveHullCheckTraceInfo_t::start, RecursiveHullCheckTraceInfo_t::trace, VectorCopy, VectorMA, and VectorSubtract.

Referenced by Mod_Q1BSP_Load(), and Mod_Q1BSP_TraceLine().

◆ Mod_Q1BSP_TraceLineAgainstSurfacesFindTextureOnNode()

static const texture_t * Mod_Q1BSP_TraceLineAgainstSurfacesFindTextureOnNode ( RecursiveHullCheckTraceInfo_t * t,
const model_t * model,
const mnode_t * node,
double mid[3] )
static

Definition at line 1345 of file model_brush.c.

1346{
1347 unsigned int i;
1348 int j;
1349 int k;
1350 const msurface_t *surface;
1351 float normal[3];
1352 float v0[3];
1353 float v1[3];
1354 float edgedir[3];
1355 float edgenormal[3];
1356 float p[4];
1357 float midf;
1358 float t1;
1359 float t2;
1360 VectorCopy(mid, p);
1361 p[3] = 1;
1362 surface = model->data_surfaces + node->firstsurface;
1363 for (i = 0;i < node->numsurfaces;i++, surface++)
1364 {
1365 if(!surface->texture)
1366 continue;
1367 // skip surfaces whose bounding box does not include the point
1368// if (!BoxesOverlap(mid, mid, surface->mins, surface->maxs))
1369// continue;
1370 // skip faces with contents we don't care about
1371 if (!(t->trace->hitsupercontentsmask & surface->texture->supercontents))
1372 continue;
1373 // ignore surfaces matching the skipsupercontentsmask (this is rare)
1375 continue;
1376 // skip surfaces matching the skipmaterialflagsmask (e.g. MATERIALFLAG_NOSHADOW)
1378 continue;
1379 // get the surface normal - since it is flat we know any vertex normal will suffice
1380 VectorCopy(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex, normal);
1381 // skip backfaces
1382 if (DotProduct(t->dist, normal) > 0)
1383 continue;
1384 // iterate edges and see if the point is outside one of them
1385 for (j = 0, k = surface->num_vertices - 1;j < surface->num_vertices;k = j, j++)
1386 {
1387 VectorCopy(model->surfmesh.data_vertex3f + 3 * (surface->num_firstvertex + k), v0);
1388 VectorCopy(model->surfmesh.data_vertex3f + 3 * (surface->num_firstvertex + j), v1);
1389 VectorSubtract(v0, v1, edgedir);
1390 CrossProduct(edgedir, normal, edgenormal);
1391 if (DotProduct(edgenormal, p) > DotProduct(edgenormal, v0))
1392 break;
1393 }
1394 // if the point is outside one of the edges, it is not within the surface
1395 if (j < surface->num_vertices)
1396 continue;
1397
1398 // we hit a surface, this is the impact point...
1400 t->trace->plane.dist = DotProduct(normal, p);
1401
1402 // calculate the return fraction which is nudged off the surface a bit
1403 t1 = DotProduct(t->start, t->trace->plane.normal) - t->trace->plane.dist;
1404 t2 = DotProduct(t->end, t->trace->plane.normal) - t->trace->plane.dist;
1405 midf = (t1 - collision_impactnudge.value) / (t1 - t2);
1406 t->trace->fraction = bound(0, midf, 1);
1407
1408 t->trace->hittexture = surface->texture->currentframe;
1409 t->trace->hitq3surfaceflags = t->trace->hittexture->surfaceflags;
1410 t->trace->hitsupercontents = t->trace->hittexture->supercontents;
1411 return surface->texture->currentframe;
1412 }
1413 return NULL;
1414}
GLfloat v0
Definition glquake.h:739
GLfloat GLfloat v1
Definition glquake.h:743
vec3 normal

References bound, collision_impactnudge, CrossProduct, texture_t::currentframe, texture_t::currentmaterialflags, plane_t::dist, RecursiveHullCheckTraceInfo_t::dist, DotProduct, RecursiveHullCheckTraceInfo_t::end, mnode_t::firstsurface, trace_t::fraction, trace_t::hitq3surfaceflags, trace_t::hitsupercontents, trace_t::hitsupercontentsmask, trace_t::hittexture, i, model, normal, plane_t::normal, NULL, msurface_t::num_firstvertex, msurface_t::num_vertices, mnode_t::numsurfaces, trace_t::plane, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, RecursiveHullCheckTraceInfo_t::start, texture_t::supercontents, msurface_t::texture, RecursiveHullCheckTraceInfo_t::trace, v0, v1, cvar_t::value, VectorCopy, and VectorSubtract.

Referenced by Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode().

◆ Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode()

static int Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode ( RecursiveHullCheckTraceInfo_t * t,
const model_t * model,
const mnode_t * node,
const double p1[3],
const double p2[3] )
static

Definition at line 1416 of file model_brush.c.

1417{
1418 const mplane_t *plane;
1419 double t1, t2;
1420 int side;
1421 double midf, mid[3];
1422 const mleaf_t *leaf;
1423
1424 while (node->plane)
1425 {
1426 plane = node->plane;
1427 if (plane->type < 3)
1428 {
1429 t1 = p1[plane->type] - plane->dist;
1430 t2 = p2[plane->type] - plane->dist;
1431 }
1432 else
1433 {
1434 t1 = DotProduct (plane->normal, p1) - plane->dist;
1435 t2 = DotProduct (plane->normal, p2) - plane->dist;
1436 }
1437 if (t1 < 0)
1438 {
1439 if (t2 < 0)
1440 {
1441 node = node->children[1];
1442 continue;
1443 }
1444 side = 1;
1445 }
1446 else
1447 {
1448 if (t2 >= 0)
1449 {
1450 node = node->children[0];
1451 continue;
1452 }
1453 side = 0;
1454 }
1455
1456 // the line intersects, find intersection point
1457 // LadyHavoc: this uses the original trace for maximum accuracy
1458 if (plane->type < 3)
1459 {
1460 t1 = t->start[plane->type] - plane->dist;
1461 t2 = t->end[plane->type] - plane->dist;
1462 }
1463 else
1464 {
1465 t1 = DotProduct (plane->normal, t->start) - plane->dist;
1466 t2 = DotProduct (plane->normal, t->end) - plane->dist;
1467 }
1468
1469 midf = t1 / (t1 - t2);
1470 VectorMA(t->start, midf, t->dist, mid);
1471
1472 // recurse both sides, front side first, return if we hit a surface
1474 return HULLCHECKSTATE_DONE;
1475
1476 // test each surface on the node
1478 if (t->trace->hittexture)
1479 return HULLCHECKSTATE_DONE;
1480
1481 // recurse back side
1482 return Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode(t, model, node->children[side ^ 1], mid, p2);
1483 }
1484 leaf = (const mleaf_t *)node;
1486 if (!t->trace->startfound)
1487 {
1488 t->trace->startfound = true;
1489 t->trace->startsupercontents |= side;
1490 }
1491 if (side & SUPERCONTENTS_LIQUIDSMASK)
1492 t->trace->inwater = true;
1493 if (side == 0)
1494 t->trace->inopen = true;
1495 if (side & t->trace->hitsupercontentsmask)
1496 {
1497 // if the first leaf is solid, set startsolid
1498 if (t->trace->allsolid)
1499 t->trace->startsolid = true;
1500 return HULLCHECKSTATE_SOLID;
1501 }
1502 else
1503 {
1504 t->trace->allsolid = false;
1505 return HULLCHECKSTATE_EMPTY;
1506 }
1507}
static const texture_t * Mod_Q1BSP_TraceLineAgainstSurfacesFindTextureOnNode(RecursiveHullCheckTraceInfo_t *t, const model_t *model, const mnode_t *node, double mid[3])

References trace_t::allsolid, mnode_t::children, mleaf_t::contents, mplane_t::dist, RecursiveHullCheckTraceInfo_t::dist, DotProduct, RecursiveHullCheckTraceInfo_t::end, trace_t::hitsupercontentsmask, trace_t::hittexture, HULLCHECKSTATE_DONE, HULLCHECKSTATE_EMPTY, HULLCHECKSTATE_SOLID, trace_t::inopen, trace_t::inwater, Mod_Q1BSP_SuperContentsFromNativeContents(), Mod_Q1BSP_TraceLineAgainstSurfacesFindTextureOnNode(), Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode(), model, mplane_t::normal, mnode_t::plane, RecursiveHullCheckTraceInfo_t::start, trace_t::startfound, trace_t::startsolid, trace_t::startsupercontents, SUPERCONTENTS_LIQUIDSMASK, RecursiveHullCheckTraceInfo_t::trace, mplane_t::type, and VectorMA.

Referenced by Mod_Q1BSP_TraceLineAgainstSurfaces(), and Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode().

◆ Mod_Q1BSP_TraceLineOfSight()

static qbool Mod_Q1BSP_TraceLineOfSight ( struct model_s * model,
const vec3_t start,
const vec3_t end,
const vec3_t acceptmins,
const vec3_t acceptmaxs )
static

Definition at line 1179 of file model_brush.c.

1180{
1181 trace_t trace;
1183 return trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, acceptmins, acceptmaxs);
1184}

References BoxesOverlap, trace_t::endpos, trace_t::fraction, MATERIALFLAGMASK_TRANSLUCENT, Mod_Q1BSP_TraceLine(), model, NULL, and SUPERCONTENTS_VISBLOCKERMASK.

Referenced by Mod_Q1BSP_Load().

◆ Mod_Q1BSP_TracePoint()

static void Mod_Q1BSP_TracePoint ( struct model_s * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
const vec3_t start,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )
static

Definition at line 877 of file model_brush.c.

878{
880
881 memset(&rhc, 0, sizeof(rhc));
882 memset(trace, 0, sizeof(trace_t));
883 rhc.trace = trace;
884 rhc.trace->fraction = 1;
885 rhc.trace->allsolid = true;
886 rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
887 VectorCopy(start, rhc.start);
888 VectorCopy(start, rhc.end);
890}

References trace_t::allsolid, RecursiveHullCheckTraceInfo_t::end, hull_t::firstclipnode, trace_t::fraction, RecursiveHullCheckTraceInfo_t::hull, Mod_Q1BSP_RecursiveHullCheckPoint(), model, RecursiveHullCheckTraceInfo_t::start, RecursiveHullCheckTraceInfo_t::trace, and VectorCopy.

Referenced by Mod_Q1BSP_Load(), Mod_Q1BSP_TraceBox(), and Mod_Q1BSP_TraceLine().

◆ Mod_Q2BSP_FindSubmodelBrushRange_r()

static void Mod_Q2BSP_FindSubmodelBrushRange_r ( model_t * mod,
mnode_t * node,
int * first,
int * last )
static

Definition at line 4825 of file model_brush.c.

4826{
4827 int i;
4828 mleaf_t *leaf;
4829 while (node->plane)
4830 {
4832 node = node->children[1];
4833 }
4834 leaf = (mleaf_t*)node;
4835 for (i = 0;i < leaf->numleafbrushes;i++)
4836 {
4837 int brushnum = leaf->firstleafbrush[i];
4838 if (*first > brushnum)
4839 *first = brushnum;
4840 if (*last < brushnum)
4841 *last = brushnum;
4842 }
4843}
GLint first
Definition glquake.h:671
static void Mod_Q2BSP_FindSubmodelBrushRange_r(model_t *mod, mnode_t *node, int *first, int *last)

References mnode_t::children, first, mleaf_t::firstleafbrush, i, mod(), Mod_Q2BSP_FindSubmodelBrushRange_r(), mleaf_t::numleafbrushes, and mnode_t::plane.

Referenced by Mod_Q2BSP_FindSubmodelBrushRange_r(), and Mod_Q2BSP_Load().

◆ Mod_Q2BSP_Load()

static void Mod_Q2BSP_Load ( model_t * mod,
void * buffer,
void * bufferend )
static

Definition at line 4845 of file model_brush.c.

4846{
4847 int i, j, k;
4848 sizebuf_t lumpsb[Q2HEADER_LUMPS];
4849 mmodel_t *bm;
4850 float dist, modelyawradius, modelradius;
4851 msurface_t *surface;
4852 int totalstylesurfaces, totalstyles, stylecounts[256], remapstyles[256];
4853 model_brush_lightstyleinfo_t styleinfo[256];
4854 int *datapointer;
4855 model_brush_lightstyleinfo_t *lsidatapointer;
4856 sizebuf_t sb;
4857
4858 MSG_InitReadBuffer(&sb, (unsigned char *)buffer, (unsigned char *)bufferend - (unsigned char *)buffer);
4859
4860 mod->type = mod_brushq2;
4861
4862 mod->brush.ishlbsp = false;
4863 mod->brush.isbsp2rmqe = false;
4864 mod->brush.isbsp2 = false;
4865 mod->brush.isq2bsp = true; // q1bsp loaders mostly work but we need a few tweaks
4866 mod->brush.isq3bsp = false;
4867 mod->brush.skymasking = true;
4868 mod->modeldatatypestring = "Q2BSP";
4869
4870 i = MSG_ReadLittleLong(&sb);
4871 if (i != Q2BSPMAGIC)
4872 Host_Error("Mod_Q2BSP_Load: %s has wrong version number (%i, should be %i)", mod->name, i, Q2BSPVERSION);
4873
4874 i = MSG_ReadLittleLong(&sb);
4875 if (i != Q2BSPVERSION)
4876 Host_Error("Mod_Q2BSP_Load: %s has wrong version number (%i, should be %i)", mod->name, i, Q2BSPVERSION);
4877
4878// read lumps
4879 for (i = 0; i < Q2HEADER_LUMPS; i++)
4880 {
4881 int offset = MSG_ReadLittleLong(&sb);
4882 int size = MSG_ReadLittleLong(&sb);
4884 Host_Error("Mod_Q2BSP_Load: %s has invalid lump %i (offset %i, size %i, file size %i)\n", mod->name, i, offset, size, (int)sb.cursize);
4885 MSG_InitReadBuffer(&lumpsb[i], sb.data + offset, size);
4886 }
4887
4888 mod->soundfromcenter = true;
4889 mod->TracePoint = Mod_CollisionBIH_TracePoint;
4890 mod->TraceLine = Mod_CollisionBIH_TraceLine;
4891 mod->TraceBox = Mod_CollisionBIH_TraceBox;
4892 mod->TraceBrush = Mod_CollisionBIH_TraceBrush;
4893 mod->PointSuperContents = Mod_CollisionBIH_PointSuperContents;
4894 mod->TraceLineAgainstSurfaces = Mod_CollisionBIH_TraceLine;
4895 mod->brush.TraceLineOfSight = Mod_Q3BSP_TraceLineOfSight;
4896 mod->brush.SuperContentsFromNativeContents = Mod_Q2BSP_SuperContentsFromNativeContents;
4897 mod->brush.NativeContentsFromSuperContents = Mod_Q2BSP_NativeContentsFromSuperContents;
4898 mod->brush.GetPVS = Mod_BSP_GetPVS;
4899 mod->brush.FatPVS = Mod_BSP_FatPVS;
4900 mod->brush.BoxTouchingPVS = Mod_BSP_BoxTouchingPVS;
4901 mod->brush.BoxTouchingLeafPVS = Mod_BSP_BoxTouchingLeafPVS;
4902 mod->brush.BoxTouchingVisibleLeafs = Mod_BSP_BoxTouchingVisibleLeafs;
4903 mod->brush.FindBoxClusters = Mod_BSP_FindBoxClusters;
4904 mod->brush.LightPoint = Mod_BSP_LightPoint;
4905 mod->brush.FindNonSolidLocation = Mod_BSP_FindNonSolidLocation;
4906 mod->brush.AmbientSoundLevelsForPoint = NULL;
4907 mod->brush.RoundUpToHullSize = NULL;
4908 mod->brush.PointInLeaf = Mod_BSP_PointInLeaf;
4909 mod->Draw = R_Mod_Draw;
4910 mod->DrawDepth = R_Mod_DrawDepth;
4911 mod->DrawDebug = R_Mod_DrawDebug;
4912 mod->DrawPrepass = R_Mod_DrawPrepass;
4913 mod->GetLightInfo = R_Mod_GetLightInfo;
4914 mod->CompileShadowMap = R_Mod_CompileShadowMap;
4915 mod->DrawShadowMap = R_Mod_DrawShadowMap;
4916 mod->DrawLight = R_Mod_DrawLight;
4917
4918// load into heap
4919
4920 mod->brush.qw_md4sum = 0;
4921 mod->brush.qw_md4sum2 = 0;
4922 for (i = 0;i < Q2HEADER_LUMPS;i++)
4923 {
4924 int temp;
4925 if (i == Q2LUMP_ENTITIES)
4926 continue;
4927 temp = Com_BlockChecksum(lumpsb[i].data, lumpsb[i].cursize);
4928 mod->brush.qw_md4sum ^= LittleLong(temp);
4929 if (i == Q2LUMP_VISIBILITY || i == Q2LUMP_LEAFS || i == Q2LUMP_NODES)
4930 continue;
4931 mod->brush.qw_md4sum2 ^= LittleLong(temp);
4932 }
4933
4934 // many of these functions are identical to Q1 loaders, so we use those where possible
4948 Mod_Q2BSP_LoadPOP(&lumpsb[Q2LUMP_POP]);
4954
4955 for (i = 0; i < Q2HEADER_LUMPS; i++)
4956 if (lumpsb[i].readcount != lumpsb[i].cursize)
4957 Host_Error("Lump %i incorrectly loaded (readcount %i, size %i)\n", i, lumpsb[i].readcount, lumpsb[i].cursize);
4958
4959 // we don't actually set MATERIALFLAG_WATERALPHA on anything, so this
4960 // doesn't enable the cvar, just indicates that transparent water is OK
4962
4963 // we don't need the compressed pvs data anymore
4964 if (mod->brushq1.data_compressedpvs)
4965 Mem_Free(mod->brushq1.data_compressedpvs);
4966 mod->brushq1.data_compressedpvs = NULL;
4967 mod->brushq1.num_compressedpvs = 0;
4968
4969 // the MakePortals code works fine on the q2bsp data as well
4972
4973 mod->numframes = 0; // q2bsp animations are kind of special, frame is unbounded...
4974 mod->numskins = 1;
4975
4978
4979 totalstylesurfaces = 0;
4980 totalstyles = 0;
4981 for (i = 0;i < mod->brush.numsubmodels;i++)
4982 {
4983 memset(stylecounts, 0, sizeof(stylecounts));
4984 for (k = 0;k < mod->brushq1.submodels[i].numfaces;k++)
4985 {
4986 surface = mod->data_surfaces + mod->brushq1.submodels[i].firstface + k;
4987 for (j = 0;j < MAXLIGHTMAPS;j++)
4988 stylecounts[surface->lightmapinfo->styles[j]]++;
4989 }
4990 for (k = 0;k < 255;k++)
4991 {
4992 totalstyles++;
4993 if (stylecounts[k])
4994 totalstylesurfaces += stylecounts[k];
4995 }
4996 }
4997 // bones_was_here: using a separate allocation for model_brush_lightstyleinfo_t
4998 // because on a 64-bit machine it no longer has the same alignment requirement as int.
4999 lsidatapointer = Mem_AllocType(mod->mempool, model_brush_lightstyleinfo_t, totalstyles * sizeof(model_brush_lightstyleinfo_t));
5000 datapointer = Mem_AllocType(mod->mempool, int, mod->num_surfaces * sizeof(int) + totalstylesurfaces * sizeof(int));
5001 mod->modelsurfaces_sorted = datapointer; datapointer += mod->num_surfaces;
5002 // set up the world model, then on each submodel copy from the world model
5003 // and set up the submodel with the respective model info.
5004 mod = loadmodel;
5005 for (i = 0;i < loadmodel->brush.numsubmodels;i++)
5006 {
5007 mnode_t *rootnode = NULL;
5008 int firstbrush = loadmodel->brush.num_brushes, lastbrush = 0;
5009 if (i > 0)
5010 {
5011 char name[10];
5012 // duplicate the basic information
5013 dpsnprintf(name, sizeof(name), "*%i", i);
5015 // copy the base model to this one
5016 *mod = *loadmodel;
5017 // rename the clone back to its proper name
5018 dp_strlcpy(mod->name, name, sizeof(mod->name));
5019 mod->brush.parentmodel = loadmodel;
5020 // textures and memory belong to the main model
5021 mod->texturepool = NULL;
5022 mod->mempool = NULL;
5023 mod->brush.GetPVS = NULL;
5024 mod->brush.FatPVS = NULL;
5025 mod->brush.BoxTouchingPVS = NULL;
5026 mod->brush.BoxTouchingLeafPVS = NULL;
5027 mod->brush.BoxTouchingVisibleLeafs = NULL;
5028 mod->brush.FindBoxClusters = NULL;
5029 mod->brush.LightPoint = NULL;
5030 mod->brush.AmbientSoundLevelsForPoint = NULL;
5031 }
5032 mod->brush.submodel = i;
5035
5036 bm = &mod->brushq1.submodels[i];
5037
5038 // we store the headnode (there's only one in Q2BSP) as if it were the first hull
5039 mod->brushq1.hulls[0].firstclipnode = bm->headnode[0];
5040
5041 mod->submodelsurfaces_start = bm->firstface;
5042 mod->submodelsurfaces_end = bm->firstface + bm->numfaces;
5043
5044 // set node/leaf parents for this submodel
5045 // note: if the root of this submodel is a leaf (headnode[0] < 0) then there is nothing to do...
5046 // (this happens in base3.bsp)
5047 if (bm->headnode[0] >= 0)
5048 rootnode = mod->brush.data_nodes + bm->headnode[0];
5049 else
5050 rootnode = (mnode_t*)(mod->brush.data_leafs + -1 - bm->headnode[0]);
5052
5053 // make the model surface list (used by shadowing/lighting)
5054 Mod_Q2BSP_FindSubmodelBrushRange_r(mod, rootnode, &firstbrush, &lastbrush);
5055 if (firstbrush <= lastbrush)
5056 {
5057 mod->firstmodelbrush = firstbrush;
5058 mod->nummodelbrushes = lastbrush + 1 - firstbrush;
5059 }
5060 else
5061 {
5062 mod->firstmodelbrush = 0;
5063 mod->nummodelbrushes = 0;
5064 }
5065
5066 VectorCopy(bm->mins, mod->normalmins);
5067 VectorCopy(bm->maxs, mod->normalmaxs);
5068 dist = max(fabs(mod->normalmins[0]), fabs(mod->normalmaxs[0]));
5069 modelyawradius = max(fabs(mod->normalmins[1]), fabs(mod->normalmaxs[1]));
5070 modelyawradius = dist*dist+modelyawradius*modelyawradius;
5071 modelradius = max(fabs(mod->normalmins[2]), fabs(mod->normalmaxs[2]));
5072 modelradius = modelyawradius + modelradius * modelradius;
5073 modelyawradius = sqrt(modelyawradius);
5074 modelradius = sqrt(modelradius);
5075 mod->yawmins[0] = mod->yawmins[1] = -modelyawradius;
5076 mod->yawmins[2] = mod->normalmins[2];
5077 mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius;
5078 mod->yawmaxs[2] = mod->normalmaxs[2];
5079 mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius;
5080 mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
5081 mod->radius = modelradius;
5082 mod->radius2 = modelradius * modelradius;
5083
5085
5086 // build lightstyle lists for quick marking of dirty lightmaps when lightstyles flicker
5087 if (mod->submodelsurfaces_start < mod->submodelsurfaces_end)
5088 {
5089 // build lightstyle update chains
5090 // (used to rapidly mark lightmapupdateflags on many surfaces
5091 // when d_lightstylevalue changes)
5092 memset(stylecounts, 0, sizeof(stylecounts));
5093 for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
5094 for (j = 0;j < MAXLIGHTMAPS;j++)
5095 stylecounts[mod->data_surfaces[k].lightmapinfo->styles[j]]++;
5096 mod->brushq1.num_lightstyles = 0;
5097 for (k = 0;k < 255;k++)
5098 {
5099 if (stylecounts[k])
5100 {
5101 styleinfo[mod->brushq1.num_lightstyles].style = k;
5102 styleinfo[mod->brushq1.num_lightstyles].value = 0;
5103 styleinfo[mod->brushq1.num_lightstyles].numsurfaces = 0;
5104 styleinfo[mod->brushq1.num_lightstyles].surfacelist = datapointer;datapointer += stylecounts[k];
5105 remapstyles[k] = mod->brushq1.num_lightstyles;
5106 mod->brushq1.num_lightstyles++;
5107 }
5108 }
5109 for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
5110 {
5111 surface = mod->data_surfaces + k;
5112 for (j = 0;j < MAXLIGHTMAPS;j++)
5113 {
5114 if (surface->lightmapinfo->styles[j] != 255)
5115 {
5116 int r = remapstyles[surface->lightmapinfo->styles[j]];
5117 styleinfo[r].surfacelist[styleinfo[r].numsurfaces++] = k;
5118 }
5119 }
5120 }
5121 mod->brushq1.data_lightstyleinfo = lsidatapointer;lsidatapointer += mod->brushq1.num_lightstyles;
5122 memcpy(mod->brushq1.data_lightstyleinfo, styleinfo, mod->brushq1.num_lightstyles * sizeof(model_brush_lightstyleinfo_t));
5123 }
5124 else
5125 {
5126 Con_Printf(CON_WARN "warning: empty submodel *%i in %s\n", i+1, loadmodel->name);
5127 }
5128 //mod->brushq1.num_visleafs = bm->visleafs;
5129
5130 // build a Bounding Interval Hierarchy for culling triangles in light rendering
5131 Mod_MakeCollisionBIH(mod, false, &mod->collision_bih);
5132
5133 // build a Bounding Interval Hierarchy for culling brushes in collision detection
5134 Mod_MakeCollisionBIH(mod, true, &mod->render_bih);
5135
5136 // generate VBOs and other shared data before cloning submodels
5137 if (i == 0)
5138 Mod_BuildVBOs();
5139 }
5140 mod = loadmodel;
5141
5142 // make the model surface list (used by shadowing/lighting)
5144
5145 Con_DPrintf("Stats for q2bsp model \"%s\": %i faces, %i nodes, %i leafs, %i clusters, %i clusterportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces);
5146}
static qbool Mod_Q3BSP_TraceLineOfSight(struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
static void Mod_Q2BSP_LoadTexinfo(sizebuf_t *sb)
static void Mod_Q2BSP_LoadAreas(sizebuf_t *sb)
static void Mod_Q2BSP_LoadLeafBrushes(sizebuf_t *sb)
static void Mod_Q2BSP_LoadLighting(sizebuf_t *sb)
static void Mod_Q2BSP_LoadLeafs(sizebuf_t *sb)
static void Mod_Q2BSP_LoadPOP(sizebuf_t *sb)
static void Mod_Q2BSP_LoadVisibility(sizebuf_t *sb)
int Mod_Q2BSP_SuperContentsFromNativeContents(int nativecontents)
static void Mod_Q2BSP_LoadBrushSides(sizebuf_t *sb)
static void Mod_Q2BSP_LoadNodes(sizebuf_t *sb)
int Mod_CollisionBIH_PointSuperContents(struct model_s *model, int frame, const vec3_t point)
int Mod_Q2BSP_NativeContentsFromSuperContents(int supercontents)
static void Mod_Q2BSP_LoadBrushes(sizebuf_t *sb)
static void Mod_Q2BSP_LoadAreaPortals(sizebuf_t *sb)
#define Q2LUMP_EDGES
Definition model_q2bsp.h:25
#define Q2LUMP_TEXINFO
Definition model_q2bsp.h:19
#define Q2LUMP_LEAFBRUSHES
Definition model_q2bsp.h:24
#define Q2LUMP_BRUSHSIDES
Definition model_q2bsp.h:29
#define Q2LUMP_MODELS
Definition model_q2bsp.h:27
#define Q2LUMP_PLANES
Definition model_q2bsp.h:15
#define Q2LUMP_LEAFS
Definition model_q2bsp.h:22
#define Q2LUMP_VERTEXES
Definition model_q2bsp.h:16
#define Q2LUMP_VISIBILITY
Definition model_q2bsp.h:17
#define Q2LUMP_FACES
Definition model_q2bsp.h:20
#define Q2LUMP_LEAFFACES
Definition model_q2bsp.h:23
#define Q2LUMP_BRUSHES
Definition model_q2bsp.h:28
#define Q2BSPMAGIC
Definition model_q2bsp.h:6
#define Q2LUMP_SURFEDGES
Definition model_q2bsp.h:26
#define Q2LUMP_AREAPORTALS
Definition model_q2bsp.h:32
#define Q2LUMP_LIGHTING
Definition model_q2bsp.h:21
#define Q2LUMP_ENTITIES
Definition model_q2bsp.h:14
#define Q2HEADER_LUMPS
Definition model_q2bsp.h:33
#define Q2LUMP_AREAS
Definition model_q2bsp.h:31
#define Q2LUMP_POP
Definition model_q2bsp.h:30
#define Q2LUMP_NODES
Definition model_q2bsp.h:18
@ mod_brushq2

References model_t::brush, buffer, ca_dedicated, cls, Com_BlockChecksum(), Con_DPrintf(), Con_Printf(), CON_WARN, sizebuf_t::cursize, data, sizebuf_t::data, dp_strlcpy, dpsnprintf(), fabs(), mmodel_t::firstface, mmodel_t::headnode, Host_Error(), i, cvar_t::integer, msurface_t::lightmapinfo, LittleLong, loadmodel, max, MAXLIGHTMAPS, mmodel_t::maxs, Mem_Alloc, Mem_AllocType, Mem_Free, model_t::mempool, mmodel_t::mins, mod(), mod_brushq2, Mod_BSP_BoxTouchingLeafPVS(), Mod_BSP_BoxTouchingPVS(), Mod_BSP_BoxTouchingVisibleLeafs(), Mod_BSP_FatPVS(), Mod_BSP_FindBoxClusters(), Mod_BSP_FindNonSolidLocation(), Mod_BSP_GetPVS(), Mod_BSP_LightPoint(), Mod_BSP_LoadNodes_RecursiveSetParent(), Mod_BSP_LoadSubmodels(), Mod_BSP_MakePortals(), Mod_BSP_PointInLeaf(), mod_bsp_portalize, Mod_BuildVBOs(), Mod_CollisionBIH_PointSuperContents(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint(), Mod_FindName(), Mod_MakeCollisionBIH(), Mod_MakeSortedSurfaces(), Mod_Q1BSP_LoadEdges(), Mod_Q1BSP_LoadEntities(), Mod_Q1BSP_LoadFaces(), Mod_Q1BSP_LoadLeaffaces(), Mod_Q1BSP_LoadPlanes(), Mod_Q1BSP_LoadSurfedges(), Mod_Q1BSP_LoadVertexes(), Mod_Q2BSP_FindSubmodelBrushRange_r(), Mod_Q2BSP_LoadAreaPortals(), Mod_Q2BSP_LoadAreas(), Mod_Q2BSP_LoadBrushes(), Mod_Q2BSP_LoadBrushSides(), Mod_Q2BSP_LoadLeafBrushes(), Mod_Q2BSP_LoadLeafs(), Mod_Q2BSP_LoadLighting(), Mod_Q2BSP_LoadNodes(), Mod_Q2BSP_LoadPOP(), Mod_Q2BSP_LoadTexinfo(), Mod_Q2BSP_LoadVisibility(), Mod_Q2BSP_NativeContentsFromSuperContents(), Mod_Q2BSP_SuperContentsFromNativeContents(), Mod_Q3BSP_TraceLineOfSight(), Mod_SetDrawSkyAndWater(), MSG_InitReadBuffer(), MSG_ReadLittleLong(), model_t::name, name, NULL, model_brush_t::num_brushes, model_brush_t::num_leafs, model_brush_t::num_nodes, model_brush_t::num_portals, model_t::num_surfaces, surfmesh_t::num_triangles, surfmesh_t::num_vertices, mmodel_t::numfaces, model_brush_t::numsubmodels, model_brush_lightstyleinfo_t::numsurfaces, offset, Q2BSPMAGIC, Q2BSPVERSION, Q2HEADER_LUMPS, Q2LUMP_AREAPORTALS, Q2LUMP_AREAS, Q2LUMP_BRUSHES, Q2LUMP_BRUSHSIDES, Q2LUMP_EDGES, Q2LUMP_ENTITIES, Q2LUMP_FACES, Q2LUMP_LEAFBRUSHES, Q2LUMP_LEAFFACES, Q2LUMP_LEAFS, Q2LUMP_LIGHTING, Q2LUMP_MODELS, Q2LUMP_NODES, Q2LUMP_PLANES, Q2LUMP_POP, Q2LUMP_SURFEDGES, Q2LUMP_TEXINFO, Q2LUMP_VERTEXES, Q2LUMP_VISIBILITY, r, R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), R_Mod_GetLightInfo(), size, sqrt(), client_static_t::state, model_brush_lightstyleinfo_t::style, msurface_lightmapinfo_t::styles, model_brush_t::submodels, model_brush_t::supportwateralpha, model_brush_lightstyleinfo_t::surfacelist, model_t::surfmesh, model_brush_lightstyleinfo_t::value, and VectorCopy.

Referenced by Mod_IBSP_Load().

◆ Mod_Q2BSP_LoadAreaPortals()

static void Mod_Q2BSP_LoadAreaPortals ( sizebuf_t * sb)
static

Definition at line 4819 of file model_brush.c.

4820{
4821 // we currently don't use areas, they represent closable doors as vis blockers
4822 sb->readcount = sb->cursize;
4823}

References sizebuf_t::cursize, and sizebuf_t::readcount.

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_LoadAreas()

static void Mod_Q2BSP_LoadAreas ( sizebuf_t * sb)
static

Definition at line 4813 of file model_brush.c.

4814{
4815 // we currently don't use areas, they represent closable doors as vis blockers
4816 sb->readcount = sb->cursize;
4817}

References sizebuf_t::cursize, and sizebuf_t::readcount.

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_LoadBrushes()

static void Mod_Q2BSP_LoadBrushes ( sizebuf_t * sb)
static

Definition at line 4706 of file model_brush.c.

4707{
4708 q3mbrush_t *out;
4709 int i, j, firstside, numsides, contents, count, maxplanes, q3surfaceflags, supercontents;
4710 colplanef_t *planes;
4711 int structsize = 12;
4712 qbool brushmissingtextures;
4713 int numbrushesmissingtextures = 0;
4714 int numcreatedtextures = 0;
4715
4716 if (sb->cursize % structsize)
4717 Host_Error("Mod_Q2BSP_LoadBrushes: funny lump size in %s",loadmodel->name);
4718 count = sb->cursize / structsize;
4719 out = (q3mbrush_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
4720
4723
4724 maxplanes = 0;
4725 planes = NULL;
4726
4727 for (i = 0; i < count; i++, out++)
4728 {
4729 firstside = MSG_ReadLittleLong(sb);
4730 numsides = MSG_ReadLittleLong(sb);
4731 contents = MSG_ReadLittleLong(sb);
4732 if (firstside < 0 || firstside + numsides > loadmodel->brush.num_brushsides)
4733 Host_Error("Mod_Q3BSP_LoadBrushes: invalid brushside range %i : %i (%i brushsides)", firstside, firstside + numsides, loadmodel->brush.num_brushsides);
4734
4735 out->firstbrushside = loadmodel->brush.data_brushsides + firstside;
4736 out->numbrushsides = numsides;
4737 // convert the contents to our values
4738 supercontents = Mod_Q2BSP_SuperContentsFromNativeContents(contents);
4739
4740 // problem: q2bsp brushes have contents but not a texture
4741 // problem: q2bsp brushsides *may* have a texture or may not
4742 // problem: all brushsides and brushes must have a texture for trace_hittexture functionality to work, and the collision code is engineered around this assumption
4743 // solution: nasty hacks
4744 brushmissingtextures = false;
4745 out->texture = NULL;
4746 for (j = 0; j < out->numbrushsides; j++)
4747 {
4748 if (out->firstbrushside[j].texture == &mod_q1bsp_texture_solid)
4749 brushmissingtextures = true;
4750 else
4751 {
4752 // if we can find a matching texture on a brush side we can use it instead of creating one
4753 if (out->firstbrushside[j].texture->supercontents == supercontents)
4754 out->texture = out->firstbrushside[j].texture;
4755 }
4756 }
4757 if (brushmissingtextures || out->texture == NULL)
4758 {
4759 numbrushesmissingtextures++;
4760 // if we didn't find any appropriate texture (matching contents), we'll have to create one
4761 // we could search earlier ones for a matching one but that can be slow
4762 if (out->texture == NULL)
4763 {
4764 texture_t *validtexture;
4765 validtexture = (texture_t *)Mem_Alloc(loadmodel->mempool, sizeof(texture_t));
4766 dpsnprintf(validtexture->name, sizeof(validtexture->name), "brushcollision%i", numcreatedtextures);
4767 validtexture->surfaceflags = 0;
4768 validtexture->supercontents = supercontents;
4769 numcreatedtextures++;
4770 out->texture = validtexture;
4771 }
4772 // out->texture now contains a texture with appropriate contents, copy onto any missing sides
4773 for (j = 0; j < out->numbrushsides; j++)
4774 if (out->firstbrushside[j].texture == &mod_q1bsp_texture_solid)
4775 out->firstbrushside[j].texture = out->texture;
4776 }
4777
4778 // make a colbrush from the brush
4779 q3surfaceflags = 0;
4780 // make a list of mplane_t structs to construct a colbrush from
4781 if (maxplanes < out->numbrushsides)
4782 {
4783 maxplanes = out->numbrushsides;
4784 if (planes)
4785 Mem_Free(planes);
4786 planes = (colplanef_t *)Mem_Alloc(tempmempool, sizeof(colplanef_t) * maxplanes);
4787 }
4788 for (j = 0;j < out->numbrushsides;j++)
4789 {
4790 VectorCopy(out->firstbrushside[j].plane->normal, planes[j].normal);
4791 planes[j].dist = out->firstbrushside[j].plane->dist;
4792 planes[j].q3surfaceflags = out->firstbrushside[j].texture->surfaceflags;
4793 planes[j].texture = out->firstbrushside[j].texture;
4794 q3surfaceflags |= planes[j].q3surfaceflags;
4795 }
4796 out->colbrushf = Collision_NewBrushFromPlanes(loadmodel->mempool, out->numbrushsides, planes, out->texture->supercontents, q3surfaceflags, out->texture, true);
4797
4798 // this whole loop can take a while (e.g. on redstarrepublic4)
4799 CL_KeepaliveMessage(false);
4800 }
4801 if (planes)
4802 Mem_Free(planes);
4803 if (numcreatedtextures)
4804 Con_DPrintf("Mod_Q2BSP_LoadBrushes: %i brushes own sides that lack textures or have differing contents from the brush, %i textures have been created to describe these contents.\n", numbrushesmissingtextures, numcreatedtextures);
4805}
void CL_KeepaliveMessage(qbool readmessages)
Definition cl_parse.c:314
colbrushf_t * Collision_NewBrushFromPlanes(mempool_t *mempool, int numoriginalplanes, const colplanef_t *originalplanes, int supercontents, int q3surfaceflags, const texture_t *texture, int hasaabbplanes)
Definition collision.c:163
struct q3mbrushside_s * data_brushsides
int numbrushsides
struct q3mbrushside_s * firstbrushside

References model_t::brush, CL_KeepaliveMessage(), q3mbrush_t::colbrushf, Collision_NewBrushFromPlanes(), Con_DPrintf(), count, sizebuf_t::cursize, model_brush_t::data_brushes, model_brush_t::data_brushsides, colplanef_t::dist, dpsnprintf(), q3mbrush_t::firstbrushside, Host_Error(), i, loadmodel, Mem_Alloc, Mem_Free, model_t::mempool, mod_q1bsp_texture_solid, Mod_Q2BSP_SuperContentsFromNativeContents(), MSG_ReadLittleLong(), model_t::name, texture_t::name, colplanef_t::normal, NULL, model_brush_t::num_brushes, model_brush_t::num_brushsides, q3mbrush_t::numbrushsides, colplanef_t::q3surfaceflags, texture_t::supercontents, texture_t::surfaceflags, tempmempool, colplanef_t::texture, q3mbrush_t::texture, and VectorCopy.

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_LoadBrushSides()

static void Mod_Q2BSP_LoadBrushSides ( sizebuf_t * sb)
static

Definition at line 4671 of file model_brush.c.

4672{
4673 q3mbrushside_t *out;
4674 int i, n, count;
4675 int structsize = 4;
4676
4677 if (sb->cursize % structsize)
4678 Host_Error("Mod_Q2BSP_LoadBrushSides: funny lump size in %s",loadmodel->name);
4679 count = sb->cursize / structsize;
4680 out = (q3mbrushside_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
4681
4684
4685 for (i = 0;i < count;i++, out++)
4686 {
4687 n = (unsigned short)MSG_ReadLittleShort(sb);
4689 Host_Error("Mod_Q2BSP_LoadBrushSides: invalid planeindex %i (%i planes)", n, loadmodel->brush.num_planes);
4690 out->plane = loadmodel->brush.data_planes + n;
4691 n = MSG_ReadLittleShort(sb);
4692 if (n >= 0)
4693 {
4694 if (n >= loadmodel->brushq1.numtexinfo)
4695 Host_Error("Mod_Q2BSP_LoadBrushSides: invalid texinfo index %i (%i texinfos)", n, loadmodel->brushq1.numtexinfo);
4696 out->texture = loadmodel->data_textures + loadmodel->brushq1.texinfo[n].textureindex;
4697 }
4698 else
4699 {
4700 //Con_Printf("Mod_Q2BSP_LoadBrushSides: brushside %i has texinfo index %i < 0, changing to generic texture!\n", i, n);
4702 }
4703 }
4704}
#define n(x, y)
struct mplane_s * plane
struct texture_s * texture

References model_t::brush, model_t::brushq1, count, sizebuf_t::cursize, model_brush_t::data_brushsides, model_brush_t::data_planes, model_t::data_textures, Host_Error(), i, loadmodel, Mem_Alloc, model_t::mempool, mod_q1bsp_texture_solid, MSG_ReadLittleShort(), n, model_t::name, model_brush_t::num_brushsides, model_brush_t::num_planes, model_brushq1_t::numtexinfo, q3mbrushside_t::plane, model_brushq1_t::texinfo, and q3mbrushside_t::texture.

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_LoadLeafBrushes()

static void Mod_Q2BSP_LoadLeafBrushes ( sizebuf_t * sb)
static

Definition at line 4652 of file model_brush.c.

4653{
4654 int i, j;
4655 int structsize = 2;
4656
4657 if (sb->cursize % structsize)
4658 Host_Error("Mod_Q2BSP_LoadLeafBrushes: funny lump size in %s",loadmodel->name);
4659 loadmodel->brush.num_leafbrushes = sb->cursize / structsize;
4661
4662 for (i = 0;i < loadmodel->brush.num_leafbrushes;i++)
4663 {
4664 j = (unsigned short) MSG_ReadLittleShort(sb);
4665 if (j >= loadmodel->brush.num_brushes)
4666 Host_Error("Mod_Q1BSP_LoadLeafBrushes: bad brush number");
4668 }
4669}
int * data_leafbrushes

References model_t::brush, sizebuf_t::cursize, model_brush_t::data_leafbrushes, Host_Error(), i, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadLittleShort(), model_t::name, model_brush_t::num_brushes, and model_brush_t::num_leafbrushes.

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_LoadLeafs()

static void Mod_Q2BSP_LoadLeafs ( sizebuf_t * sb)
static

Definition at line 4585 of file model_brush.c.

4586{
4587 mleaf_t *out;
4588 int i, j, count, firstmarksurface, nummarksurfaces, firstmarkbrush, nummarkbrushes;
4589 int structsize = 28;
4590
4591 if (sb->cursize % structsize)
4592 Host_Error("Mod_Q2BSP_LoadLeafs: funny lump size in %s",loadmodel->name);
4593 count = sb->cursize / structsize;
4594 out = (mleaf_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
4595
4596 loadmodel->brush.data_leafs = out;
4598
4599 // FIXME: this function could really benefit from some error checking
4600 for ( i=0 ; i<count ; i++, out++)
4601 {
4602 out->contents = MSG_ReadLittleLong(sb);
4604 out->areaindex = MSG_ReadLittleShort(sb);
4605 out->mins[0] = MSG_ReadLittleShort(sb);
4606 out->mins[1] = MSG_ReadLittleShort(sb);
4607 out->mins[2] = MSG_ReadLittleShort(sb);
4608 out->maxs[0] = MSG_ReadLittleShort(sb);
4609 out->maxs[1] = MSG_ReadLittleShort(sb);
4610 out->maxs[2] = MSG_ReadLittleShort(sb);
4611
4612 firstmarksurface = (unsigned short)MSG_ReadLittleShort(sb);
4613 nummarksurfaces = (unsigned short)MSG_ReadLittleShort(sb);
4614 firstmarkbrush = (unsigned short)MSG_ReadLittleShort(sb);
4615 nummarkbrushes = (unsigned short)MSG_ReadLittleShort(sb);
4616
4617 for (j = 0;j < 4;j++)
4618 out->ambient_sound_level[j] = 0;
4619
4621 {
4622 Con_Print("Mod_Q2BSP_LoadLeafs: invalid clusterindex\n");
4623 out->clusterindex = -1;
4624 }
4625
4626 if (firstmarksurface >= 0 && firstmarksurface + nummarksurfaces <= loadmodel->brush.num_leafsurfaces)
4627 {
4628 out->firstleafsurface = loadmodel->brush.data_leafsurfaces + firstmarksurface;
4629 out->numleafsurfaces = nummarksurfaces;
4630 }
4631 else
4632 {
4633 Con_Printf("Mod_Q2BSP_LoadLeafs: invalid leafsurface range %i:%i outside range %i:%i\n", firstmarksurface, firstmarksurface+nummarksurfaces, 0, loadmodel->brush.num_leafsurfaces);
4634 out->firstleafsurface = NULL;
4635 out->numleafsurfaces = 0;
4636 }
4637
4638 if (firstmarkbrush >= 0 && firstmarkbrush + nummarkbrushes <= loadmodel->brush.num_leafbrushes)
4639 {
4640 out->firstleafbrush = loadmodel->brush.data_leafbrushes + firstmarkbrush;
4641 out->numleafbrushes = nummarkbrushes;
4642 }
4643 else
4644 {
4645 Con_Printf("Mod_Q2BSP_LoadLeafs: invalid leafbrush range %i:%i outside range %i:%i\n", firstmarkbrush, firstmarkbrush+nummarkbrushes, 0, loadmodel->brush.num_leafbrushes);
4646 out->firstleafbrush = NULL;
4647 out->numleafbrushes = 0;
4648 }
4649 }
4650}

References mleaf_t::ambient_sound_level, mleaf_t::areaindex, model_t::brush, mleaf_t::clusterindex, Con_Print(), Con_Printf(), mleaf_t::contents, count, sizebuf_t::cursize, model_brush_t::data_leafbrushes, model_brush_t::data_leafs, model_brush_t::data_leafsurfaces, mleaf_t::firstleafbrush, mleaf_t::firstleafsurface, Host_Error(), i, loadmodel, mleaf_t::maxs, Mem_Alloc, model_t::mempool, mleaf_t::mins, MSG_ReadLittleLong(), MSG_ReadLittleShort(), model_t::name, NULL, model_brush_t::num_leafbrushes, model_brush_t::num_leafs, model_brush_t::num_leafsurfaces, model_brush_t::num_pvsclusters, mleaf_t::numleafbrushes, and mleaf_t::numleafsurfaces.

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_LoadLighting()

static void Mod_Q2BSP_LoadLighting ( sizebuf_t * sb)
static

Definition at line 4578 of file model_brush.c.

4579{
4580 // LadyHavoc: this fits exactly the same format that we use in .lit files
4581 loadmodel->brushq1.lightdata = (unsigned char *)Mem_Alloc(loadmodel->mempool, sb->cursize);
4583}

References model_t::brushq1, sizebuf_t::cursize, model_brushq1_t::lightdata, loadmodel, Mem_Alloc, model_t::mempool, and MSG_ReadBytes().

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_LoadNodes()

static void Mod_Q2BSP_LoadNodes ( sizebuf_t * sb)
static

Definition at line 4304 of file model_brush.c.

4305{
4306 int i, j, count, p, child[2];
4307 mnode_t *out;
4308 int structsize = 28;
4309
4310 if (sb->cursize % structsize)
4311 Host_Error("Mod_Q2BSP_LoadNodes: funny lump size in %s",loadmodel->name);
4312 count = sb->cursize / structsize;
4313 if (count == 0)
4314 Host_Error("Mod_Q2BSP_LoadNodes: missing BSP tree in %s",loadmodel->name);
4315 out = (mnode_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
4316
4317 loadmodel->brush.data_nodes = out;
4319
4320 for ( i=0 ; i<count ; i++, out++)
4321 {
4322 p = MSG_ReadLittleLong(sb);
4323 out->plane = loadmodel->brush.data_planes + p;
4324 child[0] = MSG_ReadLittleLong(sb);
4325 child[1] = MSG_ReadLittleLong(sb);
4326 out->mins[0] = MSG_ReadLittleShort(sb);
4327 out->mins[1] = MSG_ReadLittleShort(sb);
4328 out->mins[2] = MSG_ReadLittleShort(sb);
4329 out->maxs[0] = MSG_ReadLittleShort(sb);
4330 out->maxs[1] = MSG_ReadLittleShort(sb);
4331 out->maxs[2] = MSG_ReadLittleShort(sb);
4332 out->firstsurface = (unsigned short)MSG_ReadLittleShort(sb);
4333 out->numsurfaces = (unsigned short)MSG_ReadLittleShort(sb);
4334 if (out->firstsurface + out->numsurfaces > (unsigned int)loadmodel->num_surfaces)
4335 {
4336 Con_Printf("Mod_Q2BSP_LoadNodes: invalid surface index range %i+%i (file has only %i surfaces)\n", out->firstsurface, out->numsurfaces, loadmodel->num_surfaces);
4337 out->firstsurface = 0;
4338 out->numsurfaces = 0;
4339 }
4340 for (j=0 ; j<2 ; j++)
4341 {
4342 p = child[j];
4343 if (p >= 0)
4344 {
4345 if (p < loadmodel->brush.num_nodes)
4346 out->children[j] = loadmodel->brush.data_nodes + p;
4347 else
4348 {
4349 Con_Printf("Mod_Q2BSP_LoadNodes: invalid node index %i (file has only %i nodes)\n", p, loadmodel->brush.num_nodes);
4350 // map it to the solid leaf
4352 }
4353 }
4354 else
4355 {
4356 // get leaf index as a positive value starting at 0 (-1 becomes 0, -2 becomes 1, etc)
4357 p = -(p+1);
4358 if (p < loadmodel->brush.num_leafs)
4359 out->children[j] = (mnode_t *)(loadmodel->brush.data_leafs + p);
4360 else
4361 {
4362 Con_Printf("Mod_Q2BSP_LoadNodes: invalid leaf index %i (file has only %i leafs)\n", p, loadmodel->brush.num_leafs);
4363 // map it to the solid leaf
4365 }
4366 }
4367 }
4368 }
4369
4371}

References model_t::brush, mnode_t::children, Con_Printf(), count, sizebuf_t::cursize, model_brush_t::data_leafs, model_brush_t::data_nodes, model_brush_t::data_planes, mnode_t::firstsurface, Host_Error(), i, loadmodel, mnode_t::maxs, Mem_Alloc, model_t::mempool, mnode_t::mins, Mod_BSP_LoadNodes_RecursiveSetParent(), MSG_ReadLittleLong(), MSG_ReadLittleShort(), model_t::name, NULL, model_brush_t::num_leafs, model_brush_t::num_nodes, model_t::num_surfaces, mnode_t::numsurfaces, and mnode_t::plane.

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_LoadPOP()

static void Mod_Q2BSP_LoadPOP ( sizebuf_t * sb)
static

Definition at line 4807 of file model_brush.c.

4808{
4809 // this is probably a "proof of purchase" lump of some sort, it seems to be 0 size in most bsp files (but not q2dm1.bsp for instance)
4810 sb->readcount = sb->cursize;
4811}

References sizebuf_t::cursize, and sizebuf_t::readcount.

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_LoadTexinfo()

static void Mod_Q2BSP_LoadTexinfo ( sizebuf_t * sb)
static

Definition at line 4373 of file model_brush.c.

4374{
4375 mtexinfo_t *out;
4376 int i, l, count;
4377 int structsize = 76;
4378 int maxtextures = 1024; // hardcoded limit of quake2 engine, so we may as well use it as an upper bound
4379 char filename[MAX_QPATH];
4380
4381 if (sb->cursize % structsize)
4382 Host_Error("Mod_Q2BSP_LoadTexinfo: funny lump size in %s",loadmodel->name);
4383 count = sb->cursize / structsize;
4384 out = (mtexinfo_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
4385 loadmodel->brushq1.texinfo = out;
4389
4390 for (i = 0;i < count;i++, out++)
4391 {
4392 int j, k;
4393 for (k = 0;k < 2;k++)
4394 for (j = 0;j < 4;j++)
4395 out->vecs[k][j] = MSG_ReadLittleFloat(sb);
4396
4397 out->q2flags = MSG_ReadLittleLong(sb);
4398 out->q2value = MSG_ReadLittleLong(sb);
4399 MSG_ReadBytes(sb, 32, (unsigned char*)out->q2texture);
4400 out->q2texture[31] = 0; // make absolutely sure it is terminated
4402
4403 // find an existing match for the texture if possible
4404 dpsnprintf(filename, sizeof(filename), "textures/%s.wal", out->q2texture);
4405 for (j = 0;j < loadmodel->num_texturesperskin;j++)
4406 if (!strcmp(filename, loadmodel->data_textures[j].name)
4407 && out->q2flags == loadmodel->data_textures[j].q2flags
4408 && out->q2value == loadmodel->data_textures[j].q2value)
4409 break;
4410 // if we don't find the texture, store the new texture
4412 {
4413 if (loadmodel->num_texturesperskin < maxtextures)
4414 {
4416 int q2flags = out->q2flags;
4417 unsigned char *walfile = NULL;
4418 fs_offset_t walfilesize = 0;
4420 // now read the .wal file to get metadata (even if a .tga was overriding it, we still need the wal data)
4421 walfile = FS_LoadFile(filename, tempmempool, true, &walfilesize);
4422 if (walfile)
4423 {
4424 int w, h;
4425 LoadWAL_GetMetadata(walfile, (int)walfilesize, &w, &h, NULL, NULL, &tx->q2contents, NULL);
4426 tx->width = w;
4427 tx->height = h;
4428 Mem_Free(walfile);
4429 }
4430 else
4431 {
4432 tx->width = 16;
4433 tx->height = 16;
4434 }
4435 tx->q2flags = out->q2flags;
4436 tx->q2value = out->q2value;
4437 // also modify the texture to have the correct contents and such based on flags
4438 // note that we create multiple texture_t structures if q2flags differs
4439 if (q2flags & Q2SURF_LIGHT)
4440 {
4441 // doesn't mean anything to us
4442 }
4443 if (q2flags & Q2SURF_SLICK)
4444 {
4445 // would be nice to support...
4446 }
4447 if (q2flags & Q2SURF_SKY)
4448 {
4449 // sky is a rather specific thing
4450 q2flags &= ~Q2SURF_NODRAW; // quake2 had a slightly different meaning than we have in mind here...
4454 }
4455 if (q2flags & Q2SURF_WARP)
4456 {
4457 // we use a scroll instead of a warp
4459 // if it's also transparent, we can enable the WATERSHADER
4460 // but we do not set the WATERALPHA flag because we don't
4461 // want to honor r_wateralpha in q2bsp
4462 // (it would go against the artistic intent)
4463 if (q2flags & (Q2SURF_TRANS33 | Q2SURF_TRANS66))
4465 }
4466 if (q2flags & Q2SURF_TRANS33)
4467 {
4469 tx->basealpha = 1.0f / 3.0f;
4470 tx->supercontents &= ~SUPERCONTENTS_OPAQUE;
4471 if (tx->q2contents & Q2CONTENTS_SOLID)
4472 tx->q2contents = (tx->q2contents & ~Q2CONTENTS_SOLID) | Q2CONTENTS_WINDOW;
4473 }
4474 if (q2flags & Q2SURF_TRANS66)
4475 {
4477 tx->basealpha = 2.0f / 3.0f;
4478 tx->supercontents &= ~SUPERCONTENTS_OPAQUE;
4479 if (tx->q2contents & Q2CONTENTS_SOLID)
4480 tx->q2contents = (tx->q2contents & ~Q2CONTENTS_SOLID) | Q2CONTENTS_WINDOW;
4481 }
4482 if ((q2flags & Q2SURF_FLOWING) && tx->materialshaderpass != NULL)
4483 {
4485 if (q2flags & Q2SURF_WARP)
4486 tx->materialshaderpass->tcmods[0].parms[0] = -0.5f;
4487 else
4488 tx->materialshaderpass->tcmods[0].parms[0] = -1.6f;
4489 tx->materialshaderpass->tcmods[0].parms[1] = 0.0f;
4490 }
4491 if (q2flags & Q2SURF_ALPHATEST)
4492 {
4493 // KMQUAKE2 and other modded engines added this flag for lit alpha tested surfaces
4495 }
4496 else if (q2flags & (Q2SURF_TRANS33 | Q2SURF_TRANS66 | Q2SURF_WARP))
4497 {
4500 }
4501 if (q2flags & Q2SURF_NODRAW)
4502 {
4504 }
4509 if (tx->q2flags & (Q2SURF_HINT | Q2SURF_SKIP))
4510 tx->q2contents = 0;
4512 // set the current values to the base values
4513 tx->currentframe = tx;
4518 }
4519 else
4520 {
4521 Con_Printf("Mod_Q2BSP_LoadTexinfo: max textures reached (%i)\n", maxtextures);
4522 j = 0; // use first texture and give up
4523 }
4524 }
4525 // store the index we found for this texture
4526 out->textureindex = j;
4527 }
4528
4529 // realloc the textures array now that we know how many we actually need
4531
4532 // now assemble the texture chains
4533 // if we encounter the textures out of order, the later ones won't mark the earlier ones in a sequence, so the earlier
4534 for (i = 0, out = loadmodel->brushq1.texinfo;i < count;i++, out++)
4535 {
4536 int j, k;
4538 t->currentframe = t; // fix the reallocated pointer
4539
4540 // if this is not animated, skip it
4541 // if this is already processed, skip it (part of an existing sequence)
4542 if (out->q2nexttexinfo == 0 || t->animated)
4543 continue;
4544
4545 // store the array of frames to use
4546 t->animated = 2; // q2bsp animation
4547 t->anim_total[0] = 0;
4548 t->anim_total[1] = 0;
4549 // gather up to 10 frames (we don't support more)
4550 for (j = i;j >= 0 && t->anim_total[0] < (int)(sizeof(t->anim_frames[0])/sizeof(t->anim_frames[0][0]));j = loadmodel->brushq1.texinfo[j].q2nexttexinfo)
4551 {
4552 // detect looping and stop there
4553 if (t->anim_total[0] && loadmodel->brushq1.texinfo[j].textureindex == out->textureindex)
4554 break;
4555 t->anim_frames[0][t->anim_total[0]++] = &loadmodel->data_textures[loadmodel->brushq1.texinfo[j].textureindex];
4556 }
4557 // we could look for the +a sequence here if this is the +0 sequence,
4558 // but it seems that quake2 did not implement that (even though the
4559 // files exist in the baseq2 content)
4560
4561 // write the frame sequence to all the textures involved (just like
4562 // in the q1bsp loader)
4563 //
4564 // note that this can overwrite the rest of the sequence - so if the
4565 // start of a sequence is found later than the other parts of the
4566 // sequence, it will go back and rewrite them correctly.
4567 for (k = 0;k < t->anim_total[0];k++)
4568 {
4569 texture_t *txk = t->anim_frames[0][k];
4570 txk->animated = t->animated;
4571 txk->anim_total[0] = t->anim_total[0];
4572 for (l = 0;l < t->anim_total[0];l++)
4573 txk->anim_frames[0][l] = t->anim_frames[0][l];
4574 }
4575 }
4576}
qbool LoadWAL_GetMetadata(const unsigned char *f, int filesize, int *retwidth, int *retheight, int *retflags, int *retvalue, int *retcontents, char *retanimname32c)
Definition image.c:800
#define MATERIALFLAG_FULLBRIGHT
Definition model_brush.h:87
#define Q2SURF_HINT
#define Q2CONTENTS_WATER
Definition model_q2bsp.h:65
#define Q2SURF_TRANS33
#define Q2SURF_FLOWING
#define Q2SURF_NODRAW
#define Q2CONTENTS_TRANSLUCENT
Definition model_q2bsp.h:89
#define Q2SURF_TRANS66
#define Q2CONTENTS_SLIME
Definition model_q2bsp.h:64
#define Q2CONTENTS_AUX
Definition model_q2bsp.h:62
#define Q2CONTENTS_SOLID
Definition model_q2bsp.h:60
#define Q2SURF_SKIP
#define Q2SURF_LIGHT
Definition model_q2bsp.h:94
#define Q2SURF_ALPHATEST
#define Q2CONTENTS_DETAIL
Definition model_q2bsp.h:88
#define Q2CONTENTS_MONSTERCLIP
Definition model_q2bsp.h:74
#define Q2CONTENTS_MIST
Definition model_q2bsp.h:66
#define Q2CONTENTS_LAVA
Definition model_q2bsp.h:63
#define Q2CONTENTS_WINDOW
Definition model_q2bsp.h:61
#define Q2SURF_SLICK
Definition model_q2bsp.h:96
#define Q2CONTENTS_PLAYERCLIP
Definition model_q2bsp.h:73
@ Q3TCMOD_SCROLL
Definition r_qshader.h:115
char q2texture[32]
float parms[Q3TCMOD_MAXPARMS]
Definition r_qshader.h:152
q3shaderinfo_layer_tcmod_t tcmods[Q3MAXTCMODS]
Definition r_qshader.h:270

References texture_t::anim_frames, texture_t::anim_total, texture_t::animated, texture_t::basealpha, texture_t::basematerialflags, model_t::brushq1, Con_Printf(), count, texture_t::currentframe, texture_t::currentmaterialflags, texture_t::currentskinframe, sizebuf_t::cursize, model_t::data_textures, dpsnprintf(), FS_LoadFile(), texture_t::height, Host_Error(), i, int(), cvar_t::integer, loadmodel, LoadWAL_GetMetadata(), MATERIALFLAG_ALPHA, MATERIALFLAG_ALPHATEST, MATERIALFLAG_BLENDED, MATERIALFLAG_FULLBRIGHT, MATERIALFLAG_NODRAW, MATERIALFLAG_NOSHADOW, MATERIALFLAG_SKY, MATERIALFLAG_WALL, MATERIALFLAG_WATERSCROLL, MATERIALFLAG_WATERSHADER, texture_t::materialshaderpass, MAX_QPATH, Mem_Alloc, Mem_Free, Mem_Realloc, model_t::mempool, Mod_LoadTextureFromQ3Shader(), mod_q2bsp_littransparentsurfaces, Mod_Q2BSP_SuperContentsFromNativeContents(), MSG_ReadBytes(), MSG_ReadLittleFloat(), MSG_ReadLittleLong(), model_t::name, texture_t::name, NULL, model_t::num_textures, model_t::num_texturesperskin, model_brushq1_t::numtexinfo, q3shaderinfo_layer_tcmod_t::parms, texture_t::q2contents, Q2CONTENTS_AUX, Q2CONTENTS_DETAIL, Q2CONTENTS_LAVA, Q2CONTENTS_MIST, Q2CONTENTS_MONSTERCLIP, Q2CONTENTS_PLAYERCLIP, Q2CONTENTS_SLIME, Q2CONTENTS_SOLID, Q2CONTENTS_TRANSLUCENT, Q2CONTENTS_WATER, Q2CONTENTS_WINDOW, mtexinfo_t::q2flags, texture_t::q2flags, mtexinfo_t::q2nexttexinfo, Q2SURF_ALPHATEST, Q2SURF_FLOWING, Q2SURF_HINT, Q2SURF_LIGHT, Q2SURF_NODRAW, Q2SURF_SKIP, Q2SURF_SKY, Q2SURF_SLICK, Q2SURF_TRANS33, Q2SURF_TRANS66, Q2SURF_WARP, mtexinfo_t::q2texture, mtexinfo_t::q2value, texture_t::q2value, Q3SURFACEFLAG_NODLIGHT, Q3SURFACEFLAG_NOIMPACT, Q3SURFACEFLAG_NOLIGHTMAP, Q3SURFACEFLAG_NOMARKS, Q3SURFACEFLAG_SKY, Q3TCMOD_SCROLL, texture_shaderpass_t::skinframes, texture_t::supercontents, SUPERCONTENTS_NODROP, SUPERCONTENTS_OPAQUE, SUPERCONTENTS_SKY, texture_t::surfaceflags, q3shaderinfo_layer_tcmod_t::tcmod, texture_shaderpass_t::tcmods, tempmempool, TEXF_ALPHA, TEXF_COMPRESS, TEXF_ISWORLD, TEXF_MIPMAP, TEXF_PICMIP, model_brushq1_t::texinfo, mtexinfo_t::textureindex, mtexinfo_t::vecs, w, and texture_t::width.

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_LoadVisibility()

static void Mod_Q2BSP_LoadVisibility ( sizebuf_t * sb)
static

Definition at line 4276 of file model_brush.c.

4277{
4278 int i, count;
4284
4285 if (!sb->cursize)
4286 return;
4287
4292 for (i = 0;i < count;i++)
4293 {
4294 int pvsofs = MSG_ReadLittleLong(sb);
4295 /*int phsofs = */MSG_ReadLittleLong(sb);
4296 // decompress the vis data for this cluster
4297 // (note this accesses the underlying data store of sb, which is kind of evil)
4299 }
4300 // hush the loading error check later - we had to do random access on this lump, so we didn't read to the end
4301 sb->readcount = sb->cursize;
4302}

References model_t::brush, model_t::brushq1, count, sizebuf_t::cursize, sizebuf_t::data, model_brushq1_t::data_compressedpvs, model_brush_t::data_pvsclusters, i, loadmodel, Mem_Alloc, model_t::mempool, Mod_BSP_DecompressVis(), MSG_ReadLittleLong(), NULL, model_brushq1_t::num_compressedpvs, model_brush_t::num_pvsclusterbytes, model_brush_t::num_pvsclusters, and sizebuf_t::readcount.

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_NativeContentsFromSuperContents()

int Mod_Q2BSP_NativeContentsFromSuperContents ( int supercontents)

Definition at line 4252 of file model_brush.c.

4253{
4254 int nativecontents = 0;
4255 if (supercontents & SUPERCONTENTS_SOLID)
4256 nativecontents |= CONTENTSQ2_SOLID;
4257 if (supercontents & SUPERCONTENTS_WATER)
4258 nativecontents |= CONTENTSQ2_WATER;
4259 if (supercontents & SUPERCONTENTS_SLIME)
4260 nativecontents |= CONTENTSQ2_SLIME;
4261 if (supercontents & SUPERCONTENTS_LAVA)
4262 nativecontents |= CONTENTSQ2_LAVA;
4263 if (supercontents & SUPERCONTENTS_BODY)
4264 nativecontents |= CONTENTSQ2_MONSTER;
4265 if (supercontents & SUPERCONTENTS_CORPSE)
4266 nativecontents |= CONTENTSQ2_DEADMONSTER;
4267 if (supercontents & SUPERCONTENTS_PLAYERCLIP)
4268 nativecontents |= CONTENTSQ2_PLAYERCLIP;
4269 if (supercontents & SUPERCONTENTS_MONSTERCLIP)
4270 nativecontents |= CONTENTSQ2_MONSTERCLIP;
4271 if (!(supercontents & SUPERCONTENTS_OPAQUE))
4272 nativecontents |= CONTENTSQ2_TRANSLUCENT;
4273 return nativecontents;
4274}
#define CONTENTSQ2_MONSTERCLIP
Definition bspfile.h:159
#define CONTENTSQ2_LAVA
Definition bspfile.h:153
#define SUPERCONTENTS_MONSTERCLIP
Definition bspfile.h:205
#define CONTENTSQ2_DEADMONSTER
Definition bspfile.h:168
#define CONTENTSQ2_MONSTER
Definition bspfile.h:167
#define CONTENTSQ2_TRANSLUCENT
Definition bspfile.h:170
#define CONTENTSQ2_WATER
Definition bspfile.h:155
#define SUPERCONTENTS_CORPSE
Definition bspfile.h:202
#define CONTENTSQ2_PLAYERCLIP
Definition bspfile.h:158
#define SUPERCONTENTS_PLAYERCLIP
Definition bspfile.h:204
#define CONTENTSQ2_SOLID
Definition bspfile.h:150
#define CONTENTSQ2_SLIME
Definition bspfile.h:154

References CONTENTSQ2_DEADMONSTER, CONTENTSQ2_LAVA, CONTENTSQ2_MONSTER, CONTENTSQ2_MONSTERCLIP, CONTENTSQ2_PLAYERCLIP, CONTENTSQ2_SLIME, CONTENTSQ2_SOLID, CONTENTSQ2_TRANSLUCENT, CONTENTSQ2_WATER, SUPERCONTENTS_BODY, SUPERCONTENTS_CORPSE, SUPERCONTENTS_LAVA, SUPERCONTENTS_MONSTERCLIP, SUPERCONTENTS_OPAQUE, SUPERCONTENTS_PLAYERCLIP, SUPERCONTENTS_SLIME, SUPERCONTENTS_SOLID, and SUPERCONTENTS_WATER.

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_SuperContentsFromNativeContents()

int Mod_Q2BSP_SuperContentsFromNativeContents ( int nativecontents)

Definition at line 4228 of file model_brush.c.

4229{
4230 int supercontents = 0;
4231 if (nativecontents & CONTENTSQ2_SOLID)
4232 supercontents |= SUPERCONTENTS_SOLID;
4233 if (nativecontents & CONTENTSQ2_WATER)
4234 supercontents |= SUPERCONTENTS_WATER;
4235 if (nativecontents & CONTENTSQ2_SLIME)
4236 supercontents |= SUPERCONTENTS_SLIME;
4237 if (nativecontents & CONTENTSQ2_LAVA)
4238 supercontents |= SUPERCONTENTS_LAVA;
4239 if (nativecontents & CONTENTSQ2_MONSTER)
4240 supercontents |= SUPERCONTENTS_BODY;
4241 if (nativecontents & CONTENTSQ2_DEADMONSTER)
4242 supercontents |= SUPERCONTENTS_CORPSE;
4243 if (nativecontents & CONTENTSQ2_PLAYERCLIP)
4244 supercontents |= SUPERCONTENTS_PLAYERCLIP;
4245 if (nativecontents & CONTENTSQ2_MONSTERCLIP)
4246 supercontents |= SUPERCONTENTS_MONSTERCLIP;
4247 if (!(nativecontents & CONTENTSQ2_TRANSLUCENT))
4248 supercontents |= SUPERCONTENTS_OPAQUE;
4249 return supercontents;
4250}

References CONTENTSQ2_DEADMONSTER, CONTENTSQ2_LAVA, CONTENTSQ2_MONSTER, CONTENTSQ2_MONSTERCLIP, CONTENTSQ2_PLAYERCLIP, CONTENTSQ2_SLIME, CONTENTSQ2_SOLID, CONTENTSQ2_TRANSLUCENT, CONTENTSQ2_WATER, SUPERCONTENTS_BODY, SUPERCONTENTS_CORPSE, SUPERCONTENTS_LAVA, SUPERCONTENTS_MONSTERCLIP, SUPERCONTENTS_OPAQUE, SUPERCONTENTS_PLAYERCLIP, SUPERCONTENTS_SLIME, SUPERCONTENTS_SOLID, and SUPERCONTENTS_WATER.

Referenced by Mod_LoadTextureFromQ3Shader(), Mod_Q2BSP_Load(), Mod_Q2BSP_LoadBrushes(), and Mod_Q2BSP_LoadTexinfo().

◆ Mod_Q3BSP_LightPoint()

static void Mod_Q3BSP_LightPoint ( model_t * model,
const vec3_t p,
vec3_t ambientcolor,
vec3_t diffusecolor,
vec3_t diffusenormal )
static

Definition at line 6643 of file model_brush.c.

6644{
6645 int i, j, k, index[3];
6646 float transformed[3], blend1, blend2, blend, stylescale = 1;
6647 q3dlightgrid_t *a, *s;
6648
6649 // scale lighting by lightstyle[0] so that darkmode in dpmod works properly
6650 // LadyHavoc: FIXME: is this true?
6651 stylescale = 1; // added while render
6652 //stylescale = r_refdef.scene.rtlightstylevalue[0];
6653
6654 if (!model->brushq3.num_lightgrid)
6655 {
6656 ambientcolor[0] = stylescale;
6657 ambientcolor[1] = stylescale;
6658 ambientcolor[2] = stylescale;
6659 return;
6660 }
6661
6662 Matrix4x4_Transform(&model->brushq3.num_lightgrid_indexfromworld, p, transformed);
6663 //Matrix4x4_Print(&model->brushq3.num_lightgrid_indexfromworld);
6664 //Con_Printf("%f %f %f transformed %f %f %f clamped ", p[0], p[1], p[2], transformed[0], transformed[1], transformed[2]);
6665 transformed[0] = bound(0, transformed[0], model->brushq3.num_lightgrid_isize[0] - 1);
6666 transformed[1] = bound(0, transformed[1], model->brushq3.num_lightgrid_isize[1] - 1);
6667 transformed[2] = bound(0, transformed[2], model->brushq3.num_lightgrid_isize[2] - 1);
6668 index[0] = (int)floor(transformed[0]);
6669 index[1] = (int)floor(transformed[1]);
6670 index[2] = (int)floor(transformed[2]);
6671 //Con_Printf("%f %f %f index %i %i %i:\n", transformed[0], transformed[1], transformed[2], index[0], index[1], index[2]);
6672
6673 // now lerp the values
6674 VectorClear(diffusenormal);
6675 a = &model->brushq3.data_lightgrid[(index[2] * model->brushq3.num_lightgrid_isize[1] + index[1]) * model->brushq3.num_lightgrid_isize[0] + index[0]];
6676 for (k = 0;k < 2;k++)
6677 {
6678 blend1 = (k ? (transformed[2] - index[2]) : (1 - (transformed[2] - index[2])));
6679 if (blend1 < 0.001f || index[2] + k >= model->brushq3.num_lightgrid_isize[2])
6680 continue;
6681 for (j = 0;j < 2;j++)
6682 {
6683 blend2 = blend1 * (j ? (transformed[1] - index[1]) : (1 - (transformed[1] - index[1])));
6684 if (blend2 < 0.001f || index[1] + j >= model->brushq3.num_lightgrid_isize[1])
6685 continue;
6686 for (i = 0;i < 2;i++)
6687 {
6688 blend = blend2 * (i ? (transformed[0] - index[0]) : (1 - (transformed[0] - index[0]))) * stylescale;
6689 if (blend < 0.001f || index[0] + i >= model->brushq3.num_lightgrid_isize[0])
6690 continue;
6691 s = a + (k * model->brushq3.num_lightgrid_isize[1] + j) * model->brushq3.num_lightgrid_isize[0] + i;
6692 VectorMA(ambientcolor, blend * (1.0f / 128.0f), s->ambientrgb, ambientcolor);
6693 VectorMA(diffusecolor, blend * (1.0f / 128.0f), s->diffusergb, diffusecolor);
6694 // this uses the mod_md3_sin table because the values are
6695 // already in the 0-255 range, the 64+ bias fetches a cosine
6696 // instead of a sine value
6697 diffusenormal[0] += blend * (mod_md3_sin[64 + s->diffuseyaw] * mod_md3_sin[s->diffusepitch]);
6698 diffusenormal[1] += blend * (mod_md3_sin[ s->diffuseyaw] * mod_md3_sin[s->diffusepitch]);
6699 diffusenormal[2] += blend * (mod_md3_sin[64 + s->diffusepitch]);
6700 //Con_Printf("blend %f: ambient %i %i %i, diffuse %i %i %i, diffusepitch %i diffuseyaw %i (%f %f, normal %f %f %f)\n", blend, s->ambientrgb[0], s->ambientrgb[1], s->ambientrgb[2], s->diffusergb[0], s->diffusergb[1], s->diffusergb[2], s->diffusepitch, s->diffuseyaw, pitch, yaw, (cos(yaw) * cospitch), (sin(yaw) * cospitch), (-sin(pitch)));
6701 }
6702 }
6703 }
6704
6705 // normalize the light direction before turning
6706 VectorNormalize(diffusenormal);
6707 //Con_Printf("result: ambient %f %f %f diffuse %f %f %f diffusenormal %f %f %f\n", ambientcolor[0], ambientcolor[1], ambientcolor[2], diffusecolor[0], diffusecolor[1], diffusecolor[2], diffusenormal[0], diffusenormal[1], diffusenormal[2]);
6708}
GLuint index
Definition glquake.h:629
void Matrix4x4_Transform(const matrix4x4_t *in, const float v[3], float out[3])
Definition matrixlib.c:1657
float mod_md3_sin[320]
Definition model_alias.c:42
unsigned char diffusergb[3]
unsigned char ambientrgb[3]
unsigned char diffuseyaw
unsigned char diffusepitch

References a, q3dlightgrid_t::ambientrgb, bound, q3dlightgrid_t::diffusepitch, q3dlightgrid_t::diffusergb, q3dlightgrid_t::diffuseyaw, floor(), i, index, int(), Matrix4x4_Transform(), mod_md3_sin, model, VectorClear, VectorMA, and VectorNormalize.

Referenced by Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_Q3BSP_Load()

static void Mod_Q3BSP_Load ( model_t * mod,
void * buffer,
void * bufferend )
static

Definition at line 7621 of file model_brush.c.

7622{
7623 int i, j, lumps;
7624 q3dheader_t *header;
7625 float corner[3], yawradius, modelradius;
7626
7627 mod->modeldatatypestring = "Q3BSP";
7628
7629 mod->type = mod_brushq3;
7630 mod->brush.ishlbsp = false;
7631 mod->brush.isbsp2rmqe = false;
7632 mod->brush.isbsp2 = false;
7633 mod->brush.isq2bsp = false;
7634 mod->brush.isq3bsp = true;
7635 mod->brush.skymasking = true;
7636 mod->numframes = 2; // although alternate textures are not supported it is annoying to complain about no such frame 1
7637 mod->numskins = 1;
7638
7639 header = (q3dheader_t *)buffer;
7640 if((char *) bufferend < (char *) buffer + sizeof(q3dheader_t))
7641 Host_Error("Mod_Q3BSP_Load: %s is smaller than its header", mod->name);
7642
7643 i = LittleLong(header->version);
7645 Host_Error("Mod_Q3BSP_Load: %s has wrong version number (%i, should be %i)", mod->name, i, Q3BSPVERSION);
7646
7647 mod->soundfromcenter = true;
7648 mod->TraceBox = Mod_CollisionBIH_TraceBox;
7649 mod->TraceBrush = Mod_CollisionBIH_TraceBrush;
7650 mod->TraceLine = Mod_CollisionBIH_TraceLine;
7651 mod->TracePoint = Mod_CollisionBIH_TracePoint;
7652 mod->PointSuperContents = Mod_CollisionBIH_PointSuperContents;
7653 mod->TraceLineAgainstSurfaces = Mod_CollisionBIH_TraceLine;
7654 mod->brush.TraceLineOfSight = Mod_Q3BSP_TraceLineOfSight;
7655 mod->brush.SuperContentsFromNativeContents = Mod_Q3BSP_SuperContentsFromNativeContents;
7656 mod->brush.NativeContentsFromSuperContents = Mod_Q3BSP_NativeContentsFromSuperContents;
7657 mod->brush.GetPVS = Mod_BSP_GetPVS;
7658 mod->brush.FatPVS = Mod_BSP_FatPVS;
7659 mod->brush.BoxTouchingPVS = Mod_BSP_BoxTouchingPVS;
7660 mod->brush.BoxTouchingLeafPVS = Mod_BSP_BoxTouchingLeafPVS;
7661 mod->brush.BoxTouchingVisibleLeafs = Mod_BSP_BoxTouchingVisibleLeafs;
7662 mod->brush.FindBoxClusters = Mod_BSP_FindBoxClusters;
7663 mod->brush.LightPoint = Mod_Q3BSP_LightPoint;
7664 mod->brush.FindNonSolidLocation = Mod_BSP_FindNonSolidLocation;
7665 mod->brush.AmbientSoundLevelsForPoint = NULL;
7666 mod->brush.RoundUpToHullSize = NULL;
7667 mod->brush.PointInLeaf = Mod_BSP_PointInLeaf;
7668 mod->Draw = R_Mod_Draw;
7669 mod->DrawDepth = R_Mod_DrawDepth;
7670 mod->DrawDebug = R_Mod_DrawDebug;
7671 mod->DrawPrepass = R_Mod_DrawPrepass;
7672 mod->GetLightInfo = R_Mod_GetLightInfo;
7673 mod->CompileShadowMap = R_Mod_CompileShadowMap;
7674 mod->DrawShadowMap = R_Mod_DrawShadowMap;
7675 mod->DrawLight = R_Mod_DrawLight;
7676
7677 mod_base = (unsigned char *)header;
7678
7679 // swap all the lumps
7680 header->ident = LittleLong(header->ident);
7681 header->version = LittleLong(header->version);
7683 for (i = 0;i < lumps;i++)
7684 {
7685 j = (header->lumps[i].fileofs = LittleLong(header->lumps[i].fileofs));
7686 if((char *) bufferend < (char *) buffer + j)
7687 Host_Error("Mod_Q3BSP_Load: %s has a lump that starts outside the file!", mod->name);
7688 j += (header->lumps[i].filelen = LittleLong(header->lumps[i].filelen));
7689 if((char *) bufferend < (char *) buffer + j)
7690 Host_Error("Mod_Q3BSP_Load: %s has a lump that ends outside the file!", mod->name);
7691 }
7692 /*
7693 * NO, do NOT clear them!
7694 * they contain actual data referenced by other stuff.
7695 * Instead, before using the advertisements lump, check header->versio
7696 * again!
7697 * Sorry, but otherwise it breaks memory of the first lump.
7698 for (i = lumps;i < Q3HEADER_LUMPS_MAX;i++)
7699 {
7700 header->lumps[i].fileofs = 0;
7701 header->lumps[i].filelen = 0;
7702 }
7703 */
7704
7705 mod->brush.qw_md4sum = 0;
7706 mod->brush.qw_md4sum2 = 0;
7707 for (i = 0;i < lumps;i++)
7708 {
7709 if (i == Q3LUMP_ENTITIES)
7710 continue;
7711 mod->brush.qw_md4sum ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, header->lumps[i].filelen);
7712 if (i == Q3LUMP_PVS || i == Q3LUMP_LEAFS || i == Q3LUMP_NODES)
7713 continue;
7714 mod->brush.qw_md4sum2 ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, header->lumps[i].filelen);
7715
7716 // all this checksumming can take a while, so let's send keepalives here too
7717 CL_KeepaliveMessage(false);
7718 }
7719
7720 // allocate a texture pool if we need it
7721 if (mod->texturepool == NULL)
7722 mod->texturepool = R_AllocTexturePool();
7723
7727 if (header->version == Q3BSPVERSION_IG)
7729 else
7745
7746 // the MakePortals code works fine on the q3bsp data as well
7749
7750 // FIXME: shader alpha should replace r_wateralpha support in q3bsp
7752
7755
7758
7759 mod = loadmodel;
7760 mod->modelsurfaces_sorted = (int*)Mem_Alloc(loadmodel->mempool, mod->num_surfaces * sizeof(*mod->modelsurfaces_sorted));
7761 for (i = 0;i < loadmodel->brush.numsubmodels;i++)
7762 {
7763 if (i > 0)
7764 {
7765 char name[10];
7766 // duplicate the basic information
7767 dpsnprintf(name, sizeof(name), "*%i", i);
7769 // copy the base model to this one
7770 *mod = *loadmodel;
7771 // rename the clone back to its proper name
7772 dp_strlcpy(mod->name, name, sizeof(mod->name));
7773 mod->brush.parentmodel = loadmodel;
7774 // textures and memory belong to the main model
7775 mod->texturepool = NULL;
7776 mod->mempool = NULL;
7777 mod->brush.GetPVS = NULL;
7778 mod->brush.FatPVS = NULL;
7779 mod->brush.BoxTouchingPVS = NULL;
7780 mod->brush.BoxTouchingLeafPVS = NULL;
7781 mod->brush.BoxTouchingVisibleLeafs = NULL;
7782 mod->brush.FindBoxClusters = NULL;
7783 mod->brush.LightPoint = NULL;
7784 mod->brush.AmbientSoundLevelsForPoint = NULL;
7785 }
7786 mod->brush.submodel = i;
7789
7790 // make the model surface list (used by shadowing/lighting)
7791 mod->submodelsurfaces_start = mod->brushq3.data_models[i].firstface;
7792 mod->submodelsurfaces_end = mod->brushq3.data_models[i].firstface + mod->brushq3.data_models[i].numfaces;
7793 mod->firstmodelbrush = mod->brushq3.data_models[i].firstbrush;
7794 mod->nummodelbrushes = mod->brushq3.data_models[i].numbrushes;
7795
7796 VectorCopy(mod->brushq3.data_models[i].mins, mod->normalmins);
7797 VectorCopy(mod->brushq3.data_models[i].maxs, mod->normalmaxs);
7798 // enlarge the bounding box to enclose all geometry of this model,
7799 // because q3map2 sometimes lies (mostly to affect the lightgrid),
7800 // which can in turn mess up the farclip (as well as culling when
7801 // outside the level - an unimportant concern)
7802
7803 //printf("Editing model %d... BEFORE re-bounding: %f %f %f - %f %f %f\n", i, mod->normalmins[0], mod->normalmins[1], mod->normalmins[2], mod->normalmaxs[0], mod->normalmaxs[1], mod->normalmaxs[2]);
7804 for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
7805 {
7806 const msurface_t *surface = mod->data_surfaces + j;
7807 const float *v = mod->surfmesh.data_vertex3f + 3 * surface->num_firstvertex;
7808 int k;
7809 if (!surface->num_vertices)
7810 continue;
7811 for (k = 0;k < surface->num_vertices;k++, v += 3)
7812 {
7813 mod->normalmins[0] = min(mod->normalmins[0], v[0]);
7814 mod->normalmins[1] = min(mod->normalmins[1], v[1]);
7815 mod->normalmins[2] = min(mod->normalmins[2], v[2]);
7816 mod->normalmaxs[0] = max(mod->normalmaxs[0], v[0]);
7817 mod->normalmaxs[1] = max(mod->normalmaxs[1], v[1]);
7818 mod->normalmaxs[2] = max(mod->normalmaxs[2], v[2]);
7819 }
7820 }
7821 //printf("Editing model %d... AFTER re-bounding: %f %f %f - %f %f %f\n", i, mod->normalmins[0], mod->normalmins[1], mod->normalmins[2], mod->normalmaxs[0], mod->normalmaxs[1], mod->normalmaxs[2]);
7822 corner[0] = max(fabs(mod->normalmins[0]), fabs(mod->normalmaxs[0]));
7823 corner[1] = max(fabs(mod->normalmins[1]), fabs(mod->normalmaxs[1]));
7824 corner[2] = max(fabs(mod->normalmins[2]), fabs(mod->normalmaxs[2]));
7825 modelradius = sqrt(corner[0]*corner[0]+corner[1]*corner[1]+corner[2]*corner[2]);
7826 yawradius = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
7827 mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius;
7828 mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
7829 mod->yawmaxs[0] = mod->yawmaxs[1] = yawradius;
7830 mod->yawmins[0] = mod->yawmins[1] = -yawradius;
7831 mod->yawmins[2] = mod->normalmins[2];
7832 mod->yawmaxs[2] = mod->normalmaxs[2];
7833 mod->radius = modelradius;
7834 mod->radius2 = modelradius * modelradius;
7835
7837 Mod_MakeCollisionBIH(mod, false, &mod->collision_bih);
7838 Mod_MakeCollisionBIH(mod, true, &mod->render_bih);
7839
7840 // generate VBOs and other shared data before cloning submodels
7841 if (i == 0)
7842 Mod_BuildVBOs();
7843 }
7844 mod = loadmodel;
7845
7846 // make the model surface list (used by shadowing/lighting)
7848
7850 {
7852 {
7853 // actually we do in sRGB fallback with sRGB lightmaps: Image_sRGBFloatFromLinear_Lightmap(Image_LinearFloatFromsRGBFloat(x))
7854 // neutral point is at Image_sRGBFloatFromLinearFloat(0.5)
7855 // so we need to map Image_sRGBFloatFromLinearFloat(0.5) to 0.5
7856 // factor is 0.5 / Image_sRGBFloatFromLinearFloat(0.5)
7857 //loadmodel->lightmapscale *= 0.679942f; // fixes neutral level
7858 }
7859 else // if this is NOT set, regular rendering looks right by this requirement anyway
7860 {
7861 /*
7862 // we want color 1 to do the same as without sRGB
7863 // so, we want to map 1 to Image_LinearFloatFromsRGBFloat(2) instead of to 2
7864 loadmodel->lightmapscale *= 2.476923f; // fixes max level
7865 */
7866
7867 // neutral level 0.5 gets uploaded as sRGB and becomes Image_LinearFloatFromsRGBFloat(0.5)
7868 // we need to undo that
7869 loadmodel->lightmapscale *= 2.336f; // fixes neutral level
7870 }
7871 }
7872
7873 Con_DPrintf("Stats for q3bsp model \"%s\": %i faces, %i nodes, %i leafs, %i clusters, %i clusterportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces);
7874}
static void Mod_Q3BSP_LoadLeafs(lump_t *l)
static void Mod_Q3BSP_LoadPlanes(lump_t *l)
static void Mod_Q3BSP_RecursiveFindNumLeafs(mnode_t *node)
static void Mod_Q3BSP_LoadLightGrid(lump_t *l)
static void Mod_Q3BSP_LoadLightmaps(lump_t *l, lump_t *faceslump)
static int Mod_Q3BSP_SuperContentsFromNativeContents(int nativecontents)
static void Mod_Q3BSP_LoadTextures(lump_t *l)
static void Mod_Q3BSP_LoadEntities(lump_t *l)
static void Mod_Q3BSP_LoadLeafBrushes(lump_t *l)
static void Mod_Q3BSP_LoadBrushes(lump_t *l)
static void Mod_Q3BSP_LoadModels(lump_t *l)
static void Mod_Q3BSP_LoadBrushSides_IG(lump_t *l)
static void Mod_Q3BSP_LoadTriangles(lump_t *l)
static int Mod_Q3BSP_NativeContentsFromSuperContents(int supercontents)
static void Mod_Q3BSP_LoadEffects(lump_t *l)
static void Mod_Q3BSP_LoadBrushSides(lump_t *l)
static void Mod_Q3BSP_LoadVertices(lump_t *l)
static void Mod_Q3BSP_LoadLeafFaces(lump_t *l)
static void Mod_Q3BSP_LoadFaces(lump_t *l)
static void Mod_Q3BSP_LoadNodes(lump_t *l)
static void Mod_Q3BSP_LoadPVS(lump_t *l)
static void Mod_Q3BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
#define Q3LUMP_BRUSHSIDES
Definition model_q3bsp.h:24
#define Q3LUMP_TEXTURES
Definition model_q3bsp.h:16
#define Q3LUMP_LIGHTGRID
Definition model_q3bsp.h:30
#define Q3LUMP_PLANES
Definition model_q3bsp.h:17
#define Q3LUMP_TRIANGLES
Definition model_q3bsp.h:26
#define Q3HEADER_LUMPS_LIVE
Definition model_q3bsp.h:34
#define Q3LUMP_MODELS
Definition model_q3bsp.h:22
#define Q3LUMP_PVS
Definition model_q3bsp.h:31
#define Q3LUMP_NODES
Definition model_q3bsp.h:18
#define Q3LUMP_LEAFFACES
Definition model_q3bsp.h:20
#define Q3LUMP_FACES
Definition model_q3bsp.h:28
#define Q3LUMP_ENTITIES
Definition model_q3bsp.h:15
#define Q3LUMP_VERTICES
Definition model_q3bsp.h:25
#define Q3LUMP_BRUSHES
Definition model_q3bsp.h:23
#define Q3LUMP_LEAFS
Definition model_q3bsp.h:19
#define Q3LUMP_LIGHTMAPS
Definition model_q3bsp.h:29
#define Q3LUMP_EFFECTS
Definition model_q3bsp.h:27
#define Q3LUMP_LEAFBRUSHES
Definition model_q3bsp.h:21
#define Q3HEADER_LUMPS
Definition model_q3bsp.h:32
unsigned char * mod_base
@ mod_brushq3
int fileofs
Definition bspfile.h:36
int filelen
Definition bspfile.h:36
float lightmapscale
lump_t lumps[Q3HEADER_LUMPS_MAX]
Definition model_q3bsp.h:41
cvar_t vid_sRGB_fallback
Definition vid_shared.c:158
cvar_t vid_sRGB
Definition vid_shared.c:157

References model_t::brush, model_t::brushq3, buffer, ca_dedicated, CL_KeepaliveMessage(), cls, Com_BlockChecksum(), Con_DPrintf(), model_brush_t::data_nodes, dp_strlcpy, dpsnprintf(), fabs(), lump_t::filelen, lump_t::fileofs, Host_Error(), i, q3dheader_t::ident, cvar_t::integer, model_t::lightmapscale, LittleLong, loadmodel, q3dheader_t::lumps, max, Mem_Alloc, model_t::mempool, min, mod(), mod_base, mod_brushq3, Mod_BSP_BoxTouchingLeafPVS(), Mod_BSP_BoxTouchingPVS(), Mod_BSP_BoxTouchingVisibleLeafs(), Mod_BSP_FatPVS(), Mod_BSP_FindBoxClusters(), Mod_BSP_FindNonSolidLocation(), Mod_BSP_GetPVS(), Mod_BSP_MakePortals(), Mod_BSP_PointInLeaf(), mod_bsp_portalize, Mod_BuildVBOs(), Mod_CollisionBIH_PointSuperContents(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint(), Mod_FindName(), Mod_MakeCollisionBIH(), Mod_MakeSortedSurfaces(), Mod_Q3BSP_LightPoint(), Mod_Q3BSP_LoadBrushes(), Mod_Q3BSP_LoadBrushSides(), Mod_Q3BSP_LoadBrushSides_IG(), Mod_Q3BSP_LoadEffects(), Mod_Q3BSP_LoadEntities(), Mod_Q3BSP_LoadFaces(), Mod_Q3BSP_LoadLeafBrushes(), Mod_Q3BSP_LoadLeafFaces(), Mod_Q3BSP_LoadLeafs(), Mod_Q3BSP_LoadLightGrid(), Mod_Q3BSP_LoadLightmaps(), Mod_Q3BSP_LoadModels(), Mod_Q3BSP_LoadNodes(), Mod_Q3BSP_LoadPlanes(), Mod_Q3BSP_LoadPVS(), Mod_Q3BSP_LoadTextures(), Mod_Q3BSP_LoadTriangles(), Mod_Q3BSP_LoadVertices(), Mod_Q3BSP_NativeContentsFromSuperContents(), Mod_Q3BSP_RecursiveFindNumLeafs(), mod_q3bsp_sRGBlightmaps, Mod_Q3BSP_SuperContentsFromNativeContents(), Mod_Q3BSP_TraceLineOfSight(), Mod_SetDrawSkyAndWater(), model_t::name, name, NULL, msurface_t::num_firstvertex, model_brush_t::num_leafs, model_brushq3_t::num_models, model_brush_t::num_nodes, model_brush_t::num_portals, model_t::num_surfaces, surfmesh_t::num_triangles, msurface_t::num_vertices, surfmesh_t::num_vertices, model_brush_t::numsubmodels, Q3BSPVERSION, Q3BSPVERSION_IG, Q3BSPVERSION_LIVE, Q3HEADER_LUMPS, Q3HEADER_LUMPS_LIVE, Q3LUMP_BRUSHES, Q3LUMP_BRUSHSIDES, Q3LUMP_EFFECTS, Q3LUMP_ENTITIES, Q3LUMP_FACES, Q3LUMP_LEAFBRUSHES, Q3LUMP_LEAFFACES, Q3LUMP_LEAFS, Q3LUMP_LIGHTGRID, Q3LUMP_LIGHTMAPS, Q3LUMP_MODELS, Q3LUMP_NODES, Q3LUMP_PLANES, Q3LUMP_PVS, Q3LUMP_TEXTURES, Q3LUMP_TRIANGLES, Q3LUMP_VERTICES, R_AllocTexturePool(), R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), R_Mod_GetLightInfo(), sqrt(), viddef_t::sRGB3D, client_static_t::state, model_brush_t::submodels, model_brush_t::supportwateralpha, model_t::surfmesh, v, VectorCopy, q3dheader_t::version, vid, vid_sRGB, and vid_sRGB_fallback.

Referenced by Mod_IBSP_Load().

◆ Mod_Q3BSP_LoadBrushes()

static void Mod_Q3BSP_LoadBrushes ( lump_t * l)
static

Definition at line 5326 of file model_brush.c.

5327{
5328 q3dbrush_t *in;
5329 q3mbrush_t *out;
5330 int i, j, n, c, count, maxplanes, q3surfaceflags;
5331 colplanef_t *planes;
5332
5333 in = (q3dbrush_t *)(mod_base + l->fileofs);
5334 if (l->filelen % sizeof(*in))
5335 Host_Error("Mod_Q3BSP_LoadBrushes: funny lump size in %s",loadmodel->name);
5336 count = l->filelen / sizeof(*in);
5337 out = (q3mbrush_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
5338
5341
5342 maxplanes = 0;
5343 planes = NULL;
5344
5345 for (i = 0;i < count;i++, in++, out++)
5346 {
5347 n = LittleLong(in->firstbrushside);
5348 c = LittleLong(in->numbrushsides);
5350 Host_Error("Mod_Q3BSP_LoadBrushes: invalid brushside range %i : %i (%i brushsides)", n, n + c, loadmodel->brush.num_brushsides);
5352 out->numbrushsides = c;
5353 n = LittleLong(in->textureindex);
5355 Host_Error("Mod_Q3BSP_LoadBrushes: invalid textureindex %i (%i textures)", n, loadmodel->num_textures);
5356 out->texture = loadmodel->data_textures + n;
5357
5358 // make a list of mplane_t structs to construct a colbrush from
5359 if (maxplanes < out->numbrushsides)
5360 {
5361 maxplanes = out->numbrushsides;
5362 if (planes)
5363 Mem_Free(planes);
5364 planes = (colplanef_t *)Mem_Alloc(tempmempool, sizeof(colplanef_t) * maxplanes);
5365 }
5366 q3surfaceflags = 0;
5367 for (j = 0;j < out->numbrushsides;j++)
5368 {
5369 VectorCopy(out->firstbrushside[j].plane->normal, planes[j].normal);
5370 planes[j].dist = out->firstbrushside[j].plane->dist;
5371 planes[j].q3surfaceflags = out->firstbrushside[j].texture->surfaceflags;
5372 planes[j].texture = out->firstbrushside[j].texture;
5373 q3surfaceflags |= planes[j].q3surfaceflags;
5374 }
5375 // make the colbrush from the planes
5376 out->colbrushf = Collision_NewBrushFromPlanes(loadmodel->mempool, out->numbrushsides, planes, out->texture->supercontents, q3surfaceflags, out->texture, true);
5377
5378 // this whole loop can take a while (e.g. on redstarrepublic4)
5379 CL_KeepaliveMessage(false);
5380 }
5381 if (planes)
5382 Mem_Free(planes);
5383}

References model_t::brush, CL_KeepaliveMessage(), q3mbrush_t::colbrushf, Collision_NewBrushFromPlanes(), count, model_brush_t::data_brushes, model_brush_t::data_brushsides, model_t::data_textures, colplanef_t::dist, lump_t::filelen, lump_t::fileofs, q3dbrush_t::firstbrushside, q3mbrush_t::firstbrushside, Host_Error(), i, LittleLong, loadmodel, Mem_Alloc, Mem_Free, model_t::mempool, mod_base, n, model_t::name, colplanef_t::normal, NULL, model_brush_t::num_brushes, model_brush_t::num_brushsides, model_t::num_textures, q3dbrush_t::numbrushsides, q3mbrush_t::numbrushsides, colplanef_t::q3surfaceflags, tempmempool, colplanef_t::texture, q3mbrush_t::texture, q3dbrush_t::textureindex, and VectorCopy.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadBrushSides()

static void Mod_Q3BSP_LoadBrushSides ( lump_t * l)
static

Definition at line 5270 of file model_brush.c.

5271{
5272 q3dbrushside_t *in;
5273 q3mbrushside_t *out;
5274 int i, n, count;
5275
5276 in = (q3dbrushside_t *)(mod_base + l->fileofs);
5277 if (l->filelen % sizeof(*in))
5278 Host_Error("Mod_Q3BSP_LoadBrushSides: funny lump size in %s",loadmodel->name);
5279 count = l->filelen / sizeof(*in);
5280 out = (q3mbrushside_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
5281
5284
5285 for (i = 0;i < count;i++, in++, out++)
5286 {
5287 n = LittleLong(in->planeindex);
5289 Host_Error("Mod_Q3BSP_LoadBrushSides: invalid planeindex %i (%i planes)", n, loadmodel->brush.num_planes);
5290 out->plane = loadmodel->brush.data_planes + n;
5291 n = LittleLong(in->textureindex);
5293 Host_Error("Mod_Q3BSP_LoadBrushSides: invalid textureindex %i (%i textures)", n, loadmodel->num_textures);
5294 out->texture = loadmodel->data_textures + n;
5295 }
5296}

References model_t::brush, count, model_brush_t::data_brushsides, model_brush_t::data_planes, model_t::data_textures, lump_t::filelen, lump_t::fileofs, Host_Error(), i, LittleLong, loadmodel, Mem_Alloc, model_t::mempool, mod_base, n, model_t::name, model_brush_t::num_brushsides, model_brush_t::num_planes, model_t::num_textures, q3mbrushside_t::plane, q3dbrushside_t::planeindex, q3mbrushside_t::texture, and q3dbrushside_t::textureindex.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadBrushSides_IG()

static void Mod_Q3BSP_LoadBrushSides_IG ( lump_t * l)
static

Definition at line 5298 of file model_brush.c.

5299{
5301 q3mbrushside_t *out;
5302 int i, n, count;
5303
5304 in = (q3dbrushside_ig_t *)(mod_base + l->fileofs);
5305 if (l->filelen % sizeof(*in))
5306 Host_Error("Mod_Q3BSP_LoadBrushSides: funny lump size in %s",loadmodel->name);
5307 count = l->filelen / sizeof(*in);
5308 out = (q3mbrushside_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
5309
5312
5313 for (i = 0;i < count;i++, in++, out++)
5314 {
5315 n = LittleLong(in->planeindex);
5317 Host_Error("Mod_Q3BSP_LoadBrushSides: invalid planeindex %i (%i planes)", n, loadmodel->brush.num_planes);
5318 out->plane = loadmodel->brush.data_planes + n;
5319 n = LittleLong(in->textureindex);
5321 Host_Error("Mod_Q3BSP_LoadBrushSides: invalid textureindex %i (%i textures)", n, loadmodel->num_textures);
5322 out->texture = loadmodel->data_textures + n;
5323 }
5324}

References model_t::brush, count, model_brush_t::data_brushsides, model_brush_t::data_planes, model_t::data_textures, lump_t::filelen, lump_t::fileofs, Host_Error(), i, LittleLong, loadmodel, Mem_Alloc, model_t::mempool, mod_base, n, model_t::name, model_brush_t::num_brushsides, model_brush_t::num_planes, model_t::num_textures, q3mbrushside_t::plane, q3dbrushside_ig_t::planeindex, q3mbrushside_t::texture, and q3dbrushside_ig_t::textureindex.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadEffects()

static void Mod_Q3BSP_LoadEffects ( lump_t * l)
static

Definition at line 5385 of file model_brush.c.

5386{
5387 q3deffect_t *in;
5388 q3deffect_t *out;
5389 int i, n, count;
5390
5391 in = (q3deffect_t *)(mod_base + l->fileofs);
5392 if (l->filelen % sizeof(*in))
5393 Host_Error("Mod_Q3BSP_LoadEffects: funny lump size in %s",loadmodel->name);
5394 count = l->filelen / sizeof(*in);
5395 out = (q3deffect_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
5396
5399
5400 for (i = 0;i < count;i++, in++, out++)
5401 {
5402 dp_strlcpy (out->shadername, in->shadername, sizeof (out->shadername));
5403 n = LittleLong(in->brushindex);
5404 if (n >= loadmodel->brush.num_brushes)
5405 {
5406 Con_Printf("Mod_Q3BSP_LoadEffects: invalid brushindex %i (%i brushes), setting to -1\n", n, loadmodel->brush.num_brushes);
5407 n = -1;
5408 }
5409 out->brushindex = n;
5410 out->unknown = LittleLong(in->unknown);
5411 }
5412}
q3deffect_t * data_effects
char shadername[Q3PATHLENGTH]

References model_t::brush, q3deffect_t::brushindex, model_t::brushq3, Con_Printf(), count, model_brushq3_t::data_effects, dp_strlcpy, lump_t::filelen, lump_t::fileofs, Host_Error(), i, LittleLong, loadmodel, Mem_Alloc, model_t::mempool, mod_base, n, model_t::name, model_brush_t::num_brushes, model_brushq3_t::num_effects, q3deffect_t::shadername, and q3deffect_t::unknown.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadEntities()

static void Mod_Q3BSP_LoadEntities ( lump_t * l)
static

Definition at line 5151 of file model_brush.c.

5152{
5153 const char *data;
5154 char key[128], value[MAX_INPUTLINE];
5155 float v[3];
5159 if (!l->filelen)
5160 return;
5162 memcpy(loadmodel->brush.entities, mod_base + l->fileofs, l->filelen);
5165 // some Q3 maps override the lightgrid_cellsize with a worldspawn key
5166 // VorteX: q3map2 FS-R generates tangentspace deluxemaps for q3bsp and sets 'deluxeMaps' key
5168 if (data && COM_ParseToken_Simple(&data, false, false, true) && com_token[0] == '{')
5169 {
5170 while (1)
5171 {
5172 if (!COM_ParseToken_Simple(&data, false, false, true))
5173 break; // error
5174 if (com_token[0] == '}')
5175 break; // end of worldspawn
5176 if (com_token[0] == '_')
5177 dp_strlcpy(key, com_token + 1, sizeof(key));
5178 else
5179 dp_strlcpy(key, com_token, sizeof(key));
5180 while (key[strlen(key)-1] == ' ') // remove trailing spaces
5181 key[strlen(key)-1] = 0;
5182 if (!COM_ParseToken_Simple(&data, false, false, true))
5183 break; // error
5184 dp_strlcpy(value, com_token, sizeof(value));
5185 if (!strcasecmp("gridsize", key)) // this one is case insensitive to 100% match q3map2
5186 {
5187#if _MSC_VER >= 1400
5188#define sscanf sscanf_s
5189#endif
5190#if 0
5191 if (sscanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3 && v[0] != 0 && v[1] != 0 && v[2] != 0)
5193#else
5194 VectorSet(v, 64, 64, 128);
5195 if(sscanf(value, "%f %f %f", &v[0], &v[1], &v[2]) != 3)
5196 Con_Printf("Mod_Q3BSP_LoadEntities: funny gridsize \"%s\" in %s, interpreting as \"%f %f %f\" to match q3map2's parsing\n", value, loadmodel->name, v[0], v[1], v[2]);
5197 if (v[0] != 0 && v[1] != 0 && v[2] != 0)
5199#endif
5200 }
5201 else if (!strcmp("deluxeMaps", key))
5202 {
5203 if (!strcmp(com_token, "1"))
5204 {
5207 }
5208 else if (!strcmp(com_token, "2"))
5209 {
5212 }
5213 }
5214 }
5215 }
5216}
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
Definition qdefs.h:94
float num_lightgrid_cellsize[3]

References model_t::brush, model_t::brushq3, COM_ParseToken_Simple(), com_token, Con_Printf(), data, model_brushq3_t::deluxemapping, model_brushq3_t::deluxemapping_modelspace, dp_strlcpy, model_brush_t::entities, lump_t::filelen, lump_t::fileofs, loadmodel, MAX_INPUTLINE, Mem_Alloc, model_t::mempool, mod_base, model_t::name, model_brushq3_t::num_lightgrid_cellsize, strlen(), v, value, VectorCopy, and VectorSet.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadFaces()

static void Mod_Q3BSP_LoadFaces ( lump_t * l)
static

Definition at line 5806 of file model_brush.c.

5807{
5808 q3dface_t *in, *oldin;
5809 msurface_t *out, *oldout;
5810 int i, oldi, j, n, count, invalidelements, patchsize[2], finalwidth, finalheight, xtess, ytess, finalvertices, finaltriangles, firstvertex, firstelement, type, oldnumtriangles, oldnumtriangles2, meshvertices, meshtriangles, collisionvertices, collisiontriangles, numvertices, numtriangles, cxtess, cytess;
5811 float lightmaptcbase[2], lightmaptcscale[2];
5812 //int *originalelement3i;
5813 float *originalvertex3f;
5814 //float *originalsvector3f;
5815 //float *originaltvector3f;
5816 float *originalnormal3f;
5817 float *originalcolor4f;
5818 float *originaltexcoordtexture2f;
5819 float *originaltexcoordlightmap2f;
5820 float *surfacecollisionvertex3f;
5821 int *surfacecollisionelement3i;
5822 float *v;
5823 patchtess_t *patchtess = NULL;
5824 int patchtesscount = 0;
5825 qbool again;
5826
5827 in = (q3dface_t *)(mod_base + l->fileofs);
5828 if (l->filelen % sizeof(*in))
5829 Host_Error("Mod_Q3BSP_LoadFaces: funny lump size in %s",loadmodel->name);
5830 count = l->filelen / sizeof(*in);
5831 out = (msurface_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
5832
5833 loadmodel->data_surfaces = out;
5835
5836 if(count > 0)
5837 patchtess = (patchtess_t*) Mem_Alloc(tempmempool, count * sizeof(*patchtess));
5838
5839 i = 0;
5840 oldi = i;
5841 oldin = in;
5842 oldout = out;
5843 meshvertices = 0;
5844 meshtriangles = 0;
5845 for (;i < count;i++, in++, out++)
5846 {
5847 // check face type first
5848 type = LittleLong(in->type);
5849 if (type != Q3FACETYPE_FLAT
5851 && type != Q3FACETYPE_MESH
5852 && type != Q3FACETYPE_FLARE)
5853 {
5854 Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: unknown face type %i\n", i, type);
5855 continue;
5856 }
5857
5858 n = LittleLong(in->textureindex);
5860 {
5861 Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: invalid textureindex %i (%i textures)\n", i, n, loadmodel->num_textures);
5862 continue;
5863 }
5864 out->texture = loadmodel->data_textures + n;
5865 n = LittleLong(in->effectindex);
5867 {
5869 Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid effectindex %i (%i effects)\n", i, out->texture->name, n, loadmodel->brushq3.num_effects);
5870 n = -1;
5871 }
5872 if (n == -1)
5873 out->effect = NULL;
5874 else
5876
5877 if (cls.state != ca_dedicated)
5878 {
5879 out->lightmaptexture = NULL;
5881 n = LittleLong(in->lightmapindex);
5882 if (n < 0)
5883 n = -1;
5885 {
5887 Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid lightmapindex %i (%i lightmaps)\n", i, out->texture->name, n, loadmodel->brushq3.num_originallightmaps);
5888 n = -1;
5889 }
5890 else
5891 {
5895 loadmodel->lit = true;
5896 }
5897 }
5898
5899 firstvertex = LittleLong(in->firstvertex);
5900 numvertices = LittleLong(in->numvertices);
5901 firstelement = LittleLong(in->firstelement);
5902 numtriangles = LittleLong(in->numelements) / 3;
5903 if (numtriangles * 3 != LittleLong(in->numelements))
5904 {
5905 Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): numelements %i is not a multiple of 3\n", i, out->texture->name, LittleLong(in->numelements));
5906 continue;
5907 }
5908 if (firstvertex < 0 || firstvertex + numvertices > loadmodel->brushq3.num_vertices)
5909 {
5910 Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid vertex range %i : %i (%i vertices)\n", i, out->texture->name, firstvertex, firstvertex + numvertices, loadmodel->brushq3.num_vertices);
5911 continue;
5912 }
5913 if (firstelement < 0 || firstelement + numtriangles * 3 > loadmodel->brushq3.num_triangles * 3)
5914 {
5915 Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid element range %i : %i (%i elements)\n", i, out->texture->name, firstelement, firstelement + numtriangles * 3, loadmodel->brushq3.num_triangles * 3);
5916 continue;
5917 }
5918 switch(type)
5919 {
5920 case Q3FACETYPE_FLAT:
5921 case Q3FACETYPE_MESH:
5922 // no processing necessary
5923 break;
5924 case Q3FACETYPE_PATCH:
5925 patchsize[0] = LittleLong(in->specific.patch.patchsize[0]);
5926 patchsize[1] = LittleLong(in->specific.patch.patchsize[1]);
5927 if (numvertices != (patchsize[0] * patchsize[1]) || patchsize[0] < 3 || patchsize[1] < 3 || !(patchsize[0] & 1) || !(patchsize[1] & 1) || patchsize[0] * patchsize[1] >= (cls.state == ca_dedicated ? mod_q3bsp_curves_subdivisions_maxvertices.integer : min(r_subdivisions_maxvertices.integer, mod_q3bsp_curves_subdivisions_maxvertices.integer)))
5928 {
5929 Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid patchsize %ix%i\n", i, out->texture->name, patchsize[0], patchsize[1]);
5930 continue;
5931 }
5932 originalvertex3f = loadmodel->brushq3.data_vertex3f + firstvertex * 3;
5933
5934 // convert patch to Q3FACETYPE_MESH
5935 xtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
5936 ytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
5937 // bound to user settings
5940 // bound to sanity settings
5941 xtess = bound(0, xtess, 1024);
5942 ytess = bound(0, ytess, 1024);
5943
5944 // lower quality collision patches! Same procedure as before, but different cvars
5945 // convert patch to Q3FACETYPE_MESH
5946 cxtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, mod_q3bsp_curves_subdivisions_tolerance.value);
5947 cytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, mod_q3bsp_curves_subdivisions_tolerance.value);
5948 // bound to user settings
5951 // bound to sanity settings
5952 cxtess = bound(0, cxtess, 1024);
5953 cytess = bound(0, cytess, 1024);
5954
5955 // store it for the LOD grouping step
5956 patchtess[patchtesscount].info.xsize = patchsize[0];
5957 patchtess[patchtesscount].info.ysize = patchsize[1];
5958 patchtess[patchtesscount].info.lods[PATCH_LOD_VISUAL].xtess = xtess;
5959 patchtess[patchtesscount].info.lods[PATCH_LOD_VISUAL].ytess = ytess;
5960 patchtess[patchtesscount].info.lods[PATCH_LOD_COLLISION].xtess = cxtess;
5961 patchtess[patchtesscount].info.lods[PATCH_LOD_COLLISION].ytess = cytess;
5962
5963 patchtess[patchtesscount].surface_id = i;
5964 patchtess[patchtesscount].lodgroup[0] = LittleFloat(in->specific.patch.mins[0]);
5965 patchtess[patchtesscount].lodgroup[1] = LittleFloat(in->specific.patch.mins[1]);
5966 patchtess[patchtesscount].lodgroup[2] = LittleFloat(in->specific.patch.mins[2]);
5967 patchtess[patchtesscount].lodgroup[3] = LittleFloat(in->specific.patch.maxs[0]);
5968 patchtess[patchtesscount].lodgroup[4] = LittleFloat(in->specific.patch.maxs[1]);
5969 patchtess[patchtesscount].lodgroup[5] = LittleFloat(in->specific.patch.maxs[2]);
5970 patchtess[patchtesscount].originalvertex3f = originalvertex3f;
5971 ++patchtesscount;
5972 break;
5973 case Q3FACETYPE_FLARE:
5975 Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): Q3FACETYPE_FLARE not supported (yet)\n", i, out->texture->name);
5976 // don't render it
5977 continue;
5978 }
5979 out->num_vertices = numvertices;
5980 out->num_triangles = numtriangles;
5981 meshvertices += out->num_vertices;
5982 meshtriangles += out->num_triangles;
5983 }
5984
5985 // Fix patches tesselations so that they make no seams
5986 do
5987 {
5988 again = false;
5989 for(i = 0; i < patchtesscount; ++i)
5990 {
5991 for(j = i+1; j < patchtesscount; ++j)
5992 {
5993 if (!PATCHTESS_SAME_LODGROUP(patchtess[i], patchtess[j]))
5994 continue;
5995
5996 if (Q3PatchAdjustTesselation(3, &patchtess[i].info, patchtess[i].originalvertex3f, &patchtess[j].info, patchtess[j].originalvertex3f) )
5997 again = true;
5998 }
5999 }
6000 }
6001 while (again);
6002
6003 // Calculate resulting number of triangles
6004 collisionvertices = 0;
6005 collisiontriangles = 0;
6006 for(i = 0; i < patchtesscount; ++i)
6007 {
6008 finalwidth = Q3PatchDimForTess(patchtess[i].info.xsize, patchtess[i].info.lods[PATCH_LOD_VISUAL].xtess);
6009 finalheight = Q3PatchDimForTess(patchtess[i].info.ysize,patchtess[i].info.lods[PATCH_LOD_VISUAL].ytess);
6010 numvertices = finalwidth * finalheight;
6011 numtriangles = (finalwidth - 1) * (finalheight - 1) * 2;
6012
6013 oldout[patchtess[i].surface_id].num_vertices = numvertices;
6014 oldout[patchtess[i].surface_id].num_triangles = numtriangles;
6015 meshvertices += oldout[patchtess[i].surface_id].num_vertices;
6016 meshtriangles += oldout[patchtess[i].surface_id].num_triangles;
6017
6018 finalwidth = Q3PatchDimForTess(patchtess[i].info.xsize, patchtess[i].info.lods[PATCH_LOD_COLLISION].xtess);
6019 finalheight = Q3PatchDimForTess(patchtess[i].info.ysize,patchtess[i].info.lods[PATCH_LOD_COLLISION].ytess);
6020 numvertices = finalwidth * finalheight;
6021 numtriangles = (finalwidth - 1) * (finalheight - 1) * 2;
6022
6023 oldout[patchtess[i].surface_id].num_collisionvertices = numvertices;
6024 oldout[patchtess[i].surface_id].num_collisiontriangles = numtriangles;
6025 collisionvertices += oldout[patchtess[i].surface_id].num_collisionvertices;
6026 collisiontriangles += oldout[patchtess[i].surface_id].num_collisiontriangles;
6027 }
6028
6029 i = oldi;
6030 in = oldin;
6031 out = oldout;
6032 Mod_AllocSurfMesh(loadmodel->mempool, meshvertices, meshtriangles, false, true);
6033 if (collisiontriangles)
6034 {
6035 loadmodel->brush.data_collisionvertex3f = (float *)Mem_Alloc(loadmodel->mempool, collisionvertices * sizeof(float[3]));
6036 loadmodel->brush.data_collisionelement3i = (int *)Mem_Alloc(loadmodel->mempool, collisiontriangles * sizeof(int[3]));
6037 }
6038 meshvertices = 0;
6039 meshtriangles = 0;
6040 collisionvertices = 0;
6041 collisiontriangles = 0;
6042 for (;i < count && meshvertices + out->num_vertices <= loadmodel->surfmesh.num_vertices;i++, in++, out++)
6043 {
6044 if (out->num_vertices < 3 || out->num_triangles < 1)
6045 continue;
6046
6047 type = LittleLong(in->type);
6048 firstvertex = LittleLong(in->firstvertex);
6049 firstelement = LittleLong(in->firstelement);
6050 out->num_firstvertex = meshvertices;
6051 out->num_firsttriangle = meshtriangles;
6052 out->num_firstcollisiontriangle = collisiontriangles;
6053 switch(type)
6054 {
6055 case Q3FACETYPE_FLAT:
6056 case Q3FACETYPE_MESH:
6057 // no processing necessary, except for lightmap merging
6058 for (j = 0;j < out->num_vertices;j++)
6059 {
6060 (loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex)[j * 3 + 0] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 0];
6061 (loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex)[j * 3 + 1] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 1];
6062 (loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex)[j * 3 + 2] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 2];
6063 (loadmodel->surfmesh.data_normal3f + 3 * out->num_firstvertex)[j * 3 + 0] = loadmodel->brushq3.data_normal3f[(firstvertex + j) * 3 + 0];
6064 (loadmodel->surfmesh.data_normal3f + 3 * out->num_firstvertex)[j * 3 + 1] = loadmodel->brushq3.data_normal3f[(firstvertex + j) * 3 + 1];
6065 (loadmodel->surfmesh.data_normal3f + 3 * out->num_firstvertex)[j * 3 + 2] = loadmodel->brushq3.data_normal3f[(firstvertex + j) * 3 + 2];
6066 (loadmodel->surfmesh.data_texcoordtexture2f + 2 * out->num_firstvertex)[j * 2 + 0] = loadmodel->brushq3.data_texcoordtexture2f[(firstvertex + j) * 2 + 0];
6067 (loadmodel->surfmesh.data_texcoordtexture2f + 2 * out->num_firstvertex)[j * 2 + 1] = loadmodel->brushq3.data_texcoordtexture2f[(firstvertex + j) * 2 + 1];
6068 (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * out->num_firstvertex)[j * 2 + 0] = loadmodel->brushq3.data_texcoordlightmap2f[(firstvertex + j) * 2 + 0];
6069 (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * out->num_firstvertex)[j * 2 + 1] = loadmodel->brushq3.data_texcoordlightmap2f[(firstvertex + j) * 2 + 1];
6070 (loadmodel->surfmesh.data_lightmapcolor4f + 4 * out->num_firstvertex)[j * 4 + 0] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 0];
6071 (loadmodel->surfmesh.data_lightmapcolor4f + 4 * out->num_firstvertex)[j * 4 + 1] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 1];
6072 (loadmodel->surfmesh.data_lightmapcolor4f + 4 * out->num_firstvertex)[j * 4 + 2] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 2];
6073 (loadmodel->surfmesh.data_lightmapcolor4f + 4 * out->num_firstvertex)[j * 4 + 3] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 3];
6074 }
6075 for (j = 0;j < out->num_triangles*3;j++)
6077 break;
6078 case Q3FACETYPE_PATCH:
6079 patchsize[0] = LittleLong(in->specific.patch.patchsize[0]);
6080 patchsize[1] = LittleLong(in->specific.patch.patchsize[1]);
6081 originalvertex3f = loadmodel->brushq3.data_vertex3f + firstvertex * 3;
6082 originalnormal3f = loadmodel->brushq3.data_normal3f + firstvertex * 3;
6083 originaltexcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + firstvertex * 2;
6084 originaltexcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + firstvertex * 2;
6085 originalcolor4f = loadmodel->brushq3.data_color4f + firstvertex * 4;
6086
6087 xtess = ytess = cxtess = cytess = -1;
6088 for(j = 0; j < patchtesscount; ++j)
6089 if(patchtess[j].surface_id == i)
6090 {
6091 xtess = patchtess[j].info.lods[PATCH_LOD_VISUAL].xtess;
6092 ytess = patchtess[j].info.lods[PATCH_LOD_VISUAL].ytess;
6093 cxtess = patchtess[j].info.lods[PATCH_LOD_COLLISION].xtess;
6094 cytess = patchtess[j].info.lods[PATCH_LOD_COLLISION].ytess;
6095 break;
6096 }
6097 if(xtess == -1)
6098 {
6099 Con_Printf(CON_ERROR "ERROR: patch %d isn't preprocessed?!?\n", i);
6100 xtess = ytess = cxtess = cytess = 0;
6101 }
6102
6103 finalwidth = Q3PatchDimForTess(patchsize[0],xtess); //((patchsize[0] - 1) * xtess) + 1;
6104 finalheight = Q3PatchDimForTess(patchsize[1],ytess); //((patchsize[1] - 1) * ytess) + 1;
6105 finalvertices = finalwidth * finalheight;
6106 oldnumtriangles = finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2;
6108 // generate geometry
6109 // (note: normals are skipped because they get recalculated)
6110 Q3PatchTesselateFloat(3, sizeof(float[3]), (loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, xtess, ytess);
6111 Q3PatchTesselateFloat(3, sizeof(float[3]), (loadmodel->surfmesh.data_normal3f + 3 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[3]), originalnormal3f, xtess, ytess);
6112 Q3PatchTesselateFloat(2, sizeof(float[2]), (loadmodel->surfmesh.data_texcoordtexture2f + 2 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[2]), originaltexcoordtexture2f, xtess, ytess);
6113 Q3PatchTesselateFloat(2, sizeof(float[2]), (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[2]), originaltexcoordlightmap2f, xtess, ytess);
6114 Q3PatchTesselateFloat(4, sizeof(float[4]), (loadmodel->surfmesh.data_lightmapcolor4f + 4 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[4]), originalcolor4f, xtess, ytess);
6115 Q3PatchTriangleElements((loadmodel->surfmesh.data_element3i + 3 * out->num_firsttriangle), finalwidth, finalheight, out->num_firstvertex);
6116
6118
6120 {
6121 if (out->num_triangles < finaltriangles)
6122 Con_DPrintf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided to %i vertices / %i triangles, %i degenerate triangles removed (leaving %i)\n", patchsize[0], patchsize[1], out->num_vertices, finaltriangles, finaltriangles - out->num_triangles, out->num_triangles);
6123 else
6124 Con_DPrintf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided to %i vertices / %i triangles\n", patchsize[0], patchsize[1], out->num_vertices, out->num_triangles);
6125 }
6126 // q3map does not put in collision brushes for curves... ugh
6127 // build the lower quality collision geometry
6128 finalwidth = Q3PatchDimForTess(patchsize[0],cxtess); //((patchsize[0] - 1) * cxtess) + 1;
6129 finalheight = Q3PatchDimForTess(patchsize[1],cytess); //((patchsize[1] - 1) * cytess) + 1;
6130 finalvertices = finalwidth * finalheight;
6131 oldnumtriangles2 = finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2;
6132
6133 // store collision geometry for BIH collision tree
6134 out->num_collisionvertices = finalvertices;
6135 out->num_collisiontriangles = finaltriangles;
6136 surfacecollisionvertex3f = loadmodel->brush.data_collisionvertex3f + collisionvertices * 3;
6137 surfacecollisionelement3i = loadmodel->brush.data_collisionelement3i + collisiontriangles * 3;
6138 Q3PatchTesselateFloat(3, sizeof(float[3]), surfacecollisionvertex3f, patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, cxtess, cytess);
6139 Q3PatchTriangleElements(surfacecollisionelement3i, finalwidth, finalheight, collisionvertices);
6140 Mod_SnapVertices(3, finalvertices, surfacecollisionvertex3f, 1);
6141 out->num_collisiontriangles = Mod_RemoveDegenerateTriangles(finaltriangles, surfacecollisionelement3i, surfacecollisionelement3i, loadmodel->brush.data_collisionvertex3f);
6142
6144 Con_DPrintf("Mod_Q3BSP_LoadFaces: %ix%i curve became %i:%i vertices / %i:%i triangles (%i:%i degenerate)\n", patchsize[0], patchsize[1], out->num_vertices, out->num_collisionvertices, oldnumtriangles, oldnumtriangles2, oldnumtriangles - out->num_triangles, oldnumtriangles2 - out->num_collisiontriangles);
6145
6146 collisionvertices += finalvertices;
6147 collisiontriangles += out->num_collisiontriangles;
6148 break;
6149 default:
6150 break;
6151 }
6152 meshvertices += out->num_vertices;
6153 meshtriangles += out->num_triangles;
6154 for (j = 0, invalidelements = 0;j < out->num_triangles * 3;j++)
6156 invalidelements++;
6157 if (invalidelements)
6158 {
6159 Con_Printf(CON_WARN "Mod_Q3BSP_LoadFaces: Warning: face #%i has %i invalid elements, type = %i, texture->name = \"%s\", texture->surfaceflags = %i, firstvertex = %i, numvertices = %i, firstelement = %i, numelements = %i, elements list:\n", i, invalidelements, type, out->texture->name, out->texture->surfaceflags, firstvertex, out->num_vertices, firstelement, out->num_triangles * 3);
6160 for (j = 0;j < out->num_triangles * 3;j++)
6161 {
6165 }
6166 Con_Print("\n");
6167 }
6168 // calculate a bounding box
6169 VectorClear(out->mins);
6170 VectorClear(out->maxs);
6171 if (out->num_vertices)
6172 {
6173 if (cls.state != ca_dedicated && out->lightmaptexture)
6174 {
6175 // figure out which part of the merged lightmap this fits into
6176 int lightmapindex = LittleLong(in->lightmapindex) >> (loadmodel->brushq3.deluxemapping ? 1 : 0);
6179 lightmapindex &= mergewidth * mergeheight - 1;
6180 lightmaptcscale[0] = 1.0f / mergewidth;
6181 lightmaptcscale[1] = 1.0f / mergeheight;
6182 lightmaptcbase[0] = (lightmapindex % mergewidth) * lightmaptcscale[0];
6183 lightmaptcbase[1] = (lightmapindex / mergewidth) * lightmaptcscale[1];
6184 // modify the lightmap texcoords to match this region of the merged lightmap
6185 for (j = 0, v = loadmodel->surfmesh.data_texcoordlightmap2f + 2 * out->num_firstvertex;j < out->num_vertices;j++, v += 2)
6186 {
6187 v[0] = v[0] * lightmaptcscale[0] + lightmaptcbase[0];
6188 v[1] = v[1] * lightmaptcscale[1] + lightmaptcbase[1];
6189 }
6190 }
6193 for (j = 1, v = (loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex) + 3;j < out->num_vertices;j++, v += 3)
6194 {
6195 out->mins[0] = min(out->mins[0], v[0]);
6196 out->maxs[0] = max(out->maxs[0], v[0]);
6197 out->mins[1] = min(out->mins[1], v[1]);
6198 out->maxs[1] = max(out->maxs[1], v[1]);
6199 out->mins[2] = min(out->mins[2], v[2]);
6200 out->maxs[2] = max(out->maxs[2], v[2]);
6201 }
6202 out->mins[0] -= 1.0f;
6203 out->mins[1] -= 1.0f;
6204 out->mins[2] -= 1.0f;
6205 out->maxs[0] += 1.0f;
6206 out->maxs[1] += 1.0f;
6207 out->maxs[2] += 1.0f;
6208 }
6209 // set lightmap styles for consistency with q1bsp
6210 //out->lightmapinfo->styles[0] = 0;
6211 //out->lightmapinfo->styles[1] = 255;
6212 //out->lightmapinfo->styles[2] = 255;
6213 //out->lightmapinfo->styles[3] = 255;
6214 }
6215
6216 i = oldi;
6217 out = oldout;
6218 for (;i < count;i++, out++)
6219 {
6220 if(out->num_vertices && out->num_triangles)
6221 continue;
6222 if(out->num_vertices == 0)
6223 {
6224 Con_Printf("Mod_Q3BSP_LoadFaces: surface %d (texture %s) has no vertices, ignoring\n", i, out->texture ? out->texture->name : "(none)");
6225 if(out->num_triangles == 0)
6226 Con_Printf("Mod_Q3BSP_LoadFaces: surface %d (texture %s) has no triangles, ignoring\n", i, out->texture ? out->texture->name : "(none)");
6227 }
6228 else if(out->num_triangles == 0)
6229 Con_Printf("Mod_Q3BSP_LoadFaces: surface %d (texture %s, near %f %f %f) has no triangles, ignoring\n", i, out->texture ? out->texture->name : "(none)",
6230 (loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex)[0 * 3 + 0],
6231 (loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex)[1 * 3 + 0],
6232 (loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex)[2 * 3 + 0]);
6233 }
6234
6235 // for per pixel lighting
6237
6238 // generate ushort elements array if possible
6240 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
6242
6243 // free the no longer needed vertex data
6252 // free the no longer needed triangle data
6257
6258 if(patchtess)
6259 Mem_Free(patchtess);
6260}
#define LittleFloat(l)
Definition common.h:94
#define CON_ERROR
Definition console.h:102
void Q3PatchTriangleElements(int *elements, int width, int height, int firstvertex)
Definition curves.c:399
void Q3PatchTesselateFloat(int numcomponents, int outputstride, float *outputvertices, int patchwidth, int patchheight, int inputstride, float *patchvertices, int tesselationwidth, int tesselationheight)
Definition curves.c:64
int Q3PatchTesselationOnY(int patchwidth, int patchheight, int components, const float *in, float tolerance)
Definition curves.c:252
int Q3PatchAdjustTesselation(int numcomponents, patchinfo_t *patch1, float *patchvertices1, patchinfo_t *patch2, float *patchvertices2)
Definition curves.c:329
int Q3PatchTesselationOnX(int patchwidth, int patchheight, int components, const float *in, float tolerance)
Definition curves.c:232
int Q3PatchDimForTess(int size, int tess)
Definition curves.c:51
#define PATCH_LOD_VISUAL
Definition curves.h:6
#define PATCH_LOD_COLLISION
Definition curves.h:5
int R_TextureHeight(rtexture_t *rt)
int R_TextureWidth(rtexture_t *rt)
GLenum type
Definition glquake.h:656
cvar_t developer_extra
Definition host.c:49
#define PATCHTESS_SAME_LODGROUP(a, b)
#define Q3FACETYPE_FLAT
#define Q3FACETYPE_MESH
#define Q3FACETYPE_FLARE
#define Q3FACETYPE_PATCH
void Mod_SnapVertices(int numcomponents, int numvertices, float *vertices, float snap)
int Mod_RemoveDegenerateTriangles(int numtriangles, const int *inelement3i, int *outelement3i, const float *vertex3f)
int * data_collisionelement3i
float * data_collisionvertex3f
float * data_texcoordtexture2f
float * data_normal3f
float * data_texcoordlightmap2f
float * data_vertex3f
float * data_color4f
int num_lightmapmergedwidthheightdeluxepower
struct q3deffect_s * effect
fog volume info in q3bsp
int num_collisionvertices
struct patchinfo_t::@10 lods[PATCH_LODS_NUM]
int ytess
Definition curves.h:12
int xtess
Definition curves.h:12
int xsize
Definition curves.h:10
int ysize
Definition curves.h:10
float * originalvertex3f
patchinfo_t info
float lodgroup[6]
float * data_lightmapcolor4f

References bound, model_t::brush, model_t::brushq3, ca_dedicated, cls, Con_DPrintf(), CON_ERROR, Con_Print(), Con_Printf(), CON_WARN, count, model_brush_t::data_collisionelement3i, model_brush_t::data_collisionvertex3f, model_brushq3_t::data_color4f, model_brushq3_t::data_deluxemaps, model_brushq3_t::data_effects, model_brushq3_t::data_element3i, surfmesh_t::data_element3i, surfmesh_t::data_element3s, surfmesh_t::data_lightmapcolor4f, model_brushq3_t::data_lightmaps, model_brushq3_t::data_normal3f, surfmesh_t::data_normal3f, model_t::data_surfaces, surfmesh_t::data_svector3f, model_brushq3_t::data_texcoordlightmap2f, surfmesh_t::data_texcoordlightmap2f, model_brushq3_t::data_texcoordtexture2f, surfmesh_t::data_texcoordtexture2f, model_t::data_textures, surfmesh_t::data_tvector3f, model_brushq3_t::data_vertex3f, surfmesh_t::data_vertex3f, model_brushq3_t::deluxemapping, msurface_t::deluxemaptexture, developer_extra, msurface_t::effect, q3dface_t::effectindex, lump_t::filelen, lump_t::fileofs, q3dface_t::firstelement, q3dface_t::firstvertex, Host_Error(), i, patchtess_t::info, cvar_t::integer, q3dface_t::lightmapindex, model_brushq3_t::lightmapsize, msurface_t::lightmaptexture, model_t::lit, LittleFloat, LittleLong, loadmodel, patchtess_t::lodgroup, patchinfo_t::lods, max, msurface_t::maxs, q3dface_t::maxs, Mem_Alloc, Mem_Free, model_t::mempool, min, msurface_t::mins, q3dface_t::mins, Mod_AllocSurfMesh(), mod_base, Mod_BuildTextureVectorsFromNormals(), mod_q3bsp_curves_subdivisions_maxtess, mod_q3bsp_curves_subdivisions_maxvertices, mod_q3bsp_curves_subdivisions_mintess, mod_q3bsp_curves_subdivisions_tolerance, Mod_RemoveDegenerateTriangles(), Mod_SnapVertices(), n, model_t::name, texture_t::name, NULL, msurface_t::num_collisiontriangles, msurface_t::num_collisionvertices, model_brushq3_t::num_effects, msurface_t::num_firstcollisiontriangle, msurface_t::num_firsttriangle, msurface_t::num_firstvertex, model_brushq3_t::num_lightmapmergedwidthheightdeluxepower, model_brushq3_t::num_originallightmaps, model_t::num_surfaces, model_t::num_textures, model_brushq3_t::num_triangles, msurface_t::num_triangles, surfmesh_t::num_triangles, model_brushq3_t::num_vertices, msurface_t::num_vertices, surfmesh_t::num_vertices, q3dface_t::numelements, q3dface_t::numvertices, patchtess_t::originalvertex3f, q3dface_t::patch, PATCH_LOD_COLLISION, PATCH_LOD_VISUAL, q3dface_t::patchsize, PATCHTESS_SAME_LODGROUP, Q3FACETYPE_FLARE, Q3FACETYPE_FLAT, Q3FACETYPE_MESH, Q3FACETYPE_PATCH, Q3PatchAdjustTesselation(), Q3PatchDimForTess(), Q3PatchTesselateFloat(), Q3PatchTesselationOnX(), Q3PatchTesselationOnY(), Q3PatchTriangleElements(), r_smoothnormals_areaweighting, r_subdivisions_maxtess, r_subdivisions_maxvertices, r_subdivisions_mintess, r_subdivisions_tolerance, r_texture_blanknormalmap, R_TextureHeight(), R_TextureWidth(), q3dface_t::specific, client_static_t::state, patchtess_t::surface_id, texture_t::surfaceflags, model_t::surfmesh, tempmempool, msurface_t::texture, q3dface_t::textureindex, q3dface_t::type, type, v, cvar_t::value, VectorClear, VectorCopy, patchinfo_t::xsize, patchinfo_t::xtess, patchinfo_t::ysize, and patchinfo_t::ytess.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadLeafBrushes()

static void Mod_Q3BSP_LoadLeafBrushes ( lump_t * l)
static

Definition at line 6299 of file model_brush.c.

6300{
6301 int *in;
6302 int *out;
6303 int i, n, count;
6304
6305 in = (int *)(mod_base + l->fileofs);
6306 if (l->filelen % sizeof(*in))
6307 Host_Error("Mod_Q3BSP_LoadLeafBrushes: funny lump size in %s",loadmodel->name);
6308 count = l->filelen / sizeof(*in);
6309 out = (int *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
6310
6313
6314 for (i = 0;i < count;i++, in++, out++)
6315 {
6316 n = LittleLong(*in);
6318 Host_Error("Mod_Q3BSP_LoadLeafBrushes: invalid brush index %i (%i brushes)", n, loadmodel->brush.num_brushes);
6319 *out = n;
6320 }
6321}

References model_t::brush, count, model_brush_t::data_leafbrushes, lump_t::filelen, lump_t::fileofs, Host_Error(), i, LittleLong, loadmodel, Mem_Alloc, model_t::mempool, mod_base, n, model_t::name, model_brush_t::num_brushes, and model_brush_t::num_leafbrushes.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadLeafFaces()

static void Mod_Q3BSP_LoadLeafFaces ( lump_t * l)
static

Definition at line 6323 of file model_brush.c.

6324{
6325 int *in;
6326 int *out;
6327 int i, n, count;
6328
6329 in = (int *)(mod_base + l->fileofs);
6330 if (l->filelen % sizeof(*in))
6331 Host_Error("Mod_Q3BSP_LoadLeafFaces: funny lump size in %s",loadmodel->name);
6332 count = l->filelen / sizeof(*in);
6333 out = (int *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
6334
6337
6338 for (i = 0;i < count;i++, in++, out++)
6339 {
6340 n = LittleLong(*in);
6342 Host_Error("Mod_Q3BSP_LoadLeafFaces: invalid face index %i (%i faces)", n, loadmodel->num_surfaces);
6343 *out = n;
6344 }
6345}

References model_t::brush, count, model_brush_t::data_leafsurfaces, lump_t::filelen, lump_t::fileofs, Host_Error(), i, LittleLong, loadmodel, Mem_Alloc, model_t::mempool, mod_base, n, model_t::name, model_brush_t::num_leafsurfaces, and model_t::num_surfaces.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadLeafs()

static void Mod_Q3BSP_LoadLeafs ( lump_t * l)
static

Definition at line 6347 of file model_brush.c.

6348{
6349 q3dleaf_t *in;
6350 mleaf_t *out;
6351 int i, j, n, c, count;
6352
6353 in = (q3dleaf_t *)(mod_base + l->fileofs);
6354 if (l->filelen % sizeof(*in))
6355 Host_Error("Mod_Q3BSP_LoadLeafs: funny lump size in %s",loadmodel->name);
6356 count = l->filelen / sizeof(*in);
6357 out = (mleaf_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
6358
6359 loadmodel->brush.data_leafs = out;
6361
6362 for (i = 0;i < count;i++, in++, out++)
6363 {
6364 out->parent = NULL;
6365 out->plane = NULL;
6366 out->clusterindex = LittleLong(in->clusterindex);
6367 out->areaindex = LittleLong(in->areaindex);
6368 for (j = 0;j < 3;j++)
6369 {
6370 // yes the mins/maxs are ints
6371 // bones_was_here: the cast prevents signed underflow with poon-wood.bsp
6372 out->mins[j] = (vec_t)LittleLong(in->mins[j]) - 1;
6373 out->maxs[j] = (vec_t)LittleLong(in->maxs[j]) + 1;
6374 }
6375 n = LittleLong(in->firstleafface);
6376 c = LittleLong(in->numleaffaces);
6378 Host_Error("Mod_Q3BSP_LoadLeafs: invalid leafsurface range %i : %i (%i leafsurfaces)", n, n + c, loadmodel->brush.num_leafsurfaces);
6380 out->numleafsurfaces = c;
6381 n = LittleLong(in->firstleafbrush);
6382 c = LittleLong(in->numleafbrushes);
6384 Host_Error("Mod_Q3BSP_LoadLeafs: invalid leafbrush range %i : %i (%i leafbrushes)", n, n + c, loadmodel->brush.num_leafbrushes);
6386 out->numleafbrushes = c;
6387 }
6388}
mplane_t * plane
struct mnode_s * parent

References mleaf_t::areaindex, q3dleaf_t::areaindex, model_t::brush, mleaf_t::clusterindex, q3dleaf_t::clusterindex, count, model_brush_t::data_leafbrushes, model_brush_t::data_leafs, model_brush_t::data_leafsurfaces, lump_t::filelen, lump_t::fileofs, mleaf_t::firstleafbrush, q3dleaf_t::firstleafbrush, q3dleaf_t::firstleafface, mleaf_t::firstleafsurface, Host_Error(), i, LittleLong, loadmodel, mleaf_t::maxs, q3dleaf_t::maxs, Mem_Alloc, model_t::mempool, mleaf_t::mins, q3dleaf_t::mins, mod_base, n, model_t::name, NULL, model_brush_t::num_leafbrushes, model_brush_t::num_leafs, model_brush_t::num_leafsurfaces, mleaf_t::numleafbrushes, q3dleaf_t::numleafbrushes, q3dleaf_t::numleaffaces, mleaf_t::numleafsurfaces, mleaf_t::parent, and mleaf_t::plane.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadLightGrid()

static void Mod_Q3BSP_LoadLightGrid ( lump_t * l)
static

Definition at line 6443 of file model_brush.c.

6444{
6445 q3dlightgrid_t *in;
6446 q3dlightgrid_t *out;
6447 int count;
6448 int i;
6449 int texturesize[3];
6450 unsigned char *texturergba, *texturelayer[3], *texturepadding[2];
6451 double lightgridmatrix[4][4];
6452
6453 in = (q3dlightgrid_t *)(mod_base + l->fileofs);
6454 if (l->filelen % sizeof(*in))
6455 Host_Error("Mod_Q3BSP_LoadLightGrid: funny lump size in %s",loadmodel->name);
6471
6472 // if lump is empty there is nothing to load, we can deal with that in the LightPoint code
6473 if (l->filelen)
6474 {
6475 if (l->filelen < count * (int)sizeof(*in))
6476 {
6477 Con_Printf(CON_ERROR "Mod_Q3BSP_LoadLightGrid: invalid lightgrid lump size %i bytes, should be %i bytes (%ix%ix%i)", l->filelen, (int)(count * sizeof(*in)), loadmodel->brushq3.num_lightgrid_isize[0], loadmodel->brushq3.num_lightgrid_isize[1], loadmodel->brushq3.num_lightgrid_isize[2]);
6478 return; // ignore the grid if we cannot understand it
6479 }
6480 if (l->filelen != count * (int)sizeof(*in))
6481 Con_Printf(CON_WARN "Mod_Q3BSP_LoadLightGrid: Warning: calculated lightgrid size %i bytes does not match lump size %i\n", (int)(count * sizeof(*in)), l->filelen);
6482 out = (q3dlightgrid_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
6485 // no swapping or validation necessary
6486 memcpy(out, in, count * (int)sizeof(*out));
6487
6489 {
6491 {
6492 // we fix the brightness consistently via lightmapscale
6493 }
6494 else
6495 {
6496 for(i = 0; i < count; ++i)
6497 {
6498 out[i].ambientrgb[0] = floor(Image_LinearFloatFromsRGB(out[i].ambientrgb[0]) * 255.0f + 0.5f);
6499 out[i].ambientrgb[1] = floor(Image_LinearFloatFromsRGB(out[i].ambientrgb[1]) * 255.0f + 0.5f);
6500 out[i].ambientrgb[2] = floor(Image_LinearFloatFromsRGB(out[i].ambientrgb[2]) * 255.0f + 0.5f);
6501 out[i].diffusergb[0] = floor(Image_LinearFloatFromsRGB(out[i].diffusergb[0]) * 255.0f + 0.5f);
6502 out[i].diffusergb[1] = floor(Image_LinearFloatFromsRGB(out[i].diffusergb[1]) * 255.0f + 0.5f);
6503 out[i].diffusergb[2] = floor(Image_LinearFloatFromsRGB(out[i].diffusergb[2]) * 255.0f + 0.5f);
6504 }
6505 }
6506 }
6507 else
6508 {
6510 {
6511 for(i = 0; i < count; ++i)
6512 {
6513 out[i].ambientrgb[0] = floor(Image_sRGBFloatFromLinear_Lightmap(out[i].ambientrgb[0]) * 255.0f + 0.5f);
6514 out[i].ambientrgb[1] = floor(Image_sRGBFloatFromLinear_Lightmap(out[i].ambientrgb[1]) * 255.0f + 0.5f);
6515 out[i].ambientrgb[2] = floor(Image_sRGBFloatFromLinear_Lightmap(out[i].ambientrgb[2]) * 255.0f + 0.5f);
6516 out[i].diffusergb[0] = floor(Image_sRGBFloatFromLinear_Lightmap(out[i].diffusergb[0]) * 255.0f + 0.5f);
6517 out[i].diffusergb[1] = floor(Image_sRGBFloatFromLinear_Lightmap(out[i].diffusergb[1]) * 255.0f + 0.5f);
6518 out[i].diffusergb[2] = floor(Image_sRGBFloatFromLinear_Lightmap(out[i].diffusergb[2]) * 255.0f + 0.5f);
6519 }
6520 }
6521 else
6522 {
6523 // all is good
6524 }
6525 }
6526
6528 {
6529 // build a texture to hold the data for per-pixel sampling
6530 // this has 3 different kinds of data stacked in it:
6531 // ambient color
6532 // bent-normal light color
6533 // bent-normal light dir
6534
6535 texturesize[0] = loadmodel->brushq3.num_lightgrid_isize[0];
6536 texturesize[1] = loadmodel->brushq3.num_lightgrid_isize[1];
6537 texturesize[2] = (loadmodel->brushq3.num_lightgrid_isize[2] + 2) * 3;
6538 texturergba = (unsigned char*)Mem_Alloc(loadmodel->mempool, texturesize[0] * texturesize[1] * texturesize[2] * sizeof(char[4]));
6539 texturelayer[0] = texturergba + loadmodel->brushq3.num_lightgrid_isize[0] * loadmodel->brushq3.num_lightgrid_isize[1] * 4;
6540 texturelayer[1] = texturelayer[0] + (loadmodel->brushq3.num_lightgrid_isize[0] * loadmodel->brushq3.num_lightgrid_isize[1] * (loadmodel->brushq3.num_lightgrid_isize[2] + 2)) * 4;
6541 texturelayer[2] = texturelayer[1] + (loadmodel->brushq3.num_lightgrid_isize[0] * loadmodel->brushq3.num_lightgrid_isize[1] * (loadmodel->brushq3.num_lightgrid_isize[2] + 2)) * 4;
6542 // the light dir layer needs padding above/below it that is a neutral unsigned normal (127,127,127,255)
6543 texturepadding[0] = texturelayer[2] - loadmodel->brushq3.num_lightgrid_isize[0] * loadmodel->brushq3.num_lightgrid_isize[1] * 4;
6544 texturepadding[1] = texturelayer[2] + loadmodel->brushq3.num_lightgrid_isize[0] * loadmodel->brushq3.num_lightgrid_isize[1] * loadmodel->brushq3.num_lightgrid_isize[2] * 4;
6545 for (i = 0; i < texturesize[0] * texturesize[1]; i++)
6546 {
6547 texturepadding[0][i * 4] = texturepadding[1][i * 4] = 127;
6548 texturepadding[0][i * 4 + 1] = texturepadding[1][i * 4 + 1] = 127;
6549 texturepadding[0][i * 4 + 2] = texturepadding[1][i * 4 + 2] = 127;
6550 texturepadding[0][i * 4 + 3] = texturepadding[1][i * 4 + 3] = 255;
6551 }
6552 for (i = 0; i < count; i++)
6553 {
6554 texturelayer[0][i * 4 + 0] = out[i].ambientrgb[0];
6555 texturelayer[0][i * 4 + 1] = out[i].ambientrgb[1];
6556 texturelayer[0][i * 4 + 2] = out[i].ambientrgb[2];
6557 texturelayer[0][i * 4 + 3] = 255;
6558 texturelayer[1][i * 4 + 0] = out[i].diffusergb[0];
6559 texturelayer[1][i * 4 + 1] = out[i].diffusergb[1];
6560 texturelayer[1][i * 4 + 2] = out[i].diffusergb[2];
6561 texturelayer[1][i * 4 + 3] = 255;
6562 // this uses the mod_md3_sin table because the values are
6563 // already in the 0-255 range, the 64+ bias fetches a cosine
6564 // instead of a sine value
6565 texturelayer[2][i * 4 + 0] = (char)((mod_md3_sin[64 + out[i].diffuseyaw] * mod_md3_sin[out[i].diffusepitch]) * 127 + 127);
6566 texturelayer[2][i * 4 + 1] = (char)((mod_md3_sin[out[i].diffuseyaw] * mod_md3_sin[out[i].diffusepitch]) * 127 + 127);
6567 texturelayer[2][i * 4 + 2] = (char)((mod_md3_sin[64 + out[i].diffusepitch]) * 127 + 127);
6568 texturelayer[2][i * 4 + 3] = 255;
6569 }
6570#if 0
6571 // debugging hack
6572 int x, y, z;
6573 for (z = 0; z < loadmodel->brushq3.num_lightgrid_isize[2]; z++)
6574 {
6575 for (y = 0; y < loadmodel->brushq3.num_lightgrid_isize[1]; y++)
6576 {
6577 for (x = 0; x < loadmodel->brushq3.num_lightgrid_isize[0]; x++)
6578 {
6579 i = (z * texturesize[1] + y) * texturesize[0] + x;
6580 texturelayer[0][i * 4 + 0] = x * 256 / loadmodel->brushq3.num_lightgrid_isize[0];
6581 texturelayer[0][i * 4 + 1] = y * 256 / loadmodel->brushq3.num_lightgrid_isize[1];
6582 texturelayer[0][i * 4 + 2] = z * 256 / loadmodel->brushq3.num_lightgrid_isize[2];
6583 }
6584 }
6585 }
6586#endif
6587 loadmodel->brushq3.lightgridtexturesize[0] = texturesize[0];
6588 loadmodel->brushq3.lightgridtexturesize[1] = texturesize[1];
6589 loadmodel->brushq3.lightgridtexturesize[2] = texturesize[2];
6590 memset(lightgridmatrix[0], 0, sizeof(lightgridmatrix));
6591 lightgridmatrix[0][0] = loadmodel->brushq3.num_lightgrid_scale[0] / texturesize[0];
6592 lightgridmatrix[1][1] = loadmodel->brushq3.num_lightgrid_scale[1] / texturesize[1];
6593 lightgridmatrix[2][2] = loadmodel->brushq3.num_lightgrid_scale[2] / texturesize[2];
6594 lightgridmatrix[0][3] = -(loadmodel->brushq3.num_lightgrid_imins[0] - 0.5f) / texturesize[0];
6595 lightgridmatrix[1][3] = -(loadmodel->brushq3.num_lightgrid_imins[1] - 0.5f) / texturesize[1];
6596 lightgridmatrix[2][3] = -(loadmodel->brushq3.num_lightgrid_imins[2] - 1.5f) / texturesize[2];
6597 lightgridmatrix[3][3] = 1;
6599 loadmodel->brushq3.lightgridtexture = R_LoadTexture3D(loadmodel->texturepool, "lightgrid", texturesize[0], texturesize[1], texturesize[2], texturergba, TEXTYPE_RGBA, TEXF_CLAMP, 0, NULL);
6600 Mem_Free(texturergba);
6601 }
6602 }
6603}
rtexture_t * R_LoadTexture3D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette)
GLubyte GLubyte GLubyte z
Definition glquake.h:782
#define Image_LinearFloatFromsRGB(c)
Definition image.h:69
#define Image_sRGBFloatFromLinear_Lightmap(c)
Definition image.h:71
void Matrix4x4_CreateScale3(matrix4x4_t *out, double x, double y, double z)
Definition matrixlib.c:695
void Matrix4x4_ConcatTranslate(matrix4x4_t *out, double x, double y, double z)
Definition matrixlib.c:1757
void Matrix4x4_FromArrayDoubleD3D(matrix4x4_t *out, const double in[4][4])
Definition matrixlib.c:1126
@ TEXTYPE_RGBA
Definition r_textures.h:51
#define TEXF_CLAMP
Definition r_textures.h:15
int num_lightgrid_imaxs[3]
float num_lightgrid_scale[3]
matrix4x4_t num_lightgrid_indexfromworld
q3dmodel_t * data_models
int num_lightgrid_imins[3]
matrix4x4_t lightgridworldtotexturematrix
q3dlightgrid_t * data_lightgrid
int num_lightgrid_isize[3]
rtexture_t * lightgridtexture
int lightgridtexturesize[3]
float maxs[3]
Definition model_q3bsp.h:85
float mins[3]
Definition model_q3bsp.h:84

References q3dlightgrid_t::ambientrgb, model_t::brushq3, ceil(), CON_ERROR, Con_Printf(), CON_WARN, count, model_brushq3_t::data_lightgrid, model_brushq3_t::data_models, q3dlightgrid_t::diffusergb, lump_t::filelen, lump_t::fileofs, floor(), Host_Error(), i, Image_LinearFloatFromsRGB, Image_sRGBFloatFromLinear_Lightmap, int(), cvar_t::integer, model_brushq3_t::lightgridtexture, model_brushq3_t::lightgridtexturesize, model_brushq3_t::lightgridworldtotexturematrix, loadmodel, Matrix4x4_ConcatTranslate(), Matrix4x4_CreateScale3(), Matrix4x4_FromArrayDoubleD3D(), q3dmodel_t::maxs, Mem_Alloc, Mem_Free, model_t::mempool, q3dmodel_t::mins, mod_base, mod_md3_sin, mod_q3bsp_lightgrid_texture, mod_q3bsp_sRGBlightmaps, model_t::name, NULL, model_brushq3_t::num_lightgrid, model_brushq3_t::num_lightgrid_cellsize, model_brushq3_t::num_lightgrid_imaxs, model_brushq3_t::num_lightgrid_imins, model_brushq3_t::num_lightgrid_indexfromworld, model_brushq3_t::num_lightgrid_isize, model_brushq3_t::num_lightgrid_scale, R_LoadTexture3D(), viddef_t::sRGB3D, TEXF_CLAMP, model_t::texturepool, TEXTYPE_RGBA, vid, vid_sRGB, vid_sRGB_fallback, x, y, and z.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadLightmaps()

static void Mod_Q3BSP_LoadLightmaps ( lump_t * l,
lump_t * faceslump )
static

Definition at line 5516 of file model_brush.c.

5517{
5518 q3dlightmap_t *input_pointer;
5519 int i;
5520 int j;
5521 int k;
5522 int count;
5523 int powerx;
5524 int powery;
5525 int powerxy;
5526 int powerdxy;
5527 int endlightmap;
5528 int mergegoal;
5529 int lightmapindex;
5530 int realcount;
5531 int realindex;
5532 int mergedwidth;
5533 int mergedheight;
5534 int mergedcolumns;
5535 int mergedrows;
5536 int mergedrowsxcolumns;
5537 int size;
5538 int bytesperpixel;
5539 int rgbmap[3];
5540 unsigned char *c;
5541 unsigned char *mergedpixels;
5542 unsigned char *mergeddeluxepixels;
5543 unsigned char *mergebuf;
5544 char mapname[MAX_QPATH];
5545 qbool external;
5546 unsigned char *inpixels[10000]; // max count q3map2 can output (it uses 4 digits)
5547 char vabuf[1024];
5548
5549 // defaults for q3bsp
5550 size = 128;
5551 bytesperpixel = 3;
5552 rgbmap[0] = 2;
5553 rgbmap[1] = 1;
5554 rgbmap[2] = 0;
5555 external = false;
5557
5558 if (cls.state == ca_dedicated)
5559 return;
5560
5562 {
5563 return;
5564 }
5565 else if(l->filelen)
5566 {
5567 // prefer internal LMs for compatibility (a BSP contains no info on whether external LMs exist)
5569 Con_Printf("Using internal lightmaps\n");
5570 input_pointer = (q3dlightmap_t *)(mod_base + l->fileofs);
5571 if (l->filelen % sizeof(*input_pointer))
5572 Host_Error("Mod_Q3BSP_LoadLightmaps: funny lump size in %s",loadmodel->name);
5573 count = l->filelen / sizeof(*input_pointer);
5574 for(i = 0; i < count; ++i)
5575 inpixels[i] = input_pointer[i].rgb;
5576 }
5577 else
5578 {
5579 // no internal lightmaps
5580 // try external lightmaps
5582 inpixels[0] = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s/lm_%04d", mapname, 0), false, false, false, NULL);
5583 if(!inpixels[0])
5584 return;
5585 else
5586 Con_Printf("Using external lightmaps\n");
5587
5588 // using EXTERNAL lightmaps instead
5590 Con_Printf("Mod_Q3BSP_LoadLightmaps: irregularly sized external lightmap in %s",loadmodel->name);
5591
5592 size = image_width;
5593 bytesperpixel = 4;
5594 rgbmap[0] = 0;
5595 rgbmap[1] = 1;
5596 rgbmap[2] = 2;
5597 external = true;
5598
5599 for(count = 1; ; ++count)
5600 {
5601 inpixels[count] = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s/lm_%04d", mapname, count), false, false, false, NULL);
5602 if(!inpixels[count])
5603 break; // we got all of them
5604 if(image_width != size || image_height != size)
5605 {
5606 Mem_Free(inpixels[count]);
5607 inpixels[count] = NULL;
5608 Con_Printf("Mod_Q3BSP_LoadLightmaps: mismatched lightmap size in %s - external lightmap %s/lm_%04d does not match earlier ones\n", loadmodel->name, mapname, count);
5609 break;
5610 }
5611 }
5612 }
5613
5616
5617 // now check the surfaces to see if any of them index an odd numbered
5618 // lightmap, if so this is not a deluxemapped bsp file
5619 //
5620 // also check what lightmaps are actually used, because q3map2 sometimes
5621 // (always?) makes an unused one at the end, which
5622 // q3map2 sometimes (or always?) makes a second blank lightmap for no
5623 // reason when only one lightmap is used, which can throw off the
5624 // deluxemapping detection method, so check 2-lightmap bsp's specifically
5625 // to see if the second lightmap is blank, if so it is not deluxemapped.
5626 // VorteX: autodetect only if previous attempt to find "deluxeMaps" key
5627 // in Mod_Q3BSP_LoadEntities was failed
5629 {
5632 endlightmap = 0;
5634 {
5635 int facecount = faceslump->filelen / sizeof(q3dface_t);
5636 q3dface_t *faces = (q3dface_t *)(mod_base + faceslump->fileofs);
5637 for (i = 0;i < facecount;i++)
5638 {
5639 j = LittleLong(faces[i].lightmapindex);
5640 if (j >= 0)
5641 {
5642 endlightmap = max(endlightmap, j + 1);
5643 if ((j & 1) || j + 1 >= count)
5644 {
5646 break;
5647 }
5648 }
5649 }
5650 }
5651
5652 // q3map2 sometimes (or always?) makes a second blank lightmap for no
5653 // reason when only one lightmap is used, which can throw off the
5654 // deluxemapping detection method, so check 2-lightmap bsp's specifically
5655 // to see if the second lightmap is blank, if so it is not deluxemapped.
5656 //
5657 // further research has shown q3map2 sometimes creates a deluxemap and two
5658 // blank lightmaps, which must be handled properly as well
5659 if (endlightmap == 1 && count > 1)
5660 {
5661 c = inpixels[1];
5662 for (i = 0;i < size*size;i++)
5663 {
5664 if (c[bytesperpixel*i + rgbmap[0]])
5665 break;
5666 if (c[bytesperpixel*i + rgbmap[1]])
5667 break;
5668 if (c[bytesperpixel*i + rgbmap[2]])
5669 break;
5670 }
5671 if (i == size*size)
5672 {
5673 // all pixels in the unused lightmap were black...
5675 }
5676 }
5677 }
5678
5679 Con_Printf("%s is %sdeluxemapped\n", loadmodel->name, loadmodel->brushq3.deluxemapping ? "" : "not ");
5680
5681 // figure out what the most reasonable merge power is within limits
5682
5683 // find the appropriate NxN dimensions to merge to, to avoid wasted space
5684 realcount = count >> (int)loadmodel->brushq3.deluxemapping;
5685
5686 // figure out how big the merged texture has to be
5687 mergegoal = 128<<bound(0, mod_q3bsp_lightmapmergepower.integer, 6);
5688 mergegoal = bound(size, mergegoal, (int)vid.maxtexturesize_2d);
5689 while (mergegoal > size && mergegoal * mergegoal / 4 >= size * size * realcount)
5690 mergegoal /= 2;
5691 mergedwidth = mergegoal;
5692 mergedheight = mergegoal;
5693 // choose non-square size (2x1 aspect) if only half the space is used;
5694 // this really only happens when the entire set fits in one texture, if
5695 // there are multiple textures, we don't worry about shrinking the last
5696 // one to fit, because the driver prefers the same texture size on
5697 // consecutive draw calls...
5698 if (mergedwidth * mergedheight / 2 >= size*size*realcount)
5699 mergedheight /= 2;
5700
5703 while (mergedwidth > size<<loadmodel->brushq3.num_lightmapmergedwidthpower)
5705 while (mergedheight > size<<loadmodel->brushq3.num_lightmapmergedheightpower)
5708
5711 powerxy = powerx+powery;
5712 powerdxy = loadmodel->brushq3.deluxemapping + powerxy;
5713
5714 mergedcolumns = 1 << powerx;
5715 mergedrows = 1 << powery;
5716 mergedrowsxcolumns = 1 << powerxy;
5717
5718 loadmodel->brushq3.num_mergedlightmaps = (realcount + (1 << powerxy) - 1) >> powerxy;
5722
5723 mergedpixels = (unsigned char *) Mem_Alloc(tempmempool, mergedwidth * mergedheight * 4);
5724 mergeddeluxepixels = loadmodel->brushq3.deluxemapping ? (unsigned char *) Mem_Alloc(tempmempool, mergedwidth * mergedheight * 4) : NULL;
5725 for (i = 0;i < count;i++)
5726 {
5727 // figure out which merged lightmap texture this fits into
5728 realindex = i >> (int)loadmodel->brushq3.deluxemapping;
5729 lightmapindex = i >> powerdxy;
5730
5731 // choose the destination address
5732 mergebuf = (loadmodel->brushq3.deluxemapping && (i & 1)) ? mergeddeluxepixels : mergedpixels;
5733 mergebuf += 4 * (realindex & (mergedcolumns-1))*size + 4 * ((realindex >> powerx) & (mergedrows-1))*mergedwidth*size;
5734 if ((i & 1) == 0 || !loadmodel->brushq3.deluxemapping)
5735 Con_DPrintf("copying original lightmap %i (%ix%i) to %i (at %i,%i)\n", i, size, size, lightmapindex, (realindex & (mergedcolumns-1))*size, ((realindex >> powerx) & (mergedrows-1))*size);
5736
5737 // convert pixels from RGB or BGRA while copying them into the destination rectangle
5738 for (j = 0;j < size;j++)
5739 for (k = 0;k < size;k++)
5740 {
5741 mergebuf[(j*mergedwidth+k)*4+0] = inpixels[i][(j*size+k)*bytesperpixel+rgbmap[0]];
5742 mergebuf[(j*mergedwidth+k)*4+1] = inpixels[i][(j*size+k)*bytesperpixel+rgbmap[1]];
5743 mergebuf[(j*mergedwidth+k)*4+2] = inpixels[i][(j*size+k)*bytesperpixel+rgbmap[2]];
5744 mergebuf[(j*mergedwidth+k)*4+3] = 255;
5745 }
5746
5747 // upload texture if this was the last tile being written to the texture
5748 if (((realindex + 1) & (mergedrowsxcolumns - 1)) == 0 || (realindex + 1) == realcount)
5749 {
5750 if (loadmodel->brushq3.deluxemapping && (i & 1))
5751 loadmodel->brushq3.data_deluxemaps[lightmapindex] = R_LoadTexture2D(loadmodel->texturepool, va(vabuf, sizeof(vabuf), "deluxemap%04i", lightmapindex), mergedwidth, mergedheight, mergeddeluxepixels, TEXTYPE_BGRA, TEXF_FORCELINEAR | (gl_texturecompression_q3bspdeluxemaps.integer ? TEXF_COMPRESS : 0), -1, NULL);
5752 else
5753 {
5755 {
5756 textype_t t;
5758 {
5759 t = TEXTYPE_BGRA; // in stupid fallback mode, we upload lightmaps in sRGB form and just fix their brightness
5760 // we fix the brightness consistently via lightmapscale
5761 }
5762 else
5763 t = TEXTYPE_SRGB_BGRA; // normally, we upload lightmaps in sRGB form (possibly downconverted to linear)
5764 loadmodel->brushq3.data_lightmaps [lightmapindex] = R_LoadTexture2D(loadmodel->texturepool, va(vabuf, sizeof(vabuf), "lightmap%04i", lightmapindex), mergedwidth, mergedheight, mergedpixels, t, TEXF_FORCELINEAR | (gl_texturecompression_q3bsplightmaps.integer ? TEXF_COMPRESS : 0), -1, NULL);
5765 }
5766 else
5767 {
5769 Image_MakesRGBColorsFromLinear_Lightmap(mergedpixels, mergedpixels, mergedwidth * mergedheight);
5770 loadmodel->brushq3.data_lightmaps [lightmapindex] = R_LoadTexture2D(loadmodel->texturepool, va(vabuf, sizeof(vabuf), "lightmap%04i", lightmapindex), mergedwidth, mergedheight, mergedpixels, TEXTYPE_BGRA, TEXF_FORCELINEAR | (gl_texturecompression_q3bsplightmaps.integer ? TEXF_COMPRESS : 0), -1, NULL);
5771 }
5772 }
5773 }
5774 }
5775
5776 if (mergeddeluxepixels)
5777 Mem_Free(mergeddeluxepixels);
5778 Mem_Free(mergedpixels);
5779 if(external)
5780 {
5781 for(i = 0; i < count; ++i)
5782 Mem_Free(inpixels[i]);
5783 }
5784}
cvar_t gl_texturecompression_q3bsplightmaps
Definition gl_textures.c:43
cvar_t gl_texturecompression_q3bspdeluxemaps
Definition gl_textures.c:44
void Image_MakesRGBColorsFromLinear_Lightmap(unsigned char *pout, const unsigned char *pin, int numpixels)
Definition image.c:946
unsigned int CeilPowerOf2(unsigned int value)
returns the smallest integer greater than or equal to "value", or 0 if "value" is too big
Definition mathlib.c:292
textype_t
Definition r_textures.h:44
@ TEXTYPE_SRGB_BGRA
Definition r_textures.h:73
dp_FragColor rgb
int num_lightmapmergedwidthpower
int num_lightmapmergedheightpower

References bound, model_t::brushq3, ca_dedicated, CeilPowerOf2(), cls, Con_DPrintf(), Con_Printf(), count, model_brushq3_t::data_deluxemaps, model_brushq3_t::data_lightmaps, model_brushq3_t::deluxemapping, model_brushq3_t::deluxemapping_modelspace, developer_loading, lump_t::filelen, lump_t::fileofs, FS_StripExtension(), gl_texturecompression_q3bspdeluxemaps, gl_texturecompression_q3bsplightmaps, Host_Error(), i, image_height, Image_MakesRGBColorsFromLinear_Lightmap(), image_width, int(), cvar_t::integer, model_brushq3_t::lightmapsize, LittleLong, loadimagepixelsbgra(), loadmodel, mapname, max, MAX_QPATH, viddef_t::maxtexturesize_2d, Mem_Alloc, Mem_Free, model_t::mempool, mod_base, mod_q3bsp_lightmapmergepower, mod_q3bsp_nolightmaps, mod_q3bsp_sRGBlightmaps, model_t::name, NULL, model_brushq3_t::num_lightmapmergedheightpower, model_brushq3_t::num_lightmapmergedwidthheightdeluxepower, model_brushq3_t::num_lightmapmergedwidthpower, model_brushq3_t::num_mergedlightmaps, model_brushq3_t::num_originallightmaps, R_LoadTexture2D(), rgb, size, viddef_t::sRGB3D, client_static_t::state, tempmempool, TEXF_COMPRESS, TEXF_FORCELINEAR, model_t::texturepool, TEXTYPE_BGRA, TEXTYPE_SRGB_BGRA, va(), vid, vid_sRGB, and vid_sRGB_fallback.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadModels()

static void Mod_Q3BSP_LoadModels ( lump_t * l)
static

Definition at line 6262 of file model_brush.c.

6263{
6264 q3dmodel_t *in;
6265 q3dmodel_t *out;
6266 int i, j, n, c, count;
6267
6268 in = (q3dmodel_t *)(mod_base + l->fileofs);
6269 if (l->filelen % sizeof(*in))
6270 Host_Error("Mod_Q3BSP_LoadModels: funny lump size in %s",loadmodel->name);
6271 count = l->filelen / sizeof(*in);
6272 out = (q3dmodel_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
6273
6276
6277 for (i = 0;i < count;i++, in++, out++)
6278 {
6279 for (j = 0;j < 3;j++)
6280 {
6281 out->mins[j] = LittleFloat(in->mins[j]);
6282 out->maxs[j] = LittleFloat(in->maxs[j]);
6283 }
6284 n = LittleLong(in->firstface);
6285 c = LittleLong(in->numfaces);
6287 Host_Error("Mod_Q3BSP_LoadModels: invalid face range %i : %i (%i faces)", n, n + c, loadmodel->num_surfaces);
6288 out->firstface = n;
6289 out->numfaces = c;
6290 n = LittleLong(in->firstbrush);
6291 c = LittleLong(in->numbrushes);
6293 Host_Error("Mod_Q3BSP_LoadModels: invalid brush range %i : %i (%i brushes)", n, n + c, loadmodel->brush.num_brushes);
6294 out->firstbrush = n;
6295 out->numbrushes = c;
6296 }
6297}

References model_t::brush, model_t::brushq3, count, model_brushq3_t::data_models, lump_t::filelen, lump_t::fileofs, q3dmodel_t::firstbrush, q3dmodel_t::firstface, Host_Error(), i, LittleFloat, LittleLong, loadmodel, q3dmodel_t::maxs, Mem_Alloc, model_t::mempool, q3dmodel_t::mins, mod_base, n, model_t::name, model_brush_t::num_brushes, model_brushq3_t::num_models, model_t::num_surfaces, q3dmodel_t::numbrushes, and q3dmodel_t::numfaces.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadNodes()

static void Mod_Q3BSP_LoadNodes ( lump_t * l)
static

Definition at line 6390 of file model_brush.c.

6391{
6392 q3dnode_t *in;
6393 mnode_t *out;
6394 int i, j, n, count;
6395
6396 in = (q3dnode_t *)(mod_base + l->fileofs);
6397 if (l->filelen % sizeof(*in))
6398 Host_Error("Mod_Q3BSP_LoadNodes: funny lump size in %s",loadmodel->name);
6399 count = l->filelen / sizeof(*in);
6400 if (count == 0)
6401 Host_Error("Mod_Q3BSP_LoadNodes: missing BSP tree in %s",loadmodel->name);
6402 out = (mnode_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
6403
6404 loadmodel->brush.data_nodes = out;
6406
6407 for (i = 0;i < count;i++, in++, out++)
6408 {
6409 out->parent = NULL;
6410 n = LittleLong(in->planeindex);
6412 Host_Error("Mod_Q3BSP_LoadNodes: invalid planeindex %i (%i planes)", n, loadmodel->brush.num_planes);
6413 out->plane = loadmodel->brush.data_planes + n;
6414 for (j = 0;j < 2;j++)
6415 {
6416 n = LittleLong(in->childrenindex[j]);
6417 if (n >= 0)
6418 {
6419 if (n >= loadmodel->brush.num_nodes)
6420 Host_Error("Mod_Q3BSP_LoadNodes: invalid child node index %i (%i nodes)", n, loadmodel->brush.num_nodes);
6421 out->children[j] = loadmodel->brush.data_nodes + n;
6422 }
6423 else
6424 {
6425 n = -1 - n;
6426 if (n >= loadmodel->brush.num_leafs)
6427 Host_Error("Mod_Q3BSP_LoadNodes: invalid child leaf index %i (%i leafs)", n, loadmodel->brush.num_leafs);
6428 out->children[j] = (mnode_t *)(loadmodel->brush.data_leafs + n);
6429 }
6430 }
6431 for (j = 0;j < 3;j++)
6432 {
6433 // yes the mins/maxs are ints
6434 out->mins[j] = LittleLong(in->mins[j]) - 1;
6435 out->maxs[j] = LittleLong(in->maxs[j]) + 1;
6436 }
6437 }
6438
6439 // set the parent pointers
6441}

References model_t::brush, mnode_t::children, q3dnode_t::childrenindex, count, model_brush_t::data_leafs, model_brush_t::data_nodes, model_brush_t::data_planes, lump_t::filelen, lump_t::fileofs, Host_Error(), i, LittleLong, loadmodel, mnode_t::maxs, q3dnode_t::maxs, Mem_Alloc, model_t::mempool, mnode_t::mins, q3dnode_t::mins, mod_base, Mod_BSP_LoadNodes_RecursiveSetParent(), n, model_t::name, NULL, model_brush_t::num_leafs, model_brush_t::num_nodes, model_brush_t::num_planes, mnode_t::parent, mnode_t::plane, and q3dnode_t::planeindex.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadPlanes()

static void Mod_Q3BSP_LoadPlanes ( lump_t * l)
static

Definition at line 5245 of file model_brush.c.

5246{
5247 q3dplane_t *in;
5248 mplane_t *out;
5249 int i, count;
5250
5251 in = (q3dplane_t *)(mod_base + l->fileofs);
5252 if (l->filelen % sizeof(*in))
5253 Host_Error("Mod_Q3BSP_LoadPlanes: funny lump size in %s",loadmodel->name);
5254 count = l->filelen / sizeof(*in);
5255 out = (mplane_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
5256
5259
5260 for (i = 0;i < count;i++, in++, out++)
5261 {
5262 out->normal[0] = LittleFloat(in->normal[0]);
5263 out->normal[1] = LittleFloat(in->normal[1]);
5264 out->normal[2] = LittleFloat(in->normal[2]);
5265 out->dist = LittleFloat(in->dist);
5266 PlaneClassify(out);
5267 }
5268}

References model_t::brush, count, model_brush_t::data_planes, mplane_t::dist, q3dplane_t::dist, lump_t::filelen, lump_t::fileofs, Host_Error(), i, LittleFloat, loadmodel, Mem_Alloc, model_t::mempool, mod_base, model_t::name, mplane_t::normal, q3dplane_t::normal, model_brush_t::num_planes, and PlaneClassify().

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadPVS()

static void Mod_Q3BSP_LoadPVS ( lump_t * l)
static

Definition at line 6605 of file model_brush.c.

6606{
6607 q3dpvs_t *in;
6608 int totalchains;
6609
6610 if (l->filelen == 0)
6611 {
6612 int i;
6613 // unvised maps often have cluster indices even without pvs, so check
6614 // leafs to find real number of clusters
6616 for (i = 0;i < loadmodel->brush.num_leafs;i++)
6618
6619 // create clusters
6622 loadmodel->brush.data_pvsclusters = (unsigned char *)Mem_Alloc(loadmodel->mempool, totalchains);
6623 memset(loadmodel->brush.data_pvsclusters, 0xFF, totalchains);
6624 return;
6625 }
6626
6627 in = (q3dpvs_t *)(mod_base + l->fileofs);
6628 if (l->filelen < 9)
6629 Host_Error("Mod_Q3BSP_LoadPVS: funny lump size in %s",loadmodel->name);
6630
6634 Host_Error("Mod_Q3BSP_LoadPVS: (chainlength = %i) < ((numclusters = %i) + 7) / 8", loadmodel->brush.num_pvsclusterbytes, loadmodel->brush.num_pvsclusters);
6636 if (l->filelen < totalchains + (int)sizeof(*in))
6637 Host_Error("Mod_Q3BSP_LoadPVS: lump too small ((numclusters = %i) * (chainlength = %i) + sizeof(q3dpvs_t) == %i bytes, lump is %i bytes)", loadmodel->brush.num_pvsclusters, loadmodel->brush.num_pvsclusterbytes, (int)(totalchains + sizeof(*in)), l->filelen);
6638
6639 loadmodel->brush.data_pvsclusters = (unsigned char *)Mem_Alloc(loadmodel->mempool, totalchains);
6640 memcpy(loadmodel->brush.data_pvsclusters, (unsigned char *)(in + 1), totalchains);
6641}
int chainlength
int numclusters

References model_t::brush, q3dpvs_t::chainlength, mleaf_t::clusterindex, model_brush_t::data_leafs, model_brush_t::data_pvsclusters, lump_t::filelen, lump_t::fileofs, Host_Error(), i, LittleLong, loadmodel, max, Mem_Alloc, model_t::mempool, mod_base, model_t::name, model_brush_t::num_leafs, model_brush_t::num_pvsclusterbytes, model_brush_t::num_pvsclusters, and q3dpvs_t::numclusters.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadTextures()

static void Mod_Q3BSP_LoadTextures ( lump_t * l)
static

Definition at line 5218 of file model_brush.c.

5219{
5220 q3dtexture_t *in;
5221 texture_t *out;
5222 int i, count;
5223
5224 in = (q3dtexture_t *)(mod_base + l->fileofs);
5225 if (l->filelen % sizeof(*in))
5226 Host_Error("Mod_Q3BSP_LoadTextures: funny lump size in %s",loadmodel->name);
5227 count = l->filelen / sizeof(*in);
5228 out = (texture_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
5229
5230 loadmodel->data_textures = out;
5233
5234 for (i = 0;i < count;i++)
5235 {
5236 out[i].surfaceflags = LittleLong(in[i].surfaceflags);
5239 // restore the surfaceflags and supercontents
5240 out[i].surfaceflags = LittleLong(in[i].surfaceflags);
5242 }
5243}

References count, model_t::data_textures, lump_t::filelen, lump_t::fileofs, Host_Error(), i, LittleLong, loadmodel, MATERIALFLAG_WALL, Mem_Alloc, model_t::mempool, mod_base, Mod_LoadTextureFromQ3Shader(), Mod_Q3BSP_SuperContentsFromNativeContents(), model_t::name, q3dtexture_t::name, model_t::num_textures, model_t::num_texturesperskin, texture_t::supercontents, texture_t::surfaceflags, TEXF_COMPRESS, TEXF_ISWORLD, TEXF_MIPMAP, and TEXF_PICMIP.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadTriangles()

static void Mod_Q3BSP_LoadTriangles ( lump_t * l)
static

Definition at line 5482 of file model_brush.c.

5483{
5484 int *in;
5485 int *out;
5486 int i, count;
5487
5488 in = (int *)(mod_base + l->fileofs);
5489 if (l->filelen % sizeof(int[3]))
5490 Host_Error("Mod_Q3BSP_LoadTriangles: funny lump size in %s",loadmodel->name);
5491 count = l->filelen / sizeof(*in);
5492
5494 {
5495 if (count)
5496 Con_Printf("Mod_Q3BSP_LoadTriangles: %s has triangles but no vertexes, broken compiler, ignoring problem\n", loadmodel->name);
5498 return;
5499 }
5500
5501 out = (int *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
5504
5505 for (i = 0;i < count;i++, in++, out++)
5506 {
5507 *out = LittleLong(*in);
5508 if (*out < 0 || *out >= loadmodel->brushq3.num_vertices)
5509 {
5510 Con_Printf("Mod_Q3BSP_LoadTriangles: invalid vertexindex %i (%i vertices), setting to 0\n", *out, loadmodel->brushq3.num_vertices);
5511 *out = 0;
5512 }
5513 }
5514}

References model_t::brushq3, Con_Printf(), count, model_brushq3_t::data_element3i, lump_t::filelen, lump_t::fileofs, Host_Error(), i, LittleLong, loadmodel, Mem_Alloc, model_t::mempool, mod_base, model_t::name, model_brushq3_t::num_triangles, and model_brushq3_t::num_vertices.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_LoadVertices()

static void Mod_Q3BSP_LoadVertices ( lump_t * l)
static

Definition at line 5414 of file model_brush.c.

5415{
5416 q3dvertex_t *in;
5417 int i, count;
5418
5419 in = (q3dvertex_t *)(mod_base + l->fileofs);
5420 if (l->filelen % sizeof(*in))
5421 Host_Error("Mod_Q3BSP_LoadVertices: funny lump size in %s",loadmodel->name);
5422 loadmodel->brushq3.num_vertices = count = l->filelen / sizeof(*in);
5423 loadmodel->brushq3.data_vertex3f = (float *)Mem_Alloc(loadmodel->mempool, count * (sizeof(float) * (3 + 3 + 2 + 2 + 4)));
5428
5429 for (i = 0;i < count;i++, in++)
5430 {
5441 // svector/tvector are calculated later in face loading
5443 {
5444 // if lightmaps are sRGB, vertex colors are sRGB too, so we need to linearize them
5445 // note: when this is in use, lightmap color 128 is no longer neutral, but "sRGB half power" is
5446 // working like this may be odd, but matches q3map2 -gamma 2.2
5448 {
5449 loadmodel->brushq3.data_color4f[i * 4 + 0] = in->color4ub[0] * (1.0f / 255.0f);
5450 loadmodel->brushq3.data_color4f[i * 4 + 1] = in->color4ub[1] * (1.0f / 255.0f);
5451 loadmodel->brushq3.data_color4f[i * 4 + 2] = in->color4ub[2] * (1.0f / 255.0f);
5452 // we fix the brightness consistently via lightmapscale
5453 }
5454 else
5455 {
5459 }
5460 }
5461 else
5462 {
5464 {
5468 }
5469 else
5470 {
5471 loadmodel->brushq3.data_color4f[i * 4 + 0] = in->color4ub[0] * (1.0f / 255.0f);
5472 loadmodel->brushq3.data_color4f[i * 4 + 1] = in->color4ub[1] * (1.0f / 255.0f);
5473 loadmodel->brushq3.data_color4f[i * 4 + 2] = in->color4ub[2] * (1.0f / 255.0f);
5474 }
5475 }
5476 loadmodel->brushq3.data_color4f[i * 4 + 3] = in->color4ub[3] * (1.0f / 255.0f);
5477 if(in->color4ub[0] != 255 || in->color4ub[1] != 255 || in->color4ub[2] != 255)
5478 loadmodel->lit = true;
5479 }
5480}
float origin3f[3]
float normal3f[3]
float lightmap2f[2]
unsigned char color4ub[4]
float texcoord2f[2]

References model_t::brushq3, q3dvertex_t::color4ub, count, model_brushq3_t::data_color4f, model_brushq3_t::data_normal3f, model_brushq3_t::data_texcoordlightmap2f, model_brushq3_t::data_texcoordtexture2f, model_brushq3_t::data_vertex3f, lump_t::filelen, lump_t::fileofs, Host_Error(), i, Image_LinearFloatFromsRGB, Image_sRGBFloatFromLinear_Lightmap, cvar_t::integer, q3dvertex_t::lightmap2f, model_t::lit, LittleFloat, loadmodel, Mem_Alloc, model_t::mempool, mod_base, mod_q3bsp_sRGBlightmaps, model_t::name, q3dvertex_t::normal3f, model_brushq3_t::num_vertices, q3dvertex_t::origin3f, viddef_t::sRGB3D, q3dvertex_t::texcoord2f, vid, vid_sRGB, and vid_sRGB_fallback.

Referenced by Mod_Q3BSP_Load().

◆ Mod_Q3BSP_NativeContentsFromSuperContents()

static int Mod_Q3BSP_NativeContentsFromSuperContents ( int supercontents)
static

Definition at line 7578 of file model_brush.c.

7579{
7580 int nativecontents = 0;
7581 if (supercontents & SUPERCONTENTS_SOLID)
7582 nativecontents |= CONTENTSQ3_SOLID;
7583 if (supercontents & SUPERCONTENTS_WATER)
7584 nativecontents |= CONTENTSQ3_WATER;
7585 if (supercontents & SUPERCONTENTS_SLIME)
7586 nativecontents |= CONTENTSQ3_SLIME;
7587 if (supercontents & SUPERCONTENTS_LAVA)
7588 nativecontents |= CONTENTSQ3_LAVA;
7589 if (supercontents & SUPERCONTENTS_BODY)
7590 nativecontents |= CONTENTSQ3_BODY;
7591 if (supercontents & SUPERCONTENTS_CORPSE)
7592 nativecontents |= CONTENTSQ3_CORPSE;
7593 if (supercontents & SUPERCONTENTS_NODROP)
7594 nativecontents |= CONTENTSQ3_NODROP;
7595 if (supercontents & SUPERCONTENTS_PLAYERCLIP)
7596 nativecontents |= CONTENTSQ3_PLAYERCLIP;
7597 if (supercontents & SUPERCONTENTS_MONSTERCLIP)
7598 nativecontents |= CONTENTSQ3_MONSTERCLIP;
7599 if (supercontents & SUPERCONTENTS_DONOTENTER)
7600 nativecontents |= CONTENTSQ3_DONOTENTER;
7601 if (supercontents & SUPERCONTENTS_BOTCLIP)
7602 nativecontents |= CONTENTSQ3_BOTCLIP;
7603 if (!(supercontents & SUPERCONTENTS_OPAQUE))
7604 nativecontents |= CONTENTSQ3_TRANSLUCENT;
7605 return nativecontents;
7606}
#define CONTENTSQ3_MONSTERCLIP
Definition bspfile.h:181
#define SUPERCONTENTS_DONOTENTER
Definition bspfile.h:206
#define CONTENTSQ3_BOTCLIP
Definition bspfile.h:186
#define CONTENTSQ3_LAVA
Definition bspfile.h:175
#define SUPERCONTENTS_BOTCLIP
Definition bspfile.h:207
#define CONTENTSQ3_TRANSLUCENT
Definition bspfile.h:192
#define CONTENTSQ3_SOLID
Definition bspfile.h:174
#define CONTENTSQ3_DONOTENTER
Definition bspfile.h:185
#define CONTENTSQ3_BODY
Definition bspfile.h:188
#define CONTENTSQ3_NODROP
Definition bspfile.h:194
#define CONTENTSQ3_SLIME
Definition bspfile.h:176
#define CONTENTSQ3_WATER
Definition bspfile.h:177
#define CONTENTSQ3_PLAYERCLIP
Definition bspfile.h:180
#define CONTENTSQ3_CORPSE
Definition bspfile.h:189

References CONTENTSQ3_BODY, CONTENTSQ3_BOTCLIP, CONTENTSQ3_CORPSE, CONTENTSQ3_DONOTENTER, CONTENTSQ3_LAVA, CONTENTSQ3_MONSTERCLIP, CONTENTSQ3_NODROP, CONTENTSQ3_PLAYERCLIP, CONTENTSQ3_SLIME, CONTENTSQ3_SOLID, CONTENTSQ3_TRANSLUCENT, CONTENTSQ3_WATER, SUPERCONTENTS_BODY, SUPERCONTENTS_BOTCLIP, SUPERCONTENTS_CORPSE, SUPERCONTENTS_DONOTENTER, SUPERCONTENTS_LAVA, SUPERCONTENTS_MONSTERCLIP, SUPERCONTENTS_NODROP, SUPERCONTENTS_OPAQUE, SUPERCONTENTS_PLAYERCLIP, SUPERCONTENTS_SLIME, SUPERCONTENTS_SOLID, and SUPERCONTENTS_WATER.

Referenced by Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_Q3BSP_RecursiveFindNumLeafs()

static void Mod_Q3BSP_RecursiveFindNumLeafs ( mnode_t * node)
static

Definition at line 7608 of file model_brush.c.

7609{
7610 int numleafs;
7611 while (node->plane)
7612 {
7614 node = node->children[1];
7615 }
7616 numleafs = ((mleaf_t *)node - loadmodel->brush.data_leafs) + 1;
7617 if (loadmodel->brush.num_leafs < numleafs)
7618 loadmodel->brush.num_leafs = numleafs;
7619}

References model_t::brush, mnode_t::children, model_brush_t::data_leafs, loadmodel, Mod_Q3BSP_RecursiveFindNumLeafs(), model_brush_t::num_leafs, and mnode_t::plane.

Referenced by Mod_Q3BSP_Load(), and Mod_Q3BSP_RecursiveFindNumLeafs().

◆ Mod_Q3BSP_SuperContentsFromNativeContents()

static int Mod_Q3BSP_SuperContentsFromNativeContents ( int nativecontents)
static

Definition at line 7548 of file model_brush.c.

7549{
7550 int supercontents = 0;
7551 if (nativecontents & CONTENTSQ3_SOLID)
7552 supercontents |= SUPERCONTENTS_SOLID;
7553 if (nativecontents & CONTENTSQ3_WATER)
7554 supercontents |= SUPERCONTENTS_WATER;
7555 if (nativecontents & CONTENTSQ3_SLIME)
7556 supercontents |= SUPERCONTENTS_SLIME;
7557 if (nativecontents & CONTENTSQ3_LAVA)
7558 supercontents |= SUPERCONTENTS_LAVA;
7559 if (nativecontents & CONTENTSQ3_BODY)
7560 supercontents |= SUPERCONTENTS_BODY;
7561 if (nativecontents & CONTENTSQ3_CORPSE)
7562 supercontents |= SUPERCONTENTS_CORPSE;
7563 if (nativecontents & CONTENTSQ3_NODROP)
7564 supercontents |= SUPERCONTENTS_NODROP;
7565 if (nativecontents & CONTENTSQ3_PLAYERCLIP)
7566 supercontents |= SUPERCONTENTS_PLAYERCLIP;
7567 if (nativecontents & CONTENTSQ3_MONSTERCLIP)
7568 supercontents |= SUPERCONTENTS_MONSTERCLIP;
7569 if (nativecontents & CONTENTSQ3_DONOTENTER)
7570 supercontents |= SUPERCONTENTS_DONOTENTER;
7571 if (nativecontents & CONTENTSQ3_BOTCLIP)
7572 supercontents |= SUPERCONTENTS_BOTCLIP;
7573 if (!(nativecontents & CONTENTSQ3_TRANSLUCENT))
7574 supercontents |= SUPERCONTENTS_OPAQUE;
7575 return supercontents;
7576}

References CONTENTSQ3_BODY, CONTENTSQ3_BOTCLIP, CONTENTSQ3_CORPSE, CONTENTSQ3_DONOTENTER, CONTENTSQ3_LAVA, CONTENTSQ3_MONSTERCLIP, CONTENTSQ3_NODROP, CONTENTSQ3_PLAYERCLIP, CONTENTSQ3_SLIME, CONTENTSQ3_SOLID, CONTENTSQ3_TRANSLUCENT, CONTENTSQ3_WATER, SUPERCONTENTS_BODY, SUPERCONTENTS_BOTCLIP, SUPERCONTENTS_CORPSE, SUPERCONTENTS_DONOTENTER, SUPERCONTENTS_LAVA, SUPERCONTENTS_MONSTERCLIP, SUPERCONTENTS_NODROP, SUPERCONTENTS_OPAQUE, SUPERCONTENTS_PLAYERCLIP, SUPERCONTENTS_SLIME, SUPERCONTENTS_SOLID, and SUPERCONTENTS_WATER.

Referenced by Mod_Q3BSP_Load(), Mod_Q3BSP_LoadTextures(), and Mod_VBSP_Load().

◆ Mod_Q3BSP_TraceLineOfSight()

static qbool Mod_Q3BSP_TraceLineOfSight ( struct model_s * model,
const vec3_t start,
const vec3_t end,
const vec3_t acceptmins,
const vec3_t acceptmaxs )
static

Definition at line 6772 of file model_brush.c.

6773{
6774 if (model->brush.submodel || mod_q3bsp_tracelineofsight_brushes.integer)
6775 {
6776 trace_t trace;
6777 model->TraceLine(model, NULL, NULL, &trace, start, end, SUPERCONTENTS_VISBLOCKERMASK, 0, MATERIALFLAGMASK_TRANSLUCENT);
6778 return trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, acceptmins, acceptmaxs);
6779 }
6780 else
6781 {
6782 double tracestart[3], traceend[3], traceendpos[3];
6783 VectorCopy(start, tracestart);
6784 VectorCopy(end, traceend);
6785 VectorCopy(end, traceendpos);
6786 Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(model->brush.data_nodes, tracestart, traceend, traceendpos);
6787 return BoxesOverlap(traceendpos, traceendpos, acceptmins, acceptmaxs);
6788 }
6789}
static int Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(mnode_t *node, double p1[3], double p2[3], double endpos[3])

References BoxesOverlap, trace_t::endpos, trace_t::fraction, cvar_t::integer, MATERIALFLAGMASK_TRANSLUCENT, mod_q3bsp_tracelineofsight_brushes, Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(), model, NULL, SUPERCONTENTS_VISBLOCKERMASK, and VectorCopy.

Referenced by Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck()

static int Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck ( mnode_t * node,
double p1[3],
double p2[3],
double endpos[3] )
static

Definition at line 6710 of file model_brush.c.

6711{
6712 double t1, t2;
6713 double midf, mid[3];
6714 int ret, side;
6715
6716 // check for empty
6717 while (node->plane)
6718 {
6719 // find the point distances
6720 mplane_t *plane = node->plane;
6721 if (plane->type < 3)
6722 {
6723 t1 = p1[plane->type] - plane->dist;
6724 t2 = p2[plane->type] - plane->dist;
6725 }
6726 else
6727 {
6728 t1 = DotProduct (plane->normal, p1) - plane->dist;
6729 t2 = DotProduct (plane->normal, p2) - plane->dist;
6730 }
6731
6732 if (t1 < 0)
6733 {
6734 if (t2 < 0)
6735 {
6736 node = node->children[1];
6737 continue;
6738 }
6739 side = 1;
6740 }
6741 else
6742 {
6743 if (t2 >= 0)
6744 {
6745 node = node->children[0];
6746 continue;
6747 }
6748 side = 0;
6749 }
6750
6751 midf = t1 / (t1 - t2);
6752 VectorLerp(p1, midf, p2, mid);
6753
6754 // recurse both sides, front side first
6755 // return 2 if empty is followed by solid (hit something)
6756 // do not return 2 if both are solid or both empty,
6757 // or if start is solid and end is empty
6758 // as these degenerate cases usually indicate the eye is in solid and
6759 // should see the target point anyway
6760 ret = Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(node->children[side ], p1, mid, endpos);
6761 if (ret != 0)
6762 return ret;
6763 ret = Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(node->children[side ^ 1], mid, p2, endpos);
6764 if (ret != 1)
6765 return ret;
6766 VectorCopy(mid, endpos);
6767 return 2;
6768 }
6769 return ((mleaf_t *)node)->clusterindex < 0;
6770}

References mnode_t::children, mplane_t::dist, DotProduct, Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck(), mplane_t::normal, mnode_t::plane, ret, mplane_t::type, VectorCopy, and VectorLerp.

Referenced by Mod_Q3BSP_TraceLineOfSight(), and Mod_Q3BSP_TraceLineOfSight_RecursiveNodeCheck().

◆ Mod_VBSP_Load()

void Mod_VBSP_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 8312 of file model_brush.c.

8313{
8314 static cvar_t *testing = NULL; // TEMPORARY
8315 int i;
8316 sizebuf_t sb;
8317 sizebuf_t lumpsb[HL2HEADER_LUMPS];
8318
8319 if(!testing || !testing->integer)
8320 {
8321 if(!testing)
8322 testing = Cvar_Get(&cvars_all, "mod_bsp_vbsptest", "0", CF_CLIENT | CF_SERVER, "uhhh");
8323 Host_Error("Mod_VBSP_Load: not yet fully implemented. Change the now-generated \"mod_bsp_vbsptest\" to 1 if you wish to test this");
8324 }
8325 else
8326 {
8327
8328 MSG_InitReadBuffer(&sb, (unsigned char *)buffer, (unsigned char *)bufferend - (unsigned char *)buffer);
8329
8330 mod->type = mod_brushhl2;
8331
8332 MSG_ReadLittleLong(&sb);
8333 MSG_ReadLittleLong(&sb); // TODO version check
8334
8335 mod->modeldatatypestring = "VBSP";
8336
8337 // read lumps
8338 for (i = 0; i < HL2HEADER_LUMPS; i++)
8339 {
8340 int offset = MSG_ReadLittleLong(&sb);
8341 int size = MSG_ReadLittleLong(&sb);
8342 MSG_ReadLittleLong(&sb); // TODO support version
8343 MSG_ReadLittleLong(&sb); // TODO support ident
8345 Host_Error("Mod_VBSP_Load: %s has invalid lump %i (offset %i, size %i, file size %i)\n", mod->name, i, offset, size, (int)sb.cursize);
8346 MSG_InitReadBuffer(&lumpsb[i], sb.data + offset, size);
8347 }
8348
8349 MSG_ReadLittleLong(&sb); // TODO support revision field
8350
8351 mod->soundfromcenter = true;
8352 mod->TraceBox = Mod_CollisionBIH_TraceBox;
8353 mod->TraceBrush = Mod_CollisionBIH_TraceBrush;
8354 mod->TraceLine = Mod_CollisionBIH_TraceLine;
8355 mod->TracePoint = Mod_CollisionBIH_TracePoint;
8356 mod->PointSuperContents = Mod_CollisionBIH_PointSuperContents;
8357 mod->TraceLineAgainstSurfaces = Mod_CollisionBIH_TraceLine;
8358 mod->brush.TraceLineOfSight = Mod_Q3BSP_TraceLineOfSight; // probably not correct
8359 mod->brush.SuperContentsFromNativeContents = Mod_Q3BSP_SuperContentsFromNativeContents; // probably not correct
8360 mod->brush.NativeContentsFromSuperContents = Mod_Q3BSP_NativeContentsFromSuperContents; // probably not correct
8361 mod->brush.GetPVS = Mod_BSP_GetPVS;
8362 mod->brush.FatPVS = Mod_BSP_FatPVS;
8363 mod->brush.BoxTouchingPVS = Mod_BSP_BoxTouchingPVS;
8364 mod->brush.BoxTouchingLeafPVS = Mod_BSP_BoxTouchingLeafPVS;
8365 mod->brush.BoxTouchingVisibleLeafs = Mod_BSP_BoxTouchingVisibleLeafs;
8366 mod->brush.FindBoxClusters = Mod_BSP_FindBoxClusters;
8367 mod->brush.LightPoint = Mod_Q3BSP_LightPoint; // probably not correct
8368 mod->brush.FindNonSolidLocation = Mod_BSP_FindNonSolidLocation;
8369 mod->brush.AmbientSoundLevelsForPoint = NULL;
8370 mod->brush.RoundUpToHullSize = NULL;
8371 mod->brush.PointInLeaf = Mod_BSP_PointInLeaf;
8372 mod->Draw = R_Mod_Draw;
8373 mod->DrawDepth = R_Mod_DrawDepth;
8374 mod->DrawDebug = R_Mod_DrawDebug;
8375 mod->DrawPrepass = R_Mod_DrawPrepass;
8376 mod->GetLightInfo = R_Mod_GetLightInfo;
8377 mod->CompileShadowMap = R_Mod_CompileShadowMap;
8378 mod->DrawShadowMap = R_Mod_DrawShadowMap;
8379 mod->DrawLight = R_Mod_DrawLight;
8380
8381 // allocate a texture pool if we need it
8382 if (mod->texturepool == NULL)
8383 mod->texturepool = R_AllocTexturePool();
8384
8390 //Mod_VBSP_LoadLighting(&lumpsb[HL2LUMP_LIGHTING]);
8393
8394 // AHHHHHHH
8396 }
8397}
#define CF_SERVER
cvar/command that only the server can change/execute
Definition cmd.h:49
#define CF_CLIENT
cvar/command that only the client can change/execute
Definition cmd.h:48
cvar_state_t cvars_all
Definition cvar.c:28
cvar_t * Cvar_Get(cvar_state_t *cvars, const char *name, const char *value, unsigned flags, const char *newdescription)
allocates a cvar by name and returns its address, or merely sets its value if it already exists.
Definition cvar.c:695
static void Mod_VBSP_LoadEdges(sizebuf_t *sb)
static void Mod_VBSP_LoadPlanes(sizebuf_t *sb)
static void Mod_VBSP_LoadEntities(sizebuf_t *sb)
static void Mod_VBSP_LoadVertexes(sizebuf_t *sb)
static void Mod_VBSP_LoadSurfedges(sizebuf_t *sb)
static void Mod_VBSP_LoadTexinfo(sizebuf_t *sb)
static void Mod_VBSP_LoadFaces(sizebuf_t *sb)
static void Mod_VBSP_LoadTextures(sizebuf_t *sb)
@ mod_brushhl2
#define HL2HEADER_LUMPS
Definition model_vbsp.h:72
#define HL2LUMP_EDGES
Definition model_vbsp.h:86
#define HL2LUMP_TEXINFO
Definition model_vbsp.h:80
#define HL2LUMP_VERTEXES
Definition model_vbsp.h:77
#define HL2LUMP_FACES
Definition model_vbsp.h:81
#define HL2LUMP_PLANES
Definition model_vbsp.h:75
#define HL2LUMP_TEXDATA
Definition model_vbsp.h:76
#define HL2LUMP_ENTITIES
Definition model_vbsp.h:74
#define HL2LUMP_SURFEDGES
Definition model_vbsp.h:87
Definition cvar.h:66

References buffer, CF_CLIENT, CF_SERVER, sizebuf_t::cursize, Cvar_Get(), cvars_all, sizebuf_t::data, HL2HEADER_LUMPS, HL2LUMP_EDGES, HL2LUMP_ENTITIES, HL2LUMP_FACES, HL2LUMP_PLANES, HL2LUMP_SURFEDGES, HL2LUMP_TEXDATA, HL2LUMP_TEXINFO, HL2LUMP_VERTEXES, Host_Error(), i, cvar_t::integer, mod(), mod_brushhl2, Mod_BSP_BoxTouchingLeafPVS(), Mod_BSP_BoxTouchingPVS(), Mod_BSP_BoxTouchingVisibleLeafs(), Mod_BSP_FatPVS(), Mod_BSP_FindBoxClusters(), Mod_BSP_FindNonSolidLocation(), Mod_BSP_GetPVS(), Mod_BSP_PointInLeaf(), Mod_CollisionBIH_PointSuperContents(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint(), Mod_Q3BSP_LightPoint(), Mod_Q3BSP_NativeContentsFromSuperContents(), Mod_Q3BSP_SuperContentsFromNativeContents(), Mod_Q3BSP_TraceLineOfSight(), Mod_VBSP_LoadEdges(), Mod_VBSP_LoadEntities(), Mod_VBSP_LoadFaces(), Mod_VBSP_LoadPlanes(), Mod_VBSP_LoadSurfedges(), Mod_VBSP_LoadTexinfo(), Mod_VBSP_LoadTextures(), Mod_VBSP_LoadVertexes(), MSG_InitReadBuffer(), MSG_ReadLittleLong(), NULL, offset, R_AllocTexturePool(), R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), R_Mod_GetLightInfo(), and size.

◆ Mod_VBSP_LoadEdges()

static void Mod_VBSP_LoadEdges ( sizebuf_t * sb)
static

Definition at line 7919 of file model_brush.c.

7920{
7921 medge_t *out;
7922 int i, count;
7923 int structsize = 4;
7924
7925 if (sb->cursize % structsize)
7926 Host_Error("Mod_VBSP_LoadEdges: funny lump size in %s",loadmodel->name);
7927 count = sb->cursize / structsize;
7928 out = (medge_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
7929
7930 loadmodel->brushq1.edges = out;
7932
7933 for ( i=0 ; i<count ; i++, out++)
7934 {
7935 out->v[0] = (unsigned short)MSG_ReadLittleShort(sb);
7936 out->v[1] = (unsigned short)MSG_ReadLittleShort(sb);
7937
7938 if ((int)out->v[0] >= loadmodel->brushq1.numvertexes || (int)out->v[1] >= loadmodel->brushq1.numvertexes)
7939 {
7940 Con_Printf("Mod_VBSP_LoadEdges: %s has invalid vertex indices in edge %i (vertices %i %i >= numvertices %i)\n", loadmodel->name, i, out->v[0], out->v[1], loadmodel->brushq1.numvertexes);
7942 Host_Error("Mod_VBSP_LoadEdges: %s has edges but no vertexes, cannot fix\n", loadmodel->name);
7943
7944 out->v[0] = 0;
7945 out->v[1] = 0;
7946 }
7947 }
7948}

References model_t::brushq1, Con_Printf(), count, sizebuf_t::cursize, model_brushq1_t::edges, Host_Error(), i, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadLittleShort(), model_t::name, model_brushq1_t::numedges, model_brushq1_t::numvertexes, and medge_t::v.

Referenced by Mod_VBSP_Load().

◆ Mod_VBSP_LoadEntities()

static void Mod_VBSP_LoadEntities ( sizebuf_t * sb)
static

Definition at line 7887 of file model_brush.c.

7888{
7890 if (!sb->cursize)
7891 return;
7893 MSG_ReadBytes(sb, sb->cursize, (unsigned char *)loadmodel->brush.entities);
7894 loadmodel->brush.entities[sb->cursize] = 0;
7895}

References model_t::brush, sizebuf_t::cursize, model_brush_t::entities, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadBytes(), and NULL.

Referenced by Mod_VBSP_Load().

◆ Mod_VBSP_LoadFaces()

static void Mod_VBSP_LoadFaces ( sizebuf_t * sb)
static

Definition at line 8040 of file model_brush.c.

8041{
8042 msurface_t *surface;
8043 int i, j, count, surfacenum, planenum, smax, tmax, ssize, tsize, firstedge, numedges, totalverts, totaltris, lightmapnumber, lightmapsize, totallightmapsamples, lightmapoffset, texinfoindex;
8044 float texmins[2], texmaxs[2], val;
8045 rtexture_t *lightmaptexture, *deluxemaptexture;
8046 char vabuf[1024];
8047 int structsize = 56;
8048
8049 if (sb->cursize % structsize)
8050 Host_Error("Mod_VBSP_LoadFaces: funny lump size in %s",loadmodel->name);
8051 count = sb->cursize / structsize;
8054
8056
8058 loadmodel->brushq1.lightmapupdateflags = (unsigned char *)Mem_Alloc(loadmodel->mempool, count*sizeof(unsigned char));
8059
8060 totalverts = 0;
8061 totaltris = 0;
8062 for (surfacenum = 0;surfacenum < count;surfacenum++)
8063 {
8064 numedges = BuffLittleShort(sb->data + structsize * surfacenum + 8);
8065 totalverts += numedges;
8066 totaltris += numedges - 2;
8067 }
8068
8069 Mod_AllocSurfMesh(loadmodel->mempool, totalverts, totaltris, true, false);
8070
8071 lightmaptexture = NULL;
8072 deluxemaptexture = r_texture_blanknormalmap;
8073 lightmapnumber = 0;
8074 lightmapsize = bound(256, gl_max_lightmapsize.integer, (int)vid.maxtexturesize_2d);
8075 totallightmapsamples = 0;
8076
8077 totalverts = 0;
8078 totaltris = 0;
8079 for (surfacenum = 0, surface = loadmodel->data_surfaces;surfacenum < count;surfacenum++, surface++)
8080 {
8081 surface->lightmapinfo = loadmodel->data_surfaces_lightmapinfo + surfacenum;
8082 planenum = (unsigned short)MSG_ReadLittleShort(sb);
8083 /*side = */MSG_ReadLittleShort(sb); // TODO support onNode?
8084 firstedge = MSG_ReadLittleLong(sb);
8085 numedges = (unsigned short)MSG_ReadLittleShort(sb);
8086 texinfoindex = (unsigned short)MSG_ReadLittleShort(sb);
8087 MSG_ReadLittleLong(sb); // skipping over dispinfo and surfaceFogVolumeID, both short
8088 for (i = 0;i < MAXLIGHTMAPS;i++)
8089 surface->lightmapinfo->styles[i] = MSG_ReadByte(sb);
8090 lightmapoffset = MSG_ReadLittleLong(sb);
8091
8092 // FIXME: validate edges, texinfo, etc?
8093 if ((unsigned int) firstedge > (unsigned int) loadmodel->brushq1.numsurfedges || (unsigned int) numedges > (unsigned int) loadmodel->brushq1.numsurfedges || (unsigned int) firstedge + (unsigned int) numedges > (unsigned int) loadmodel->brushq1.numsurfedges)
8094 Host_Error("Mod_VBSP_LoadFaces: invalid edge range (firstedge %i, numedges %i, model edges %i)", firstedge, numedges, loadmodel->brushq1.numsurfedges);
8095 if ((unsigned int) texinfoindex >= (unsigned int) loadmodel->brushq1.numtexinfo)
8096 Host_Error("Mod_VBSP_LoadFaces: invalid texinfo index %i(model has %i texinfos)", texinfoindex, loadmodel->brushq1.numtexinfo);
8097 if ((unsigned int) planenum >= (unsigned int) loadmodel->brush.num_planes)
8098 Host_Error("Mod_VBSP_LoadFaces: invalid plane index %i (model has %i planes)", planenum, loadmodel->brush.num_planes);
8099
8100 surface->lightmapinfo->texinfo = loadmodel->brushq1.texinfo + texinfoindex;
8102
8103 // Q2BSP doesn't use lightmaps on sky or warped surfaces (water), but still has a lightofs of 0
8104 if (lightmapoffset == 0 && (surface->texture->q2flags & (Q2SURF_SKY | Q2SURF_WARP)))
8105 lightmapoffset = -1;
8106
8107 //surface->flags = surface->texture->flags;
8108 //if (LittleShort(in->side))
8109 // surface->flags |= SURF_PLANEBACK;
8110 //surface->plane = loadmodel->brush.data_planes + planenum;
8111
8112 surface->num_firstvertex = totalverts;
8113 surface->num_vertices = numedges;
8114 surface->num_firsttriangle = totaltris;
8115 surface->num_triangles = numedges - 2;
8116 totalverts += numedges;
8117 totaltris += numedges - 2;
8118
8119 // convert edges back to a normal polygon
8120 for (i = 0;i < surface->num_vertices;i++)
8121 {
8122 int lindex = loadmodel->brushq1.surfedges[firstedge + i];
8123 float s, t;
8124 // note: the q1bsp format does not allow a 0 surfedge (it would have no negative counterpart)
8125 if (lindex >= 0)
8127 else
8129 s = DotProduct(((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3), surface->lightmapinfo->texinfo->vecs[0]) + surface->lightmapinfo->texinfo->vecs[0][3];
8130 t = DotProduct(((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3), surface->lightmapinfo->texinfo->vecs[1]) + surface->lightmapinfo->texinfo->vecs[1][3];
8131 (loadmodel->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[i * 2 + 0] = s / surface->texture->width;
8132 (loadmodel->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[i * 2 + 1] = t / surface->texture->height;
8133 (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[i * 2 + 0] = 0;
8134 (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[i * 2 + 1] = 0;
8136 }
8137
8138 for (i = 0;i < surface->num_triangles;i++)
8139 {
8140 (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle)[i * 3 + 0] = 0 + surface->num_firstvertex;
8141 (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle)[i * 3 + 1] = i + 1 + surface->num_firstvertex;
8142 (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle)[i * 3 + 2] = i + 2 + surface->num_firstvertex;
8143 }
8144
8145 // compile additional data about the surface geometry
8148 BoxFromPoints(surface->mins, surface->maxs, surface->num_vertices, (loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex));
8149
8150 // generate surface extents information
8151 texmins[0] = texmaxs[0] = DotProduct((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex), surface->lightmapinfo->texinfo->vecs[0]) + surface->lightmapinfo->texinfo->vecs[0][3];
8152 texmins[1] = texmaxs[1] = DotProduct((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex), surface->lightmapinfo->texinfo->vecs[1]) + surface->lightmapinfo->texinfo->vecs[1][3];
8153 for (i = 1;i < surface->num_vertices;i++)
8154 {
8155 for (j = 0;j < 2;j++)
8156 {
8157 val = DotProduct((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3, surface->lightmapinfo->texinfo->vecs[j]) + surface->lightmapinfo->texinfo->vecs[j][3];
8158 texmins[j] = min(texmins[j], val);
8159 texmaxs[j] = max(texmaxs[j], val);
8160 }
8161 }
8162 for (i = 0;i < 2;i++)
8163 {
8164 surface->lightmapinfo->texturemins[i] = (int) floor(texmins[i] / 16.0) * 16;
8165 surface->lightmapinfo->extents[i] = (int) ceil(texmaxs[i] / 16.0) * 16 - surface->lightmapinfo->texturemins[i];
8166 }
8167
8168 smax = surface->lightmapinfo->extents[0] >> 4;
8169 tmax = surface->lightmapinfo->extents[1] >> 4;
8170 ssize = (surface->lightmapinfo->extents[0] >> 4) + 1;
8171 tsize = (surface->lightmapinfo->extents[1] >> 4) + 1;
8172
8173 // lighting info
8174 surface->lightmaptexture = NULL;
8176 if (lightmapoffset == -1)
8177 {
8178 surface->lightmapinfo->samples = NULL;
8179#if 1
8180 // give non-lightmapped water a 1x white lightmap
8181 if (!loadmodel->brush.isq2bsp && surface->texture->name[0] == '*' && (surface->lightmapinfo->texinfo->q1flags & TEX_SPECIAL) && ssize <= 256 && tsize <= 256)
8182 {
8183 surface->lightmapinfo->samples = (unsigned char *)Mem_Alloc(loadmodel->mempool, ssize * tsize * 3);
8184 surface->lightmapinfo->styles[0] = 0;
8185 memset(surface->lightmapinfo->samples, 128, ssize * tsize * 3);
8186 }
8187#endif
8188 }
8189 else
8190 surface->lightmapinfo->samples = loadmodel->brushq1.lightdata + lightmapoffset;
8191
8192 // check if we should apply a lightmap to this
8193 if (!(surface->lightmapinfo->texinfo->q1flags & TEX_SPECIAL) || surface->lightmapinfo->samples)
8194 {
8195 if (ssize > 256 || tsize > 256)
8196 Host_Error("Bad surface extents");
8197
8198 if (lightmapsize < ssize)
8199 lightmapsize = ssize;
8200 if (lightmapsize < tsize)
8201 lightmapsize = tsize;
8202
8203 totallightmapsamples += ssize*tsize;
8204
8205 // force lightmap upload on first time seeing the surface
8206 //
8207 // additionally this is used by the later code to see if a
8208 // lightmap is needed on this surface (rather than duplicating the
8209 // logic above)
8210 loadmodel->brushq1.lightmapupdateflags[surfacenum] = true;
8211 loadmodel->lit = true;
8212 }
8213 }
8214
8215 // small maps (such as ammo boxes especially) don't need big lightmap
8216 // textures, so this code tries to guess a good size based on
8217 // totallightmapsamples (size of the lightmaps lump basically), as well as
8218 // trying to max out the size if there is a lot of lightmap data to store
8219 // additionally, never choose a lightmapsize that is smaller than the
8220 // largest surface encountered (as it would fail)
8221 i = lightmapsize;
8222 for (lightmapsize = 64; (lightmapsize < i) && (lightmapsize < bound(128, gl_max_lightmapsize.integer, (int)vid.maxtexturesize_2d)) && (totallightmapsamples > lightmapsize*lightmapsize); lightmapsize*=2)
8223 ;
8224
8225 // now that we've decided the lightmap texture size, we can do the rest
8226 if (cls.state != ca_dedicated)
8227 {
8228 int stainmapsize = 0;
8229 mod_alloclightmap_state_t allocState;
8230
8231 Mod_AllocLightmap_Init(&allocState, loadmodel->mempool, lightmapsize, lightmapsize);
8232 for (surfacenum = 0, surface = loadmodel->data_surfaces;surfacenum < count;surfacenum++, surface++)
8233 {
8234 int iu, iv, lightmapx = 0, lightmapy = 0;
8235 float u, v, ubase, vbase, uscale, vscale;
8236
8237 if (!loadmodel->brushq1.lightmapupdateflags[surfacenum])
8238 continue;
8239
8240 smax = surface->lightmapinfo->extents[0] >> 4;
8241 tmax = surface->lightmapinfo->extents[1] >> 4;
8242 ssize = (surface->lightmapinfo->extents[0] >> 4) + 1;
8243 tsize = (surface->lightmapinfo->extents[1] >> 4) + 1;
8244 stainmapsize += ssize * tsize * 3;
8245
8246 if (!lightmaptexture || !Mod_AllocLightmap_Block(&allocState, ssize, tsize, &lightmapx, &lightmapy))
8247 {
8248 // allocate a texture pool if we need it
8249 if (loadmodel->texturepool == NULL)
8251 // could not find room, make a new lightmap
8252 loadmodel->brushq3.num_mergedlightmaps = lightmapnumber + 1;
8255 loadmodel->brushq3.data_lightmaps[lightmapnumber] = lightmaptexture = R_LoadTexture2D(loadmodel->texturepool, va(vabuf, sizeof(vabuf), "lightmap%i", lightmapnumber), lightmapsize, lightmapsize, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_ALLOWUPDATES, -1, NULL);
8257 loadmodel->brushq3.data_deluxemaps[lightmapnumber] = deluxemaptexture = R_LoadTexture2D(loadmodel->texturepool, va(vabuf, sizeof(vabuf), "deluxemap%i", lightmapnumber), lightmapsize, lightmapsize, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_ALLOWUPDATES, -1, NULL);
8258 lightmapnumber++;
8259 Mod_AllocLightmap_Reset(&allocState);
8260 Mod_AllocLightmap_Block(&allocState, ssize, tsize, &lightmapx, &lightmapy);
8261 }
8262 surface->lightmaptexture = lightmaptexture;
8263 surface->deluxemaptexture = deluxemaptexture;
8264 surface->lightmapinfo->lightmaporigin[0] = lightmapx;
8265 surface->lightmapinfo->lightmaporigin[1] = lightmapy;
8266
8267 uscale = 1.0f / (float)lightmapsize;
8268 vscale = 1.0f / (float)lightmapsize;
8269 ubase = lightmapx * uscale;
8270 vbase = lightmapy * vscale;
8271
8272 for (i = 0;i < surface->num_vertices;i++)
8273 {
8274 u = ((DotProduct(((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3), surface->lightmapinfo->texinfo->vecs[0]) + surface->lightmapinfo->texinfo->vecs[0][3]) + 8 - surface->lightmapinfo->texturemins[0]) * (1.0 / 16.0);
8275 v = ((DotProduct(((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3), surface->lightmapinfo->texinfo->vecs[1]) + surface->lightmapinfo->texinfo->vecs[1][3]) + 8 - surface->lightmapinfo->texturemins[1]) * (1.0 / 16.0);
8276 (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[i * 2 + 0] = u * uscale + ubase;
8277 (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[i * 2 + 1] = v * vscale + vbase;
8278 // LadyHavoc: calc lightmap data offset for vertex lighting to use
8279 iu = (int) u;
8280 iv = (int) v;
8281 (loadmodel->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i] = (bound(0, iv, tmax) * ssize + bound(0, iu, smax)) * 3;
8282 }
8283 }
8284
8286 {
8287 // allocate stainmaps for permanent marks on walls and clear white
8288 unsigned char *stainsamples = NULL;
8289 stainsamples = (unsigned char *)Mem_Alloc(loadmodel->mempool, stainmapsize);
8290 memset(stainsamples, 255, stainmapsize);
8291 // assign pointers
8292 for (surfacenum = 0, surface = loadmodel->data_surfaces;surfacenum < count;surfacenum++, surface++)
8293 {
8294 if (!loadmodel->brushq1.lightmapupdateflags[surfacenum])
8295 continue;
8296 ssize = (surface->lightmapinfo->extents[0] >> 4) + 1;
8297 tsize = (surface->lightmapinfo->extents[1] >> 4) + 1;
8298 surface->lightmapinfo->stainsamples = stainsamples;
8299 stainsamples += ssize * tsize * 3;
8300 }
8301 }
8302 }
8303
8304 // generate ushort elements array if possible
8306 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
8308}

References bound, BoxFromPoints(), model_t::brush, model_t::brushq1, model_t::brushq3, BuffLittleShort(), ca_dedicated, ceil(), cl_stainmaps, cls, count, sizebuf_t::cursize, sizebuf_t::data, model_brushq3_t::data_deluxemaps, surfmesh_t::data_element3i, surfmesh_t::data_element3s, surfmesh_t::data_lightmapoffsets, model_brushq3_t::data_lightmaps, surfmesh_t::data_normal3f, model_t::data_surfaces, model_t::data_surfaces_lightmapinfo, surfmesh_t::data_svector3f, surfmesh_t::data_texcoordlightmap2f, surfmesh_t::data_texcoordtexture2f, model_t::data_textures, surfmesh_t::data_tvector3f, surfmesh_t::data_vertex3f, msurface_t::deluxemaptexture, DotProduct, model_brushq1_t::edges, msurface_lightmapinfo_t::extents, model_brushq1_t::firstrender, float, floor(), gl_max_lightmapsize, texture_t::height, Host_Error(), i, int(), cvar_t::integer, model_brush_t::isq2bsp, model_brushq1_t::lightdata, msurface_t::lightmapinfo, msurface_lightmapinfo_t::lightmaporigin, msurface_t::lightmaptexture, model_brushq1_t::lightmapupdateflags, model_t::lit, loadmodel, max, MAXLIGHTMAPS, msurface_t::maxs, viddef_t::maxtexturesize_2d, Mem_Alloc, Mem_Realloc, model_t::mempool, min, msurface_t::mins, Mod_AllocLightmap_Block(), Mod_AllocLightmap_Init(), Mod_AllocLightmap_Reset(), Mod_AllocSurfMesh(), Mod_BuildNormals(), Mod_BuildTextureVectorsFromNormals(), MSG_ReadByte, MSG_ReadLittleLong(), MSG_ReadLittleShort(), model_t::name, texture_t::name, model_brushq1_t::nmaplightdata, NULL, msurface_t::num_firsttriangle, msurface_t::num_firstvertex, model_brushq3_t::num_mergedlightmaps, model_brush_t::num_planes, model_t::num_surfaces, msurface_t::num_triangles, surfmesh_t::num_triangles, msurface_t::num_vertices, model_brushq1_t::numsurfedges, model_brushq1_t::numtexinfo, mvertex_t::position, mtexinfo_t::q1flags, texture_t::q2flags, Q2SURF_SKY, Q2SURF_WARP, R_AllocTexturePool(), R_LoadTexture2D(), r_smoothnormals_areaweighting, r_texture_blanknormalmap, msurface_lightmapinfo_t::samples, msurface_lightmapinfo_t::stainsamples, client_static_t::state, msurface_lightmapinfo_t::styles, model_brushq1_t::surfedges, model_t::surfmesh, TEX_SPECIAL, TEXF_ALLOWUPDATES, TEXF_FORCELINEAR, model_brushq1_t::texinfo, msurface_lightmapinfo_t::texinfo, msurface_t::texture, mtexinfo_t::textureindex, msurface_lightmapinfo_t::texturemins, model_t::texturepool, TEXTYPE_BGRA, medge_t::v, v, va(), mtexinfo_t::vecs, VectorCopy, model_brushq1_t::vertexes, vid, and texture_t::width.

Referenced by Mod_VBSP_Load().

◆ Mod_VBSP_LoadPlanes()

static void Mod_VBSP_LoadPlanes ( sizebuf_t * sb)
static

Definition at line 7969 of file model_brush.c.

7970{
7971 int i;
7972 mplane_t *out;
7973 int structsize = 20;
7974
7975 if (sb->cursize % structsize)
7976 Host_Error("Mod_VBSP_LoadPlanes: funny lump size in %s", loadmodel->name);
7977 loadmodel->brush.num_planes = sb->cursize / structsize;
7979
7980 for (i = 0;i < loadmodel->brush.num_planes;i++, out++)
7981 {
7982 out->normal[0] = MSG_ReadLittleFloat(sb);
7983 out->normal[1] = MSG_ReadLittleFloat(sb);
7984 out->normal[2] = MSG_ReadLittleFloat(sb);
7985 out->dist = MSG_ReadLittleFloat(sb);
7986 MSG_ReadLittleLong(sb); // type is not used, we use PlaneClassify
7987 PlaneClassify(out);
7988 }
7989}

References model_t::brush, sizebuf_t::cursize, model_brush_t::data_planes, mplane_t::dist, Host_Error(), i, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadLittleFloat(), MSG_ReadLittleLong(), model_t::name, mplane_t::normal, model_brush_t::num_planes, and PlaneClassify().

Referenced by Mod_VBSP_Load().

◆ Mod_VBSP_LoadSurfedges()

static void Mod_VBSP_LoadSurfedges ( sizebuf_t * sb)
static

Definition at line 7950 of file model_brush.c.

7951{
7952 int i;
7953 int structsize = 4;
7954
7955 if (sb->cursize % structsize)
7956 Host_Error("Mod_VBSP_LoadSurfedges: funny lump size in %s",loadmodel->name);
7957 loadmodel->brushq1.numsurfedges = sb->cursize / structsize;
7959
7960 for (i = 0;i < loadmodel->brushq1.numsurfedges;i++)
7962}

References model_t::brushq1, sizebuf_t::cursize, Host_Error(), i, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadLittleLong(), model_t::name, model_brushq1_t::numsurfedges, and model_brushq1_t::surfedges.

Referenced by Mod_VBSP_Load().

◆ Mod_VBSP_LoadTexinfo()

static void Mod_VBSP_LoadTexinfo ( sizebuf_t * sb)
static

Definition at line 7991 of file model_brush.c.

7992{
7993 mtexinfo_t *out;
7994 int i, j, k, count, miptex;
7995 int structsize = 72;
7996
7997 if (sb->cursize % structsize)
7998 Host_Error("Mod_VBSP_LoadTexinfo: funny lump size in %s",loadmodel->name);
7999 count = sb->cursize / structsize;
8000 out = (mtexinfo_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
8001
8002 loadmodel->brushq1.texinfo = out;
8004
8005 for (i = 0;i < count;i++, out++)
8006 {
8007 for (k = 0;k < 2;k++)
8008 for (j = 0;j < 4;j++)
8009 out->vecs[k][j] = MSG_ReadLittleFloat(sb);
8010
8011 for (k = 0;k < 2;k++)
8012 for (j = 0;j < 4;j++)
8013 MSG_ReadLittleFloat(sb); // TODO lightmapVecs
8014
8015 out->q1flags = MSG_ReadLittleLong(sb);
8016 miptex = MSG_ReadLittleLong(sb);
8017
8018 if (out->q1flags & TEX_SPECIAL)
8019 {
8020 // if texture chosen is NULL or the shader needs a lightmap,
8021 // force to notexture water shader
8023 }
8024 else
8025 {
8026 // if texture chosen is NULL, force to notexture
8028 }
8029 // see if the specified miptex is valid and try to use it instead
8031 {
8032 if ((unsigned int) miptex >= (unsigned int) loadmodel->num_textures)
8033 Con_Printf("error in model \"%s\": invalid miptex index %i(of %i)\n", loadmodel->name, miptex, loadmodel->num_textures);
8034 else
8035 out->textureindex = miptex;
8036 }
8037 }
8038}

References model_t::brushq1, Con_Printf(), count, sizebuf_t::cursize, model_t::data_textures, Host_Error(), i, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadLittleFloat(), MSG_ReadLittleLong(), model_t::name, model_t::num_textures, model_brushq1_t::numtexinfo, mtexinfo_t::q1flags, TEX_SPECIAL, model_brushq1_t::texinfo, mtexinfo_t::textureindex, and mtexinfo_t::vecs.

Referenced by Mod_VBSP_Load().

◆ Mod_VBSP_LoadTextures()

static void Mod_VBSP_LoadTextures ( sizebuf_t * sb)
static

Definition at line 7964 of file model_brush.c.

7965{
7966 Con_Printf(CON_WARN "Mod_VBSP_LoadTextures: Don't know how to do this yet\n");
7967}

References Con_Printf(), and CON_WARN.

Referenced by Mod_VBSP_Load().

◆ Mod_VBSP_LoadVertexes()

static void Mod_VBSP_LoadVertexes ( sizebuf_t * sb)
static

Definition at line 7897 of file model_brush.c.

7898{
7899 mvertex_t *out;
7900 int i, count;
7901 int structsize = 12;
7902
7903 if (sb->cursize % structsize)
7904 Host_Error("Mod_VBSP_LoadVertexes: funny lump size in %s",loadmodel->name);
7905 count = sb->cursize / structsize;
7906 out = (mvertex_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
7907
7908 loadmodel->brushq1.vertexes = out;
7910
7911 for ( i=0 ; i<count ; i++, out++)
7912 {
7913 out->position[0] = MSG_ReadLittleFloat(sb);
7914 out->position[1] = MSG_ReadLittleFloat(sb);
7915 out->position[2] = MSG_ReadLittleFloat(sb);
7916 }
7917}

References model_t::brushq1, count, sizebuf_t::cursize, Host_Error(), i, loadmodel, Mem_Alloc, model_t::mempool, MSG_ReadLittleFloat(), model_t::name, model_brushq1_t::numvertexes, mvertex_t::position, and model_brushq1_t::vertexes.

Referenced by Mod_VBSP_Load().

◆ RemovePortalFromNodes()

static void RemovePortalFromNodes ( portal_t * portal)
static

Definition at line 3569 of file model_brush.c.

3570{
3571 int i;
3572 mnode_t *node;
3573 void **portalpointer;
3574 portal_t *t;
3575 for (i = 0;i < 2;i++)
3576 {
3577 node = portal->nodes[i];
3578
3579 portalpointer = (void **) &node->portals;
3580 while (1)
3581 {
3582 t = (portal_t *)*portalpointer;
3583 if (!t)
3584 Host_Error("RemovePortalFromNodes: portal not in leaf");
3585
3586 if (t == portal)
3587 {
3588 if (portal->nodes[0] == node)
3589 {
3590 *portalpointer = portal->next[0];
3591 portal->nodes[0] = NULL;
3592 }
3593 else if (portal->nodes[1] == node)
3594 {
3595 *portalpointer = portal->next[1];
3596 portal->nodes[1] = NULL;
3597 }
3598 else
3599 Host_Error("RemovePortalFromNodes: portal not bounding leaf");
3600 break;
3601 }
3602
3603 if (t->nodes[0] == node)
3604 portalpointer = (void **) &t->next[0];
3605 else if (t->nodes[1] == node)
3606 portalpointer = (void **) &t->next[1];
3607 else
3608 Host_Error("RemovePortalFromNodes: portal not bounding leaf");
3609 }
3610 }
3611}

References Host_Error(), i, portal_t::next, portal_t::nodes, NULL, and mnode_t::portals.

Referenced by Mod_BSP_RecursiveNodePortals().

Variable Documentation

◆ gl_max_lightmapsize

cvar_t gl_max_lightmapsize
extern

Definition at line 28 of file gl_textures.c.

28{CF_CLIENT | CF_ARCHIVE, "gl_max_lightmapsize", "512", "maximum allowed texture size for lightmap textures, use larger values to improve rendering speed, as long as there is enough video memory available (setting it too high for the hardware will cause very bad performance)"};
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
Definition cmd.h:53

Referenced by Mod_Q1BSP_LoadFaces(), Mod_VBSP_LoadFaces(), and R_Textures_Init().

◆ mod_bsp_portalize

cvar_t mod_bsp_portalize = {CF_CLIENT, "mod_bsp_portalize", "0", "enables portal generation from BSP tree (takes a minute or more and GBs of memory when loading a complex map), used by r_drawportals, r_useportalculling, r_shadow_realtime_dlight_portalculling, r_shadow_realtime_world_compileportalculling"}

Definition at line 67 of file model_brush.c.

67{CF_CLIENT, "mod_bsp_portalize", "0", "enables portal generation from BSP tree (takes a minute or more and GBs of memory when loading a complex map), used by r_drawportals, r_useportalculling, r_shadow_realtime_dlight_portalculling, r_shadow_realtime_world_compileportalculling"};

Referenced by Mod_BrushInit(), Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), and Mod_Q3BSP_Load().

◆ mod_noshader_default_offsetmapping

cvar_t mod_noshader_default_offsetmapping = {CF_CLIENT | CF_ARCHIVE, "mod_noshader_default_offsetmapping", "1", "use offsetmapping by default on all surfaces that are not using q3 shader files"}

Definition at line 51 of file model_brush.c.

51{CF_CLIENT | CF_ARCHIVE, "mod_noshader_default_offsetmapping", "1", "use offsetmapping by default on all surfaces that are not using q3 shader files"};

Referenced by Mod_BrushInit(), Mod_LoadCustomMaterial(), and Mod_LoadTextureFromQ3Shader().

◆ mod_obj_orientation

cvar_t mod_obj_orientation = {CF_CLIENT | CF_SERVER, "mod_obj_orientation", "1", "fix orientation of OBJ models to the usual conventions (if zero, use coordinates as is)"}

Definition at line 70 of file model_brush.c.

70{CF_CLIENT | CF_SERVER, "mod_obj_orientation", "1", "fix orientation of OBJ models to the usual conventions (if zero, use coordinates as is)"};

Referenced by Mod_BrushInit(), Mod_Decompile_OBJ(), and Mod_OBJ_Load().

◆ mod_q1bsp_polygoncollisions

cvar_t mod_q1bsp_polygoncollisions = {CF_CLIENT | CF_SERVER, "mod_q1bsp_polygoncollisions", "0", "disables use of precomputed cliphulls and instead collides with polygons (uses Bounding Interval Hierarchy optimizations)"}

Definition at line 63 of file model_brush.c.

63{CF_CLIENT | CF_SERVER, "mod_q1bsp_polygoncollisions", "0", "disables use of precomputed cliphulls and instead collides with polygons (uses Bounding Interval Hierarchy optimizations)"};

Referenced by Mod_BrushInit(), and Mod_Q1BSP_Load().

◆ mod_q1bsp_texture_lava

texture_t mod_q1bsp_texture_lava
static

◆ mod_q1bsp_texture_sky

texture_t mod_q1bsp_texture_sky
static

◆ mod_q1bsp_texture_slime

texture_t mod_q1bsp_texture_slime
static

◆ mod_q1bsp_texture_solid

◆ mod_q1bsp_texture_water

texture_t mod_q1bsp_texture_water
static

◆ mod_q1bsp_traceoutofsolid

cvar_t mod_q1bsp_traceoutofsolid = {CF_SHARED, "mod_q1bsp_traceoutofsolid", "1", "enables tracebox to move an entity that's stuck in solid brushwork out to empty space, 1 matches FTEQW and QSS and is required by many community maps (items/monsters will be missing otherwise), 0 matches old versions of DP and the original Quake engine (if your map or QC needs 0 it's buggy)"}

Definition at line 64 of file model_brush.c.

64{CF_SHARED, "mod_q1bsp_traceoutofsolid", "1", "enables tracebox to move an entity that's stuck in solid brushwork out to empty space, 1 matches FTEQW and QSS and is required by many community maps (items/monsters will be missing otherwise), 0 matches old versions of DP and the original Quake engine (if your map or QC needs 0 it's buggy)"};
#define CF_SHARED
Definition cmd.h:67

Referenced by Mod_BrushInit(), and Mod_Q1BSP_RecursiveHullCheck().

◆ mod_q1bsp_zero_hullsize_cutoff

cvar_t mod_q1bsp_zero_hullsize_cutoff = {CF_CLIENT | CF_SERVER, "mod_q1bsp_zero_hullsize_cutoff", "3", "bboxes with an X dimension smaller than this will use the smallest cliphull (0x0x0) instead of being rounded up to the player cliphull (32x32x56) in Q1BSP, or crouching player (32x32x36) in HLBSP"}

Definition at line 65 of file model_brush.c.

65{CF_CLIENT | CF_SERVER, "mod_q1bsp_zero_hullsize_cutoff", "3", "bboxes with an X dimension smaller than this will use the smallest cliphull (0x0x0) instead of being rounded up to the player cliphull (32x32x56) in Q1BSP, or crouching player (32x32x36) in HLBSP"};

Referenced by Mod_BrushInit(), Mod_Q1BSP_RoundUpToHullSize(), and Mod_Q1BSP_TraceBox().

◆ mod_q2bsp_littransparentsurfaces

cvar_t mod_q2bsp_littransparentsurfaces = {CF_CLIENT, "mod_q2bsp_littransparentsurfaces", "0", "allows lighting on rain in 3v3gloom3 and other cases of transparent surfaces that have lightmaps that were ignored by quake2"}

Definition at line 61 of file model_brush.c.

61{CF_CLIENT, "mod_q2bsp_littransparentsurfaces", "0", "allows lighting on rain in 3v3gloom3 and other cases of transparent surfaces that have lightmaps that were ignored by quake2"};

Referenced by Mod_BrushInit(), and Mod_Q2BSP_LoadTexinfo().

◆ mod_q3bsp_curves_collisions

cvar_t mod_q3bsp_curves_collisions = {CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_collisions", "1", "enables collisions with curves (SLOW)"}

Definition at line 42 of file model_brush.c.

42{CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_collisions", "1", "enables collisions with curves (SLOW)"};

Referenced by Mod_BrushInit(), Mod_CollisionBIH_TraceBrush(), and Mod_CollisionBIH_TraceLineShared().

◆ mod_q3bsp_curves_subdivisions_maxtess

cvar_t mod_q3bsp_curves_subdivisions_maxtess = {CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_subdivisions_maxtess", "1024", "maximum number of subdivisions for collision purposes (prevents curves beyond a certain detail level, limits smoothing)"}

Definition at line 40 of file model_brush.c.

40{CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_subdivisions_maxtess", "1024", "maximum number of subdivisions for collision purposes (prevents curves beyond a certain detail level, limits smoothing)"};

Referenced by Mod_BrushInit(), and Mod_Q3BSP_LoadFaces().

◆ mod_q3bsp_curves_subdivisions_maxvertices

cvar_t mod_q3bsp_curves_subdivisions_maxvertices = {CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_subdivisions_maxvertices", "4225", "maximum vertices allowed per subdivided curve for collision purposes"}

Definition at line 41 of file model_brush.c.

41{CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_subdivisions_maxvertices", "4225", "maximum vertices allowed per subdivided curve for collision purposes"};

Referenced by Mod_BrushInit(), and Mod_Q3BSP_LoadFaces().

◆ mod_q3bsp_curves_subdivisions_mintess

cvar_t mod_q3bsp_curves_subdivisions_mintess = {CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_subdivisions_mintess", "0", "minimum number of subdivisions for collision purposes (values above 0 will smooth curves that don't need it)"}

Definition at line 39 of file model_brush.c.

39{CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_subdivisions_mintess", "0", "minimum number of subdivisions for collision purposes (values above 0 will smooth curves that don't need it)"};

Referenced by Mod_BrushInit(), and Mod_Q3BSP_LoadFaces().

◆ mod_q3bsp_curves_subdivisions_tolerance

cvar_t mod_q3bsp_curves_subdivisions_tolerance = {CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_subdivisions_tolerance", "15", "maximum error tolerance on curve subdivision for collision purposes (usually a larger error tolerance than for rendering)"}

Definition at line 38 of file model_brush.c.

38{CF_CLIENT | CF_SERVER, "mod_q3bsp_curves_subdivisions_tolerance", "15", "maximum error tolerance on curve subdivision for collision purposes (usually a larger error tolerance than for rendering)"};

Referenced by Mod_BrushInit(), and Mod_Q3BSP_LoadFaces().

◆ mod_q3bsp_lightgrid_bsp_surfaces

cvar_t mod_q3bsp_lightgrid_bsp_surfaces = {CF_CLIENT, "mod_q3bsp_lightgrid_bsp_surfaces", "0", "apply lightgrid lighting to bsp models other than the world rather than using their lightmaps (experimental/debug tool)"}

Definition at line 50 of file model_brush.c.

50{CF_CLIENT, "mod_q3bsp_lightgrid_bsp_surfaces", "0", "apply lightgrid lighting to bsp models other than the world rather than using their lightmaps (experimental/debug tool)"};

Referenced by CL_UpdateEntityShading_Entity(), and Mod_BrushInit().

◆ mod_q3bsp_lightgrid_texture

cvar_t mod_q3bsp_lightgrid_texture = {CF_CLIENT, "mod_q3bsp_lightgrid_texture", "1", "directly apply the lightgrid as a global texture rather than only reading it at the entity origin"}

Definition at line 48 of file model_brush.c.

48{CF_CLIENT, "mod_q3bsp_lightgrid_texture", "1", "directly apply the lightgrid as a global texture rather than only reading it at the entity origin"};

Referenced by CL_UpdateEntityShading_Entity(), Mod_BrushInit(), and Mod_Q3BSP_LoadLightGrid().

◆ mod_q3bsp_lightgrid_world_surfaces

cvar_t mod_q3bsp_lightgrid_world_surfaces = {CF_CLIENT, "mod_q3bsp_lightgrid_world_surfaces", "0", "apply lightgrid lighting to the world bsp geometry rather than using lightmaps (experimental/debug tool)"}

Definition at line 49 of file model_brush.c.

49{CF_CLIENT, "mod_q3bsp_lightgrid_world_surfaces", "0", "apply lightgrid lighting to the world bsp geometry rather than using lightmaps (experimental/debug tool)"};

Referenced by CL_UpdateEntityShading_Entity(), and Mod_BrushInit().

◆ mod_q3bsp_lightmapmergepower

cvar_t mod_q3bsp_lightmapmergepower = {CF_CLIENT | CF_ARCHIVE, "mod_q3bsp_lightmapmergepower", "4", "merges the quake3 128x128 lightmap textures into larger lightmap group textures to speed up rendering, 1 = 256x256, 2 = 512x512, 3 = 1024x1024, 4 = 2048x2048, 5 = 4096x4096, ..."}

Definition at line 44 of file model_brush.c.

44{CF_CLIENT | CF_ARCHIVE, "mod_q3bsp_lightmapmergepower", "4", "merges the quake3 128x128 lightmap textures into larger lightmap group textures to speed up rendering, 1 = 256x256, 2 = 512x512, 3 = 1024x1024, 4 = 2048x2048, 5 = 4096x4096, ..."};

Referenced by Mod_BrushInit(), and Mod_Q3BSP_LoadLightmaps().

◆ mod_q3bsp_nolightmaps

cvar_t mod_q3bsp_nolightmaps = {CF_CLIENT | CF_ARCHIVE, "mod_q3bsp_nolightmaps", "0", "do not load lightmaps in Q3BSP maps (to save video RAM, but be warned: it looks ugly)"}

Definition at line 45 of file model_brush.c.

45{CF_CLIENT | CF_ARCHIVE, "mod_q3bsp_nolightmaps", "0", "do not load lightmaps in Q3BSP maps (to save video RAM, but be warned: it looks ugly)"};

Referenced by Mod_BrushInit(), Mod_GenerateLightmaps(), and Mod_Q3BSP_LoadLightmaps().

◆ mod_q3bsp_optimizedtraceline

cvar_t mod_q3bsp_optimizedtraceline = {CF_CLIENT | CF_SERVER, "mod_q3bsp_optimizedtraceline", "1", "whether to use optimized traceline code for line traces (as opposed to tracebox code)"}

Definition at line 43 of file model_brush.c.

43{CF_CLIENT | CF_SERVER, "mod_q3bsp_optimizedtraceline", "1", "whether to use optimized traceline code for line traces (as opposed to tracebox code)"};

Referenced by Mod_BrushInit(), and Mod_CollisionBIH_TraceBrush().

◆ mod_q3bsp_sRGBlightmaps

cvar_t mod_q3bsp_sRGBlightmaps = {CF_CLIENT, "mod_q3bsp_sRGBlightmaps", "0", "treat lightmaps from Q3 maps as sRGB when vid_sRGB is active"}

Definition at line 47 of file model_brush.c.

47{CF_CLIENT, "mod_q3bsp_sRGBlightmaps", "0", "treat lightmaps from Q3 maps as sRGB when vid_sRGB is active"};

Referenced by Mod_BrushInit(), Mod_Q3BSP_Load(), Mod_Q3BSP_LoadLightGrid(), Mod_Q3BSP_LoadLightmaps(), and Mod_Q3BSP_LoadVertices().

◆ mod_q3bsp_tracelineofsight_brushes

cvar_t mod_q3bsp_tracelineofsight_brushes = {CF_CLIENT | CF_SERVER, "mod_q3bsp_tracelineofsight_brushes", "0", "enables culling of entities behind detail brushes, curves, etc"}

Definition at line 46 of file model_brush.c.

46{CF_CLIENT | CF_SERVER, "mod_q3bsp_tracelineofsight_brushes", "0", "enables culling of entities behind detail brushes, curves, etc"};

Referenced by Mod_BrushInit(), and Mod_Q3BSP_TraceLineOfSight().

◆ mod_q3shader_default_offsetmapping

cvar_t mod_q3shader_default_offsetmapping = {CF_CLIENT | CF_ARCHIVE, "mod_q3shader_default_offsetmapping", "1", "use offsetmapping by default on all surfaces that are using q3 shader files"}

Definition at line 52 of file model_brush.c.

52{CF_CLIENT | CF_ARCHIVE, "mod_q3shader_default_offsetmapping", "1", "use offsetmapping by default on all surfaces that are using q3 shader files"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_q3shader_default_offsetmapping_bias

cvar_t mod_q3shader_default_offsetmapping_bias = {CF_CLIENT | CF_ARCHIVE, "mod_q3shader_default_offsetmapping_bias", "0", "default bias used for offsetmapping"}

Definition at line 54 of file model_brush.c.

54{CF_CLIENT | CF_ARCHIVE, "mod_q3shader_default_offsetmapping_bias", "0", "default bias used for offsetmapping"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_q3shader_default_offsetmapping_scale

cvar_t mod_q3shader_default_offsetmapping_scale = {CF_CLIENT | CF_ARCHIVE, "mod_q3shader_default_offsetmapping_scale", "1", "default scale used for offsetmapping"}

Definition at line 53 of file model_brush.c.

53{CF_CLIENT | CF_ARCHIVE, "mod_q3shader_default_offsetmapping_scale", "1", "default scale used for offsetmapping"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_q3shader_default_polygonfactor

cvar_t mod_q3shader_default_polygonfactor = {CF_CLIENT, "mod_q3shader_default_polygonfactor", "0", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"}

Definition at line 55 of file model_brush.c.

55{CF_CLIENT, "mod_q3shader_default_polygonfactor", "0", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_q3shader_default_polygonoffset

cvar_t mod_q3shader_default_polygonoffset = {CF_CLIENT, "mod_q3shader_default_polygonoffset", "-2", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"}

Definition at line 56 of file model_brush.c.

56{CF_CLIENT, "mod_q3shader_default_polygonoffset", "-2", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_q3shader_default_refractive_index

cvar_t mod_q3shader_default_refractive_index = {CF_CLIENT, "mod_q3shader_default_refractive_index", "1.33", "angle of refraction specified as n to apply when a photon is refracted, example values are: 1.0003 = air, water = 1.333, crown glass = 1.517, flint glass = 1.655, diamond = 2.417"}

Definition at line 57 of file model_brush.c.

57{CF_CLIENT, "mod_q3shader_default_refractive_index", "1.33", "angle of refraction specified as n to apply when a photon is refracted, example values are: 1.0003 = air, water = 1.333, crown glass = 1.517, flint glass = 1.655, diamond = 2.417"};

Referenced by Mod_BrushInit(), Mod_LoadTextureFromQ3Shader(), and Mod_Q1BSP_LoadTextures().

◆ mod_q3shader_force_addalpha

cvar_t mod_q3shader_force_addalpha = {CF_CLIENT, "mod_q3shader_force_addalpha", "0", "treat GL_ONE GL_ONE (or add) blendfunc as GL_SRC_ALPHA GL_ONE for compatibility with older DarkPlaces releases"}

Definition at line 58 of file model_brush.c.

58{CF_CLIENT, "mod_q3shader_force_addalpha", "0", "treat GL_ONE GL_ONE (or add) blendfunc as GL_SRC_ALPHA GL_ONE for compatibility with older DarkPlaces releases"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_q3shader_force_terrain_alphaflag

cvar_t mod_q3shader_force_terrain_alphaflag = {CF_CLIENT, "mod_q3shader_force_terrain_alphaflag", "0", "for multilayered terrain shaders force TEXF_ALPHA flag on both layers"}

Definition at line 59 of file model_brush.c.

59{CF_CLIENT, "mod_q3shader_force_terrain_alphaflag", "0", "for multilayered terrain shaders force TEXF_ALPHA flag on both layers"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_recalculatenodeboxes

cvar_t mod_recalculatenodeboxes = {CF_CLIENT | CF_SERVER, "mod_recalculatenodeboxes", "1", "enables use of generated node bounding boxes based on BSP tree portal reconstruction, rather than the node boxes supplied by the map compiler"}

Definition at line 68 of file model_brush.c.

68{CF_CLIENT | CF_SERVER, "mod_recalculatenodeboxes", "1", "enables use of generated node bounding boxes based on BSP tree portal reconstruction, rather than the node boxes supplied by the map compiler"};

Referenced by Mod_BrushInit(), and Mod_BSP_FinalizePortals().

◆ nobsp_pvs

unsigned char nobsp_pvs[1] = {1}
static

Definition at line 8415 of file model_brush.c.

8415{1};

Referenced by Mod_OBJ_Load().

◆ portalarray

◆ portalpointsbuffer

double* portalpointsbuffer
static

Definition at line 3614 of file model_brush.c.

Referenced by Mod_BSP_MakePortals(), and Mod_BSP_RecursiveNodePortals().

◆ portalpointsbufferoffset

int portalpointsbufferoffset
static

Definition at line 3615 of file model_brush.c.

Referenced by Mod_BSP_MakePortals(), and Mod_BSP_RecursiveNodePortals().

◆ portalpointsbuffersize

int portalpointsbuffersize
static

Definition at line 3616 of file model_brush.c.

Referenced by Mod_BSP_MakePortals(), and Mod_BSP_RecursiveNodePortals().

◆ r_nosurftextures

cvar_t r_nosurftextures = {CF_CLIENT, "r_nosurftextures", "0", "pretends there was no texture lump found in the q1bsp/hlbsp loading (useful for debugging this rare case)"}

Definition at line 32 of file model_brush.c.

32{CF_CLIENT, "r_nosurftextures", "0", "pretends there was no texture lump found in the q1bsp/hlbsp loading (useful for debugging this rare case)"};

Referenced by Mod_BrushInit(), and Mod_Q1BSP_LoadTextures().

◆ r_novis

cvar_t r_novis = {CF_CLIENT, "r_novis", "0", "draws whole level, see also sv_cullentities_pvs 0"}

Definition at line 31 of file model_brush.c.

31{CF_CLIENT, "r_novis", "0", "draws whole level, see also sv_cullentities_pvs 0"};

Referenced by Mod_BrushInit(), Mod_BSP_FatPVS(), R_GetCurrentTexture(), R_View_UpdateEntityVisible(), R_View_WorldVisibility(), and SV_MarkWriteEntityStateToClient().

◆ r_subdivisions_maxtess

cvar_t r_subdivisions_maxtess = {CF_CLIENT, "r_subdivisions_maxtess", "1024", "maximum number of subdivisions (prevents curves beyond a certain detail level, limits smoothing)"}

Definition at line 36 of file model_brush.c.

36{CF_CLIENT, "r_subdivisions_maxtess", "1024", "maximum number of subdivisions (prevents curves beyond a certain detail level, limits smoothing)"};

Referenced by Mod_BrushInit(), and Mod_Q3BSP_LoadFaces().

◆ r_subdivisions_maxvertices

cvar_t r_subdivisions_maxvertices = {CF_CLIENT, "r_subdivisions_maxvertices", "65536", "maximum vertices allowed per subdivided curve"}

Definition at line 37 of file model_brush.c.

37{CF_CLIENT, "r_subdivisions_maxvertices", "65536", "maximum vertices allowed per subdivided curve"};

Referenced by Mod_BrushInit(), and Mod_Q3BSP_LoadFaces().

◆ r_subdivisions_mintess

cvar_t r_subdivisions_mintess = {CF_CLIENT, "r_subdivisions_mintess", "0", "minimum number of subdivisions (values above 0 will smooth curves that don't need it)"}

Definition at line 35 of file model_brush.c.

35{CF_CLIENT, "r_subdivisions_mintess", "0", "minimum number of subdivisions (values above 0 will smooth curves that don't need it)"};

Referenced by Mod_BrushInit(), and Mod_Q3BSP_LoadFaces().

◆ r_subdivisions_tolerance

cvar_t r_subdivisions_tolerance = {CF_CLIENT, "r_subdivisions_tolerance", "4", "maximum error tolerance on curve subdivision for rendering purposes (in other words, the curves will be given as many polygons as necessary to represent curves at this quality)"}

Definition at line 34 of file model_brush.c.

34{CF_CLIENT, "r_subdivisions_tolerance", "4", "maximum error tolerance on curve subdivision for rendering purposes (in other words, the curves will be given as many polygons as necessary to represent curves at this quality)"};

Referenced by Mod_BrushInit(), and Mod_Q3BSP_LoadFaces().

◆ r_trippy