12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895 |
- /*
-
- CONSTRUCTIVE SOLID GEOMETRY -aka- C S G
- Code based on original code from Valve Software,
- Modified by Sean "Zoner" Cavanaugh ([email protected]) with permission.
- Modified by Tony "Merl" Moore ([email protected]) [AJM]
-
- */
- #ifdef SYSTEM_WIN32
- #pragma warning(disable:4996)
- #endif
- #pragma warning(disable:4018) // '<' : signed/unsigned mismatch
- #include "csg.h"
- /*
- NOTES
- - check map size for +/- 4k limit at load time
- - allow for multiple wad.cfg configurations per compile
- */
- static FILE* out[NUM_HULLS]; // pointer to each of the hull out files (.p0, .p1, ect.)
- static int c_tiny;
- static int c_tiny_clip;
- static int c_outfaces;
- static int c_csgfaces;
- BoundingBox world_bounds;
- #ifdef HLCSG_WADCFG
- char wadconfigname[MAX_WAD_CFG_NAME];
- #endif
- vec_t g_tiny_threshold = DEFAULT_TINY_THRESHOLD;
-
- bool g_noclip = DEFAULT_NOCLIP; // no clipping hull "-noclip"
- bool g_onlyents = DEFAULT_ONLYENTS; // onlyents mode "-onlyents"
- bool g_wadtextures = DEFAULT_WADTEXTURES; // "-nowadtextures"
- bool g_chart = DEFAULT_CHART; // show chart "-chart"
- bool g_skyclip = DEFAULT_SKYCLIP; // no sky clipping "-noskyclip"
- bool g_estimate = DEFAULT_ESTIMATE; // progress estimates "-estimate"
- bool g_info = DEFAULT_INFO; // "-info" ?
- const char* g_hullfile = NULL; // external hullfile "-hullfie sdfsd"
- #ifdef ZHLT_NULLTEX // AJM
- bool g_bUseNullTex = DEFAULT_NULLTEX; // "-nonulltex"
- #endif
- #ifdef HLCSG_PRECISIONCLIP // KGP
- cliptype g_cliptype = DEFAULT_CLIPTYPE; // "-cliptype <value>"
- #endif
- #ifdef HLCSG_NULLIFY_INVISIBLE
- const char* g_nullfile = NULL;
- #endif
- #ifdef HLCSG_CLIPECONOMY // AJM
- bool g_bClipNazi = DEFAULT_CLIPNAZI; // "-noclipeconomy"
- #endif
- #ifdef HLCSG_AUTOWAD // AJM
- bool g_bWadAutoDetect = DEFAULT_WADAUTODETECT; // "-wadautodetect"
- #endif
- #ifdef ZHLT_DETAIL // AJM
- bool g_bDetailBrushes = DEFAULT_DETAIL; // "-detail"
- #endif
- #ifdef ZHLT_PROGRESSFILE // AJM
- char* g_progressfile = DEFAULT_PROGRESSFILE; // "-progressfile path"
- #endif
- #ifdef ZHLT_INFO_COMPILE_PARAMETERS
- // =====================================================================================
- // GetParamsFromEnt
- // parses entity keyvalues for setting information
- // =====================================================================================
- void GetParamsFromEnt(entity_t* mapent)
- {
- int iTmp;
- char szTmp[256];
- Log("\nCompile Settings detected from info_compile_parameters entity\n");
- // verbose(choices) : "Verbose compile messages" : 0 = [ 0 : "Off" 1 : "On" ]
- iTmp = IntForKey(mapent, "verbose");
- if (iTmp == 1)
- {
- g_verbose = true;
- }
- else if (iTmp == 0)
- {
- g_verbose = false;
- }
- Log("%30s [ %-9s ]\n", "Compile Option", "setting");
- Log("%30s [ %-9s ]\n", "Verbose Compile Messages", g_verbose ? "on" : "off");
- // estimate(choices) :"Estimate Compile Times?" : 0 = [ 0: "Yes" 1: "No" ]
- if (IntForKey(mapent, "estimate"))
- {
- g_estimate = true;
- }
- else
- {
- g_estimate = false;
- }
- Log("%30s [ %-9s ]\n", "Estimate Compile Times", g_estimate ? "on" : "off");
- // priority(choices) : "Priority Level" : 0 = [ 0 : "Normal" 1 : "High" -1 : "Low" ]
- if (!strcmp(ValueForKey(mapent, "priority"), "1"))
- {
- g_threadpriority = eThreadPriorityHigh;
- Log("%30s [ %-9s ]\n", "Thread Priority", "high");
- }
- else if (!strcmp(ValueForKey(mapent, "priority"), "-1"))
- {
- g_threadpriority = eThreadPriorityLow;
- Log("%30s [ %-9s ]\n", "Thread Priority", "low");
- }
- // texdata(string) : "Texture Data Memory" : "4096"
- iTmp = IntForKey(mapent, "texdata") * 1024;
- if (iTmp > g_max_map_miptex)
- {
- g_max_map_miptex = iTmp;
- }
- sprintf_s(szTmp, "%i", g_max_map_miptex);
- Log("%30s [ %-9s ]\n", "Texture Data Memory", szTmp);
- // hullfile(string) : "Custom Hullfile"
- if (ValueForKey(mapent, "hullfile"))
- {
- g_hullfile = ValueForKey(mapent, "hullfile");
- Log("%30s [ %-9s ]\n", "Custom Hullfile", g_hullfile);
- }
- #ifdef HLCSG_AUTOWAD
- // wadautodetect(choices) : "Wad Auto Detect" : 0 = [ 0 : "Off" 1 : "On" ]
- if (!strcmp(ValueForKey(mapent, "wadautodetect"), "1"))
- {
- g_bWadAutoDetect = true;
- }
- else
- {
- g_bWadAutoDetect = false;
- }
- Log("%30s [ %-9s ]\n", "Wad Auto Detect", g_bWadAutoDetect ? "on" : "off");
- #endif
- #ifdef HLCSG_WADCFG
- // wadconfig(string) : "Custom Wad Configuration" : ""
- if (strlen(ValueForKey(mapent, "wadconfig")) > 0)
- {
- safe_strncpy(wadconfigname, ValueForKey(mapent, "wadconfig"), MAX_WAD_CFG_NAME);
- Log("%30s [ %-9s ]\n", "Custom Wad Configuration", wadconfigname);
- }
- #endif
- #ifdef HLCSG_CLIPECONOMY
- // noclipeconomy(choices) : "Strip Uneeded Clipnodes?" : 1 = [ 1 : "Yes" 0 : "No" ]
- iTmp = IntForKey(mapent, "noclipeconomy");
- if (iTmp == 1)
- {
- g_bClipNazi = true;
- }
- else if (iTmp == 0)
- {
- g_bClipNazi = false;
- }
- Log("%30s [ %-9s ]\n", "Clipnode Economy Mode", g_bClipNazi ? "on" : "off");
- #endif
- /*
- hlcsg(choices) : "HLCSG" : 1 =
- [
- 1 : "Normal"
- 2 : "Onlyents"
- 0 : "Off"
- ]
- */
- iTmp = IntForKey(mapent, "hlcsg");
- g_onlyents = false;
- if (iTmp == 2)
- {
- g_onlyents = true;
- }
- else if (iTmp == 0)
- {
- Fatal(assume_TOOL_CANCEL,
- "%s was set to \"Off\" (0) in info_compile_parameters entity, execution cancelled", g_Program);
- CheckFatal();
- }
- Log("%30s [ %-9s ]\n", "Onlyents", g_onlyents ? "on" : "off");
- /*
- nocliphull(choices) : "Generate clipping hulls" : 0 =
- [
- 0 : "Yes"
- 1 : "No"
- ]
- */
- iTmp = IntForKey(mapent, "nocliphull");
- if (iTmp == 1)
- {
- g_noclip = true;
- }
- else
- {
- g_noclip = false;
- }
- Log("%30s [ %-9s ]\n", "Clipping Hull Generation", g_noclip ? "off" : "on");
- #ifdef HLCSG_PRECISIONCLIP
- // cliptype(choices) : "Clip Hull Type" : 4 = [ 0 : "Smallest" 1 : "Normalized" 2: "Simple" 3 : "Precise" 4 : "Legacy" ]
- iTmp = IntForKey(mapent, "cliptype");
- switch(iTmp)
- {
- case 0:
- g_cliptype = clip_smallest;
- break;
- case 1:
- g_cliptype = clip_normalized;
- break;
- case 2:
- g_cliptype = clip_simple;
- break;
- case 3:
- g_cliptype = clip_precise;
- break;
- default:
- g_cliptype = clip_legacy;
- break;
- }
- Log("%30s [ %-9s ]\n", "Clip Hull Type", GetClipTypeString(g_cliptype));
- #endif
- /*
- noskyclip(choices) : "No Sky Clip" : 0 =
- [
- 1 : "On"
- 0 : "Off"
- ]
- */
- iTmp = IntForKey(mapent, "noskyclip");
- if (iTmp == 1)
- {
- g_skyclip = false;
- }
- else
- {
- g_skyclip = true;
- }
- Log("%30s [ %-9s ]\n", "Sky brush clip generation", g_skyclip ? "on" : "off");
- ///////////////
- Log("\n");
- }
- #endif
- // =====================================================================================
- // FixBevelTextures
- // =====================================================================================
- void FixBevelTextures()
- {
- for(int counter = 0; counter < g_numtexinfo; counter++)
- {
- if(g_texinfo[counter].flags & TEX_BEVEL)
- { g_texinfo[counter].flags &= ~TEX_BEVEL; }
- }
- }
- // =====================================================================================
- // NewFaceFromFace
- // Duplicates the non point information of a face, used by SplitFace
- // =====================================================================================
- bface_t* NewFaceFromFace(const bface_t* const in)
- {
- bface_t* newf;
- newf = (bface_t*)Alloc(sizeof(bface_t));
- newf->contents = in->contents;
- newf->texinfo = in->texinfo;
- newf->planenum = in->planenum;
- newf->plane = in->plane;
- return newf;
- }
- // =====================================================================================
- // FreeFace
- // =====================================================================================
- void FreeFace(bface_t* f)
- {
- delete f->w;
- Free(f);
- }
- // =====================================================================================
- // ClipFace
- // Clips a faces by a plane, returning the fragment on the backside and adding any
- // fragment to the outside.
- // Faces exactly on the plane will stay inside unless overdrawn by later brush.
- // Frontside is the side of the plane that holds the outside list.
- // Precedence is necesary to handle overlapping coplanar faces.
- #define SPLIT_EPSILON 0.3
- // =====================================================================================
- static bface_t* ClipFace(bface_t* f, bface_t** outside, const int splitplane, const bool precedence)
- {
- bface_t* front; // clip face
- Winding* fw; // forward wind
- Winding* bw; // back wind
- plane_t* split; // plane to clip on
- // handle exact plane matches special
- if (f->planenum == (splitplane ^ 1))
- return f; // opposite side, so put on inside list
- if (f->planenum == splitplane) // coplanar
- {
- // this fragment will go to the inside, because
- // the earlier one was clipped to the outside
- if (precedence)
- return f;
- f->next = *outside;
- *outside = f;
- return NULL;
- }
- split = &g_mapplanes[splitplane];
- f->w->Clip(split->normal, split->dist, &fw, &bw);
- if (!fw)
- {
- delete bw;
- return f;
- }
- else if (!bw)
- {
- delete fw;
- f->next = *outside;
- *outside = f;
- return NULL;
- }
- else
- {
- delete f->w;
-
- front = NewFaceFromFace(f);
- front->w = fw;
- fw->getBounds(front->bounds);
- front->next = *outside;
- *outside = front;
-
- f->w = bw;
- bw->getBounds(f->bounds);
-
- return f;
- }
- }
- // =====================================================================================
- // WriteFace
- // =====================================================================================
- void WriteFace(const int hull, const bface_t* const f)
- {
- unsigned int i;
- Winding* w;
- ThreadLock();
- if (!hull)
- c_csgfaces++;
- // .p0 format
- w = f->w;
- // plane summary
- fprintf(out[hull], "%i %i %i %u\n", f->planenum, f->texinfo, f->contents, w->m_NumPoints);
- // for each of the points on the face
- for (i = 0; i < w->m_NumPoints; i++)
- {
- // write the co-ords
- fprintf(out[hull], "%5.2f %5.2f %5.2f\n", w->m_Points[i][0], w->m_Points[i][1], w->m_Points[i][2]);
- }
- // put in an extra line break
- fprintf(out[hull], "\n");
- ThreadUnlock();
- }
- // =====================================================================================
- // SaveOutside
- // The faces remaining on the outside list are final polygons. Write them to the
- // output file.
- // Passable contents (water, lava, etc) will generate a mirrored copy of the face
- // to be seen from the inside.
- // =====================================================================================
- static void SaveOutside(const brush_t* const b, const int hull, bface_t* outside, const int mirrorcontents)
- {
- bface_t* f;
- bface_t* f2;
- bface_t* next;
- int i;
- vec3_t temp;
- for (f = outside; f; f = next)
- {
- next = f->next;
- if (f->w->getArea() < g_tiny_threshold)
- {
- c_tiny++;
- Verbose("Entity %i, Brush %i: tiny fragment\n", b->entitynum, b->brushnum);
- continue;
- }
- // count unique faces
- if (!hull)
- {
- for (f2 = b->hulls[hull].faces; f2; f2 = f2->next)
- {
- if (f2->planenum == f->planenum)
- {
- if (!f2->used)
- {
- f2->used = true;
- c_outfaces++;
- }
- break;
- }
- }
- }
- WriteFace(hull, f);
-
- // if (mirrorcontents != CONTENTS_SOLID)
- {
- f->planenum ^= 1;
- f->plane = &g_mapplanes[f->planenum];
- f->contents = mirrorcontents;
- // swap point orders
- for (i = 0; i < f->w->m_NumPoints / 2; i++) // add points backwards
- {
- VectorCopy(f->w->m_Points[i], temp);
- VectorCopy(f->w->m_Points[f->w->m_NumPoints - 1 - i], f->w->m_Points[i]);
- VectorCopy(temp, f->w->m_Points[f->w->m_NumPoints - 1 - i]);
- }
- WriteFace(hull, f);
- }
- FreeFace(f);
- }
- }
- // =====================================================================================
- // CopyFace
- // =====================================================================================
- bface_t* CopyFace(const bface_t* const f)
- {
- bface_t* n;
- n = NewFaceFromFace(f);
- n->w = f->w->Copy();
- n->bounds = f->bounds;
- return n;
- }
- // =====================================================================================
- // CopyFaceList
- // =====================================================================================
- bface_t* CopyFaceList(bface_t* f)
- {
- bface_t* head;
- bface_t* n;
- if (f)
- {
- head = CopyFace(f);
- n = head;
- f = f->next;
- while (f)
- {
- n->next = CopyFace(f);
- n = n->next;
- f = f->next;
- }
- return head;
- }
- else
- {
- return NULL;
- }
- }
- // =====================================================================================
- // FreeFaceList
- // =====================================================================================
- void FreeFaceList(bface_t* f)
- {
- if (f)
- {
- if (f->next)
- {
- FreeFaceList(f->next);
- }
- FreeFace(f);
- }
- }
- // =====================================================================================
- // CopyFacesToOutside
- // Make a copy of all the faces of the brush, so they can be chewed up by other
- // brushes.
- // All of the faces start on the outside list.
- // As other brushes take bites out of the faces, the fragments are moved to the
- // inside list, so they can be freed when they are determined to be completely
- // enclosed in solid.
- // =====================================================================================
- static bface_t* CopyFacesToOutside(brushhull_t* bh)
- {
- bface_t* f;
- bface_t* newf;
- bface_t* outside;
- outside = NULL;
- for (f = bh->faces; f; f = f->next)
- {
- newf = CopyFace(f);
- newf->w->getBounds(newf->bounds);
- newf->next = outside;
- outside = newf;
- }
- return outside;
- }
- // =====================================================================================
- // CSGBrush
- // =====================================================================================
- static void CSGBrush(int brushnum)
- {
- int hull;
- brush_t* b1;
- brush_t* b2;
- brushhull_t* bh1;
- brushhull_t* bh2;
- int bn;
- bool overwrite;
- bface_t* f;
- bface_t* f2;
- bface_t* next;
- bface_t* fcopy;
- bface_t* outside;
- bface_t* oldoutside;
- entity_t* e;
- vec_t area;
- // get entity and brush info from the given brushnum that we can work with
- b1 = &g_mapbrushes[brushnum];
- e = &g_entities[b1->entitynum];
- // for each of the hulls
- for (hull = 0; hull < NUM_HULLS; hull++)
- {
- bh1 = &b1->hulls[hull];
- // set outside to a copy of the brush's faces
- outside = CopyFacesToOutside(bh1);
- overwrite = false;
- // for each brush in entity e
- for (bn = 0; bn < e->numbrushes; bn++)
- {
- // see if b2 needs to clip a chunk out of b1
- if (bn == brushnum)
- {
- overwrite = true; // later brushes now overwrite
- continue;
- }
- b2 = &g_mapbrushes[e->firstbrush + bn];
- bh2 = &b2->hulls[hull];
- if (!bh2->faces)
- continue; // brush isn't in this hull
- // check brush bounding box first
- // TODO: use boundingbox method instead
- if (bh1->bounds.testDisjoint(bh2->bounds))
- {
- continue;
- }
- // divide faces by the planes of the b2 to find which
- // fragments are inside
- f = outside;
- outside = NULL;
- for (; f; f = next)
- {
- next = f->next;
- // check face bounding box first
- if (bh2->bounds.testDisjoint(f->bounds))
- { // this face doesn't intersect brush2's bbox
- f->next = outside;
- outside = f;
- continue;
- }
- oldoutside = outside;
- fcopy = CopyFace(f); // save to avoid fake splits
- // throw pieces on the front sides of the planes
- // into the outside list, return the remains on the inside
- for (f2 = bh2->faces; f2 && f; f2 = f2->next)
- {
- f = ClipFace(f, &outside, f2->planenum, overwrite);
- }
- area = f ? f->w->getArea() : 0;
- if (f && area < g_tiny_threshold)
- {
- Verbose("Entity %i, Brush %i: tiny penetration\n", b1->entitynum, b1->brushnum);
- c_tiny_clip++;
- FreeFace(f);
- f = NULL;
- }
- if (f)
- {
- // there is one convex fragment of the original
- // face left inside brush2
- FreeFace(fcopy);
- if (b1->contents > b2->contents)
- { // inside a water brush
- f->contents = b2->contents;
- f->next = outside;
- outside = f;
- }
- else // inside a solid brush
- {
- FreeFace(f); // throw it away
- }
- }
- else
- { // the entire thing was on the outside, even
- // though the bounding boxes intersected,
- // which will never happen with axial planes
- // free the fragments chopped to the outside
- while (outside != oldoutside)
- {
- f2 = outside->next;
- FreeFace(outside);
- outside = f2;
- }
- // revert to the original face to avoid
- // unneeded false cuts
- fcopy->next = outside;
- outside = fcopy;
- }
- }
- }
- // all of the faces left in outside are real surface faces
- SaveOutside(b1, hull, outside, b1->contents);
- }
- }
- //
- // =====================================================================================
- //
- // =====================================================================================
- // EmitPlanes
- // =====================================================================================
- static void EmitPlanes()
- {
- int i;
- dplane_t* dp;
- plane_t* mp;
- g_numplanes = g_nummapplanes;
- mp = g_mapplanes;
- dp = g_dplanes;
- for (i = 0; i < g_nummapplanes; i++, mp++, dp++)
- {
- //if (!(mp->redundant))
- //{
- // Log("EmitPlanes: plane %i non redundant\n", i);
- VectorCopy(mp->normal, dp->normal);
- dp->dist = mp->dist;
- dp->type = mp->type;
- // }
- //else
- // {
- // Log("EmitPlanes: plane %i redundant\n", i);
- // }
- }
- }
- // =====================================================================================
- // SetModelNumbers
- // blah
- // =====================================================================================
- static void SetModelNumbers()
- {
- int i;
- int models;
- char value[10];
- models = 1;
- for (i = 1; i < g_numentities; i++)
- {
- if (g_entities[i].numbrushes)
- {
- safe_snprintf(value, sizeof(value), "*%i", models);
- models++;
- SetKeyValue(&g_entities[i], "model", value);
- }
- }
- }
- // =====================================================================================
- // SetLightStyles
- // =====================================================================================
- #define MAX_SWITCHED_LIGHTS 32
- #define MAX_LIGHTTARGETS_NAME 64
- static void SetLightStyles()
- {
- int stylenum;
- const char* t;
- entity_t* e;
- int i, j;
- char value[10];
- char lighttargets[MAX_SWITCHED_LIGHTS][MAX_LIGHTTARGETS_NAME];
- #ifdef ZHLT_TEXLIGHT
- bool newtexlight = false;
- #endif
- // any light that is controlled (has a targetname)
- // must have a unique style number generated for it
- stylenum = 0;
- for (i = 1; i < g_numentities; i++)
- {
- e = &g_entities[i];
- t = ValueForKey(e, "classname");
- if (strncasecmp(t, "light", 5))
- {
- #ifdef ZHLT_TEXLIGHT
- //LRC:
- // if it's not a normal light entity, allocate it a new style if necessary.
- t = ValueForKey(e, "style");
- switch (atoi(t))
- {
- case 0: // not a light, no style, generally pretty boring
- continue;
- case -1: // normal switchable texlight
- safe_snprintf(value, sizeof(value), "%i", 32 + stylenum);
- SetKeyValue(e, "style", value);
- stylenum++;
- continue;
- case -2: // backwards switchable texlight
- safe_snprintf(value, sizeof(value), "%i", -(32 + stylenum));
- SetKeyValue(e, "style", value);
- stylenum++;
- continue;
- case -3: // (HACK) a piggyback texlight: switched on and off by triggering a real light that has the same name
- SetKeyValue(e, "style", "0"); // just in case the level designer didn't give it a name
- newtexlight = true;
- // don't 'continue', fall out
- }
- //LRC (ends)
- #else
- continue;
- #endif
- }
- t = ValueForKey(e, "targetname");
- if (!t[0])
- {
- continue;
- }
- // find this targetname
- for (j = 0; j < stylenum; j++)
- {
- if (!strcmp(lighttargets[j], t))
- {
- break;
- }
- }
- if (j == stylenum)
- {
- hlassume(stylenum < MAX_SWITCHED_LIGHTS, assume_MAX_SWITCHED_LIGHTS);
- safe_strncpy(lighttargets[j], t, MAX_LIGHTTARGETS_NAME);
- stylenum++;
- }
- safe_snprintf(value, sizeof(value), "%i", 32 + j);
- SetKeyValue(e, "style", value);
- }
- }
- // =====================================================================================
- // ConvertHintToEmtpy
- // =====================================================================================
- static void ConvertHintToEmpty()
- {
- int i;
- // Convert HINT brushes to EMPTY after they have been carved by csg
- for (i = 0; i < MAX_MAP_BRUSHES; i++)
- {
- if (g_mapbrushes[i].contents == CONTENTS_HINT)
- {
- g_mapbrushes[i].contents = CONTENTS_EMPTY;
- }
- }
- }
- // =====================================================================================
- // WriteBSP
- // =====================================================================================
- void WriteBSP(const char* const name)
- {
- char path[_MAX_PATH];
- safe_strncpy(path, name, _MAX_PATH);
- DefaultExtension(path, ".bsp");
- SetModelNumbers();
- SetLightStyles();
- if (!g_onlyents)
- WriteMiptex();
- UnparseEntities();
- ConvertHintToEmpty();
- WriteBSPFile(path);
- }
- //
- // =====================================================================================
- //
- // AJM: added in function
- // =====================================================================================
- // CopyGenerictoCLIP
- // clips a generic brush
- // =====================================================================================
- static void CopyGenerictoCLIP(const brush_t* const b)
- {
- // code blatently ripped from CopySKYtoCLIP()
- int i;
- entity_t* mapent;
- brush_t* newbrush;
- mapent = &g_entities[b->entitynum];
- mapent->numbrushes++;
- newbrush = &g_mapbrushes[g_nummapbrushes];
- newbrush->entitynum = b->entitynum;
- newbrush->brushnum = g_nummapbrushes - mapent->firstbrush;
- newbrush->firstside = g_numbrushsides;
- newbrush->numsides = b->numsides;
- newbrush->contents = CONTENTS_CLIP;
- newbrush->noclip = 0;
- for (i = 0; i < b->numsides; i++)
- {
- int j;
- side_t* side = &g_brushsides[g_numbrushsides];
- *side = g_brushsides[b->firstside + i];
- safe_strncpy(side->td.name, "CLIP", sizeof(side->td.name));
- for (j = 0; j < NUM_HULLS; j++)
- {
- newbrush->hulls[j].faces = NULL;
- newbrush->hulls[j].bounds = b->hulls[j].bounds;
- }
- g_numbrushsides++;
- hlassume(g_numbrushsides < MAX_MAP_SIDES, assume_MAX_MAP_SIDES);
- }
- g_nummapbrushes++;
- hlassume(g_nummapbrushes < MAX_MAP_BRUSHES, assume_MAX_MAP_BRUSHES);
- }
- #ifdef HLCSG_CLIPECONOMY
- // AJM: added in
- unsigned int BrushClipHullsDiscarded = 0;
- unsigned int ClipNodesDiscarded = 0;
- //AJM: added in function
- static void MarkEntForNoclip(entity_t* ent)
- {
- int i;
- brush_t* b;
- for (i = ent->firstbrush; i < ent->firstbrush + ent->numbrushes; i++)
- {
- b = &g_mapbrushes[i];
- b->noclip = 1;
- BrushClipHullsDiscarded++;
- ClipNodesDiscarded += b->numsides;
- }
- }
- // AJM
- // =====================================================================================
- // CheckForNoClip
- // marks the noclip flag on any brushes that dont need clipnode generation, eg. func_illusionaries
- // =====================================================================================
- static void CheckForNoClip()
- {
- int i;
- entity_t* ent;
- char entclassname[MAX_KEY];
- int spawnflags;
- if (!g_bClipNazi)
- return; // NO CLIP FOR YOU!!!
- for (i = 0; i < g_numentities; i++)
- {
- if (!g_entities[i].numbrushes)
- continue; // not a model
- if (!i)
- continue; // dont waste our time with worldspawn
- ent = &g_entities[i];
- strcpy_s(entclassname, ValueForKey(ent, "classname"));
- spawnflags = atoi(ValueForKey(ent, "spawnflags"));
- // condition 0, it's marked noclip (KGP)
- if(strlen(ValueForKey(ent,"zhlt_noclip")) && strcmp(ValueForKey(ent,"zhlt_noclip"),"0"))
- {
- MarkEntForNoclip(ent);
- }
- // condition 1, its a func_illusionary
- else if (!strncasecmp(entclassname, "func_illusionary", 16))
- {
- MarkEntForNoclip(ent);
- }
- // condition 2, flag 4 (8) is set and it is either a func_door, func_train, momentary_door,
- // func_door_rotating or func_tracktrain (passable, not-solid flag )
- else if ( (spawnflags & 8)
- &&
- ( /* NOTE: func_doors as far as i can tell may need clipnodes for their
- player collision detection, so for now, they stay out of it. */
- (!strncasecmp(entclassname, "func_train", 10))
- || (!strncasecmp(entclassname, "func_door", 9))
- // || (!strncasecmp(entclassname, "momentary_door", 14))
- // || (!strncasecmp(entclassname, "func_door_rotating", 18))
- || (!strncasecmp(entclassname, "func_tracktrain", 15))
- )
- )
- {
- MarkEntForNoclip(ent);
- }
- // condition 3: flag 2 (2) is set, and its a func_conveyor (not solid flag)
- else if ( (spawnflags & 2) && (!strncasecmp(entclassname, "func_conveyor", 13)) )
- {
- MarkEntForNoclip(ent);
- }
- // condition 4: flag 1 (1) is set, and its a func_rot_button (not solid flag)
- else if ( (spawnflags & 1) && (!strncasecmp(entclassname, "func_rot_button", 15)) )
- {
- MarkEntForNoclip(ent);
- }
- // condition 5: flag 7 (64) is set, and its a func_rotating
- else if ( (spawnflags & 64) && (!strncasecmp(entclassname, "func_rotating", 13)) )
- {
- MarkEntForNoclip(ent);
- }
- /*
- // condition 6: its a func_wall, while we noclip it, we remake the clipnodes manually
- else if (!strncasecmp(entclassname, "func_wall", 9))
- {
- for (int j = ent->firstbrush; j < ent->firstbrush + ent->numbrushes; j++)
- CopyGenerictoCLIP(&g_mapbrushes[i]);
- MarkEntForNoclip(ent);
- }
- */
- }
- Log("Brushes discarded from clipping hulls: %i (totalling %i sides)\n", BrushClipHullsDiscarded, ClipNodesDiscarded);
- }
- #endif
- // =====================================================================================
- // ProcessModels
- // =====================================================================================
- #ifndef HLCSG_SORTBRUSH_FIX
- #define NUM_TYPECONTENTS 5 // AJM: should reflect the number of values below
- int typecontents[NUM_TYPECONTENTS] = {
- CONTENTS_WATER, CONTENTS_SLIME, CONTENTS_LAVA, CONTENTS_SKY, CONTENTS_HINT
- };
- #endif
- static void ProcessModels()
- {
- int i, j;
- #ifndef HLCSG_SORTBRUSH_FIX
- int type;
- #endif
- int placed;
- int first, contents;
- brush_t temp;
-
- for (i = 0; i < g_numentities; i++)
- {
- if (!g_entities[i].numbrushes) // only models
- continue;
-
- #ifdef HLCSG_SORTBRUSH_FIX
- first = g_entities[i].firstbrush;
- placed = 0;
- while (placed < g_entities[i].numbrushes)
- {
- for (j = placed; j < g_entities[i].numbrushes; j++)
- {
- if (j == placed)
- {
- contents = g_mapbrushes[first + j].contents;
- }
- else
- {
- contents = min(g_mapbrushes[first + j].contents, contents);
- }
- }
- for (j = placed; j < g_entities[i].numbrushes; j++)
- {
- if (g_mapbrushes[first + j].contents == contents)
- {
- temp = g_mapbrushes[first + placed];
- g_mapbrushes[first + placed] = g_mapbrushes[first + j];
- g_mapbrushes[first + j] = temp;
- placed++;
- }
- }
- }
- #else
- first = g_entities[i].firstbrush;
- placed = 0;
- for (type = 0; type < NUM_TYPECONTENTS; type++) // for each of the contents types
- {
- contents = typecontents[type];
- for (j = placed + 1; j < g_entities[i].numbrushes; j++) // for each of the model's brushes
- {
- // if this brush is of the contents type in this for iteration
- if (g_mapbrushes[first + j].contents == contents)
- {
- temp = g_mapbrushes[first + placed];
- g_mapbrushes[first + placed] = g_mapbrushes[j];
- g_mapbrushes[j] = temp;
- placed++;
- }
- }
- }
- #endif
- // csg them in order
- if (i == 0) // if its worldspawn....
- {
- NamedRunThreadsOnIndividual(g_entities[i].numbrushes, g_estimate, CSGBrush);
- CheckFatal();
- }
- else
- {
- for (j = 0; j < g_entities[i].numbrushes; j++)
- {
- CSGBrush(first + j);
- }
- }
- // write end of model marker
- for (j = 0; j < NUM_HULLS; j++)
- {
- fprintf(out[j], "-1 -1 -1 -1\n");
- }
- }
- }
- // =====================================================================================
- // SetModelCenters
- // =====================================================================================
- static void SetModelCenters(int entitynum)
- {
- int i;
- int last;
- char string[MAXTOKEN];
- entity_t* e = &g_entities[entitynum];
- BoundingBox bounds;
- vec3_t center;
- if ((entitynum == 0) || (e->numbrushes == 0)) // skip worldspawn and point entities
- return;
- if (!*ValueForKey(e, "light_origin")) // skip if its not a zhlt_flags light_origin
- return;
- for (i = e->firstbrush, last = e->firstbrush + e->numbrushes; i < last; i++)
- {
- if (g_mapbrushes[i].contents != CONTENTS_ORIGIN)
- {
- bounds.add(g_mapbrushes[i].hulls->bounds);
- }
- }
- VectorAdd(bounds.m_Mins, bounds.m_Maxs, center);
- VectorScale(center, 0.5, center);
- safe_snprintf(string, MAXTOKEN, "%i %i %i", (int)center[0], (int)center[1], (int)center[2]);
- SetKeyValue(e, "model_center", string);
- }
- //
- // =====================================================================================
- //
- // =====================================================================================
- // BoundWorld
- // =====================================================================================
- static void BoundWorld()
- {
- int i;
- brushhull_t* h;
- world_bounds.reset();
- for (i = 0; i < g_nummapbrushes; i++)
- {
- h = &g_mapbrushes[i].hulls[0];
- if (!h->faces)
- {
- continue;
- }
- world_bounds.add(h->bounds);
- }
- Verbose("World bounds: (%i %i %i) to (%i %i %i)\n",
- (int)world_bounds.m_Mins[0], (int)world_bounds.m_Mins[1], (int)world_bounds.m_Mins[2],
- (int)world_bounds.m_Maxs[0], (int)world_bounds.m_Maxs[1], (int)world_bounds.m_Maxs[2]);
- }
- // =====================================================================================
- // Usage
- // prints out usage sheet
- // =====================================================================================
- static void Usage()
- {
- Banner(); // TODO: Call banner from main CSG process?
- Log("\n-= %s Options =-\n\n", g_Program);
- Log(" -nowadtextures : include all used textures into bsp\n");
- Log(" -wadinclude file : place textures used from wad specified into bsp\n");
- Log(" -noclip : don't create clipping hull\n");
-
- #ifdef HLCSG_CLIPECONOMY // AJM
- Log(" -noclipeconomy : turn clipnode economy mode off\n");
- #endif
- #ifdef HLCSG_PRECISIONCLIP // KGP
- Log(" -cliptype value : set to smallest, normalized, simple, precise, or legacy (default)\n");
- #endif
- #ifdef HLCSG_NULLIFY_INVISIBLE // KGP
- Log(" -nullfile file : specify list of entities to retexture with NULL\n");
- #endif
- Log(" -onlyents : do an entity update from .map to .bsp\n");
- Log(" -noskyclip : disable automatic clipping of SKY brushes\n");
- Log(" -tiny # : minmum brush face surface area before it is discarded\n");
- Log(" -brushunion # : threshold to warn about overlapping brushes\n\n");
- Log(" -hullfile file : Reads in custom collision hull dimensions\n");
- Log(" -texdata # : Alter maximum texture memory limit (in kb)\n");
- Log(" -lightdata # : Alter maximum lighting memory limit (in kb)\n");
- Log(" -chart : display bsp statitics\n");
- Log(" -low | -high : run program an altered priority level\n");
- Log(" -nolog : don't generate the compile logfiles\n");
- Log(" -threads # : manually specify the number of threads to run\n");
- Log(" -noconcolors : Disable Windows console text coloring\n");
- #ifdef SYSTEM_WIN32
- Log(" -estimate : display estimated time during compile\n");
- #endif
- #ifdef ZHLT_PROGRESSFILE // AJM
- Log(" -progressfile path : specify the path to a file for progress estimate output\n");
- #endif
- #ifdef SYSTEM_POSIX
- Log(" -noestimate : do not display continuous compile time estimates\n");
- #endif
- Log(" -verbose : compile with verbose messages\n");
- Log(" -noinfo : Do not show tool configuration information\n");
- #ifdef ZHLT_NULLTEX // AJM
- Log(" -nonulltex : Turns off null texture stripping\n");
- #endif
- #ifdef ZHLT_DETAIL // AJM
- Log(" -nodetail : dont handle detail brushes\n");
- #endif
- Log(" -dev # : compile with developer message\n\n");
- #ifdef HLCSG_WADCFG // AJM
- Log(" -wadconfig name : Specify a configuration to use from wad.cfg\n");
- Log(" -wadcfgfile path : Manually specify a path to the wad.cfg file\n"); //JK:
- #endif
- #ifdef HLCSG_AUTOWAD // AJM:
- Log(" -wadautodetect : Force auto-detection of wadfiles\n");
- #endif
- Log(" mapfile : The mapfile to compile\n\n");
- exit(1);
- }
- // =====================================================================================
- // DumpWadinclude
- // prints out the wadinclude list
- // =====================================================================================
- static void DumpWadinclude()
- {
- Log("Wadinclude list :\n");
- WadInclude_i it;
- for (it = g_WadInclude.begin(); it != g_WadInclude.end(); it++)
- {
- Log("[%s]\n", it->c_str());
- }
- }
- // =====================================================================================
- // Settings
- // prints out settings sheet
- // =====================================================================================
- static void Settings()
- {
- char* tmp;
- if (!g_info)
- return;
- Log("\nCurrent %s Settings\n", g_Program);
- Log("Name | Setting | Default\n"
- "---------------------|-------------|-------------------------\n");
- // ZHLT Common Settings
- if (DEFAULT_NUMTHREADS == -1)
- {
- Log("threads [ %9d ] [ Varies ]\n", g_numthreads);
- }
- else
- {
- Log("threads [ %9d ] [ %9d ]\n", g_numthreads, DEFAULT_NUMTHREADS);
- }
- Log("verbose [ %9s ] [ %9s ]\n", g_verbose ? "on" : "off", DEFAULT_VERBOSE ? "on" : "off");
- Log("log [ %9s ] [ %9s ]\n", g_log ? "on" : "off", DEFAULT_LOG ? "on" : "off");
- Log("developer [ %9d ] [ %9d ]\n", g_developer, DEFAULT_DEVELOPER);
- Log("chart [ %9s ] [ %9s ]\n", g_chart ? "on" : "off", DEFAULT_CHART ? "on" : "off");
- Log("estimate [ %9s ] [ %9s ]\n", g_estimate ? "on" : "off", DEFAULT_ESTIMATE ? "on" : "off");
- Log("max texture memory [ %9d ] [ %9d ]\n", g_max_map_miptex, DEFAULT_MAX_MAP_MIPTEX);
- Log("max lighting memory [ %9d ] [ %9d ]\n", g_max_map_lightdata, DEFAULT_MAX_MAP_LIGHTDATA);
- switch (g_threadpriority)
- {
- case eThreadPriorityNormal:
- default:
- tmp = "Normal";
- break;
- case eThreadPriorityLow:
- tmp = "Low";
- break;
- case eThreadPriorityHigh:
- tmp = "High";
- break;
- }
- Log("priority [ %9s ] [ %9s ]\n", tmp, "Normal");
- Log("\n");
- // HLCSG Specific Settings
- Log("noclip [ %9s ] [ %9s ]\n", g_noclip ? "on" : "off", DEFAULT_NOCLIP ? "on" : "off");
- #ifdef ZHLT_NULLTEX // AJM:
- Log("null texture stripping[ %9s ] [ %9s ]\n", g_bUseNullTex ? "on" : "off", DEFAULT_NULLTEX ? "on" : "off");
- #endif
- #ifdef ZHLT_DETAIL // AJM
- Log("detail brushes [ %9s ] [ %9s ]\n", g_bDetailBrushes ? "on" : "off", DEFAULT_DETAIL ? "on" : "off");
- #endif
- #ifdef HLCSG_CLIPECONOMY // AJM
- Log("clipnode economy mode [ %9s ] [ %9s ]\n", g_bClipNazi ? "on" : "off", DEFAULT_CLIPNAZI ? "on" : "off");
- #endif
- #ifdef HLCSG_PRECISIONCLIP // KGP
- Log("clip hull type [ %9s ] [ %9s ]\n", GetClipTypeString(g_cliptype), GetClipTypeString(DEFAULT_CLIPTYPE));
- #endif
- Log("onlyents [ %9s ] [ %9s ]\n", g_onlyents ? "on" : "off", DEFAULT_ONLYENTS ? "on" : "off");
- Log("wadtextures [ %9s ] [ %9s ]\n", g_wadtextures ? "on" : "off", DEFAULT_WADTEXTURES ? "on" : "off");
- Log("skyclip [ %9s ] [ %9s ]\n", g_skyclip ? "on" : "off", DEFAULT_SKYCLIP ? "on" : "off");
- Log("hullfile [ %9s ] [ %9s ]\n", g_hullfile ? g_hullfile : "None", "None");
- #ifdef HLCSG_NULLIFY_INVISIBLE // KGP
- Log("nullfile [ %9s ] [ %9s ]\n", g_nullfile ? g_nullfile : "None", "None");
- #endif
- // calc min surface area
- {
- char tiny_penetration[10];
- char default_tiny_penetration[10];
- safe_snprintf(tiny_penetration, sizeof(tiny_penetration), "%3.3f", g_tiny_threshold);
- safe_snprintf(default_tiny_penetration, sizeof(default_tiny_penetration), "%3.3f", DEFAULT_TINY_THRESHOLD);
- Log("min surface area [ %9s ] [ %9s ]\n", tiny_penetration, default_tiny_penetration);
- }
- // calc union threshold
- {
- char brush_union[10];
- char default_brush_union[10];
- safe_snprintf(brush_union, sizeof(brush_union), "%3.3f", g_BrushUnionThreshold);
- safe_snprintf(default_brush_union, sizeof(default_brush_union), "%3.3f", DEFAULT_BRUSH_UNION_THRESHOLD);
- Log("brush union threshold [ %9s ] [ %9s ]\n", brush_union, default_brush_union);
- }
- Log("\n");
- }
- // AJM: added in
- // =====================================================================================
- // CSGCleanup
- // =====================================================================================
- void CSGCleanup()
- {
- //Log("CSGCleanup\n");
- #ifdef HLCSG_AUTOWAD
- autowad_cleanup();
- #endif
- #ifdef HLCSG_WADCFG
- WadCfg_cleanup();
- #endif
- #ifdef HLCSG_NULLIFY_TEXTURES
- properties_cleanup();
- #endif
- FreeWadPaths();
- }
- // =====================================================================================
- // Main
- // Oh, come on.
- // =====================================================================================
- int main(const int argc, char** argv)
- {
- int i;
- char name[_MAX_PATH]; // mapanme
- double start, end; // start/end time log
- const char* mapname_from_arg = NULL; // mapname path from passed argvar
- g_Program = "hlcsg";
- if (argc == 1)
- Usage();
- // Hard coded list of -wadinclude files, used for HINT texture brushes so lazy
- // mapmakers wont cause beta testers (or possibly end users) to get a wad
- // error on zhlt.wad etc
- g_WadInclude.push_back("zhlt.wad");
- memset(wadconfigname, 0, sizeof(wadconfigname));//AJM
- // detect argv
- for (i = 1; i < argc; i++)
- {
- if (!strcasecmp(argv[i], "-threads"))
- {
- if (i < argc)
- {
- g_numthreads = atoi(argv[++i]);
- if (g_numthreads < 1)
- {
- Log("Expected value of at least 1 for '-threads'\n");
- Usage();
- }
- }
- else
- {
- Usage();
- }
- }
- #ifdef SYSTEM_WIN32
- else if (!strcasecmp(argv[i], "-estimate"))
- {
- g_estimate = true;
- }
- #endif
- #ifdef SYSTEM_POSIX
- else if (!strcasecmp(argv[i], "-noestimate"))
- {
- g_estimate = false;
- }
- #endif
- else if (!strcasecmp(argv[i], "-dev"))
- {
- if (i < argc)
- {
- g_developer = (developer_level_t)atoi(argv[++i]);
- }
- else
- {
- Usage();
- }
- }
- else if (!strcasecmp(argv[i], "-verbose"))
- {
- g_verbose = true;
- }
- else if (!strcasecmp(argv[i], "-noinfo"))
- {
- g_info = false;
- }
- else if (!strcasecmp(argv[i], "-chart"))
- {
- g_chart = true;
- }
- else if (!strcasecmp(argv[i], "-low"))
- {
- g_threadpriority = eThreadPriorityLow;
- }
- else if (!strcasecmp(argv[i], "-high"))
- {
- g_threadpriority = eThreadPriorityHigh;
- }
- else if (!strcasecmp(argv[i], "-nolog"))
- {
- g_log = false;
- }
- else if (!strcasecmp(argv[i], "-skyclip"))
- {
- g_skyclip = true;
- }
- else if (!strcasecmp(argv[i], "-noskyclip"))
- {
- g_skyclip = false;
- }
- else if (!strcasecmp(argv[i], "-noclip"))
- {
- g_noclip = true;
- }
- else if (!strcasecmp(argv[i], "-onlyents"))
- {
- g_onlyents = true;
- }
- #ifdef ZHLT_NULLTEX // AJM: added in -nonulltex
- else if (!strcasecmp(argv[i], "-nonulltex"))
- {
- g_bUseNullTex = false;
- }
- #endif
- #ifdef HLCSG_CLIPECONOMY // AJM: added in -noclipeconomy
- else if (!strcasecmp(argv[i], "-noclipeconomy"))
- {
- g_bClipNazi = false;
- }
- #endif
- #ifdef HLCSG_PRECISIONCLIP // KGP: added in -cliptype
- else if (!strcasecmp(argv[i], "-cliptype"))
- {
- if (i < argc)
- {
- ++i;
- if(!strcasecmp(argv[i],"smallest"))
- { g_cliptype = clip_smallest; }
- else if(!strcasecmp(argv[i],"normalized"))
- { g_cliptype = clip_normalized; }
- else if(!strcasecmp(argv[i],"simple"))
- { g_cliptype = clip_simple; }
- else if(!strcasecmp(argv[i],"precise"))
- { g_cliptype = clip_precise; }
- else if(!strcasecmp(argv[i],"legacy"))
- { g_cliptype = clip_legacy; }
- }
- else
- {
- Log("Error: -cliptype: incorrect usage of parameter\n");
- Usage();
- }
- }
- #endif
- #ifdef HLCSG_WADCFG
- // AJM: added in -wadconfig
- else if (!strcasecmp(argv[i], "-wadconfig"))
- {
- if (i < argc)
- {
- safe_strncpy(wadconfigname, argv[++i], MAX_WAD_CFG_NAME);
- if (strlen(argv[i]) > MAX_WAD_CFG_NAME)
- {
- Warning("wad configuration name was truncated to %i chars", MAX_WAD_CFG_NAME);
- wadconfigname[MAX_WAD_CFG_NAME] = 0;
- }
- }
- else
- {
- Log("Error: -wadconfig: incorrect usage of parameter\n");
- Usage();
- }
- }
- //JK: added in -wadcfgfile
- else if (!strcasecmp(argv[i], "-wadcfgfile"))
- {
- if (i < argc)
- {
- g_wadcfgfile = argv[++i];
- }
- else
- {
- Log("Error: -wadcfgfile: incorrect usage of parameter\n");
- Usage();
- }
- }
- #endif
- #ifdef HLCSG_NULLIFY_INVISIBLE
- else if (!strcasecmp(argv[i], "-nullfile"))
- {
- if (i < argc)
- {
- g_nullfile = argv[++i];
- }
- else
- {
- Log("Error: -nullfile: expected path to null ent file following parameter\n");
- Usage();
- }
- }
- #endif
- #ifdef HLCSG_AUTOWAD // AJM
- else if (!strcasecmp(argv[i], "-wadautodetect"))
- {
- g_bWadAutoDetect = true;
- }
- #endif
- #ifdef ZHLT_DETAIL // AJM
- else if (!strcasecmp(argv[i], "-nodetail"))
- {
- g_bDetailBrushes = false;
- }
- #endif
- #ifdef ZHLT_PROGRESSFILE // AJM
- else if (!strcasecmp(argv[i], "-progressfile"))
- {
- if (i < argc)
- {
- g_progressfile = argv[++i];
- }
- else
- {
- Log("Error: -progressfile: expected path to progress file following parameter\n");
- Usage();
- }
- }
- #endif
- else if (!strcasecmp(argv[i], "-nowadtextures"))
- {
- g_wadtextures = false;
- }
- else if (!strcasecmp(argv[i], "-wadinclude"))
- {
- if (i < argc)
- {
- g_WadInclude.push_back(argv[++i]);
- }
- else
- {
- Usage();
- }
- }
- else if (!strcasecmp(argv[i], "-texdata"))
- {
- if (i < argc)
- {
- int x = atoi(argv[++i]) * 1024;
- if (x > g_max_map_miptex)
- {
- g_max_map_miptex = x;
- }
- }
- else
- {
- Usage();
- }
- }
- else if (!strcasecmp(argv[i], "-lightdata"))
- {
- if (i < argc)
- {
- int x = atoi(argv[++i]) * 1024;
- if (x > g_max_map_lightdata)
- {
- g_max_map_lightdata = x;
- }
- }
- else
- {
- Usage();
- }
- }
- else if (!strcasecmp(argv[i], "-brushunion"))
- {
- if (i < argc)
- {
- g_BrushUnionThreshold = (float)atof(argv[++i]);
- }
- else
- {
- Usage();
- }
- }
- else if (!strcasecmp(argv[i], "-tiny"))
- {
- if (i < argc)
- {
- g_tiny_threshold = (float)atof(argv[++i]);
- }
- else
- {
- Usage();
- }
- }
- else if (!strcasecmp(argv[i], "-hullfile"))
- {
- if (i < argc)
- {
- g_hullfile = argv[++i];
- }
- else
- {
- Usage();
- }
- }
- // SILENCER -->
- else if (!strcasecmp(argv[i], "-noconcolors"))
- {
- g_noConColors = true;
- }
- // <-- SILENCER
- else if (argv[i][0] == '-')
- {
- Log("Unknown option \"%s\"\n", argv[i]);
- Usage();
- }
- else if (!mapname_from_arg)
- {
- mapname_from_arg = argv[i];
- }
- else
- {
- Log("Unknown option \"%s\"\n", argv[i]);
- Usage();
- }
- }
- // no mapfile?
- if (!mapname_from_arg)
- {
- // what a shame.
- Log("No mapfile specified\n");
- Usage();
- }
- // handle mapname
- safe_strncpy(g_Mapname, mapname_from_arg, _MAX_PATH);
- FlipSlashes(g_Mapname);
- StripExtension(g_Mapname);
- // onlyents
- if (!g_onlyents)
- ResetTmpFiles();
- // other stuff
- ResetErrorLog();
- ResetLog();
- OpenLog(g_clientid);
- atexit(CloseLog);
- LogStart(argc, argv);
- atexit(CSGCleanup); // AJM
- dtexdata_init();
- atexit(dtexdata_free);
- // START CSG
- // AJM: re-arranged some stuff up here so that the mapfile is loaded
- // before settings are finalised and printed out, so that the info_compile_parameters
- // entity can be dealt with effectively
- start = I_FloatTime();
-
- LoadHullfile(g_hullfile); // if the user specified a hull file, load it now
- #ifdef HLCSG_NULLIFY_INVISIBLE
- if(g_bUseNullTex)
- { properties_initialize(g_nullfile); }
- #endif
- safe_strncpy(name, mapname_from_arg, _MAX_PATH); // make a copy of the nap name
- DefaultExtension(name, ".map"); // might be .reg
-
- LoadMapFile(name);
- ThreadSetDefault();
- ThreadSetPriority(g_threadpriority);
- Settings();
- #ifdef HLCSG_WADCFG // AJM
- // figure out what to do with the texture settings
- if (wadconfigname[0]) // custom wad configuations will take precedence
- {
- LoadWadConfigFile();
- ProcessWadConfiguration();
- }
- else
- {
- Log("Using mapfile wad configuration\n");
- }
- if (!g_bWadConfigsLoaded) // dont try and override wad.cfg
- #endif
- {
- GetUsedWads();
- }
- #ifdef HLCSG_AUTOWAD
- if (g_bWadAutoDetect)
- {
- Log("Wadfiles not in use by the map will be excluded\n");
- }
- #endif
- DumpWadinclude();
- Log("\n");
- // if onlyents, just grab the entites and resave
- if (g_onlyents)
- {
- char out[_MAX_PATH];
- safe_snprintf(out, _MAX_PATH, "%s.bsp", g_Mapname);
- LoadBSPFile(out);
- LoadWadincludeFile(g_Mapname);
- HandleWadinclude();
- // Write it all back out again.
- if (g_chart)
- {
- PrintBSPFileSizes();
- }
- WriteBSP(g_Mapname);
- end = I_FloatTime();
- LogTimeElapsed(end - start);
- return 0;
- }
- else
- {
- SaveWadincludeFile(g_Mapname);
- }
- #ifdef HLCSG_CLIPECONOMY // AJM
- CheckForNoClip();
- #endif
- // createbrush
- NamedRunThreadsOnIndividual(g_nummapbrushes, g_estimate, CreateBrush);
- CheckFatal();
- #ifdef HLCSG_PRECISIONCLIP // KGP - drop TEX_BEVEL flag
- FixBevelTextures();
- #endif
- // boundworld
- BoundWorld();
- Verbose("%5i map planes\n", g_nummapplanes);
- // Set model centers
- NamedRunThreadsOnIndividual(g_numentities, g_estimate, SetModelCenters);
- // Calc brush unions
- if ((g_BrushUnionThreshold > 0.0) && (g_BrushUnionThreshold <= 100.0))
- {
- NamedRunThreadsOnIndividual(g_nummapbrushes, g_estimate, CalculateBrushUnions);
- }
- // open hull files
- for (i = 0; i < NUM_HULLS; i++)
- {
- char name[_MAX_PATH];
- safe_snprintf(name, _MAX_PATH, "%s.p%i", g_Mapname, i);
- out[i] = fopen(name, "w");
- if (!out[i])
- Error("Couldn't open %s", name);
- }
- ProcessModels();
- Verbose("%5i csg faces\n", c_csgfaces);
- Verbose("%5i used faces\n", c_outfaces);
- Verbose("%5i tiny faces\n", c_tiny);
- Verbose("%5i tiny clips\n", c_tiny_clip);
- // close hull files
- for (i = 0; i < NUM_HULLS; i++)
- fclose(out[i]);
- EmitPlanes();
- if (g_chart)
- PrintBSPFileSizes();
- WriteBSP(g_Mapname);
- // AJM: debug
- #if 0
- Log("\n---------------------------------------\n"
- "Map Plane Usage:\n"
- " # normal origin dist type\n"
- " ( x, y, z) ( x, y, z) ( )\n"
- );
- for (i = 0; i < g_nummapplanes; i++)
- {
- plane_t* p = &g_mapplanes[i];
- Log(
- "%3i (%4.0f, %4.0f, %4.0f) (%4.0f, %4.0f, %4.0f) (%5.0f) %i\n",
- i,
- p->normal[1], p->normal[2], p->normal[3],
- p->origin[1], p->origin[2], p->origin[3],
- p->dist,
- p->type
- );
- }
- Log("---------------------------------------\n\n");
- #endif
- // elapsed time
- end = I_FloatTime();
- LogTimeElapsed(end - start);
- return 0;
- }
|