/* ================ CalcTerrainSize ================ */ void CalcTerrainSize( vec3_t mins, vec3_t maxs, vec3_t size ) { bspbrush_t *brush; int i; const char *key; // calculate the size of the terrain ClearBounds( mins, maxs ); for( brush = mapent->brushes; brush != NULL; brush = brush->next ) { AddPointToBounds( brush->mins, mins, maxs ); AddPointToBounds( brush->maxs, mins, maxs ); } key = ValueForKey( mapent, "min" ); if ( key[ 0 ] ) { GetVectorForKey( mapent, "min", mins ); } key = ValueForKey( mapent, "max" ); if ( key[ 0 ] ) { GetVectorForKey( mapent, "max", maxs ); } for( i = 0; i < 3; i++ ) { mins[ i ] = floor( mins[ i ] + 0.1 ); maxs[ i ] = floor( maxs[ i ] + 0.1 ); } VectorSubtract( maxs, mins, size ); if ( ( size[ 0 ] <= 0 ) || ( size[ 1 ] <= 0 ) ) { Error ("CalcTerrainSize: Invalid terrain size: %fx%f", size[ 0 ], size[ 1 ] ); } }
void InitMacroTexture( const char *pBSPFilename ) { // Get the world bounds (same ones used by minimaps and level designers know how to use). int i = 0; for (i = 0; i < num_entities; ++i) { char* pEntity = ValueForKey(&entities[i], "classname"); if( !strcmp(pEntity, "worldspawn") ) { GetVectorForKey( &entities[i], "world_mins", g_MacroWorldMins ); GetVectorForKey( &entities[i], "world_maxs", g_MacroWorldMaxs ); break; } } if ( i == num_entities ) { Warning( "MaskOnMacroTexture: can't find worldspawn" ); return; } // Load the macro texture that is mapped onto everything. char mapName[512], vtfFilename[512]; Q_FileBase( pBSPFilename, mapName, sizeof( mapName ) ); Q_snprintf( vtfFilename, sizeof( vtfFilename ), "materials/macro/%s/base.vtf", mapName ); g_pGlobalMacroTextureData = LoadMacroTextureFile( vtfFilename ); // Now load the macro texture for each face. g_FaceMacroTextures.SetSize( numfaces ); for ( int iFace=0; iFace < numfaces; iFace++ ) { g_FaceMacroTextures[iFace] = NULL; if ( iFace < g_FaceMacroTextureInfos.Count() ) { unsigned short stringID = g_FaceMacroTextureInfos[iFace].m_MacroTextureNameID; if ( stringID != 0xFFFF ) { const char *pMacroTextureName = &g_TexDataStringData[ g_TexDataStringTable[stringID] ]; Q_snprintf( vtfFilename, sizeof( vtfFilename ), "%smaterials/%s.vtf", gamedir, pMacroTextureName ); g_FaceMacroTextures[iFace] = FindMacroTexture( vtfFilename ); if ( !g_FaceMacroTextures[iFace] ) { g_FaceMacroTextures[iFace] = LoadMacroTextureFile( vtfFilename ); if ( g_FaceMacroTextures[iFace] ) { g_MacroTextureLookup.Insert( vtfFilename, g_FaceMacroTextures[iFace] ); } } } } } }
/* ================== LoadEntities ================== */ void LoadEntities (void) { char *s, *s2; entity_t *e; lightentity_t *le; int i, j; ParseEntities (); // go through all the entities for (i=1 ; i<num_entities ; i++) { e = &entities[i]; s = ValueForKey (e, "classname"); if (strncmp (s, "light", 5)) continue; le = &lightentities[numlightentities]; numlightentities++; strcpy (le->classname, s); le->light = FloatForKey (e, "light"); if (!le->light) le->light = DEFAULTLIGHTLEVEL; le->style = FloatForKey (e, "style"); le->angle = FloatForKey (e, "angle"); GetVectorForKey (e, "origin", le->origin); s = ValueForKey (e, "target"); if (!s[0]) continue; // find matching targetname for (j=1 ; j<num_entities ; j++) { s2 = ValueForKey (&entities[j], "targetname"); if (!strcmp (s, s2)) { le->targetent = true; GetVectorForKey (&entities[j], "origin", le->targetorigin); break; } } if (j == num_entities) printf ("WARNING: entity %i has unmatched target %s\n", i, s); } qprintf ("%d lightentities\n", numlightentities); }
// // move the view to a start position // void Map_StartPosition(){ entity_t *ent = AngledEntity(); g_pParentWnd->GetCamWnd()->Camera()->angles[PITCH] = 0; if ( ent ) { GetVectorForKey( ent, "origin", g_pParentWnd->GetCamWnd()->Camera()->origin ); GetVectorForKey( ent, "origin", g_pParentWnd->GetXYWnd()->GetOrigin() ); g_pParentWnd->GetCamWnd()->Camera()->angles[YAW] = FloatForKey( ent, "angle" ); } else { g_pParentWnd->GetCamWnd()->Camera()->angles[YAW] = 0; VectorCopy( vec3_origin, g_pParentWnd->GetCamWnd()->Camera()->origin ); VectorCopy( vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin() ); } }
/* ================ ParseEntity ================ */ qboolean ParseEntity (void) { if (!GetToken (true)) return false; if (strcmp (token, "{") ) Error ("ParseEntity: { not found"); if (num_entities == MAX_MAP_ENTITIES) Error ("num_entities == MAX_MAP_ENTITIES"); mapent = &entities[num_entities]; num_entities++; do { fflush(stdout); if (!GetToken (true)) Error ("ParseEntity: EOF without closing brace"); if (!strcmp (token, "}") ) break; if (!strcmp (token, "{") ) ParseBrush (); else ParseEpair (); } while (1); GetVectorForKey (mapent, "origin", mapent->origin); return true; }
static void ParseEpair(void) { epair_t *e; e = AllocMem(OTHER, sizeof(epair_t), true); e->next = map.rgEntities[map.iEntities].epairs; map.rgEntities[map.iEntities].epairs = e; if (strlen(token) >= MAX_KEY - 1) Message(msgError, errEpairTooLong, linenum); e->key = copystring(token); ParseToken(PARSE_SAMELINE); if (strlen(token) >= MAX_VALUE - 1) Message(msgError, errEpairTooLong, linenum); e->value = copystring(token); if (!strcasecmp(e->key, "origin")) GetVectorForKey(map.iEntities, e->key, map.rgEntities[map.iEntities].origin); else if (!strcasecmp(e->key, "classname")) { if (!strcasecmp(e->value, "info_player_start")) { if (rgfStartSpots & info_player_start) Message(msgWarning, warnMultipleStarts); rgfStartSpots |= info_player_start; } else if (!strcasecmp(e->value, "info_player_deathmatch")) rgfStartSpots |= info_player_deathmatch; else if (!strcasecmp(e->value, "info_player_coop")) rgfStartSpots |= info_player_coop; } }
static void ParseEpair(parser_t *parser, mapentity_t *ent) { epair_t *epair; epair = AllocMem(OTHER, sizeof(epair_t), true); epair->next = ent->epairs; ent->epairs = epair; if (strlen(parser->token) >= MAX_KEY - 1) Error(errEpairTooLong, parser->linenum); epair->key = copystring(parser->token); ParseToken(parser, PARSE_SAMELINE); if (strlen(parser->token) >= MAX_VALUE - 1) Error(errEpairTooLong, parser->linenum); epair->value = copystring(parser->token); if (!strcasecmp(epair->key, "origin")) { GetVectorForKey(ent, epair->key, ent->origin); } else if (!strcasecmp(epair->key, "classname")) { if (!strcasecmp(epair->value, "info_player_start")) { if (rgfStartSpots & info_player_start) Message(msgWarning, warnMultipleStarts); rgfStartSpots |= info_player_start; } else if (!strcasecmp(epair->value, "info_player_deathmatch")) { rgfStartSpots |= info_player_deathmatch; } else if (!strcasecmp(epair->value, "info_player_coop")) { rgfStartSpots |= info_player_coop; } } }
/* ================= FixRotateOrigin ================= */ void FixRotateOrigin(entity_t *Ent, vec3_t offset) { int FoundEnt = -1, BadTarget = -1; char *Search, Origin[100], Str[100]; static entity_t *PrevEnt = NULL; // Prevent multiple warnings for same entity Search = ValueForKey(Ent, "target"); if (strlen(Search) != 0) { FoundEnt = FindTargetEntity(Search, &BadTarget); if (FoundEnt != -1) GetVectorForKey(&entities[FoundEnt], "origin", offset); } if (Ent != PrevEnt) { if (FoundEnt == -1) { Str[0] = '\0'; if (BadTarget != -1) sprintf(Str, " (line %d)", entities[BadTarget].Line); Message (MSGWARN, "Bad target%s for rotation entity on line %d", Str, Ent->Line); } PrevEnt = Ent; } sprintf(Origin, "%d %d %d", (int)offset[0], (int)offset[1], (int)offset[2]); SetKeyValue(Ent, "origin", Origin); }
/* * @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 < d_bsp.num_models; i++) { const d_bsp_model_t *mod = &d_bsp.models[i]; const entity_t *ent = EntityForModel(i); // bmodels with origin brushes need to be offset into their // in-use position GetVectorForKey(ent, "origin", origin); for (j = 0; j < mod->num_faces; j++) { const int32_t facenum = mod->first_face + j; d_bsp_face_t *f = &d_bsp.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); } } }
// // ======================================================================================================================= // Entity_WriteSelected to a CMemFile // ======================================================================================================================= // void Entity_WriteSelected(entity_t *e, CMemFile *pMemFile) { brush_t *b; idVec3 origin; char text[128]; int count; for (b = e->brushes.onext; b != &e->brushes; b = b->onext) { if (IsBrushSelected(b)) { break; // got one } } if (b == &e->brushes) { return; // nothing selected } // if fixedsize, calculate a new origin based on the current brush position if (e->eclass->fixedsize || EntityHasModel(e)) { if (!GetVectorForKey(e, "origin", origin)) { VectorSubtract(e->brushes.onext->mins, e->eclass->mins, origin); sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); SetKeyValue(e, "origin", text); } } MemFile_fprintf(pMemFile, "{\n"); count = e->epairs.GetNumKeyVals(); for (int j = 0; j < count; j++) { MemFile_fprintf(pMemFile, "\"%s\" \"%s\"\n", e->epairs.GetKeyVal(j)->GetKey().c_str(), e->epairs.GetKeyVal(j)->GetValue().c_str()); } if (!EntityHasModel(e)) { count = 0; for (b = e->brushes.onext; b != &e->brushes; b = b->onext) { if (e->eclass->fixedsize && !b->entityModel) { continue; } if (IsBrushSelected(b)) { MemFile_fprintf(pMemFile, "// brush %i\n", count); count++; Brush_Write( b, pMemFile, e->origin, ( g_PrefsDlg.m_bNewMapFormat != FALSE ) ); } } } MemFile_fprintf(pMemFile, "}\n"); }
entity_t *EntityFromMapEntity(idMapEntity *mapent, CWaitDlg *dlg) { entity_t *ent = NULL; if (mapent) { ent = Entity_New(); ent->brushes.onext = ent->brushes.oprev = &ent->brushes; ent->origin.Zero(); ent->epairs = mapent->epairs; GetVectorForKey(ent, "origin", ent->origin); int count = mapent->GetNumPrimitives(); long lastUpdate = 0; idStr status; for (int i = 0; i < count; i++) { idMapPrimitive *prim = mapent->GetPrimitive(i); if (prim) { // update 20 times a second if ((GetTickCount() - lastUpdate) > 50) { lastUpdate = GetTickCount(); if (prim->GetType() == idMapPrimitive::TYPE_BRUSH) { sprintf(status, "Reading primitive %i (brush)", i); } else if (prim->GetType() == idMapPrimitive::TYPE_PATCH) { sprintf(status, "Reading primitive %i (patch)", i); } dlg->SetText(status, true); } if (dlg->CancelPressed()) { return ent; } brush_t *b = NULL; if (prim->GetType() == idMapPrimitive::TYPE_BRUSH) { idMapBrush *mapbrush = reinterpret_cast<idMapBrush *>(prim); b = BrushFromMapBrush(mapbrush, ent->origin); } else if (prim->GetType() == idMapPrimitive::TYPE_PATCH) { idMapPatch *mappatch = reinterpret_cast<idMapPatch *>(prim); b = BrushFromMapPatch(mappatch, ent->origin); } if (b) { b->owner = ent; // add to the end of the entity chain b->onext = &ent->brushes; b->oprev = ent->brushes.oprev; ent->brushes.oprev->onext = b; ent->brushes.oprev = b; } } } } return ent; }
/* ============= LeakFile Finds the shortest possible chain of portals that leads from the outside leaf to a specifically occupied leaf ============= */ void LeakFile (tree_t *tree) { vec3_t mid; FILE *linefile; char filename[1024]; node_t *node; int count; if (!tree->outside_node.occupied) return; qprintf ("--- LeakFile ---\n"); // // write the points to the file // sprintf (filename, "%s.lin", source); qprintf ("%s\n", filename); linefile = fopen (filename, "w"); if (!linefile) Error ("Couldn't open %s\n", filename); count = 0; node = &tree->outside_node; while (node->occupied > 1) { int next; portal_t *p, *nextportal; node_t *nextnode; int s; // find the best portal exit next = node->occupied; for (p=node->portals ; p ; p = p->next[!s]) { s = (p->nodes[0] == node); if (p->nodes[s]->occupied && p->nodes[s]->occupied < next) { nextportal = p; nextnode = p->nodes[s]; next = nextnode->occupied; } } node = nextnode; WindingCenter (nextportal->winding, mid); fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]); count++; } // add the occupant center GetVectorForKey (node->occupant, "origin", mid); fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]); qprintf ("%5i point linefile\n", count+1); fclose (linefile); }
//=========================================================================== // this function sets the func_rotating_door in it's final position // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_PositionFuncRotatingBrush(entity_t *mapent, mapbrush_t *brush) { int spawnflags, i; float distance; vec3_t movedir, angles, pos1, pos2; side_t *s; spawnflags = FloatForKey(mapent, "spawnflags"); VectorClear(movedir); if (spawnflags & DOOR_X_AXIS) { movedir[2] = 1.0; //roll } else if (spawnflags & DOOR_Y_AXIS) { movedir[0] = 1.0; //pitch } else // Z_AXIS { movedir[1] = 1.0; //yaw } // check for reverse rotation if (spawnflags & DOOR_REVERSE) { VectorInverse(movedir); } distance = FloatForKey(mapent, "distance"); if (!distance) { distance = 90; } GetVectorForKey(mapent, "angles", angles); VectorCopy(angles, pos1); VectorMA(angles, -distance, movedir, pos2); // if it starts open, switch the positions if (spawnflags & DOOR_START_OPEN) { VectorCopy(pos2, angles); VectorCopy(pos1, pos2); VectorCopy(angles, pos1); VectorInverse(movedir); } //end if // for (i = 0; i < brush->numsides; i++) { s = &brush->original_sides[i]; s->planenum = AAS_TransformPlane(s->planenum, mapent->origin, pos2); } //end for // FreeBrushWindings(brush); AAS_MakeBrushWindings(brush); AddBrushBevels(brush); FreeBrushWindings(brush); } //end of the function AAS_PositionFuncRotatingBrush
//=========================================================================== //=========================================================================== qboolean Q3_ParseBSPEntity(int entnum) { entity_t *mapent; char *model; int startbrush, startsides; startbrush = nummapbrushes; startsides = nummapbrushsides; mapent = &entities[entnum]; //num_entities]; mapent->firstbrush = nummapbrushes; mapent->numbrushes = 0; mapent->modelnum = -1; //-1 = no BSP model model = ValueForKey(mapent, "model"); if(model && strlen(model)) { if(*model == '*') { //get the model number of this entity (skip the leading *) mapent->modelnum = atoi(&model[1]); } //end if } //end if GetVectorForKey(mapent, "origin", mapent->origin); //if this is the world entity it has model number zero //the world entity has no model key if(!strcmp("worldspawn", ValueForKey(mapent, "classname"))) { mapent->modelnum = 0; } //end if //if the map entity has a BSP model (a modelnum of -1 is used for //entities that aren't using a BSP model) if(mapent->modelnum >= 0) { //parse the bsp brushes Q3_ParseBSPBrushes(mapent); } //end if // //the origin of the entity is already taken into account // //func_group entities can't be in the bsp file // //check out the func_areaportal entities if(!strcmp("func_areaportal", ValueForKey(mapent, "classname"))) { c_areaportals++; mapent->areaportalnum = c_areaportals; return true; } //end if return true; } //end of the function Q3_ParseBSPEntity
/* * @brief Marks all nodes that can be reached by entites */ _Bool FloodEntities(tree_t *tree) { int32_t i; vec3_t origin; const char *cl; _Bool inside; node_t *head_node; head_node = tree->head_node; Com_Debug("--- FloodEntities ---\n"); inside = false; tree->outside_node.occupied = 0; cl = ""; for (i = 1; i < num_entities; i++) { GetVectorForKey(&entities[i], "origin", origin); if (VectorCompare(origin, vec3_origin)) continue; cl = ValueForKey(&entities[i], "classname"); origin[2] += 1; // so objects on floor are ok // nudge playerstart around if needed so clipping hulls always // have a valid point if (!g_strcmp0(cl, "info_player_start")) { int32_t x, y; for (x = -16; x <= 16; x += 16) { for (y = -16; y <= 16; y += 16) { origin[0] += x; origin[1] += y; if (PlaceOccupant(head_node, origin, &entities[i])) { inside = true; goto gotit; } origin[0] -= x; origin[1] -= y; } } gotit: ; } else { if (PlaceOccupant(head_node, origin, &entities[i])) inside = true; } } if (!inside) { Com_Debug("no entities in open -- no filling\n"); } else if (tree->outside_node.occupied) { Com_Debug("entity %s reached from outside -- no filling\n", cl); } return inside && !tree->outside_node.occupied; }
/* ======================================================================================================================= Entity_Parse If onlypairs is set, the classname info will not be looked up, and the entity will not be added to the global list. Used for parsing the project. ======================================================================================================================= */ entity_t *Entity_Parse(bool onlypairs, brush_t *pList) { entity_t *ent; if (!GetToken(true)) { return NULL; } if (strcmp(token, "{")) { Error("ParseEntity: { not found"); } ent = Entity_New(); ent->brushes.onext = ent->brushes.oprev = &ent->brushes; ent->origin.Zero(); int n = 0; do { if (!GetToken(true)) { Warning("ParseEntity: EOF without closing brace"); return NULL; } if (!strcmp(token, "}")) { break; } if (!strcmp(token, "{")) { GetVectorForKey(ent, "origin", ent->origin); brush_t *b = Brush_Parse(ent->origin); if (b != NULL) { b->owner = ent; // add to the end of the entity chain b->onext = &ent->brushes; b->oprev = ent->brushes.oprev; ent->brushes.oprev->onext = b; ent->brushes.oprev = b; } else { break; } } else { ParseEpair(&ent->epairs); } } while (1); if (onlypairs) { return ent; } return Entity_PostParse(ent, pList); }
/* ================ ParseEntity ================ */ qboolean ParseEntity (void) { if (!GetToken (true)) return false; if (strcmp (token, "{") ) Error ("ParseEntity: { not found"); if (num_entities == MAX_MAP_ENTITIES) Error ("num_entities == MAX_MAP_ENTITIES"); mapent = &entities[num_entities]; num_entities++; do { fflush(stdout); if (!GetToken (true)) Error ("ParseEntity: EOF without closing brace"); if (!strcmp (token, "}") ) break; if (!strcmp (token, "{") ) ParseBrush (); else ParseEpair (); } while (1); // all fields have been parsed if (!strncmp (mapent->classname, "light", 5)) { if (!mapent->light) { mapent->color[0] = mapent->color[1] = mapent->color[2] = 1; mapent->light = DEFAULTLIGHTLEVEL; } // LordHavoc: added falloff and color if (!mapent->falloff) mapent->falloff = DEFAULTFALLOFF * DEFAULTFALLOFF; } if (!strcmp (mapent->classname, "light")) if (mapent->targetname[0] && !mapent->style) { char s[16]; mapent->style = LightStyleForTargetname (mapent->targetname, true); sprintf (s,"%i", mapent->style); SetKeyValue (mapent, "style", s); } GetVectorForKey (mapent, "origin", mapent->origin); return true; }
/* ======================================================================================================================= ======================================================================================================================= */ void SetKeyVec3(entity_t *ent, const char *key, idVec3 v) { if (ent == NULL) { return; } if (!key || !key[0]) { return; } idStr str; sprintf(str, "%g %g %g", v.x, v.y, v.z); ent->epairs.Set(key, str); GetVectorForKey(ent, "origin", ent->origin); }
/* ================= SetEntityBounds finds the bounds of an entity's brushes (necessary for terrain-style generic metashaders) ================= */ void SetEntityBounds( entity_t *e ) { int i; brush_t *b; parseMesh_t *p; vec3_t mins, maxs; const char *value; ClearBounds( mins, maxs ); for( b = e->brushes; b; b = b->next ) { AddPointToBounds( b->mins, mins, maxs ); AddPointToBounds( b->maxs, mins, maxs ); } for( p = e->patches; p; p = p->next ) { for( i = 0; i < (p->mesh.width * p->mesh.height); i++ ) AddPointToBounds( p->mesh.verts[i].xyz, mins, maxs ); } value = ValueForKey( e, "min" ); if( value[0] != '\0' ) GetVectorForKey( e, "min", mins ); value = ValueForKey( e, "max" ); if( value[0] != '\0' ) GetVectorForKey( e, "max", maxs ); for( b = e->brushes; b; b = b->next ) { VectorCopy( mins, b->eMins ); VectorCopy( maxs, b->eMaxs ); } for( p = e->patches; p; p = p->next ) { VectorCopy( mins, p->eMins ); VectorCopy( maxs, p->eMaxs ); } }
/* ======================================================================================================================= ======================================================================================================================= */ void SetKeyMat3(entity_t *ent, const char *key, idMat3 m) { if (ent == NULL) { return; } if (!key || !key[0]) { return; } idStr str; sprintf(str, "%g %g %g %g %g %g %g %g %g",m[0][0],m[0][1],m[0][2],m[1][0],m[1][1],m[1][2],m[2][0],m[2][1],m[2][2]); ent->epairs.Set(key, str); GetVectorForKey(ent, "origin", ent->origin); }
//----------------------------------------------------------------------------- // Computes the lighting origin //----------------------------------------------------------------------------- static bool ComputeLightingOrigin( StaticPropBuild_t const& build, Vector& lightingOrigin ) { for (int i = s_LightingInfo.Count(); --i >= 0; ) { int entIndex = s_LightingInfo[i]; // Check against all lighting info entities char const* pTargetName = ValueForKey( &entities[entIndex], "targetname" ); if (!Q_strcmp(pTargetName, build.m_pLightingOrigin)) { GetVectorForKey( &entities[entIndex], "origin", lightingOrigin ); return true; } } return false; }
/* ======================================================================================================================= ======================================================================================================================= */ void SetKeyValue(entity_t *ent, const char *key, const char *value, bool trackAngles) { if (ent == NULL) { return; } if (!key || !key[0]) { return; } if (trackAngles) { TrackMD3Angles(ent, key, value); } ent->epairs.Set(key, value); GetVectorForKey(ent, "origin", ent->origin); // update sound in case this key was relevent Entity_UpdateSoundEmitter( ent ); }
/* ================ ParseEntity ================ */ static qboolean ParseEntity (void) { if (!GetToken (true)) return false; if (strcmp (token, "{") ) Error ("%s: { not found", __thisfunc__); if (num_entities == MAX_MAP_ENTITIES) Error ("num_entities == MAX_MAP_ENTITIES"); mapent = &entities[num_entities]; num_entities++; do { if (!GetToken (true)) Error ("%s: EOF without closing brace", __thisfunc__); if (!strcmp (token, "}") ) break; if (!strcmp (token, "{") ) ParseBrush (); else ParseEpair (); } while (1); GetVectorForKey (mapent, "origin", mapent->origin); // JDC 8/8/97: adjust for origin brush if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2]) { mbrush_t *b; mface_t *f; for (b = mapent->brushes ; b ; b = b->next) { for (f = b->faces ; f ; f = f->next) f->plane.dist -= DotProduct (mapent->origin, f->plane.normal); } } return true; }
void FindFaceOffsets (void) { int i, j; entity_t *ent; char name[20]; vec3_t org; faceoffset = malloc (numfaces * sizeof (vec3_t)); memset (faceoffset, 0, numfaces * sizeof (vec3_t)); for (i = 1; i < nummodels; i++) { sprintf (name, "*%d", i); ent = FindEntityWithKeyPair ("model", name); if (!ent) logprintf ("WARNING: FindFaceOffsets: Couldn't find entity for model %s\n", name); else if (!strncmp (ValueForKey (ent, "classname"), "rotate_", 7)) { int start; int end; GetVectorForKey (ent, "origin", org); start = dmodels[ i ].firstface; end = start + dmodels[ i ].numfaces; if (start >= numfaces || end > numfaces) Error ("FindFaceOffsets: numfaces (%d) exceeded, start=%d, end=%d", numfaces, start, end); for (j = start; j < end; j++) { faceoffset[ j ][ 0 ] = org[ 0 ]; faceoffset[ j ][ 1 ] = org[ 1 ]; faceoffset[ j ][ 2 ] = org[ 2 ]; } } } }
static void FindFaceOffsets(void) { int i, j; entity_t *ent; char name[20]; const char *classname; vec3_t org; memset(nolightface, 0, sizeof(nolightface)); for (j = dmodels[0].firstface; j < dmodels[0].numfaces; j++) nolightface[j] = 0; for (i = 1; i < nummodels; i++) { sprintf(name, "*%d", i); ent = FindEntityWithKeyPair("model", name); if (!ent) Error("%s: Couldn't find entity for model %s.\n", __func__, name); classname = ValueForKey(ent, "classname"); if (!strncmp(classname, "rotate_", 7)) { int start; int end; GetVectorForKey(ent, "origin", org); start = dmodels[i].firstface; end = start + dmodels[i].numfaces; for (j = start; j < end; j++) { nolightface[j] = 300; faceoffset[j][0] = org[0]; faceoffset[j][1] = org[1]; faceoffset[j][2] = org[2]; } } } }
/* ============= MakePatches ============= */ void MakePatches( void ){ int i, j, k; dface_t *f; int fn; winding_t *w; dmodel_t *mod; vec3_t origin; entity_t *ent; Sys_FPrintf( SYS_VRB, "%i faces\n", numfaces ); for ( i = 0 ; i < nummodels ; i++ ) { mod = &dmodels[i]; ent = EntityForModel( i ); // bmodels with origin brushes need to be offset into their // in-use position GetVectorForKey( ent, "origin", origin ); //VectorCopy (vec3_origin, origin); for ( j = 0 ; j < mod->numfaces ; j++ ) { fn = mod->firstface + j; face_entity[fn] = ent; VectorCopy( origin, face_offset[fn] ); f = &dfaces[fn]; w = WindingFromFace( f ); for ( k = 0 ; k < w->numpoints ; k++ ) { VectorAdd( w->p[k], origin, w->p[k] ); } MakePatchForFace( fn, w ); } } Sys_FPrintf( SYS_VRB, "%i sqaure feet\n", (int)( totalarea / 64 ) ); }
/** * @brief Create surface fragments for light-emitting surfaces so that light sources * may be computed along them. */ void BuildPatches (void) { int i; OBJZERO(face_patches); for (i = 0; i < curTile->nummodels; i++) { const dBspModel_t* mod = &curTile->models[i]; const entity_t* ent = EntityForModel(i); vec3_t origin; int j; /* bmodels with origin brushes (like func_door) need to be offset into their * in-use position */ GetVectorForKey(ent, "origin", origin); for (j = 0; j < mod->numfaces; j++) { const int facenum = mod->firstface + j; dBspSurface_t* f = &curTile->faces[facenum]; winding_t* w; int k; /* store the origin in case of moving bmodels (e.g. func_door) */ VectorCopy(origin, face_offset[facenum]); if (!HasLight(f)) /* no light */ continue; w = WindingFromFace(f); for (k = 0; k < w->numpoints; k++) VectorAdd(w->p[k], origin, w->p[k]); BuildPatch(facenum, w); } } }
int WriteASEFile(char *filename) { int i, j, s, modelNum; FILE *f; dshader_t *shader; dmodel_t *dm; drawSurface_t *ds; entity_t *e; vec3_t origin; const char *key; char name[1024], base[1024]; Sys_Printf("writing %s\n", filename); f = fopen(filename, "wb"); if(!f) Error("Can't write %s\b", filename); // print header fprintf(f, "*3DSMAX_ASCIIEXPORT\t200\r\n"); fprintf(f, "*COMMENT\t\"Generated by XMap (XreaL) -bsp2ase\"\r\n"); fprintf(f, "*SCENE\t{\r\n"); fprintf(f, "\t*SCENE_FILENAME\t\"%s\"\r\n", base); fprintf(f, "\t*SCENE_FIRSTFRAME\t0\r\n"); fprintf(f, "\t*SCENE_LASTFRAME\t100\r\n"); fprintf(f, "\t*SCENE_FRAMESPEED\t30\r\n"); fprintf(f, "\t*SCENE_TICKSPERFRAME\t160\r\n"); fprintf(f, "\t*SCENE_BACKGROUND_STATIC\t0.0000\t0.0000\t0.0000\r\n"); fprintf(f, "\t*SCENE_AMBIENT_STATIC\t0.0000\t0.0000\t0.0000\r\n"); fprintf(f, "}\r\n"); // print materials fprintf(f, "*MATERIAL_LIST\t{\r\n"); fprintf(f, "\t*MATERIAL_COUNT\t%d\r\n", numShaders); for(i = 0; i < numShaders; i++) { shader = &dshaders[i]; ConvertShader(f, shader, i); } fprintf(f, "}\r\n"); // walk entity list for(i = 0; i < numEntities; i++) { // get entity and model e = &entities[i]; if(i == 0) { modelNum = 0; } else { key = ValueForKey(e, "model"); if(key[0] != '*') { continue; } modelNum = atoi(key + 1); } dm = &dmodels[modelNum]; // get entity origin key = ValueForKey(e, "origin"); if(key[0] == '\0') VectorClear(origin); else GetVectorForKey(e, "origin", origin); // convert model for(j = 0; j < dm->numSurfaces; j++) { s = j + dm->firstSurface; ds = &drawSurfaces[s]; ConvertSurface(f, dm, modelNum, ds, s, origin); } } // close the file fclose(f); // return to sender return 0; }
/* =========== FillOutside =========== */ node_t *FillOutside (node_t *node, qboolean leakfile) { int s; vec_t *v; int i; qboolean inside; qboolean ret; vec3_t origin; char *cl; qprintf ("----- FillOutside ----\n"); if (nofill) { printf ("skipped\n"); return node; } // // place markers for all entities so // we know if we leak inside // inside = false; for (i=1 ; i<num_entities ; i++) { GetVectorForKey (&entities[i], "origin", origin); if (!VectorCompare(origin, vec3_origin)) { cl = ValueForKey (&entities[i], "classname"); origin[2] += 1; // so objects on floor are ok // nudge playerstart around if needed so clipping hulls allways // have a vlaid point if (!strcmp (cl, "info_player_start")) { int x, y; for (x=-16 ; x<=16 ; x += 16) { for (y=-16 ; y<=16 ; y += 16) { origin[0] += x; origin[1] += y; if (PlaceOccupant (i, origin, node)) { inside = true; goto gotit; } origin[0] -= x; origin[1] -= y; } } gotit: ; } else { if (PlaceOccupant (i, origin, node)) inside = true; } } } if (!inside) { printf ("Hullnum %i: No entities in empty space -- no filling performed\n", hullnum); return node; } s = !(outside_node.portals->nodes[1] == &outside_node); // first check to see if an occupied leaf is hit outleafs = 0; valid++; prevleaknode = NULL; if (leakfile) { pointfile = fopen (pointfilename, "w"); if (!pointfile) Error ("Couldn't open %s\n", pointfilename); StripExtension (pointfilename); strcat (pointfilename, ".lin"); linefile = fopen (pointfilename, "w"); if (!linefile) Error ("Couldn't open %s\n", pointfilename); } ret = RecursiveFillOutside (outside_node.portals->nodes[s], false); if (leakfile) { fclose (pointfile); fclose (linefile); } if (ret) { printf("LEAK LEAK LEAK\n"); GetVectorForKey (&entities[hit_occupied], "origin", origin); qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n" , origin[0], origin[1], origin[2]); qprintf ("no filling performed\n"); qprintf ("point file and line file generated\n"); qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); if (leakonly) Error ("Stopped by leak."); return node; } // now go back and fill things in valid++; RecursiveFillOutside (outside_node.portals->nodes[s], true); // remove faces and nodes from filled in leafs c_falsenodes = 0; c_free_faces = 0; c_keep_faces = 0; node = ClearOutFaces_r (node); qprintf ("%5i outleafs\n", outleafs); qprintf ("%5i freed faces\n", c_free_faces); qprintf ("%5i keep faces\n", c_keep_faces); qprintf ("%5i falsenodes\n", c_falsenodes); // save portal file for vis tracing if (leakfile) WritePortalfile (node); return node; }
void LeakFile(tree_t * tree) #endif { vec3_t mid; FILE *linefile; char filename[1024]; node_t *node; int count; #if defined(USE_XML) xmlNodePtr xml_node, point; #endif if(!tree->outside_node.occupied) { #if defined(USE_XML) return NULL; #endif } Sys_FPrintf(SYS_VRB, "--- LeakFile ---\n"); // // write the points to the file // sprintf(filename, "%s.lin", source); linefile = fopen(filename, "w"); if(!linefile) Error("Couldn't open %s", filename); #if defined(USE_XML) xml_node = xmlNewNode(NULL, "polyline"); #endif count = 0; node = &tree->outside_node; while(node->occupied > 1) { int next; portal_t *p, *nextportal = NULL; // STFU, compiler node_t *nextnode = NULL; // STFU, compiler int s; // find the best portal exit next = node->occupied; for(p = node->portals; p; p = p->next[!s]) { s = (p->nodes[0] == node); if(p->nodes[s]->occupied && p->nodes[s]->occupied < next) { nextportal = p; nextnode = p->nodes[s]; next = nextnode->occupied; } } node = nextnode; WindingCenter(nextportal->winding, mid); fprintf(linefile, "%f %f %f\n", mid[0], mid[1], mid[2]); #if defined(USE_XML) point = xml_NodeForVec(mid); xmlAddChild(xml_node, point); #endif count++; } // add the occupant center GetVectorForKey(node->occupant, "origin", mid); fprintf(linefile, "%f %f %f\n", mid[0], mid[1], mid[2]); #if defined(USE_XML) point = xml_NodeForVec(mid); xmlAddChild(xml_node, point); #endif Sys_FPrintf(SYS_VRB, "%9d point linefile\n", count + 1); fclose(linefile); #if defined(USE_XML) return xml_node; #endif }