/** * @brief Consume raw lightmap and deluxemap RGB/XYZ data from the surface samples, * writing processed lightmap and deluxemap RGB to the specified destinations. * * @param in The beginning of the surface lightmap [and deluxemap] data. * @param sout The destination for processed lightmap data. * @param dout The destination for processed deluxemap data. */ static void R_BuildLightmap(const r_bsp_model_t *bsp, const r_bsp_surface_t *surf, const byte *in, byte *lout, byte *dout, size_t stride) { const uint32_t smax = surf->lightmap_size[0]; const uint32_t tmax = surf->lightmap_size[1]; const size_t size = smax * tmax; stride -= (smax * 3); byte *lightmap = (byte *) Mem_TagMalloc(size * 3, MEM_TAG_RENDERER); byte *lm = lightmap; byte *deluxemap = (byte *) Mem_TagMalloc(size * 3, MEM_TAG_RENDERER); byte *dm = deluxemap; // convert the raw lightmap samples to RGBA for softening for (size_t i = 0; i < size; i++) { *lm++ = *in++; *lm++ = *in++; *lm++ = *in++; // read in directional samples for per-pixel lighting as well if (bsp->version == BSP_VERSION_QUETOO) { *dm++ = *in++; *dm++ = *in++; *dm++ = *in++; } else { *dm++ = 127; *dm++ = 127; *dm++ = 255; } } // apply modulate, contrast, saturation, etc.. R_FilterLightmap(smax, tmax, lightmap); // the lightmap is uploaded to the card via the strided block lm = lightmap; dm = deluxemap; for (uint32_t t = 0; t < tmax; t++, lout += stride, dout += stride) { for (uint32_t s = 0; s < smax; s++) { // copy the lightmap and deluxemap to the strided block *lout++ = *lm++; *lout++ = *lm++; *lout++ = *lm++; *dout++ = *dm++; *dout++ = *dm++; *dout++ = *dm++; } } Mem_Free(lightmap); Mem_Free(deluxemap); }
/** * @brief */ static void Cm_LoadBspSurfaces(void) { const int32_t num_texinfo = cm_bsp.bsp.num_texinfo; const bsp_texinfo_t *in = cm_bsp.bsp.texinfo; cm_bsp_texinfo_t *out = cm_bsp.texinfos = Mem_TagMalloc(sizeof(cm_bsp_texinfo_t) * num_texinfo, MEM_TAG_CMODEL); for (int32_t i = 0; i < num_texinfo; i++, in++, out++) { g_strlcpy(out->name, in->texture, sizeof(out->name)); out->flags = in->flags; out->value = in->value; char material_name[MAX_QPATH]; g_snprintf(material_name, sizeof(material_name), "textures/%s", out->name); Cm_MaterialName(material_name, material_name, sizeof(material_name)); for (cm_material_t *material = cm_bsp.materials; material; material = material->next) { if (!g_strcmp0(material->base, material_name)) { out->material = material; break; } } } }
/** * @brief */ static void Cm_LoadBspBrushSides(void) { static cm_bsp_texinfo_t null_texinfo; const int32_t num_brush_sides = cm_bsp.bsp.num_brush_sides; const bsp_brush_side_t *in = cm_bsp.bsp.brush_sides; cm_bsp_brush_side_t *out = cm_bsp.brush_sides = Mem_TagMalloc(sizeof(cm_bsp_brush_side_t) * (num_brush_sides + 6), MEM_TAG_CMODEL); // extra for box hull for (int32_t i = 0; i < num_brush_sides; i++, in++, out++) { const int32_t p = in->plane_num; if (p >= cm_bsp.bsp.num_planes) { Com_Error(ERROR_DROP, "Brush side %d has invalid plane %d\n", i, p); } out->plane = &cm_bsp.planes[p]; const int32_t s = in->surf_num; if (s == USHRT_MAX) { out->surface = &null_texinfo; } else { // NOTE: "surface" and "texinfo" are used interchangably here. yuck. if (s >= cm_bsp.bsp.num_texinfo) { Com_Error(ERROR_DROP, "Brush side %d has invalid surface %d\n", i, s); } out->surface = &cm_bsp.texinfos[s]; } } }
/* * @brief Returns a newly allocated s_media_t with the specified name. * * @param size_t size The number of bytes to allocate for the media. * * @return The newly initialized media. */ s_media_t *S_AllocMedia(const char *name, size_t size) { if (!name || !*name) { Com_Error(ERR_DROP, "NULL name\n"); } s_media_t *media = Mem_TagMalloc(size, MEM_TAG_SOUND); g_strlcpy(media->name, name, sizeof(media->name)); return media; }
/** * @brief */ static cl_server_info_t *Cl_AddServer(const net_addr_t *addr) { cl_server_info_t *s; s = (cl_server_info_t *) Mem_TagMalloc(sizeof(*s), MEM_TAG_CLIENT); s->addr = *addr; g_strlcpy(s->hostname, Net_NetaddrToString(&s->addr), sizeof(s->hostname)); cls.servers = g_list_prepend(cls.servers, s); return s; }
/** * @brief */ static void Cm_LoadBspLeafBrushes(void) { const int32_t num_leaf_brushes = cm_bsp.bsp.num_leaf_brushes; const uint16_t *in = cm_bsp.bsp.leaf_brushes; uint16_t *out = cm_bsp.leaf_brushes = Mem_TagMalloc(sizeof(uint16_t) * (num_leaf_brushes + 1), MEM_TAG_CMODEL); // extra for box hull for (int32_t i = 0; i < num_leaf_brushes; i++, in++, out++) { *out = *in; } }
/** * @brief */ winding_t *AllocWinding(int32_t points) { if (debug) { SDL_SemPost(semaphores.active_windings); uint32_t active_windings = SDL_SemValue(semaphores.active_windings); if (active_windings > c_peak_windings) { c_peak_windings = active_windings; } } return Mem_TagMalloc(sizeof(int32_t) + sizeof(vec3_t) * points, MEM_TAG_WINDING); }
/** * @brief */ static void Cm_LoadBspBrushes(void) { const int32_t num_brushes = cm_bsp.bsp.num_brushes; const bsp_brush_t *in = cm_bsp.bsp.brushes; cm_bsp_brush_t *out = cm_bsp.brushes = Mem_TagMalloc(sizeof(cm_bsp_brush_t) * (num_brushes + 1), MEM_TAG_CMODEL); // extra for box hull for (int32_t i = 0; i < num_brushes; i++, in++, out++) { out->first_brush_side = in->first_brush_side; out->num_sides = in->num_sides; out->contents = in->contents; } }
/** * @brief */ static void Cm_LoadBspAreas(void) { const int32_t num_areas = cm_bsp.bsp.num_areas; const bsp_area_t *in = cm_bsp.bsp.areas; cm_bsp_area_t *out = cm_bsp.areas = Mem_TagMalloc(sizeof(cm_bsp_area_t) * num_areas, MEM_TAG_CMODEL); for (int32_t i = 0; i < num_areas; i++, in++, out++) { out->num_area_portals = in->num_area_portals; out->first_area_portal = in->first_area_portal; out->flood_valid = 0; out->flood_num = 0; } }
/** * @brief */ static void Cm_LoadBspNodes(void) { const int32_t num_nodes = cm_bsp.bsp.num_nodes; const bsp_node_t *in = cm_bsp.bsp.nodes; cm_bsp_node_t *out = cm_bsp.nodes = Mem_TagMalloc(sizeof(cm_bsp_node_t) * (num_nodes + 6), MEM_TAG_CMODEL); // extra for box hull for (int32_t i = 0; i < num_nodes; i++, in++, out++) { out->plane = cm_bsp.planes + in->plane_num; for (int32_t j = 0; j < 2; j++) { out->children[j] = in->children[j]; } } }
/** * @brief */ static void Cm_LoadBspInlineModels(void) { const int32_t num_models = cm_bsp.bsp.num_models; const bsp_model_t *in = cm_bsp.bsp.models; cm_bsp_model_t *out = cm_bsp.models = Mem_TagMalloc(sizeof(cm_bsp_model_t) * num_models, MEM_TAG_CMODEL); for (int32_t i = 0; i < num_models; i++, in++, out++) { for (int32_t j = 0; j < 3; j++) { out->mins[j] = in->mins[j] - 1.0; out->maxs[j] = in->maxs[j] + 1.0; out->origin[j] = in->origin[j]; } out->head_node = in->head_node; } }
/** * @brief */ static void Cm_LoadBspPlanes(void) { const int32_t num_planes = cm_bsp.bsp.num_planes; const bsp_plane_t *in = cm_bsp.bsp.planes; cm_bsp_plane_t *out = cm_bsp.planes = Mem_TagMalloc(sizeof(cm_bsp_plane_t) * (num_planes + 12), MEM_TAG_CMODEL); // extra for box hull for (int32_t i = 0; i < num_planes; i++, in++, out++) { // copied from bsp_ VectorCopy(in->normal, out->normal); out->dist = in->dist; out->type = in->type; // local to cm_ out->sign_bits = Cm_SignBitsForPlane(out); out->num = (i >> 1) + 1; } }
/** * @brief */ static void Cm_LoadBspLeafs(void) { const int32_t num_leafs = cm_bsp.bsp.num_leafs; const bsp_leaf_t *in = cm_bsp.bsp.leafs; cm_bsp_leaf_t *out = cm_bsp.leafs = Mem_TagMalloc(sizeof(cm_bsp_leaf_t) * (num_leafs + 1), MEM_TAG_CMODEL); // extra for box hull for (int32_t i = 0; i < num_leafs; i++, in++, out++) { out->contents = in->contents; out->cluster = in->cluster; out->area = in->area; out->first_leaf_brush = in->first_leaf_brush; out->num_leaf_brushes = in->num_leaf_brushes; } if (cm_bsp.leafs[0].contents != CONTENTS_SOLID) { Com_Error(ERROR_DROP, "Map leaf 0 is not CONTENTS_SOLID\n"); } }
/** * @brief */ void R_InitProgram_default(r_program_t *program) { r_default_program_t *p = &r_default_program; p->program = program; R_ProgramVariable(&program->attributes[R_ARRAY_POSITION], R_ATTRIBUTE, "POSITION", true); R_ProgramVariable(&program->attributes[R_ARRAY_COLOR], R_ATTRIBUTE, "COLOR", true); R_ProgramVariable(&program->attributes[R_ARRAY_DIFFUSE], R_ATTRIBUTE, "TEXCOORD0", true); R_ProgramVariable(&program->attributes[R_ARRAY_LIGHTMAP], R_ATTRIBUTE, "TEXCOORD1", true); R_ProgramVariable(&program->attributes[R_ARRAY_NORMAL], R_ATTRIBUTE, "NORMAL", true); R_ProgramVariable(&program->attributes[R_ARRAY_TANGENT], R_ATTRIBUTE, "TANGENT", true); R_ProgramVariable(&program->attributes[R_ARRAY_NEXT_POSITION], R_ATTRIBUTE, "NEXT_POSITION", true); R_ProgramVariable(&program->attributes[R_ARRAY_NEXT_NORMAL], R_ATTRIBUTE, "NEXT_NORMAL", true); R_ProgramVariable(&program->attributes[R_ARRAY_NEXT_TANGENT], R_ATTRIBUTE, "NEXT_TANGENT", true); R_ProgramVariable(&p->diffuse, R_UNIFORM_INT, "DIFFUSE", true); R_ProgramVariable(&p->lightmap, R_UNIFORM_INT, "LIGHTMAP", true); R_ProgramVariable(&p->normalmap, R_UNIFORM_INT, "NORMALMAP", true); R_ProgramVariable(&p->glossmap, R_UNIFORM_INT, "GLOSSMAP", true); R_ProgramVariable(&p->bump, R_UNIFORM_FLOAT, "BUMP", true); R_ProgramVariable(&p->parallax, R_UNIFORM_FLOAT, "PARALLAX", true); R_ProgramVariable(&p->hardness, R_UNIFORM_FLOAT, "HARDNESS", true); R_ProgramVariable(&p->specular, R_UNIFORM_FLOAT, "SPECULAR", true); R_ProgramVariable(&p->sampler0, R_SAMPLER_2D, "SAMPLER0", true); R_ProgramVariable(&p->sampler1, R_SAMPLER_2D, "SAMPLER1", true); R_ProgramVariable(&p->sampler2, R_SAMPLER_2D, "SAMPLER2", true); R_ProgramVariable(&p->sampler3, R_SAMPLER_2D, "SAMPLER3", true); R_ProgramVariable(&p->sampler4, R_SAMPLER_2D, "SAMPLER4", true); R_ProgramVariable(&p->fog.start, R_UNIFORM_FLOAT, "FOG.START", true); R_ProgramVariable(&p->fog.end, R_UNIFORM_FLOAT, "FOG.END", true); R_ProgramVariable(&p->fog.color, R_UNIFORM_VEC3, "FOG.COLOR", true); R_ProgramVariable(&p->fog.density, R_UNIFORM_FLOAT, "FOG.DENSITY", true); if (r_state.max_active_lights) { p->lights = Mem_TagMalloc(sizeof(r_uniform_light_t) * r_state.max_active_lights, MEM_TAG_RENDERER); for (int32_t i = 0; i < r_state.max_active_lights; ++i) { R_ProgramVariable(&p->lights[i].origin, R_UNIFORM_VEC3, va("LIGHTS.ORIGIN[%i]", i), true); R_ProgramVariable(&p->lights[i].color, R_UNIFORM_VEC3, va("LIGHTS.COLOR[%i]", i), true); R_ProgramVariable(&p->lights[i].radius, R_UNIFORM_FLOAT, va("LIGHTS.RADIUS[%i]", i), true); } R_ProgramParameter1f(&p->lights[0].radius, 0.0); } else { p->lights = NULL; } R_ProgramVariable(&p->caustic.enable, R_UNIFORM_INT, "CAUSTIC.ENABLE", true); R_ProgramVariable(&p->caustic.color, R_UNIFORM_VEC3, "CAUSTIC.COLOR", true); R_ProgramVariable(&p->normal_mat, R_UNIFORM_MAT4, "NORMAL_MAT", true); R_ProgramVariable(&p->alpha_threshold, R_UNIFORM_FLOAT, "ALPHA_THRESHOLD", true); R_ProgramVariable(&p->time_fraction, R_UNIFORM_FLOAT, "TIME_FRACTION", true); R_ProgramVariable(&p->time, R_UNIFORM_FLOAT, "TIME", true); R_ProgramParameter1i(&p->lightmap, 0); R_ProgramParameter1i(&p->normalmap, 0); R_ProgramParameter1i(&p->glossmap, 0); R_ProgramParameter1f(&p->bump, 1.0); R_ProgramParameter1f(&p->parallax, 1.0); R_ProgramParameter1f(&p->hardness, 1.0); R_ProgramParameter1f(&p->specular, 1.0); R_ProgramParameter1i(&p->sampler0, R_TEXUNIT_DIFFUSE); R_ProgramParameter1i(&p->sampler1, R_TEXUNIT_LIGHTMAP); R_ProgramParameter1i(&p->sampler2, R_TEXUNIT_DELUXEMAP); R_ProgramParameter1i(&p->sampler3, R_TEXUNIT_NORMALMAP); R_ProgramParameter1i(&p->sampler4, R_TEXUNIT_SPECULARMAP); R_ProgramParameter1f(&p->fog.density, 0.0); R_ProgramParameter1f(&p->alpha_threshold, ALPHA_TEST_DISABLED_THRESHOLD); R_ProgramParameter1i(&p->caustic.enable, 0); R_ProgramParameter1f(&p->time_fraction, 0.0f); R_ProgramParameter1f(&p->time, 0.0f); }
/** * @brief If the variable already exists, the value will not be modified. The * default value, flags, and description will, however, be updated. This way, * variables set at the command line can receive their meta data through the * various subsystem initialization routines. */ cvar_t *Cvar_Add(const char *name, const char *value, uint32_t flags, const char *description) { assert(name); assert(value); if (flags & (CVAR_USER_INFO | CVAR_SERVER_INFO)) { if (!Cvar_InfoValidate(name)) { Com_Print("Invalid variable name: %s\n", name); return NULL; } if (!Cvar_InfoValidate(value)) { Com_Print("Invalid variable value: %s\n", value); return NULL; } } // update existing variables with meta data from owning subsystem cvar_t *var = Cvar_Get(name); if (var) { if (value) { if (var->default_string) { Mem_Free((void *) var->default_string); } var->default_string = Mem_Link(Mem_TagCopyString(value, MEM_TAG_CVAR), var); } var->flags |= flags; if (description) { if (var->description) { Mem_Free((void *) var->description); } var->description = Mem_Link(Mem_TagCopyString(description, MEM_TAG_CVAR), var); } return var; } // create a new variable var = Mem_TagMalloc(sizeof(*var), MEM_TAG_CVAR); assert(var); var->name = Mem_Link(Mem_TagCopyString(name, MEM_TAG_CVAR), var); var->default_string = Mem_Link(Mem_TagCopyString(value, MEM_TAG_CVAR), var); var->string = Mem_Link(Mem_TagCopyString(value, MEM_TAG_CVAR), var); var->value = strtof(var->string, NULL); var->integer = (int32_t) strtol(var->string, NULL, 0); var->modified = true; var->flags = flags; if (description) { var->description = Mem_Link(Mem_TagCopyString(description, MEM_TAG_CVAR), var); } gpointer key = (gpointer) var->name; GQueue *queue = (GQueue *) g_hash_table_lookup(cvar_vars, key); if (!queue) { queue = g_queue_new(); g_hash_table_insert(cvar_vars, key, queue); } g_queue_push_head(queue, var); return var; }
/** * @brief */ static void Cm_LoadBspAreaPortals(void) { const int32_t num_area_portals = cm_bsp.bsp.num_area_portals; cm_bsp.portal_open = Mem_TagMalloc(sizeof(bool) * num_area_portals, MEM_TAG_CMODEL); }