/** * @brief Create surface fragments for light-emitting surfaces so that light sources * may be computed along them. */ void BuildPatches(void) { int32_t i, j, k; winding_t *w; vec3_t origin; for (i = 0; i < bsp_file.num_models; i++) { const bsp_model_t *mod = &bsp_file.models[i]; const entity_t *ent = EntityForModel(i); // bmodels with origin brushes need to be offset into their // in-use position VectorForKey(ent, "origin", origin); for (j = 0; j < mod->num_faces; j++) { const int32_t facenum = mod->first_face + j; bsp_face_t *f = &bsp_file.faces[facenum]; VectorCopy(origin, face_offset[facenum]); if (!HasLight(f)) { // no light continue; } w = WindingForFace(f); for (k = 0; k < w->num_points; k++) { VectorAdd(w->points[k], origin, w->points[k]); } BuildPatch(facenum, w); } } }
/* * @brief */ static _Bool ParseMapEntity(void) { entity_t *mapent; epair_t *e; side_t *s; int32_t i, j; vec_t newdist; map_brush_t *b; if (!GetToken(true)) return false; if (g_strcmp0(token, "{")) Com_Error(ERR_FATAL, "\"{\" not found\n"); if (num_entities == MAX_BSP_ENTITIES) Com_Error(ERR_FATAL, "MAX_BSP_ENTITIES\n"); mapent = &entities[num_entities]; num_entities++; memset(mapent, 0, sizeof(*mapent)); mapent->first_brush = num_map_brushes; mapent->num_brushes = 0; do { if (!GetToken(true)) Com_Error(ERR_FATAL, "EOF without closing brace\n"); if (!g_strcmp0(token, "}")) break; if (!g_strcmp0(token, "{")) ParseBrush(mapent); else { e = ParseEpair(); e->next = mapent->epairs; mapent->epairs = e; } } while (true); VectorForKey(mapent, "origin", mapent->origin); // if there was an origin brush, offset all of the planes and texinfo if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2]) { for (i = 0; i < mapent->num_brushes; i++) { b = &map_brushes[mapent->first_brush + i]; for (j = 0; j < b->num_sides; j++) { s = &b->original_sides[j]; newdist = map_planes[s->plane_num].dist - DotProduct(map_planes[s->plane_num].normal, mapent->origin); s->plane_num = FindPlane(map_planes[s->plane_num].normal, newdist); s->texinfo = TexinfoForBrushTexture(&map_planes[s->plane_num], &map_brush_textures[s - map_brush_sides], mapent->origin); } MakeBrushWindings(b); } } // group entities are just for editor convenience // toss all brushes into the world entity if (!g_strcmp0("func_group", ValueForKey(mapent, "classname"))) { MoveBrushesToWorld(mapent); mapent->num_brushes = 0; return true; } // areaportal entities move their brushes, but don't eliminate the entity if (!g_strcmp0("func_areaportal", ValueForKey(mapent, "classname"))) { char str[128]; if (mapent->num_brushes != 1) Com_Error( ERR_FATAL, "ParseMapEntity: %i func_areaportal can only be a single brush\n", num_entities - 1); b = &map_brushes[num_map_brushes - 1]; b->contents = CONTENTS_AREA_PORTAL; c_area_portals++; mapent->area_portal_num = c_area_portals; // set the portal number as "style" sprintf(str, "%i", c_area_portals); SetKeyValue(mapent, "areaportal", str); MoveBrushesToWorld(mapent); return true; } return true; }