static void DumpHullWindings(const brushhull_t* const hull) { int x = 0; bface_t* face; for (face = hull->faces; face; face = face->next) { Developer(DEVELOPER_LEVEL_MEGASPAM, "Winding %d\n", x++); face->w->Print(); Developer(DEVELOPER_LEVEL_MEGASPAM, "\n"); } }
static Winding* NewWindingFromPlane(const brushhull_t* const hull, const int planenum) { Winding* winding; Winding* front; Winding* back; bface_t* face; plane_t* plane; plane = &g_mapplanes[planenum]; winding = new Winding(plane->normal, plane->dist); for (face = hull->faces; face; face = face->next) { plane = &g_mapplanes[face->planenum]; winding->Clip(plane->normal, plane->dist, &front, &back); delete winding; if (front) { delete front; } if (back) { winding = back; } else { Developer(DEVELOPER_LEVEL_ERROR, "NewFaceFromPlane returning NULL"); return NULL; } } return winding; }
static vec_t CalculateSolidVolume(const brushhull_t* const hull) { // calculate polyhedron origin // subdivide face winding into triangles // for each face // calculate volume of triangle of face to origin // add subidivided volume chunk to total int x = 0; vec_t volume = 0.0; vec_t inverse; vec3_t midpoint = { 0.0, 0.0, 0.0 }; bface_t* face; for (face = hull->faces; face; face = face->next, x++) { vec3_t facemid; face->w->getCenter(facemid); VectorAdd(midpoint, facemid, midpoint); Developer(DEVELOPER_LEVEL_MESSAGE, "Midpoint for face %d is %f %f %f\n", x, facemid[0], facemid[1], facemid[2]); } inverse = 1.0 / x; VectorScale(midpoint, inverse, midpoint); Developer(DEVELOPER_LEVEL_MESSAGE, "Midpoint for hull is %f %f %f\n", midpoint[0], midpoint[1], midpoint[2]); for (face = hull->faces; face; face = face->next, x++) { plane_t* plane = &g_mapplanes[face->planenum]; vec_t area = face->w->getArea(); vec_t dist = DotProduct(plane->normal, midpoint); dist -= plane->dist; dist = fabs(dist); volume += area * dist / 3.0; } Developer(DEVELOPER_LEVEL_MESSAGE, "Volume for brush is %f\n", volume); return volume; }
/* * ================ * exists * ================ */ bool q_exists(const char* const filename) { FILE* f; f = fopen(filename, "rb"); if (!f) { IfDebug(Developer(DEVELOPER_LEVEL_SPAM, "Checking for existance of file %s (failed)\n", filename)); return false; } else { fclose(f); IfDebug(Developer(DEVELOPER_LEVEL_SPAM, "Checking for existance of file %s (success)\n", filename)); return true; } }
void LoadWadcfgfile (const char *filename) { int count = 0; int size; char *buffer; size = LoadFile (filename, &buffer); ParseFromMemory (buffer, size); while (GetToken (true)) { bool include = false; wadpath_t *current; if (!stricmp (g_token, "include")) { include = true; if (!GetToken (true)) { Error ("parsing '%s': unexpected end of file.", filename); } } Developer (DEVELOPER_LEVEL_MESSAGE, "LoadWadcfgfile: adding wad file '%s'.\n", g_token); if (g_iNumWadPaths >= MAX_WADPATHS) { Error ("parsing '%s': too many wad files.", filename); } count++; current = (wadpath_t *)malloc (sizeof (wadpath_t)); hlassume (current != NULL, assume_NoMemory); g_pWadPaths[g_iNumWadPaths] = current; g_iNumWadPaths++; safe_strncpy (current->path, g_token, _MAX_PATH); current->usedbymap = true; // what's this? current->usedtextures = 0; if (include) { Developer (DEVELOPER_LEVEL_MESSAGE, "LoadWadcfgfile: including '%s'.\n", current->path); g_WadInclude.push_back(current->path); } } free (buffer); // should not be freed because it is still being used as script buffer Log ("Using custom wadfile configuration: '%s' (with %i wad%s)\n", filename, count, count > 1 ? "s" : ""); }
// ===================================================================================== // LoadLump // ===================================================================================== int LoadLump(const lumpinfo_t* const source, byte* dest, int* texsize) { //Log("** PnFNFUNC: LoadLump\n"); *texsize = 0; if (source->filepos) { if (fseek(texfiles[source->iTexFile], source->filepos, SEEK_SET)) { Warning("fseek to %d failed\n", source->filepos); } *texsize = source->disksize; bool wadinclude = false; std::map< int, bool >::iterator it; it = s_WadIncludeMap.find(source->iTexFile); if (it != s_WadIncludeMap.end()) { wadinclude = it->second; } // Should we just load the texture header w/o the palette & bitmap? if ((g_wadtextures && !wadinclude) || !TestIncludeTextureNamed(source->name)) { // Just read the miptex header and zero out the data offsets. // We will load the entire texture from the WAD at engine runtime int i; miptex_t* miptex = (miptex_t*)dest; SafeRead(texfiles[source->iTexFile], dest, sizeof(miptex_t)); for (i = 0; i < MIPLEVELS; i++) miptex->offsets[i] = 0; return sizeof(miptex_t); } else { Developer(DEVELOPER_LEVEL_MESSAGE,"Including texture %s\n",source->name); // Load the entire texture here so the BSP contains the texture SafeRead(texfiles[source->iTexFile], dest, source->disksize); return source->disksize; } } Warning("::LoadLump() texture %s not found!", source->name); return 0; }
void CalculateBrushUnions(const int brushnum) { int bn, hull; brush_t* b1; brush_t* b2; brushhull_t* bh1; brushhull_t* bh2; entity_t* e; b1 = &g_mapbrushes[brushnum]; e = &g_entities[b1->entitynum]; for (hull = 0; hull < 1 /* NUM_HULLS */ ; hull++) { bh1 = &b1->hulls[hull]; if (!bh1->faces) // Skip it if it is not in this hull { continue; } for (bn = brushnum + 1; bn < e->numbrushes; bn++) { // Only compare if b2 > b1, tests are communitive b2 = &g_mapbrushes[e->firstbrush + bn]; bh2 = &b2->hulls[hull]; if (!bh2->faces) // Skip it if it is not in this hull { continue; } if (b1->contents != b2->contents) { continue; // different contents, ignore } Developer(DEVELOPER_LEVEL_SPAM, "Processing hull %d brush %d and brush %d\n", hull, brushnum, bn); { brushhull_t union_hull; bface_t* face; union_hull.bounds = bh1->bounds; union_hull.faces = CopyFaceList(bh1->faces); for (face = bh2->faces; face; face = face->next) { AddPlaneToUnion(&union_hull, face->planenum); } // union was clipped away (no intersection) if (!union_hull.faces) { continue; } if (g_developer >= DEVELOPER_LEVEL_MESSAGE) { Log("\nUnion windings\n"); DumpHullWindings(&union_hull); Log("\nBrush %d windings\n", brushnum); DumpHullWindings(bh1); Log("\nBrush %d windings\n", bn); DumpHullWindings(bh2); } { vec_t volume_brush_1; vec_t volume_brush_2; vec_t volume_brush_union; vec_t volume_ratio_1; vec_t volume_ratio_2; if (isInvalidHull(&union_hull)) { FreeFaceList(union_hull.faces); continue; } volume_brush_union = CalculateSolidVolume(&union_hull); volume_brush_1 = CalculateSolidVolume(bh1); volume_brush_2 = CalculateSolidVolume(bh2); volume_ratio_1 = volume_brush_union / volume_brush_1; volume_ratio_2 = volume_brush_union / volume_brush_2; if ((volume_ratio_1 > g_BrushUnionThreshold) || (g_developer >= DEVELOPER_LEVEL_MESSAGE)) { volume_ratio_1 *= 100.0; Warning("Entity %d : Brush %d intersects with brush %d by %2.3f percent", #ifdef HLCSG_COUNT_NEW b1->originalentitynum, b1->originalbrushnum, b2->originalbrushnum, #else b1->entitynum, brushnum, bn, #endif volume_ratio_1); } if ((volume_ratio_2 > g_BrushUnionThreshold) || (g_developer >= DEVELOPER_LEVEL_MESSAGE)) { volume_ratio_2 *= 100.0; Warning("Entity %d : Brush %d intersects with brush %d by %2.3f percent", #ifdef HLCSG_COUNT_NEW b1->originalentitynum, b2->originalbrushnum, b1->originalbrushnum, #else b1->entitynum, bn, brushnum, #endif volume_ratio_2); } } FreeFaceList(union_hull.faces); } } } }
int GetThreadWork() { int r, f, i; double ct, finish, finish2, finish3; ThreadLock(); if (dispatch == 0) { oldf = 0; } if (dispatch > workcount) { Developer(DEVELOPER_LEVEL_ERROR, "dispatch > workcount!!!\n"); ThreadUnlock(); return -1; } if (dispatch == workcount) { Developer(DEVELOPER_LEVEL_MESSAGE, "dispatch == workcount, work is complete\n"); ThreadUnlock(); return -1; } if (dispatch < 0) { Developer(DEVELOPER_LEVEL_ERROR, "negative dispatch!!!\n"); ThreadUnlock(); return -1; } f = THREADTIMES_SIZE * dispatch / workcount; if (pacifier) { printf("\r%6d /%6d", dispatch, workcount); #ifdef ZHLT_PROGRESSFILE // AJM if (g_progressfile) { } #endif if (f != oldf) { ct = I_FloatTime(); /* Fill in current time for threadtimes record */ for (i = oldf; i <= f; i++) { if (threadtimes[i] < 1) { threadtimes[i] = ct; } } oldf = f; if (f > 10) { finish = (ct - threadtimes[0]) * (THREADTIMES_SIZEf - f) / f; finish2 = 10.0 * (ct - threadtimes[f - 10]) * (THREADTIMES_SIZEf - f) / THREADTIMES_SIZEf; finish3 = THREADTIMES_SIZEf * (ct - threadtimes[f - 1]) * (THREADTIMES_SIZEf - f) / THREADTIMES_SIZEf; if (finish > 1.0) { printf(" (%d%%: est. time to completion %ld/%ld/%ld secs) ", f, (long)(finish), (long)(finish2), (long)(finish3)); #ifdef ZHLT_PROGRESSFILE // AJM if (g_progressfile) { } #endif } else { printf(" (%d%%: est. time to completion <1 sec) ", f); #ifdef ZHLT_PROGRESSFILE // AJM if (g_progressfile) { } #endif } } } } else { if (f != oldf) { oldf = f; switch (f) { case 10: case 20: case 30: case 40: case 50: case 60: case 70: case 80: case 90: case 100: /* case 5: case 15: case 25: case 35: case 45: case 55: case 65: case 75: case 85: case 95: */ printf("%d%%...", f); default: break; } } } r = dispatch; dispatch++; ThreadUnlock(); return r; }
void RunThreadsOn(int workcnt, bool showpacifier, q_threadfunction func) { DWORD threadid[MAX_THREADS]; HANDLE threadhandle[MAX_THREADS]; int i; double start, end; threadstart = I_FloatTime(); start = threadstart; for (i = 0; i < THREADTIMES_SIZE; i++) { threadtimes[i] = 0; } dispatch = 0; workcount = workcnt; oldf = -1; pacifier = showpacifier; threaded = true; q_entry = func; if (workcount < dispatch) { Developer(DEVELOPER_LEVEL_ERROR, "RunThreadsOn: Workcount(%i) < dispatch(%i)\n", workcount, dispatch); } hlassume(workcount >= dispatch, assume_BadWorkcount); // // Create all the threads (suspended) // threads_InitCrit(); for (i = 0; i < g_numthreads; i++) { HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadEntryStub, (LPVOID) i, CREATE_SUSPENDED, &threadid[i]); if (hThread != NULL) { threadhandle[i] = hThread; } else { LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) & lpMsgBuf, 0, NULL); // Process any inserts in lpMsgBuf. // ... // Display the string. Developer(DEVELOPER_LEVEL_ERROR, "CreateThread #%d [%08X] failed : %s\n", i, threadhandle[i], lpMsgBuf); Fatal(assume_THREAD_ERROR, "Unable to create thread #%d", i); // Free the buffer. LocalFree(lpMsgBuf); } } CheckFatal(); // Start all the threads for (i = 0; i < g_numthreads; i++) { if (ResumeThread(threadhandle[i]) == 0xFFFFFFFF) { LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) & lpMsgBuf, 0, NULL); // Process any inserts in lpMsgBuf. // ... // Display the string. Developer(DEVELOPER_LEVEL_ERROR, "ResumeThread #%d [%08X] failed : %s\n", i, threadhandle[i], lpMsgBuf); Fatal(assume_THREAD_ERROR, "Unable to start thread #%d", i); // Free the buffer. LocalFree(lpMsgBuf); } } CheckFatal(); // Wait for threads to complete for (i = 0; i < g_numthreads; i++) { Developer(DEVELOPER_LEVEL_MESSAGE, "WaitForSingleObject on thread #%d [%08X]\n", i, threadhandle[i]); WaitForSingleObject(threadhandle[i], INFINITE); } threads_UninitCrit(); q_entry = NULL; threaded = false; end = I_FloatTime(); if (pacifier) { printf("\r%60s\r", ""); } Log(" (%.2f seconds)\n", end - start); }
// ===================================================================================== // SubdivideFace // If the face is >256 in either texture direction, carve a valid sized // piece off and insert the remainder in the next link // ===================================================================================== void SubdivideFace(face_t* f, face_t** prevptr) { vec_t mins, maxs; vec_t v; int axis; int i; dplane_t plane; face_t* front; face_t* back; face_t* next; texinfo_t* tex; vec3_t temp; // special (non-surface cached) faces don't need subdivision #ifdef HLCSG_HLBSP_VOIDTEXINFO if (f->texturenum == -1) { return; } #endif tex = &g_texinfo[f->texturenum]; if (tex->flags & TEX_SPECIAL) { return; } if (f->facestyle == face_hint) { return; } if (f->facestyle == face_skip) { return; } #ifdef ZHLT_NULLTEX // AJM if (f->facestyle == face_null) return; // ideally these should have their tex_special flag set, so its here jic #endif #ifdef HLCSG_HLBSP_SOLIDHINT if (f->facestyle == face_discardable) return; #endif for (axis = 0; axis < 2; axis++) { while (1) { #ifdef HLBSP_SUBDIVIDE_INMID const int maxlightmapsize = g_subdivide_size / TEXTURE_STEP + 1; int lightmapmins, lightmapmaxs; if (f->numpoints == 0) { break; } for (i = 0; i < f->numpoints; i++) { v = DotProduct (f->pts[i], tex->vecs[axis]) + tex->vecs[axis][3]; if (i == 0 || v < mins) { mins = v; } if (i == 0 || v > maxs) { maxs = v; } } lightmapmins = (int)floor (mins / TEXTURE_STEP - 0.05); // the worst case lightmapmaxs = (int)ceil (maxs / TEXTURE_STEP + 0.05); // the worst case if (lightmapmaxs - lightmapmins <= maxlightmapsize) { break; } #else mins = 999999; maxs = -999999; for (i = 0; i < f->numpoints; i++) { v = DotProduct(f->pts[i], tex->vecs[axis]); if (v < mins) { mins = v; } if (v > maxs) { maxs = v; } } if ((maxs - mins) <= g_subdivide_size) { break; } #endif // split it subdivides++; VectorCopy(tex->vecs[axis], temp); v = VectorNormalize(temp); VectorCopy(temp, plane.normal); #ifdef HLBSP_SUBDIVIDE_INMID int splitpos; if ((lightmapmaxs - lightmapmins - 1) - (maxlightmapsize - 1) < (maxlightmapsize - 1) / 4) // don't create very thin face { splitpos = lightmapmins + (maxlightmapsize - 1) - (maxlightmapsize - 1) / 4; } else { splitpos = lightmapmins + (maxlightmapsize - 1); } plane.dist = ((splitpos + 0.5) * TEXTURE_STEP - tex->vecs[axis][3]) / v; #else plane.dist = (mins + g_subdivide_size - TEXTURE_STEP) / v; //plane.dist = (mins + g_subdivide_size - 16) / v; //--vluzacn #endif next = f->next; SplitFace(f, &plane, &front, &back); if (!front || !back) { Developer(DEVELOPER_LEVEL_SPAM, "SubdivideFace: didn't split the %d-sided polygon @(%.0f,%.0f,%.0f)", f->numpoints, f->pts[0][0], f->pts[0][1], f->pts[0][2]); #ifndef HLBSP_SubdivideFace_FIX break; #endif } #ifdef HLBSP_SubdivideFace_FIX f = next; if (front) { front->next = f; f = front; } if (back) { back->next = f; f = back; } *prevptr = f; #else *prevptr = back; back->next = front; front->next = next; f = back; #endif } } }