void UnparseEntities (void) { int i; entity_t *ent; char *buf, *end; buf = dentdata; end = buf; *end = 0; // Vic: write "worldspawn" as the very first entity (engines might depend on it) ent = FindEntityWithKeyPair( "classname", "worldspawn" ); if( ent ) UnparseEntity( ent, buf, &end ); for (i=0 ; i<num_entities ; i++) { if( &entities[i] != ent ) UnparseEntity( &entities[i], buf, &end ); } entdatasize = end - buf + 1; }
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]; } } } }
/* ================= CreateHulls ================= */ void CreateHulls (void) { int i; // hull 0 is always point-sized VectorClear (hullinfo.hullsizes[0][0]); VectorClear (hullinfo.hullsizes[0][1]); CreateSingleHull (0); // commanded to ignore the hulls altogether if (noclip) { hullinfo.numhulls = 1; hullinfo.filehulls = (ismcbsp ? 1 : 4); return; } // create the hulls sequentially printf ("building hulls sequentially...\n"); // get the hull sizes if (ismcbsp) { entity_t *world; char keymins[16], keymaxs[16]; vec3_t v; int i; // read hull values from _hull# fields in worldspawn world = FindEntityWithKeyPair ("classname", "worldspawn"); for (hullinfo.numhulls = 1; hullinfo.numhulls < MAX_MAP_HULLS; hullinfo.numhulls++) { sprintf (keymins, "_hull%d_mins", hullinfo.numhulls); sprintf (keymaxs, "_hull%d_maxs", hullinfo.numhulls); if ((ValueForKey(world, keymins))[0] && (ValueForKey(world, keymaxs))[0]) { GetVectorForKey (world, keymins, v); VectorCopy (v, hullinfo.hullsizes[hullinfo.numhulls][0]); GetVectorForKey (world, keymaxs, v); VectorCopy (v, hullinfo.hullsizes[hullinfo.numhulls][1]); } else break; } hullinfo.filehulls = hullinfo.numhulls; printf ("Map has %d hulls:\n", hullinfo.numhulls); for (i = 0; i < hullinfo.numhulls; i++) printf ("%2d: %.1f %.1f %.1f, %.1f %.1f %.1f\n", i, hullinfo.hullsizes[i][0][0], hullinfo.hullsizes[i][0][1], hullinfo.hullsizes[i][0][2], hullinfo.hullsizes[i][1][0], hullinfo.hullsizes[i][1][1], hullinfo.hullsizes[i][1][2]); } else { hullinfo.numhulls = 3; hullinfo.filehulls = 4; VectorSet (hullinfo.hullsizes[1][0], -16, -16, -24); VectorSet (hullinfo.hullsizes[1][1], 16, 16, 32); VectorSet (hullinfo.hullsizes[2][0], -32, -32, -24); VectorSet (hullinfo.hullsizes[2][1], 32, 32, 64); } for (i = 1; i < hullinfo.numhulls; i++) CreateSingleHull (i); }
/* ============= LightWorld ============= */ void LightWorld( void ) { int i, k, n, m, count; unsigned short *mark; time_t lightstarttime, oldtime, newtime; directlight_t *light; dleaf_t *leaf; int lightcount = 0, castcount = 0, emptycount = 0, solidcount = 0, watercount = 0, slimecount = 0, lavacount = 0, skycount = 0, misccount = 0, ignorevis; vec3_t org; char name[8]; entity_t *ent; if( !relight ) lightdatasize = 0; rgblightdatasize = 0; lightstarttime = time( NULL ); lightchainbufindex = 0; novislights = alllights = 0; memset( surfacelightchain, 0, sizeof( surfacelightchain ) ); // LordHavoc: find the right leaf for each entity for( i = 0, light = directlights; i < num_directlights; i++, light++ ) { lightcount++; alllight[alllights++] = light; leaf = Light_PointInLeaf(light->origin); ignorevis = false; switch( leaf->contents ) { case CONTENTS_EMPTY: emptycount++; break; case CONTENTS_SOLID: solidcount++; ignorevis = true; break; case CONTENTS_WATER: watercount++; break; case CONTENTS_SLIME: slimecount++; break; case CONTENTS_LAVA: lavacount++; break; case CONTENTS_SKY: skycount++; ignorevis = true; break; default: misccount++; break; } if( ignorevis ) printf( "light at origin '%f %f %f' is in solid or sky, ignoring vis\n", light->origin[0], light->origin[1], light->origin[2] ); if( leaf->visofs == -1 || ignorevis || !lightvis || light->type == LIGHTTYPE_SUN ) { /* if ((lightchainbufindex + numfaces) > LIGHTCHAINS) Error("LightWorld: ran out of light chains! complain to maintainer of hlight\n"); for (m = 0;m < numfaces;m++) { castcount++; lightchainbuf[lightchainbufindex].light = entity; lightchainbuf[lightchainbufindex].next = surfacelightchain[m]; surfacelightchain[m] = &lightchainbuf[lightchainbufindex++]; } */ castcount += numfaces; novislight[novislights++] = light; } else { DecompressVis( dvisdata + leaf->visofs, currentvis, (dmodels[0].visleafs + 7) >> 3 ); memset( surfacehit, 0, numfaces ); for( n = 0, leaf = dleafs + 1; n < numleafs; n++, leaf++ ) { // leafs begin at 1 if( !leaf->nummarksurfaces ) continue; if( !(currentvis[n >> 3] & (1 << (n & 7))) ) continue; if( (lightchainbufindex + leaf->nummarksurfaces) > LIGHTCHAINS ) Error( "LightWorld: ran out of light chains! complain to maintainer of hlight\n" ); for( m = 0, mark = dmarksurfaces + leaf->firstmarksurface; m < leaf->nummarksurfaces; m++, mark++ ) { if( surfacehit[*mark] ) continue; surfacehit[*mark] = true; castcount++; lightchainbuf[lightchainbufindex].light = light; lightchainbuf[lightchainbufindex].next = surfacelightchain[*mark]; surfacelightchain[*mark] = &lightchainbuf[lightchainbufindex++]; } } } } printf( "%4i lights, %4i air, %4i solid, %4i water, %4i slime, %4i lava, %4i sky, %4i unknown\n", lightcount, emptycount, solidcount, watercount, slimecount, lavacount, skycount, misccount ); i = 0; for( m = 0; m < numfaces; m++ ) { if( surfacelightchain[m] ) i++; } printf( "%5i faces, %5i (%3i%%) may receive light\n", numfaces, i, i * 100 / numfaces ); if( solidcount || skycount ) printf( "warning: %4i lights of %4i lights (%3i%%) were found in sky or solid and will not be accelerated using vis, move them out of the solid or sky to accelerate compiling\n", solidcount+skycount, lightcount, (solidcount+skycount) * 100 / lightcount ); printf( "%4i lights will be cast onto %5i surfaces, %10i casts will be performed\n", lightcount, numfaces, castcount ); // LordHavoc: let there be light count = dmodels[0].numfaces; org[0] = org[1] = org[2] = 0; oldtime = time( NULL ); c_occluded = 0; for( m = 0; m < count; ) { LightFace( dfaces + m + dmodels[0].firstface, surfacelightchain[m + dmodels[0].firstface], novislight, novislights, org ); m++; newtime = time( NULL ); if( newtime != oldtime ) { printf( "\rworld face %5i of %5i (%3i%%), estimated time left: %5i ", m, count, (int) (m*100)/count, (int) (((count-m)*(newtime-lightstarttime))/m) ); fflush( stdout ); oldtime = newtime; } } printf( "\n%5i faces done\nlightdatasize: %i\n", numfaces, lightdatasize ); printf( "c_occluded: %i\n", c_occluded ); printf( "\nlighting %5i submodels:\n", nummodels ); fflush( stdout ); c_occluded = 0; // LordHavoc: light bmodels for( k = 1; k < nummodels; k++ ) { newtime = time( NULL ); if( newtime != oldtime ) { m = k; count = nummodels; printf( "\rsubmodel %3i of %3i (%3i%%), estimated time left: %5i ", m, count, (int) (m*100)/count, (int) (((count-m)*(newtime-lightstarttime))/m) ); fflush( stdout ); oldtime = newtime; } sprintf( name, "*%d", k ); ent = FindEntityWithKeyPair( "model", name ); if( !ent ) Error( "FindFaceOffsets: Couldn't find entity for model %s.\n", name ); // LordHavoc: changed this to support origins on all submodels GetVectorForKey( ent, "origin", org ); for( m = 0; m < dmodels[k].numfaces; m++ ) LightFace( dfaces + m + dmodels[k].firstface, NULL, alllight, alllights, org ); } printf( "\n%5i submodels done\nlightdatasize: %i\n", nummodels, lightdatasize ); printf( "c_occluded: %i\n", c_occluded ); }