From 5399e988c715ec70edf8eeb7938743322c04c726 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 2 Nov 2018 22:21:32 +0100 Subject: [PATCH] - changed the output to be one lump using a compressed rgb16f format with 3d floors support --- CMakeLists.txt | 2 + src/level/doomdata.h | 40 +- src/level/level.cpp | 7 +- src/level/level_udmf.cpp | 6 +- src/lightmap/halffloat.cpp | 3381 +++++++++++++++++++++++++++++++++ src/lightmap/halffloat.h | 68 + src/lightmap/lightmap.cpp | 597 ++---- src/lightmap/lightmap.h | 21 +- src/lightmap/lightsurface.cpp | 61 +- src/lightmap/lightsurface.h | 6 - src/lightmap/mapdata.cpp | 317 +--- src/lightmap/surfaces.cpp | 124 +- src/lightmap/surfaces.h | 10 +- src/lightmap/trace.cpp | 244 --- src/lightmap/trace.h | 15 +- src/main.cpp | 227 --- 16 files changed, 3658 insertions(+), 1468 deletions(-) create mode 100644 src/lightmap/halffloat.cpp create mode 100644 src/lightmap/halffloat.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 45c9cc6..e9a7f00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,6 +152,7 @@ set( SOURCES src/lightmap/wad.cpp src/lightmap/worker.cpp src/lightmap/collision.cpp + src/lightmap/halffloat.cpp src/lightmap/kexlib/binfile.cpp src/lightmap/kexlib/kstring.cpp src/lightmap/kexlib/memheap.cpp @@ -194,6 +195,7 @@ set( HEADERS src/lightmap/wad.h src/lightmap/worker.h src/lightmap/collision.h + src/lightmap/halffloat.h src/lightmap/kexlib/array.h src/lightmap/kexlib/binfile.h src/lightmap/kexlib/kstring.h diff --git a/src/level/doomdata.h b/src/level/doomdata.h index 750fbf1..5a4c00f 100644 --- a/src/level/doomdata.h +++ b/src/level/doomdata.h @@ -40,6 +40,8 @@ struct MapSideDef WORD sector; }; +struct IntLineDef; + struct IntSideDef { // the first 5 values are only used for binary format maps @@ -51,6 +53,8 @@ struct IntSideDef int sector; + IntLineDef *line; + TArray props; }; @@ -248,12 +252,6 @@ struct FloatVertex float y; }; -struct leaf_t -{ - FloatVertex vertex; - MapSegGLEx *seg; -}; - struct lightDef_t { int doomednum; @@ -291,9 +289,6 @@ struct thingLight_t struct surfaceLightDef { int tag; - float outerCone; - float innerCone; - float falloff; float distance; float intensity; bool bIgnoreFloor; @@ -362,23 +357,7 @@ struct FLevel TArray MeshSurfaces; std::unique_ptr CollisionMesh; - leaf_t *leafs = nullptr; - uint8_t *mapPVS = nullptr; - bool *bSkySectors = nullptr; - bool *bSSectsVisibleToSky = nullptr; - - int numLeafs = 0; - - int *segLeafLookup = nullptr; - int *ssLeafLookup = nullptr; - int *ssLeafCount = nullptr; - kexBBox *ssLeafBounds = nullptr; - - kexBBox *nodeBounds = nullptr; - - surface_t **segSurfaces[3] = { nullptr, nullptr, nullptr }; - surface_t **leafSurfaces[2] = { nullptr, nullptr }; TArray thingLights; TArray lightSurfaces; @@ -389,20 +368,13 @@ struct FLevel const kexVec3 &GetSunColor() const; const kexVec3 &GetSunDirection() const; - IntSideDef *GetSideDef(const MapSegGLEx *seg); - IntSector *GetFrontSector(const MapSegGLEx *seg); - IntSector *GetBackSector(const MapSegGLEx *seg); + IntSector *GetFrontSector(const IntSideDef *side); + IntSector *GetBackSector(const IntSideDef *side); IntSector *GetSectorFromSubSector(const MapSubsectorEx *sub); MapSubsectorEx *PointInSubSector(const int x, const int y); - bool PointInsideSubSector(const float x, const float y, const MapSubsectorEx *sub); - bool LineIntersectSubSector(const kexVec3 &start, const kexVec3 &end, const MapSubsectorEx *sub, kexVec2 &out); FloatVertex GetSegVertex(int index); - bool CheckPVS(MapSubsectorEx *s1, MapSubsectorEx *s2); private: - void BuildNodeBounds(); - void BuildLeafs(); - void BuildPVS(); void CheckSkySectors(); }; diff --git a/src/level/level.cpp b/src/level/level.cpp index 81229ae..67d3191 100644 --- a/src/level/level.cpp +++ b/src/level/level.cpp @@ -822,11 +822,10 @@ void FProcessor::Write (FWadWriter &out) out.CopyLump (Wad, Wad.FindMapLump ("BEHAVIOR", Lump)); out.CopyLump (Wad, Wad.FindMapLump ("SCRIPTS", Lump)); } - if (LightmapsBuilt) + /*if (LightmapsBuilt) { - LMBuilder.AddLightGridLump(out); - LMBuilder.AddLightmapLumps(out); - } + LMBuilder.AddLightmapLump(out); + }*/ if (Level.GLNodes != NULL && !compressGL) { char glname[9]; diff --git a/src/level/level_udmf.cpp b/src/level/level_udmf.cpp index 8de21af..dffd0f9 100644 --- a/src/level/level_udmf.cpp +++ b/src/level/level_udmf.cpp @@ -789,7 +789,8 @@ void FProcessor::WriteUDMF(FWadWriter &out) const char *lumpname = Wad.LumpName(i); if (stricmp(lumpname, "ZNODES") && stricmp(lumpname, "BLOCKMAP") && - stricmp(lumpname, "REJECT")) + stricmp(lumpname, "REJECT") && + stricmp(lumpname, "LIGHTMAP")) { out.CopyLump(Wad, i); } @@ -797,8 +798,7 @@ void FProcessor::WriteUDMF(FWadWriter &out) if (LightmapsBuilt) { - LMBuilder.AddLightGridLump(out); - LMBuilder.AddLightmapLumps(out); + LMBuilder.AddLightmapLump(out); } out.CreateLabel("ENDMAP"); diff --git a/src/lightmap/halffloat.cpp b/src/lightmap/halffloat.cpp new file mode 100644 index 0000000..437a35b --- /dev/null +++ b/src/lightmap/halffloat.cpp @@ -0,0 +1,3381 @@ +/* +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +** +** Note: Some of the libraries UICore may link to may have additional +** requirements or restrictions. +** +** Based on the paper "Fast Half Float Conversions" by Jeroen van der Zijp. +*/ + +#include "halffloat.h" + +namespace HalfFloatTables +{ + unsigned int mantissa_table[2048] = + { + 0, + 864026624, + 872415232, + 876609536, + 880803840, + 882900992, + 884998144, + 887095296, + 889192448, + 890241024, + 891289600, + 892338176, + 893386752, + 894435328, + 895483904, + 896532480, + 897581056, + 898105344, + 898629632, + 899153920, + 899678208, + 900202496, + 900726784, + 901251072, + 901775360, + 902299648, + 902823936, + 903348224, + 903872512, + 904396800, + 904921088, + 905445376, + 905969664, + 906231808, + 906493952, + 906756096, + 907018240, + 907280384, + 907542528, + 907804672, + 908066816, + 908328960, + 908591104, + 908853248, + 909115392, + 909377536, + 909639680, + 909901824, + 910163968, + 910426112, + 910688256, + 910950400, + 911212544, + 911474688, + 911736832, + 911998976, + 912261120, + 912523264, + 912785408, + 913047552, + 913309696, + 913571840, + 913833984, + 914096128, + 914358272, + 914489344, + 914620416, + 914751488, + 914882560, + 915013632, + 915144704, + 915275776, + 915406848, + 915537920, + 915668992, + 915800064, + 915931136, + 916062208, + 916193280, + 916324352, + 916455424, + 916586496, + 916717568, + 916848640, + 916979712, + 917110784, + 917241856, + 917372928, + 917504000, + 917635072, + 917766144, + 917897216, + 918028288, + 918159360, + 918290432, + 918421504, + 918552576, + 918683648, + 918814720, + 918945792, + 919076864, + 919207936, + 919339008, + 919470080, + 919601152, + 919732224, + 919863296, + 919994368, + 920125440, + 920256512, + 920387584, + 920518656, + 920649728, + 920780800, + 920911872, + 921042944, + 921174016, + 921305088, + 921436160, + 921567232, + 921698304, + 921829376, + 921960448, + 922091520, + 922222592, + 922353664, + 922484736, + 922615808, + 922746880, + 922812416, + 922877952, + 922943488, + 923009024, + 923074560, + 923140096, + 923205632, + 923271168, + 923336704, + 923402240, + 923467776, + 923533312, + 923598848, + 923664384, + 923729920, + 923795456, + 923860992, + 923926528, + 923992064, + 924057600, + 924123136, + 924188672, + 924254208, + 924319744, + 924385280, + 924450816, + 924516352, + 924581888, + 924647424, + 924712960, + 924778496, + 924844032, + 924909568, + 924975104, + 925040640, + 925106176, + 925171712, + 925237248, + 925302784, + 925368320, + 925433856, + 925499392, + 925564928, + 925630464, + 925696000, + 925761536, + 925827072, + 925892608, + 925958144, + 926023680, + 926089216, + 926154752, + 926220288, + 926285824, + 926351360, + 926416896, + 926482432, + 926547968, + 926613504, + 926679040, + 926744576, + 926810112, + 926875648, + 926941184, + 927006720, + 927072256, + 927137792, + 927203328, + 927268864, + 927334400, + 927399936, + 927465472, + 927531008, + 927596544, + 927662080, + 927727616, + 927793152, + 927858688, + 927924224, + 927989760, + 928055296, + 928120832, + 928186368, + 928251904, + 928317440, + 928382976, + 928448512, + 928514048, + 928579584, + 928645120, + 928710656, + 928776192, + 928841728, + 928907264, + 928972800, + 929038336, + 929103872, + 929169408, + 929234944, + 929300480, + 929366016, + 929431552, + 929497088, + 929562624, + 929628160, + 929693696, + 929759232, + 929824768, + 929890304, + 929955840, + 930021376, + 930086912, + 930152448, + 930217984, + 930283520, + 930349056, + 930414592, + 930480128, + 930545664, + 930611200, + 930676736, + 930742272, + 930807808, + 930873344, + 930938880, + 931004416, + 931069952, + 931135488, + 931168256, + 931201024, + 931233792, + 931266560, + 931299328, + 931332096, + 931364864, + 931397632, + 931430400, + 931463168, + 931495936, + 931528704, + 931561472, + 931594240, + 931627008, + 931659776, + 931692544, + 931725312, + 931758080, + 931790848, + 931823616, + 931856384, + 931889152, + 931921920, + 931954688, + 931987456, + 932020224, + 932052992, + 932085760, + 932118528, + 932151296, + 932184064, + 932216832, + 932249600, + 932282368, + 932315136, + 932347904, + 932380672, + 932413440, + 932446208, + 932478976, + 932511744, + 932544512, + 932577280, + 932610048, + 932642816, + 932675584, + 932708352, + 932741120, + 932773888, + 932806656, + 932839424, + 932872192, + 932904960, + 932937728, + 932970496, + 933003264, + 933036032, + 933068800, + 933101568, + 933134336, + 933167104, + 933199872, + 933232640, + 933265408, + 933298176, + 933330944, + 933363712, + 933396480, + 933429248, + 933462016, + 933494784, + 933527552, + 933560320, + 933593088, + 933625856, + 933658624, + 933691392, + 933724160, + 933756928, + 933789696, + 933822464, + 933855232, + 933888000, + 933920768, + 933953536, + 933986304, + 934019072, + 934051840, + 934084608, + 934117376, + 934150144, + 934182912, + 934215680, + 934248448, + 934281216, + 934313984, + 934346752, + 934379520, + 934412288, + 934445056, + 934477824, + 934510592, + 934543360, + 934576128, + 934608896, + 934641664, + 934674432, + 934707200, + 934739968, + 934772736, + 934805504, + 934838272, + 934871040, + 934903808, + 934936576, + 934969344, + 935002112, + 935034880, + 935067648, + 935100416, + 935133184, + 935165952, + 935198720, + 935231488, + 935264256, + 935297024, + 935329792, + 935362560, + 935395328, + 935428096, + 935460864, + 935493632, + 935526400, + 935559168, + 935591936, + 935624704, + 935657472, + 935690240, + 935723008, + 935755776, + 935788544, + 935821312, + 935854080, + 935886848, + 935919616, + 935952384, + 935985152, + 936017920, + 936050688, + 936083456, + 936116224, + 936148992, + 936181760, + 936214528, + 936247296, + 936280064, + 936312832, + 936345600, + 936378368, + 936411136, + 936443904, + 936476672, + 936509440, + 936542208, + 936574976, + 936607744, + 936640512, + 936673280, + 936706048, + 936738816, + 936771584, + 936804352, + 936837120, + 936869888, + 936902656, + 936935424, + 936968192, + 937000960, + 937033728, + 937066496, + 937099264, + 937132032, + 937164800, + 937197568, + 937230336, + 937263104, + 937295872, + 937328640, + 937361408, + 937394176, + 937426944, + 937459712, + 937492480, + 937525248, + 937558016, + 937590784, + 937623552, + 937656320, + 937689088, + 937721856, + 937754624, + 937787392, + 937820160, + 937852928, + 937885696, + 937918464, + 937951232, + 937984000, + 938016768, + 938049536, + 938082304, + 938115072, + 938147840, + 938180608, + 938213376, + 938246144, + 938278912, + 938311680, + 938344448, + 938377216, + 938409984, + 938442752, + 938475520, + 938508288, + 938541056, + 938573824, + 938606592, + 938639360, + 938672128, + 938704896, + 938737664, + 938770432, + 938803200, + 938835968, + 938868736, + 938901504, + 938934272, + 938967040, + 938999808, + 939032576, + 939065344, + 939098112, + 939130880, + 939163648, + 939196416, + 939229184, + 939261952, + 939294720, + 939327488, + 939360256, + 939393024, + 939425792, + 939458560, + 939491328, + 939524096, + 939540480, + 939556864, + 939573248, + 939589632, + 939606016, + 939622400, + 939638784, + 939655168, + 939671552, + 939687936, + 939704320, + 939720704, + 939737088, + 939753472, + 939769856, + 939786240, + 939802624, + 939819008, + 939835392, + 939851776, + 939868160, + 939884544, + 939900928, + 939917312, + 939933696, + 939950080, + 939966464, + 939982848, + 939999232, + 940015616, + 940032000, + 940048384, + 940064768, + 940081152, + 940097536, + 940113920, + 940130304, + 940146688, + 940163072, + 940179456, + 940195840, + 940212224, + 940228608, + 940244992, + 940261376, + 940277760, + 940294144, + 940310528, + 940326912, + 940343296, + 940359680, + 940376064, + 940392448, + 940408832, + 940425216, + 940441600, + 940457984, + 940474368, + 940490752, + 940507136, + 940523520, + 940539904, + 940556288, + 940572672, + 940589056, + 940605440, + 940621824, + 940638208, + 940654592, + 940670976, + 940687360, + 940703744, + 940720128, + 940736512, + 940752896, + 940769280, + 940785664, + 940802048, + 940818432, + 940834816, + 940851200, + 940867584, + 940883968, + 940900352, + 940916736, + 940933120, + 940949504, + 940965888, + 940982272, + 940998656, + 941015040, + 941031424, + 941047808, + 941064192, + 941080576, + 941096960, + 941113344, + 941129728, + 941146112, + 941162496, + 941178880, + 941195264, + 941211648, + 941228032, + 941244416, + 941260800, + 941277184, + 941293568, + 941309952, + 941326336, + 941342720, + 941359104, + 941375488, + 941391872, + 941408256, + 941424640, + 941441024, + 941457408, + 941473792, + 941490176, + 941506560, + 941522944, + 941539328, + 941555712, + 941572096, + 941588480, + 941604864, + 941621248, + 941637632, + 941654016, + 941670400, + 941686784, + 941703168, + 941719552, + 941735936, + 941752320, + 941768704, + 941785088, + 941801472, + 941817856, + 941834240, + 941850624, + 941867008, + 941883392, + 941899776, + 941916160, + 941932544, + 941948928, + 941965312, + 941981696, + 941998080, + 942014464, + 942030848, + 942047232, + 942063616, + 942080000, + 942096384, + 942112768, + 942129152, + 942145536, + 942161920, + 942178304, + 942194688, + 942211072, + 942227456, + 942243840, + 942260224, + 942276608, + 942292992, + 942309376, + 942325760, + 942342144, + 942358528, + 942374912, + 942391296, + 942407680, + 942424064, + 942440448, + 942456832, + 942473216, + 942489600, + 942505984, + 942522368, + 942538752, + 942555136, + 942571520, + 942587904, + 942604288, + 942620672, + 942637056, + 942653440, + 942669824, + 942686208, + 942702592, + 942718976, + 942735360, + 942751744, + 942768128, + 942784512, + 942800896, + 942817280, + 942833664, + 942850048, + 942866432, + 942882816, + 942899200, + 942915584, + 942931968, + 942948352, + 942964736, + 942981120, + 942997504, + 943013888, + 943030272, + 943046656, + 943063040, + 943079424, + 943095808, + 943112192, + 943128576, + 943144960, + 943161344, + 943177728, + 943194112, + 943210496, + 943226880, + 943243264, + 943259648, + 943276032, + 943292416, + 943308800, + 943325184, + 943341568, + 943357952, + 943374336, + 943390720, + 943407104, + 943423488, + 943439872, + 943456256, + 943472640, + 943489024, + 943505408, + 943521792, + 943538176, + 943554560, + 943570944, + 943587328, + 943603712, + 943620096, + 943636480, + 943652864, + 943669248, + 943685632, + 943702016, + 943718400, + 943734784, + 943751168, + 943767552, + 943783936, + 943800320, + 943816704, + 943833088, + 943849472, + 943865856, + 943882240, + 943898624, + 943915008, + 943931392, + 943947776, + 943964160, + 943980544, + 943996928, + 944013312, + 944029696, + 944046080, + 944062464, + 944078848, + 944095232, + 944111616, + 944128000, + 944144384, + 944160768, + 944177152, + 944193536, + 944209920, + 944226304, + 944242688, + 944259072, + 944275456, + 944291840, + 944308224, + 944324608, + 944340992, + 944357376, + 944373760, + 944390144, + 944406528, + 944422912, + 944439296, + 944455680, + 944472064, + 944488448, + 944504832, + 944521216, + 944537600, + 944553984, + 944570368, + 944586752, + 944603136, + 944619520, + 944635904, + 944652288, + 944668672, + 944685056, + 944701440, + 944717824, + 944734208, + 944750592, + 944766976, + 944783360, + 944799744, + 944816128, + 944832512, + 944848896, + 944865280, + 944881664, + 944898048, + 944914432, + 944930816, + 944947200, + 944963584, + 944979968, + 944996352, + 945012736, + 945029120, + 945045504, + 945061888, + 945078272, + 945094656, + 945111040, + 945127424, + 945143808, + 945160192, + 945176576, + 945192960, + 945209344, + 945225728, + 945242112, + 945258496, + 945274880, + 945291264, + 945307648, + 945324032, + 945340416, + 945356800, + 945373184, + 945389568, + 945405952, + 945422336, + 945438720, + 945455104, + 945471488, + 945487872, + 945504256, + 945520640, + 945537024, + 945553408, + 945569792, + 945586176, + 945602560, + 945618944, + 945635328, + 945651712, + 945668096, + 945684480, + 945700864, + 945717248, + 945733632, + 945750016, + 945766400, + 945782784, + 945799168, + 945815552, + 945831936, + 945848320, + 945864704, + 945881088, + 945897472, + 945913856, + 945930240, + 945946624, + 945963008, + 945979392, + 945995776, + 946012160, + 946028544, + 946044928, + 946061312, + 946077696, + 946094080, + 946110464, + 946126848, + 946143232, + 946159616, + 946176000, + 946192384, + 946208768, + 946225152, + 946241536, + 946257920, + 946274304, + 946290688, + 946307072, + 946323456, + 946339840, + 946356224, + 946372608, + 946388992, + 946405376, + 946421760, + 946438144, + 946454528, + 946470912, + 946487296, + 946503680, + 946520064, + 946536448, + 946552832, + 946569216, + 946585600, + 946601984, + 946618368, + 946634752, + 946651136, + 946667520, + 946683904, + 946700288, + 946716672, + 946733056, + 946749440, + 946765824, + 946782208, + 946798592, + 946814976, + 946831360, + 946847744, + 946864128, + 946880512, + 946896896, + 946913280, + 946929664, + 946946048, + 946962432, + 946978816, + 946995200, + 947011584, + 947027968, + 947044352, + 947060736, + 947077120, + 947093504, + 947109888, + 947126272, + 947142656, + 947159040, + 947175424, + 947191808, + 947208192, + 947224576, + 947240960, + 947257344, + 947273728, + 947290112, + 947306496, + 947322880, + 947339264, + 947355648, + 947372032, + 947388416, + 947404800, + 947421184, + 947437568, + 947453952, + 947470336, + 947486720, + 947503104, + 947519488, + 947535872, + 947552256, + 947568640, + 947585024, + 947601408, + 947617792, + 947634176, + 947650560, + 947666944, + 947683328, + 947699712, + 947716096, + 947732480, + 947748864, + 947765248, + 947781632, + 947798016, + 947814400, + 947830784, + 947847168, + 947863552, + 947879936, + 947896320, + 939524096, + 939532288, + 939540480, + 939548672, + 939556864, + 939565056, + 939573248, + 939581440, + 939589632, + 939597824, + 939606016, + 939614208, + 939622400, + 939630592, + 939638784, + 939646976, + 939655168, + 939663360, + 939671552, + 939679744, + 939687936, + 939696128, + 939704320, + 939712512, + 939720704, + 939728896, + 939737088, + 939745280, + 939753472, + 939761664, + 939769856, + 939778048, + 939786240, + 939794432, + 939802624, + 939810816, + 939819008, + 939827200, + 939835392, + 939843584, + 939851776, + 939859968, + 939868160, + 939876352, + 939884544, + 939892736, + 939900928, + 939909120, + 939917312, + 939925504, + 939933696, + 939941888, + 939950080, + 939958272, + 939966464, + 939974656, + 939982848, + 939991040, + 939999232, + 940007424, + 940015616, + 940023808, + 940032000, + 940040192, + 940048384, + 940056576, + 940064768, + 940072960, + 940081152, + 940089344, + 940097536, + 940105728, + 940113920, + 940122112, + 940130304, + 940138496, + 940146688, + 940154880, + 940163072, + 940171264, + 940179456, + 940187648, + 940195840, + 940204032, + 940212224, + 940220416, + 940228608, + 940236800, + 940244992, + 940253184, + 940261376, + 940269568, + 940277760, + 940285952, + 940294144, + 940302336, + 940310528, + 940318720, + 940326912, + 940335104, + 940343296, + 940351488, + 940359680, + 940367872, + 940376064, + 940384256, + 940392448, + 940400640, + 940408832, + 940417024, + 940425216, + 940433408, + 940441600, + 940449792, + 940457984, + 940466176, + 940474368, + 940482560, + 940490752, + 940498944, + 940507136, + 940515328, + 940523520, + 940531712, + 940539904, + 940548096, + 940556288, + 940564480, + 940572672, + 940580864, + 940589056, + 940597248, + 940605440, + 940613632, + 940621824, + 940630016, + 940638208, + 940646400, + 940654592, + 940662784, + 940670976, + 940679168, + 940687360, + 940695552, + 940703744, + 940711936, + 940720128, + 940728320, + 940736512, + 940744704, + 940752896, + 940761088, + 940769280, + 940777472, + 940785664, + 940793856, + 940802048, + 940810240, + 940818432, + 940826624, + 940834816, + 940843008, + 940851200, + 940859392, + 940867584, + 940875776, + 940883968, + 940892160, + 940900352, + 940908544, + 940916736, + 940924928, + 940933120, + 940941312, + 940949504, + 940957696, + 940965888, + 940974080, + 940982272, + 940990464, + 940998656, + 941006848, + 941015040, + 941023232, + 941031424, + 941039616, + 941047808, + 941056000, + 941064192, + 941072384, + 941080576, + 941088768, + 941096960, + 941105152, + 941113344, + 941121536, + 941129728, + 941137920, + 941146112, + 941154304, + 941162496, + 941170688, + 941178880, + 941187072, + 941195264, + 941203456, + 941211648, + 941219840, + 941228032, + 941236224, + 941244416, + 941252608, + 941260800, + 941268992, + 941277184, + 941285376, + 941293568, + 941301760, + 941309952, + 941318144, + 941326336, + 941334528, + 941342720, + 941350912, + 941359104, + 941367296, + 941375488, + 941383680, + 941391872, + 941400064, + 941408256, + 941416448, + 941424640, + 941432832, + 941441024, + 941449216, + 941457408, + 941465600, + 941473792, + 941481984, + 941490176, + 941498368, + 941506560, + 941514752, + 941522944, + 941531136, + 941539328, + 941547520, + 941555712, + 941563904, + 941572096, + 941580288, + 941588480, + 941596672, + 941604864, + 941613056, + 941621248, + 941629440, + 941637632, + 941645824, + 941654016, + 941662208, + 941670400, + 941678592, + 941686784, + 941694976, + 941703168, + 941711360, + 941719552, + 941727744, + 941735936, + 941744128, + 941752320, + 941760512, + 941768704, + 941776896, + 941785088, + 941793280, + 941801472, + 941809664, + 941817856, + 941826048, + 941834240, + 941842432, + 941850624, + 941858816, + 941867008, + 941875200, + 941883392, + 941891584, + 941899776, + 941907968, + 941916160, + 941924352, + 941932544, + 941940736, + 941948928, + 941957120, + 941965312, + 941973504, + 941981696, + 941989888, + 941998080, + 942006272, + 942014464, + 942022656, + 942030848, + 942039040, + 942047232, + 942055424, + 942063616, + 942071808, + 942080000, + 942088192, + 942096384, + 942104576, + 942112768, + 942120960, + 942129152, + 942137344, + 942145536, + 942153728, + 942161920, + 942170112, + 942178304, + 942186496, + 942194688, + 942202880, + 942211072, + 942219264, + 942227456, + 942235648, + 942243840, + 942252032, + 942260224, + 942268416, + 942276608, + 942284800, + 942292992, + 942301184, + 942309376, + 942317568, + 942325760, + 942333952, + 942342144, + 942350336, + 942358528, + 942366720, + 942374912, + 942383104, + 942391296, + 942399488, + 942407680, + 942415872, + 942424064, + 942432256, + 942440448, + 942448640, + 942456832, + 942465024, + 942473216, + 942481408, + 942489600, + 942497792, + 942505984, + 942514176, + 942522368, + 942530560, + 942538752, + 942546944, + 942555136, + 942563328, + 942571520, + 942579712, + 942587904, + 942596096, + 942604288, + 942612480, + 942620672, + 942628864, + 942637056, + 942645248, + 942653440, + 942661632, + 942669824, + 942678016, + 942686208, + 942694400, + 942702592, + 942710784, + 942718976, + 942727168, + 942735360, + 942743552, + 942751744, + 942759936, + 942768128, + 942776320, + 942784512, + 942792704, + 942800896, + 942809088, + 942817280, + 942825472, + 942833664, + 942841856, + 942850048, + 942858240, + 942866432, + 942874624, + 942882816, + 942891008, + 942899200, + 942907392, + 942915584, + 942923776, + 942931968, + 942940160, + 942948352, + 942956544, + 942964736, + 942972928, + 942981120, + 942989312, + 942997504, + 943005696, + 943013888, + 943022080, + 943030272, + 943038464, + 943046656, + 943054848, + 943063040, + 943071232, + 943079424, + 943087616, + 943095808, + 943104000, + 943112192, + 943120384, + 943128576, + 943136768, + 943144960, + 943153152, + 943161344, + 943169536, + 943177728, + 943185920, + 943194112, + 943202304, + 943210496, + 943218688, + 943226880, + 943235072, + 943243264, + 943251456, + 943259648, + 943267840, + 943276032, + 943284224, + 943292416, + 943300608, + 943308800, + 943316992, + 943325184, + 943333376, + 943341568, + 943349760, + 943357952, + 943366144, + 943374336, + 943382528, + 943390720, + 943398912, + 943407104, + 943415296, + 943423488, + 943431680, + 943439872, + 943448064, + 943456256, + 943464448, + 943472640, + 943480832, + 943489024, + 943497216, + 943505408, + 943513600, + 943521792, + 943529984, + 943538176, + 943546368, + 943554560, + 943562752, + 943570944, + 943579136, + 943587328, + 943595520, + 943603712, + 943611904, + 943620096, + 943628288, + 943636480, + 943644672, + 943652864, + 943661056, + 943669248, + 943677440, + 943685632, + 943693824, + 943702016, + 943710208, + 943718400, + 943726592, + 943734784, + 943742976, + 943751168, + 943759360, + 943767552, + 943775744, + 943783936, + 943792128, + 943800320, + 943808512, + 943816704, + 943824896, + 943833088, + 943841280, + 943849472, + 943857664, + 943865856, + 943874048, + 943882240, + 943890432, + 943898624, + 943906816, + 943915008, + 943923200, + 943931392, + 943939584, + 943947776, + 943955968, + 943964160, + 943972352, + 943980544, + 943988736, + 943996928, + 944005120, + 944013312, + 944021504, + 944029696, + 944037888, + 944046080, + 944054272, + 944062464, + 944070656, + 944078848, + 944087040, + 944095232, + 944103424, + 944111616, + 944119808, + 944128000, + 944136192, + 944144384, + 944152576, + 944160768, + 944168960, + 944177152, + 944185344, + 944193536, + 944201728, + 944209920, + 944218112, + 944226304, + 944234496, + 944242688, + 944250880, + 944259072, + 944267264, + 944275456, + 944283648, + 944291840, + 944300032, + 944308224, + 944316416, + 944324608, + 944332800, + 944340992, + 944349184, + 944357376, + 944365568, + 944373760, + 944381952, + 944390144, + 944398336, + 944406528, + 944414720, + 944422912, + 944431104, + 944439296, + 944447488, + 944455680, + 944463872, + 944472064, + 944480256, + 944488448, + 944496640, + 944504832, + 944513024, + 944521216, + 944529408, + 944537600, + 944545792, + 944553984, + 944562176, + 944570368, + 944578560, + 944586752, + 944594944, + 944603136, + 944611328, + 944619520, + 944627712, + 944635904, + 944644096, + 944652288, + 944660480, + 944668672, + 944676864, + 944685056, + 944693248, + 944701440, + 944709632, + 944717824, + 944726016, + 944734208, + 944742400, + 944750592, + 944758784, + 944766976, + 944775168, + 944783360, + 944791552, + 944799744, + 944807936, + 944816128, + 944824320, + 944832512, + 944840704, + 944848896, + 944857088, + 944865280, + 944873472, + 944881664, + 944889856, + 944898048, + 944906240, + 944914432, + 944922624, + 944930816, + 944939008, + 944947200, + 944955392, + 944963584, + 944971776, + 944979968, + 944988160, + 944996352, + 945004544, + 945012736, + 945020928, + 945029120, + 945037312, + 945045504, + 945053696, + 945061888, + 945070080, + 945078272, + 945086464, + 945094656, + 945102848, + 945111040, + 945119232, + 945127424, + 945135616, + 945143808, + 945152000, + 945160192, + 945168384, + 945176576, + 945184768, + 945192960, + 945201152, + 945209344, + 945217536, + 945225728, + 945233920, + 945242112, + 945250304, + 945258496, + 945266688, + 945274880, + 945283072, + 945291264, + 945299456, + 945307648, + 945315840, + 945324032, + 945332224, + 945340416, + 945348608, + 945356800, + 945364992, + 945373184, + 945381376, + 945389568, + 945397760, + 945405952, + 945414144, + 945422336, + 945430528, + 945438720, + 945446912, + 945455104, + 945463296, + 945471488, + 945479680, + 945487872, + 945496064, + 945504256, + 945512448, + 945520640, + 945528832, + 945537024, + 945545216, + 945553408, + 945561600, + 945569792, + 945577984, + 945586176, + 945594368, + 945602560, + 945610752, + 945618944, + 945627136, + 945635328, + 945643520, + 945651712, + 945659904, + 945668096, + 945676288, + 945684480, + 945692672, + 945700864, + 945709056, + 945717248, + 945725440, + 945733632, + 945741824, + 945750016, + 945758208, + 945766400, + 945774592, + 945782784, + 945790976, + 945799168, + 945807360, + 945815552, + 945823744, + 945831936, + 945840128, + 945848320, + 945856512, + 945864704, + 945872896, + 945881088, + 945889280, + 945897472, + 945905664, + 945913856, + 945922048, + 945930240, + 945938432, + 945946624, + 945954816, + 945963008, + 945971200, + 945979392, + 945987584, + 945995776, + 946003968, + 946012160, + 946020352, + 946028544, + 946036736, + 946044928, + 946053120, + 946061312, + 946069504, + 946077696, + 946085888, + 946094080, + 946102272, + 946110464, + 946118656, + 946126848, + 946135040, + 946143232, + 946151424, + 946159616, + 946167808, + 946176000, + 946184192, + 946192384, + 946200576, + 946208768, + 946216960, + 946225152, + 946233344, + 946241536, + 946249728, + 946257920, + 946266112, + 946274304, + 946282496, + 946290688, + 946298880, + 946307072, + 946315264, + 946323456, + 946331648, + 946339840, + 946348032, + 946356224, + 946364416, + 946372608, + 946380800, + 946388992, + 946397184, + 946405376, + 946413568, + 946421760, + 946429952, + 946438144, + 946446336, + 946454528, + 946462720, + 946470912, + 946479104, + 946487296, + 946495488, + 946503680, + 946511872, + 946520064, + 946528256, + 946536448, + 946544640, + 946552832, + 946561024, + 946569216, + 946577408, + 946585600, + 946593792, + 946601984, + 946610176, + 946618368, + 946626560, + 946634752, + 946642944, + 946651136, + 946659328, + 946667520, + 946675712, + 946683904, + 946692096, + 946700288, + 946708480, + 946716672, + 946724864, + 946733056, + 946741248, + 946749440, + 946757632, + 946765824, + 946774016, + 946782208, + 946790400, + 946798592, + 946806784, + 946814976, + 946823168, + 946831360, + 946839552, + 946847744, + 946855936, + 946864128, + 946872320, + 946880512, + 946888704, + 946896896, + 946905088, + 946913280, + 946921472, + 946929664, + 946937856, + 946946048, + 946954240, + 946962432, + 946970624, + 946978816, + 946987008, + 946995200, + 947003392, + 947011584, + 947019776, + 947027968, + 947036160, + 947044352, + 947052544, + 947060736, + 947068928, + 947077120, + 947085312, + 947093504, + 947101696, + 947109888, + 947118080, + 947126272, + 947134464, + 947142656, + 947150848, + 947159040, + 947167232, + 947175424, + 947183616, + 947191808, + 947200000, + 947208192, + 947216384, + 947224576, + 947232768, + 947240960, + 947249152, + 947257344, + 947265536, + 947273728, + 947281920, + 947290112, + 947298304, + 947306496, + 947314688, + 947322880, + 947331072, + 947339264, + 947347456, + 947355648, + 947363840, + 947372032, + 947380224, + 947388416, + 947396608, + 947404800, + 947412992, + 947421184, + 947429376, + 947437568, + 947445760, + 947453952, + 947462144, + 947470336, + 947478528, + 947486720, + 947494912, + 947503104, + 947511296, + 947519488, + 947527680, + 947535872, + 947544064, + 947552256, + 947560448, + 947568640, + 947576832, + 947585024, + 947593216, + 947601408, + 947609600, + 947617792, + 947625984, + 947634176, + 947642368, + 947650560, + 947658752, + 947666944, + 947675136, + 947683328, + 947691520, + 947699712, + 947707904, + 947716096, + 947724288, + 947732480, + 947740672, + 947748864, + 947757056, + 947765248, + 947773440, + 947781632, + 947789824, + 947798016, + 947806208, + 947814400, + 947822592, + 947830784, + 947838976, + 947847168, + 947855360, + 947863552, + 947871744, + 947879936, + 947888128, + 947896320, + 947904512, + }; + + unsigned int exponent_table[64] = + { + 0, + 8388608, + 16777216, + 25165824, + 33554432, + 41943040, + 50331648, + 58720256, + 67108864, + 75497472, + 83886080, + 92274688, + 100663296, + 109051904, + 117440512, + 125829120, + 134217728, + 142606336, + 150994944, + 159383552, + 167772160, + 176160768, + 184549376, + 192937984, + 201326592, + 209715200, + 218103808, + 226492416, + 234881024, + 243269632, + 251658240, + 1199570944, + 2147483648, + 2155872256, + 2164260864, + 2172649472, + 2181038080, + 2189426688, + 2197815296, + 2206203904, + 2214592512, + 2222981120, + 2231369728, + 2239758336, + 2248146944, + 2256535552, + 2264924160, + 2273312768, + 2281701376, + 2290089984, + 2298478592, + 2306867200, + 2315255808, + 2323644416, + 2332033024, + 2340421632, + 2348810240, + 2357198848, + 2365587456, + 2373976064, + 2382364672, + 2390753280, + 2399141888, + 3347054592, + }; + + unsigned short offset_table[64] = + { + 0, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 1024, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }; + + unsigned short base_table[512] = + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 2, + 4, + 8, + 16, + 32, + 64, + 128, + 256, + 512, + 1024, + 2048, + 3072, + 4096, + 5120, + 6144, + 7168, + 8192, + 9216, + 10240, + 11264, + 12288, + 13312, + 14336, + 15360, + 16384, + 17408, + 18432, + 19456, + 20480, + 21504, + 22528, + 23552, + 24576, + 25600, + 26624, + 27648, + 28672, + 29696, + 30720, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 31744, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32768, + 32769, + 32770, + 32772, + 32776, + 32784, + 32800, + 32832, + 32896, + 33024, + 33280, + 33792, + 34816, + 35840, + 36864, + 37888, + 38912, + 39936, + 40960, + 41984, + 43008, + 44032, + 45056, + 46080, + 47104, + 48128, + 49152, + 50176, + 51200, + 52224, + 53248, + 54272, + 55296, + 56320, + 57344, + 58368, + 59392, + 60416, + 61440, + 62464, + 63488, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + 64512, + }; + + unsigned char shift_table[512] = + { + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 23, + 22, + 21, + 20, + 19, + 18, + 17, + 16, + 15, + 14, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 13, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 23, + 22, + 21, + 20, + 19, + 18, + 17, + 16, + 15, + 14, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 13, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 24, + 13, + }; + + /* + + void generate_tables() + { + unsigned int mantissa_table[2048]; + unsigned int exponent_table[64]; + unsigned short offset_table[64]; + unsigned short base_table[512]; + unsigned char shift_table[512]; + + mantissa_table[0] = 0; + for (int i = 1; i < 1024; i++) + { + unsigned int m=i<<13; // Zero pad mantissa bits + unsigned int e=0; // Zero exponent + while(!(m&0x00800000)) // While not normalized + { + e-=0x00800000; // Decrement exponent (1<<23) + m<<=1; // Shift mantissa + } + m&=~0x00800000; // Clear leading 1 bit + e+=0x38800000; // Adjust bias ((127-14)<<23) + mantissa_table[i] = m | e; + } + for (int i = 1024; i < 2048; i++) + { + mantissa_table[i] = 0x38000000 + ((i - 1024) << 13); + } + + exponent_table[0] = 0; + exponent_table[32] = 0x80000000; + + for (int i = 1; i < 31; i++) + exponent_table[i] = i<<23; + for (int i = 33; i < 63; i++) + exponent_table[i] = 0x80000000 + ((i-32)<<23); + + exponent_table[31] = 0x47800000; + exponent_table[63] = 0xC7800000; + + offset_table[0] = 0; + offset_table[32] = 0; + for (int i = 1; i < 32; i++) + offset_table[i] = 1024; + + for(unsigned int i=0; i<256; ++i) + { + int e=i-127; + if (e<-24) // Very small numbers map to zero + { + base_table[i|0x000]=0x0000; + base_table[i|0x100]=0x8000; + shift_table[i|0x000]=24; + shift_table[i|0x100]=24; + } + else if (e<-14) // Small numbers map to denorms + { + base_table[i|0x000]=(0x0400>>(-e-14)); + base_table[i|0x100]=(0x0400>>(-e-14)) | 0x8000; + shift_table[i|0x000]=-e-1; + shift_table[i|0x100]=-e-1; + } + else if (e<=15) // Normal numbers just lose precision + { + base_table[i|0x000]=((e+15)<<10); + base_table[i|0x100]=((e+15)<<10) | 0x8000; + shift_table[i|0x000]=13; + shift_table[i|0x100]=13; + } + else if (e<128) // Large numbers map to Infinity + { + base_table[i|0x000]=0x7C00; + base_table[i|0x100]=0xFC00; + shift_table[i|0x000]=24; + shift_table[i|0x100]=24; + } + else // Infinity and NaN's stay Infinity and NaN's + { + base_table[i|0x000]=0x7C00; + base_table[i|0x100]=0xFC00; + shift_table[i|0x000]=13; + shift_table[i|0x100]=13; + } + } + + File file("tables.txt", File::create_always, File::access_read_write); + file.write_string_text("unsigned int mantissa_table[2048] ="); + file.write_string_text("{"); + for (int i = 0; i < 2048; i++) + { + file.write_string_text("\t" + Text::to_string(mantissa_table[i]) + ","); + } + file.write_string_text("};"); + file.write_string_text(""); + + file.write_string_text("unsigned int exponent_table[64] ="); + file.write_string_text("{"); + for (int i = 0; i < 64; i++) + { + file.write_string_text("\t" + Text::to_string(exponent_table[i]) + ","); + } + file.write_string_text("};"); + file.write_string_text(""); + + file.write_string_text("unsigned short offset_table[64] ="); + file.write_string_text("{"); + for (int i = 0; i < 64; i++) + { + file.write_string_text("\t" + Text::to_string(offset_table[i]) + ","); + } + file.write_string_text("};"); + file.write_string_text(""); + + file.write_string_text("unsigned short base_table[512] ="); + file.write_string_text("{"); + for (int i = 0; i < 512; i++) + { + file.write_string_text("\t" + Text::to_string(base_table[i]) + ","); + } + file.write_string_text("};"); + file.write_string_text(""); + + file.write_string_text("unsigned char shift_table[512] ="); + file.write_string_text("{"); + for (int i = 0; i < 512; i++) + { + file.write_string_text("\t" + Text::to_string(shift_table[i]) + ","); + } + file.write_string_text("};"); + file.write_string_text(""); + } + */ +} diff --git a/src/lightmap/halffloat.h b/src/lightmap/halffloat.h new file mode 100644 index 0000000..1d3fc4b --- /dev/null +++ b/src/lightmap/halffloat.h @@ -0,0 +1,68 @@ +/* +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +** +** Note: Some of the libraries UICore may link to may have additional +** requirements or restrictions. +** +** Based on the paper "Fast Half Float Conversions" by Jeroen van der Zijp. +*/ + +#pragma once + +namespace HalfFloatTables +{ + extern unsigned int mantissa_table[2048]; + extern unsigned int exponent_table[64]; + extern unsigned short offset_table[64]; + extern unsigned short base_table[512]; + extern unsigned char shift_table[512]; +}; + +/// Convert half-float to float. Only works for 'normal' half-float values +inline float halfToFloatSimple(unsigned short hf) +{ + unsigned int float_value = ((hf & 0x8000) << 16) | (((hf & 0x7c00) + 0x1C000) << 13) | ((hf & 0x03FF) << 13); + void *ptr = static_cast(&float_value); + return *static_cast(ptr); +} + +/// Convert float to half-float. Only works for 'normal' half-float values +inline unsigned short floatToHalfSimple(float float_value) +{ + void *ptr = static_cast(&float_value); + unsigned int f = *static_cast(ptr); + return ((f >> 16) & 0x8000) | ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) | ((f >> 13) & 0x03ff); +} + +/// Convert half-float to float +inline float halfToFloat(unsigned short hf) +{ + using namespace HalfFloatTables; + unsigned int float_value = mantissa_table[offset_table[hf >> 10] + (hf & 0x3ff)] + exponent_table[hf >> 10]; + void *ptr = static_cast(&float_value); + return *static_cast(ptr); +} + +/// Convert float to half-float +inline unsigned short floatToHalf(float float_value) +{ + using namespace HalfFloatTables; + void *ptr = static_cast(&float_value); + unsigned int f = *static_cast(ptr); + return base_table[(f >> 23) & 0x1ff] + ((f & 0x007fffff) >> shift_table[(f >> 23) & 0x1ff]); +} diff --git a/src/lightmap/lightmap.cpp b/src/lightmap/lightmap.cpp index 81eaf01..ab45b01 100644 --- a/src/lightmap/lightmap.cpp +++ b/src/lightmap/lightmap.cpp @@ -39,6 +39,7 @@ #include "kexlib/binfile.h" #include "wad.h" #include "framework/templates.h" +#include "halffloat.h" #include #include @@ -60,7 +61,6 @@ kexLightmapBuilder::kexLightmapBuilder() this->extraSamples = 2; this->ambience = 0.0f; this->tracedTexels = 0; - this->gridMap = NULL; } // @@ -86,7 +86,7 @@ void kexLightmapBuilder::NewTexture() memset(allocBlocks[numTextures-1], 0, sizeof(int) * textureWidth); - byte *texture = (byte*)Mem_Calloc((textureWidth * textureHeight) * 3, hb_static); + uint16_t *texture = (uint16_t*)Mem_Calloc((textureWidth * textureHeight) * 3 * 2, hb_static); textures.Push(texture); } @@ -203,9 +203,9 @@ kexBBox kexLightmapBuilder::GetBoundsFromSurface(const surface_t *surface) bool kexLightmapBuilder::EmitFromCeiling(kexTrace &trace, const surface_t *surface, const kexVec3 &origin, const kexVec3 &normal, kexVec3 &color) { - float dist = normal.Dot(map->GetSunDirection()); + float attenuation = normal.Dot(map->GetSunDirection()); - if(dist <= 0) + if(attenuation <= 0) { // plane is not even facing the sunlight return false; @@ -222,11 +222,14 @@ bool kexLightmapBuilder::EmitFromCeiling(kexTrace &trace, const surface_t *surfa if(trace.hitSurface->bSky == false) { + if (trace.hitSurface->type == ST_CEILING) + return false; + // not a ceiling/sky surface return false; } - color += map->GetSunColor() * dist; + color += map->GetSunColor() * attenuation; return true; } @@ -260,12 +263,6 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori { thingLight_t *tl = map->thingLights[i]; - // try to early out if PVS data exists - if(!map->CheckPVS(surface->subSector, tl->ssect)) - { - continue; - } - float originZ; if (!tl->bCeiling) originZ = tl->sector->floorplane.zAt(tl->origin.x, tl->origin.y) + tl->height; @@ -330,7 +327,7 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori tracedTexels++; } - if(surface->type != ST_CEILING && map->bSSectsVisibleToSky[surface->subSector - map->GLSubsectors]) + if(surface->type != ST_CEILING) { // see if it's exposed to sunlight if(EmitFromCeiling(trace, surface, origin, plane.Normal(), color)) @@ -342,12 +339,6 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori { kexLightSurface *surfaceLight = map->lightSurfaces[i]; - // try to early out if PVS data exists - if(!map->CheckPVS(surface->subSector, surfaceLight->Surface()->subSector)) - { - continue; - } - float attenuation; if(surfaceLight->TraceSurface(map, trace, surface, origin, &attenuation)) { @@ -484,7 +475,7 @@ void kexLightmapBuilder::TraceSurface(surface_t *surface) int i; int j; kexTrace trace; - byte *currentTexture; + uint16_t *currentTexture; bool bShouldLookupTexture = false; trace.Init(*map); @@ -599,9 +590,9 @@ void kexLightmapBuilder::TraceSurface(surface_t *surface) int offs = (((textureWidth * (i + surface->lightmapOffs[1])) + surface->lightmapOffs[0]) * 3); // convert RGB to bytes - currentTexture[offs + j * 3 + 0] = (uint32_t)(colorSamples[i * 1024 + j].x * 255 + 0.5f); - currentTexture[offs + j * 3 + 1] = (uint32_t)(colorSamples[i * 1024 + j].y * 255 + 0.5f); - currentTexture[offs + j * 3 + 2] = (uint32_t)(colorSamples[i * 1024 + j].z * 255 + 0.5f); + currentTexture[offs + j * 3 + 0] = floatToHalf(colorSamples[i * 1024 + j].x); + currentTexture[offs + j * 3 + 1] = floatToHalf(colorSamples[i * 1024 + j].y); + currentTexture[offs + j * 3 + 2] = floatToHalf(colorSamples[i * 1024 + j].z); } } } @@ -636,227 +627,10 @@ void kexLightmapBuilder::LightSurface(const int surfid) } } -// -// kexLightmapBuilder::LightCellSample -// -// Traces a line from the cell's origin to the sunlight direction -// and against all nearby thing lights -// - -kexVec3 kexLightmapBuilder::LightCellSample(const int gridid, kexTrace &trace, const kexVec3 &origin, const MapSubsectorEx *sub) -{ - kexVec3 color; - kexVec3 dir; - IntSector *mapSector; - float intensity; - float radius; - float dist; - float colorAdd; - thingLight_t *tl; - kexVec3 lightOrigin; - bool bInSkySector; - kexVec3 org; - - mapSector = map->GetSectorFromSubSector(sub); - bInSkySector = map->bSkySectors[mapSector - &map->Sectors[0]]; - - trace.Trace(origin, origin + (map->GetSunDirection() * 32768)); - - // did we traced a ceiling surface with a sky texture? - if(trace.fraction != 1 && trace.hitSurface != NULL) - { - if(trace.hitSurface->bSky && origin.z + gridSize[2] > mapSector->data.floorheight) - { - color = map->GetSunColor(); - // this cell is inside a sector with a sky texture and is also exposed to sunlight. - // mark this cell as a sun type. cells of this type will simply sample the - // sector's light level - gridMap[gridid].sunShadow = 2; - return color; - } - - // if this cell is inside a sector with a sky texture but is NOT exposed to sunlight, then - // mark this cell as a sun shade type. cells of this type will halve the sector's light level - if(bInSkySector) - { - gridMap[gridid].sunShadow = 1; - } - } - // if the cell is technically inside a sector with a sky but is not actually on an actual surface - // then this cell is considered occluded - else if(bInSkySector && !map->PointInsideSubSector(origin.x, origin.y, sub)) - { - gridMap[gridid].sunShadow = 1; - } - - // trace against all thing lights - for(unsigned int i = 0; i < map->thingLights.Size(); i++) - { - tl = map->thingLights[i]; - - lightOrigin.Set(tl->origin.x, - tl->origin.y, - !tl->bCeiling ? - (float)tl->sector->data.floorheight + 16 : - (float)tl->sector->data.ceilingheight - 16); - - radius = tl->radius; - intensity = tl->intensity * 4; - - if(intensity < 1.0f) - { - intensity = 1.0f; - } - - if(origin.DistanceSq(lightOrigin) > (radius*radius)) - { - // not within range - continue; - } - - trace.Trace(origin, lightOrigin); - - if(trace.fraction != 1) - { - // something is occluding it - continue; - } - - dir = (lightOrigin - origin); - dist = dir.Unit(); - - dir.Normalize(); - - colorAdd = (radius / (dist * dist)) * intensity; - kexMath::Clamp(colorAdd, 0, 1); - - // accumulate results - color = color.Lerp(tl->rgb, colorAdd); - kexMath::Clamp(color, 0, 1); - } - - org = origin; - - // if the cell is sticking out from the ground then at least - // clamp the origin to the ground level so it can at least - // have a chance to be sampled by the light - if(origin.z + gridSize[2] > mapSector->data.floorheight) - { - org.z = (float)mapSector->data.floorheight + 2; - } - - // trace against all light surfaces - for(unsigned int i = 0; i < map->lightSurfaces.Size(); ++i) - { - kexLightSurface *surfaceLight = map->lightSurfaces[i]; - - if(surfaceLight->TraceSurface(map, trace, NULL, org, &dist)) - { - dist = (dist * (surfaceLight->Intensity() * 0.5f)) * 0.5f; - kexMath::Clamp(dist, 0, 1); - - // accumulate results - color = color.Lerp(surfaceLight->GetRGB(), dist); - kexMath::Clamp(color, 0, 1); - } - } - - return color; -} - -// -// kexLightmapBuilder::LightGrid -// - -void kexLightmapBuilder::LightGrid(const int gridid) -{ - float remaining; - int x, y, z; - int mod; - int secnum; - bool bInRange; - int gx = (int)gridBlock.x; - int gy = (int)gridBlock.y; - kexTrace trace; - MapSubsectorEx *ss; - - // convert grid id to xyz coordinates - mod = gridid; - z = mod / (gx * gy); - mod -= z * (gx * gy); - - y = mod / gx; - mod -= y * gx; - - x = mod; - - // get world-coordinates - kexVec3 org(worldGrid.min[0] + x * gridSize[0], - worldGrid.min[1] + y * gridSize[1], - worldGrid.min[2] + z * gridSize[2]); - - ss = NULL; - secnum = ((int)gridBlock.x * y) + x; - - // determine what sector this cell is in - if(gridSectors[secnum] == NULL) - { - ss = map->PointInSubSector((int)org.x, (int)org.y); - gridSectors[secnum] = ss; - } - else - { - ss = gridSectors[secnum]; - } - - trace.Init(*map); - kexBBox bounds = gridBound + org; - - bInRange = false; - - // is this cell even inside the world? - for(int i = 0; i < map->NumGLSubsectors; ++i) - { - if(bounds.IntersectingBox(map->ssLeafBounds[i])) - { - bInRange = true; - break; - } - } - - if(bInRange) - { - // mark grid cell and accumulate color results - gridMap[gridid].marked = 1; - gridMap[gridid].color += LightCellSample(gridid, trace, org, ss); - - kexMath::Clamp(gridMap[gridid].color, 0, 1); - } - - std::unique_lock lock(mutex); - - int lastproc = processed * 100 / numLightGrids; - processed++; - int curproc = processed * 100 / numLightGrids; - - if (lastproc != curproc || processed == 1) - { - remaining = (float)processed / (float)numLightGrids; - printf("%i%c cells done\r", (int)(remaining * 100.0f), '%'); - } -} - -// -// kexLightmapBuilder::CreateLightmaps -// - void kexLightmapBuilder::CreateLightmaps(FLevel &doomMap) { map = &doomMap; - printf("------------- Building light grid -------------\n"); - CreateLightGrid(); - printf("------------- Tracing surfaces -------------\n"); processed = 0; @@ -867,262 +641,119 @@ void kexLightmapBuilder::CreateLightmaps(FLevel &doomMap) printf("Texels traced: %i \n\n", tracedTexels); } -// -// kexLightmapBuilder::CreateLightGrid -// - -void kexLightmapBuilder::CreateLightGrid() +void kexLightmapBuilder::AddLightmapLump(FWadWriter &wadFile) { - int count; - int numNodes; - kexVec3 mins, maxs; + // Calculate size of lump + int numTexCoords = 0; + int numSurfaces = 0; + for (unsigned int i = 0; i < surfaces.Length(); i++) + { + if (surfaces[i]->lightmapNum != -1) + { + numTexCoords += surfaces[i]->numVerts; + numSurfaces++; + } + } + int version = 0; + int headerSize = 3 * sizeof(uint32_t) + 2 * sizeof(uint16_t); + int surfacesSize = surfaces.Length() * 5 * sizeof(uint32_t); + int texCoordsSize = numTexCoords * 2 * sizeof(float); + int texDataSize = textures.Length() * textureWidth * textureHeight * 3 * 2; + int lumpSize = headerSize + surfacesSize + texCoordsSize + texDataSize; - // get the bounding box of the root BSP node - numNodes = map->NumGLNodes-1; - if(numNodes < 0) - { - numNodes = 0; - } + // Setup buffer + std::vector buffer(lumpSize); + kexBinFile lumpFile; + lumpFile.SetBuffer(buffer.data()); - worldGrid = map->nodeBounds[numNodes]; + // Write header + lumpFile.Write32(version); + lumpFile.Write16(textureWidth); + lumpFile.Write16(textures.Length()); + lumpFile.Write32(numSurfaces); + lumpFile.Write32(numTexCoords); - // determine the size of the grid block - for(int i = 0; i < 3; ++i) - { - mins[i] = gridSize[i] * kexMath::Floor(worldGrid.min[i] / gridSize[i]); - maxs[i] = gridSize[i] * kexMath::Ceil(worldGrid.max[i] / gridSize[i]); - gridBlock[i] = (maxs[i] - mins[i]) / gridSize[i] + 1; - } + // Write surfaces + int coordOffsets = 0; + for (unsigned int i = 0; i < surfaces.Length(); i++) + { + if (surfaces[i]->lightmapNum == -1) + continue; - worldGrid.min = mins; - worldGrid.max = maxs; + lumpFile.Write32(surfaces[i]->type); + lumpFile.Write32(surfaces[i]->typeIndex); + lumpFile.Write32(0xffffffff/*surfaces[i]->controlSector*/); + lumpFile.Write32(surfaces[i]->lightmapNum); + lumpFile.Write32(coordOffsets); + coordOffsets += surfaces[i]->numVerts; + } - gridBound.min = -(gridSize * 0.5f); - gridBound.max = (gridSize * 0.5f); + // Write texture coordinates + for (unsigned int i = 0; i < surfaces.Length(); i++) + { + if (surfaces[i]->lightmapNum == -1) + continue; - // get the total number of grid cells - count = (int)(gridBlock.x * gridBlock.y * gridBlock.z); - numLightGrids = count; + int count = surfaces[i]->numVerts; + if (surfaces[i]->type == ST_FLOOR) + { + for (int j = count - 1; j >= 0; j--) + { + lumpFile.WriteFloat(surfaces[i]->lightmapCoords[j * 2]); + lumpFile.WriteFloat(surfaces[i]->lightmapCoords[j * 2 + 1]); + } + } + else if (surfaces[i]->type == ST_CEILING) + { + for (int j = 0; j < count; j++) + { + lumpFile.WriteFloat(surfaces[i]->lightmapCoords[j * 2]); + lumpFile.WriteFloat(surfaces[i]->lightmapCoords[j * 2 + 1]); + } + } + else + { + // zdray uses triangle strip internally, lump/gzd uses triangle fan - // allocate data - gridMap = (gridMap_t*)Mem_Calloc(sizeof(gridMap_t) * count, hb_static); - gridSectors = (MapSubsectorEx**)Mem_Calloc(sizeof(MapSubsectorEx*) * - (int)(gridBlock.x * gridBlock.y), hb_static); + lumpFile.WriteFloat(surfaces[i]->lightmapCoords[0]); + lumpFile.WriteFloat(surfaces[i]->lightmapCoords[1]); - // process all grid cells - processed = 0; - kexWorker::RunJob(count, [=](int id) { - LightGrid(id); - }); + lumpFile.WriteFloat(surfaces[i]->lightmapCoords[4]); + lumpFile.WriteFloat(surfaces[i]->lightmapCoords[5]); - printf("\nGrid cells: %i\n\n", count); + lumpFile.WriteFloat(surfaces[i]->lightmapCoords[6]); + lumpFile.WriteFloat(surfaces[i]->lightmapCoords[7]); + + lumpFile.WriteFloat(surfaces[i]->lightmapCoords[2]); + lumpFile.WriteFloat(surfaces[i]->lightmapCoords[3]); + } + } + + // Write lightmap textures + for (unsigned int i = 0; i < textures.Length(); i++) + { + unsigned int count = (textureWidth * textureHeight) * 3; + for (unsigned int j = 0; j < count; j++) + { + lumpFile.Write16(textures[i][j]); + } + } + +#if 0 + // Apply compression predictor + uint8_t *texBytes = lumpFile.BufferAt() - texDataSize; + for (int i = texDataSize - 1; i > 0; i--) + { + texBytes[i] -= texBytes[i - 1]; + } +#endif + + // Compress and store in lump + ZLibOut zout(wadFile); + wadFile.StartWritingLump("LIGHTMAP"); + zout.Write(buffer.data(), lumpFile.BufferAt() - lumpFile.Buffer()); } -// -// kexLightmapBuilder::AddLightGridLump -// - -void kexLightmapBuilder::AddLightGridLump(FWadWriter &wadFile) -{ - kexBinFile lumpFile; - int lumpSize = 0; - int bit; - int bitmask; - byte *data; - - lumpSize = 28 + numLightGrids; - - for(int i = 0; i < numLightGrids; ++i) - { - if(gridMap[i].marked) - { - lumpSize += 4; - } - } - - lumpSize += 512; // add some extra slop - - data = (byte*)Mem_Calloc(lumpSize, hb_static); - lumpFile.SetBuffer(data); - - lumpFile.Write32(numLightGrids); - lumpFile.Write16((short)worldGrid.min[0]); - lumpFile.Write16((short)worldGrid.min[1]); - lumpFile.Write16((short)worldGrid.min[2]); - lumpFile.Write16((short)worldGrid.max[0]); - lumpFile.Write16((short)worldGrid.max[1]); - lumpFile.Write16((short)worldGrid.max[2]); - lumpFile.Write16((short)gridSize.x); - lumpFile.Write16((short)gridSize.y); - lumpFile.Write16((short)gridSize.z); - lumpFile.Write16((short)gridBlock.x); - lumpFile.Write16((short)gridBlock.y); - lumpFile.Write16((short)gridBlock.z); - - bit = 0; - bitmask = 0; - - for(int i = 0; i < numLightGrids; ++i) - { -#if 0 - bit |= (gridMap[i].marked << bitmask); - - if(++bitmask == 8) - { - lumpFile.Write8(bit); - bit = 0; - bitmask = 0; - } -#else - lumpFile.Write8(gridMap[i].marked); -#endif - } - -#if 0 - if(bit) - { - lumpFile.Write8(bit); - } -#endif - - for(int i = 0; i < numLightGrids; ++i) - { - if(gridMap[i].marked) - { - lumpFile.Write8((byte)(gridMap[i].color[0] * 255.0f)); - lumpFile.Write8((byte)(gridMap[i].color[1] * 255.0f)); - lumpFile.Write8((byte)(gridMap[i].color[2] * 255.0f)); - } - } - - bit = 0; - bitmask = 0; - - for(int i = 0; i < numLightGrids; ++i) - { - if(gridMap[i].marked) - { -#if 0 - bit |= (gridMap[i].sunShadow << bitmask); - bitmask += 2; - - if(bitmask >= 8) - { - lumpFile.Write8(bit); - bit = 0; - bitmask = 0; - } -#else - lumpFile.Write8(gridMap[i].sunShadow); -#endif - } - } - -#if 0 - if(bit) - { - lumpFile.Write8(bit); - } -#endif - - wadFile.WriteLump("LM_CELLS", data, lumpFile.BufferAt() - lumpFile.Buffer()); -} - -// -// kexLightmapBuilder::CreateLightmapLump -// - -void kexLightmapBuilder::AddLightmapLumps(FWadWriter &wadFile) -{ - int lumpSize = 0; - unsigned int i; - byte *data, *surfs, *txcrd, *lmaps; - int offs; - int size; - int j; - int coordOffsets; - kexBinFile lumpFile; - - // try to guess the actual lump size - lumpSize += ((textureWidth * textureHeight) * 3) * textures.Length(); - lumpSize += (12 * surfaces.Length()); - lumpSize += sizeof(kexVec3); - lumpSize += 2048; // add some extra slop - - for(i = 0; i < surfaces.Length(); i++) - { - lumpSize += (surfaces[i]->numVerts * 2) * sizeof(float); - } - - data = (byte*)Mem_Calloc(lumpSize, hb_static); - lumpFile.SetBuffer(data); - - lumpFile.WriteVector(map->GetSunDirection()); - wadFile.WriteLump("LM_SUN", data, sizeof(kexVec3)); - - offs = lumpFile.BufferAt() - lumpFile.Buffer(); - surfs = data + offs; - - coordOffsets = 0; - size = 0; - - // begin writing LM_SURFS lump - for(i = 0; i < surfaces.Length(); i++) - { - lumpFile.Write16(surfaces[i]->type); - lumpFile.Write16(surfaces[i]->typeIndex); - lumpFile.Write16(surfaces[i]->lightmapNum); - lumpFile.Write16(surfaces[i]->numVerts * 2); - lumpFile.Write32(coordOffsets); - - size += 12; - coordOffsets += (surfaces[i]->numVerts * 2); - } - - offs = lumpFile.BufferAt() - lumpFile.Buffer(); - wadFile.WriteLump("LM_SURFS", data, size); - txcrd = data + offs; - - size = 0; - - // begin writing LM_TXCRD lump - for(i = 0; i < surfaces.Length(); i++) - { - for(j = 0; j < surfaces[i]->numVerts * 2; j++) - { - lumpFile.WriteFloat(surfaces[i]->lightmapCoords[j]); - size += 4; - } - } - - offs = (lumpFile.BufferAt() - lumpFile.Buffer()) - offs; - wadFile.WriteLump("LM_TXCRD", txcrd, size); - lmaps = txcrd + offs; - - // begin writing LM_LMAPS lump - lumpFile.Write32(textures.Length()); - lumpFile.Write32(textureWidth); - lumpFile.Write32(textureHeight); - - size = 12; - - for(i = 0; i < textures.Length(); i++) - { - for(j = 0; j < (textureWidth * textureHeight) * 3; j++) - { - lumpFile.Write8(textures[i][j]); - size++; - } - } - - offs = (lumpFile.BufferAt() - lumpFile.Buffer()) - offs; - wadFile.WriteLump("LM_LMAPS", lmaps, size); -} - -// -// kexLightmapBuilder::WriteTexturesToTGA -// - void kexLightmapBuilder::WriteTexturesToTGA() { kexBinFile file; diff --git a/src/lightmap/lightmap.h b/src/lightmap/lightmap.h index 05113bc..f3396cf 100644 --- a/src/lightmap/lightmap.h +++ b/src/lightmap/lightmap.h @@ -43,14 +43,11 @@ public: void BuildSurfaceParams(surface_t *surface); void TraceSurface(surface_t *surface); - void CreateLightGrid(); void CreateLightmaps(FLevel &doomMap); void LightSurface(const int surfid); - void LightGrid(const int gridid); void WriteTexturesToTGA(); void WriteMeshToOBJ(); - void AddLightGridLump(FWadWriter &wadFile); - void AddLightmapLumps(FWadWriter &wadFile); + void AddLightmapLump(FWadWriter &wadFile); int samples; float ambience; @@ -64,30 +61,16 @@ private: bool MakeRoomForBlock(const int width, const int height, int *x, int *y, int *num); kexBBox GetBoundsFromSurface(const surface_t *surface); kexVec3 LightTexelSample(kexTrace &trace, const kexVec3 &origin, surface_t *surface); - kexVec3 LightCellSample(const int gridid, kexTrace &trace, const kexVec3 &origin, const MapSubsectorEx *sub); bool EmitFromCeiling(kexTrace &trace, const surface_t *surface, const kexVec3 &origin, const kexVec3 &normal, kexVec3 &color); void ExportTexelsToObjFile(FILE *f, const kexVec3 &org, int indices); void WriteBlock(FILE *f, const int i, const kexVec3 &org, int indices, kexBBox &box); - struct gridMap_t - { - byte marked; - byte sunShadow; - kexVec3 color; - }; - FLevel *map; - kexArray textures; + kexArray textures; int **allocBlocks; int numTextures; int extraSamples; int tracedTexels; - int numLightGrids; - gridMap_t *gridMap; - MapSubsectorEx **gridSectors; - kexBBox worldGrid; - kexBBox gridBound; - kexVec3 gridBlock; std::mutex mutex; int processed = 0; diff --git a/src/lightmap/lightsurface.cpp b/src/lightmap/lightsurface.cpp index a2e7046..c889d49 100644 --- a/src/lightmap/lightsurface.cpp +++ b/src/lightmap/lightsurface.cpp @@ -62,9 +62,6 @@ void kexLightSurface::Init(const surfaceLightDef &lightSurfaceDef, const bool bWall, const bool bNoCenterPoint) { - this->outerCone = lightSurfaceDef.outerCone; - this->innerCone = lightSurfaceDef.innerCone; - this->falloff = lightSurfaceDef.falloff; this->intensity = lightSurfaceDef.intensity; this->distance = lightSurfaceDef.distance; this->rgb = lightSurfaceDef.rgb; @@ -292,9 +289,6 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa { kexVec3 normal; kexVec3 lnormal; - kexVec3 center; - bool bInside; - float angle; float curDist; *dist = -M_INFINITY; @@ -306,29 +300,6 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa return true; } - bInside = false; - - // nudge the origin around to see if it's actually in the subsector - float nudges[4] = { -2, 2, -4, 4 }; - - for(int x = 0; x < 4; x++) - { - for(int y = 0; y < 4; y++) - { - if(doomMap->PointInsideSubSector(origin.x + nudges[x], - origin.y + nudges[y], surface->subSector)) - { - bInside = true; - break; - } - } - - if(bInside) - { - break; - } - } - lnormal = surface->plane.Normal(); if(surf) @@ -350,7 +321,7 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa // that we have to trace each one... which could really blow up the compile time for(unsigned int i = 0; i < origins.Length(); ++i) { - center = origins[i]; + kexVec3 center = origins[i]; if(!bWall && origin.z > center.z) { @@ -360,7 +331,7 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa continue; } - if(bWall) + /*if(bWall) { angle = (origin - center).ToVec2().Normalize().Dot(lnormal.ToVec2()); } @@ -378,18 +349,7 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa } angle = dir.Dot(lnormal); - - if(angle > innerCone) - { - angle = innerCone; - } - } - - if(!bInside && angle < outerCone) - { - // out of the cone range - continue; - } + }*/ if(bWall) { @@ -430,21 +390,6 @@ bool kexLightSurface::TraceSurface(FLevel *doomMap, kexTrace &trace, const surfa } } - // determine how much to fade out - if(angle < innerCone) - { - float div = (innerCone - outerCone); - - if(div != 0) - { - curDist *= ((angle - outerCone) / div); - } - else - { - curDist *= angle; - } - } - if(curDist > *dist) { *dist = curDist; diff --git a/src/lightmap/lightsurface.h b/src/lightmap/lightsurface.h index b92a5ef..d3081f3 100644 --- a/src/lightmap/lightsurface.h +++ b/src/lightmap/lightsurface.h @@ -44,9 +44,6 @@ public: void CreateCenterOrigin(); bool TraceSurface(FLevel *doomMap, kexTrace &trace, const surface_t *surface, const kexVec3 &origin, float *dist); - const float OuterCone() const { return outerCone; } - const float InnerCone() const { return innerCone; } - const float FallOff() const { return falloff; } const float Distance() const { return distance; } const float Intensity() const { return intensity; } const kexVec3 GetRGB() const { return rgb; } @@ -59,9 +56,6 @@ private: bool SubdivideRecursion(vertexBatch_t &surfPoints, float divide, kexArray &points); void Clip(vertexBatch_t &points, const kexVec3 &normal, float dist, vertexBatch_t *frontPoints, vertexBatch_t *backPoints); - float outerCone; - float innerCone; - float falloff; float distance; float intensity; kexVec3 rgb; diff --git a/src/lightmap/mapdata.cpp b/src/lightmap/mapdata.cpp index a0613f1..b4912c2 100644 --- a/src/lightmap/mapdata.cpp +++ b/src/lightmap/mapdata.cpp @@ -40,119 +40,14 @@ static const kexVec3 defaultSunDirection(0.45f, 0.3f, 0.9f); void FLevel::SetupDlight() { - BuildNodeBounds(); - BuildLeafs(); - BuildPVS(); CheckSkySectors(); } -void FLevel::BuildNodeBounds() -{ - int i; - int j; - kexVec3 point; - float high = -M_INFINITY; - float low = M_INFINITY; - - nodeBounds = (kexBBox*)Mem_Calloc(sizeof(kexBBox) * NumGLNodes, hb_static); - - for (i = 0; i < (int)Sectors.Size(); ++i) - { - if (Sectors[i].data.ceilingheight > high) - { - high = Sectors[i].data.ceilingheight; - } - if (Sectors[i].data.floorheight < low) - { - low = Sectors[i].data.floorheight; - } - } - - for (i = 0; i < NumGLNodes; ++i) - { - nodeBounds[i].Clear(); - - for (j = 0; j < 2; ++j) - { - point.Set(GLNodes[i].bbox[j][BOXLEFT], GLNodes[i].bbox[j][BOXBOTTOM], low); - nodeBounds[i].AddPoint(point); - point.Set(GLNodes[i].bbox[j][BOXRIGHT], GLNodes[i].bbox[j][BOXTOP], high); - nodeBounds[i].AddPoint(point); - } - } -} - -void FLevel::BuildLeafs() -{ - MapSubsectorEx *ss; - leaf_t *lf; - int i; - int j; - kexVec3 point; - IntSector *sector; - int count; - - leafs = (leaf_t*)Mem_Calloc(sizeof(leaf_t*) * NumGLSegs * 2, hb_static); - numLeafs = NumGLSubsectors; - - ss = GLSubsectors; - - segLeafLookup = (int*)Mem_Calloc(sizeof(int) * NumGLSegs, hb_static); - ssLeafLookup = (int*)Mem_Calloc(sizeof(int) * NumGLSubsectors, hb_static); - ssLeafCount = (int*)Mem_Calloc(sizeof(int) * NumGLSubsectors, hb_static); - ssLeafBounds = (kexBBox*)Mem_Calloc(sizeof(kexBBox) * NumGLSubsectors, hb_static); - - count = 0; - - for (i = 0; i < NumGLSubsectors; ++i, ++ss) - { - ssLeafCount[i] = ss->numlines; - ssLeafLookup[i] = ss->firstline; - - ssLeafBounds[i].Clear(); - sector = GetSectorFromSubSector(ss); - - if (ss->numlines) - { - for (j = 0; j < (int)ss->numlines; ++j) - { - MapSegGLEx *seg = &GLSegs[ss->firstline + j]; - lf = &leafs[count++]; - - segLeafLookup[ss->firstline + j] = i; - - lf->vertex = GetSegVertex(seg->v1); - lf->seg = seg; - - point.Set(lf->vertex.x, lf->vertex.y, sector->data.floorheight); - ssLeafBounds[i].AddPoint(point); - - point.z = sector->data.ceilingheight; - ssLeafBounds[i].AddPoint(point); - } - } - } -} - -void FLevel::BuildPVS() -{ - // don't do anything if already loaded - if (mapPVS != NULL) - { - return; - } - - int len = ((NumGLSubsectors + 7) / 8) * NumGLSubsectors; - mapPVS = (byte*)Mem_Malloc(len, hb_static); - memset(mapPVS, 0xff, len); -} - void FLevel::CheckSkySectors() { char name[9]; bSkySectors = (bool*)Mem_Calloc(sizeof(bool) * Sectors.Size(), hb_static); - bSSectsVisibleToSky = (bool*)Mem_Calloc(sizeof(bool) * NumGLSubsectors, hb_static); for (int i = 0; i < (int)Sectors.Size(); ++i) { @@ -167,27 +62,6 @@ void FLevel::CheckSkySectors() bSkySectors[i] = true; } } - - // try to early out by quickly checking which subsector can potentially - // see a sky sector - for (int i = 0; i < NumGLSubsectors; ++i) - { - for (int j = 0; j < NumGLSubsectors; ++j) - { - IntSector *sec = GetSectorFromSubSector(&GLSubsectors[j]); - - if (bSkySectors[sec - &Sectors[0]] == false) - { - continue; - } - - if (CheckPVS(&GLSubsectors[i], &GLSubsectors[j])) - { - bSSectsVisibleToSky[i] = true; - break; - } - } - } } const kexVec3 &FLevel::GetSunColor() const @@ -200,65 +74,41 @@ const kexVec3 &FLevel::GetSunDirection() const return defaultSunDirection; } -IntSideDef *FLevel::GetSideDef(const MapSegGLEx *seg) +IntSector *FLevel::GetFrontSector(const IntSideDef *side) { - if (seg->linedef == NO_LINE_INDEX) - { - // skip minisegs - return NULL; - } - - IntLineDef *line = &Lines[seg->linedef]; - return &Sides[line->sidenum[seg->side]]; -} - -IntSector *FLevel::GetFrontSector(const MapSegGLEx *seg) -{ - IntSideDef *side = GetSideDef(seg); - - if (side == NULL) - { - return NULL; - } - return &Sectors[side->sector]; } -IntSector *FLevel::GetBackSector(const MapSegGLEx *seg) +IntSector *FLevel::GetBackSector(const IntSideDef *side) { - if (seg->linedef == NO_LINE_INDEX) - { - // skip minisegs - return NULL; - } + IntLineDef *line = side->line; + if (!(line->flags & ML_TWOSIDED)) + return nullptr; - IntLineDef *line = &Lines[seg->linedef]; + int sidenum = (ptrdiff_t)(side - &Sides[0]); + if (line->sidenum[0] == sidenum) + sidenum = line->sidenum[1]; + else + sidenum = line->sidenum[0]; - if ((line->flags & ML_TWOSIDED) && line->sidenum[seg->side ^ 1] != 0xffffffff) - { - IntSideDef *backSide = &Sides[line->sidenum[seg->side ^ 1]]; - return &Sectors[backSide->sector]; - } + if (sidenum == NO_SIDE_INDEX) + return nullptr; - return NULL; + return GetFrontSector(&Sides[sidenum]); } IntSector *FLevel::GetSectorFromSubSector(const MapSubsectorEx *sub) { - IntSector *sector = NULL; - - // try to find a sector that the subsector belongs to for (int i = 0; i < (int)sub->numlines; i++) { MapSegGLEx *seg = &GLSegs[sub->firstline + i]; if (seg->side != NO_SIDE_INDEX) { - sector = GetFrontSector(seg); - break; + IntLineDef *line = &Lines[seg->linedef]; + return GetFrontSector(&Sides[line->sidenum[seg->side]]); } } - - return sector; + return nullptr; } MapSubsectorEx *FLevel::PointInSubSector(const int x, const int y) @@ -300,113 +150,6 @@ MapSubsectorEx *FLevel::PointInSubSector(const int x, const int y) return &GLSubsectors[nodenum & ~NFX_SUBSECTOR]; } -bool FLevel::PointInsideSubSector(const float x, const float y, const MapSubsectorEx *sub) -{ - surface_t *surf; - int i; - kexVec2 p(x, y); - kexVec2 dp1, dp2; - kexVec2 pt1, pt2; - - surf = leafSurfaces[0][sub - GLSubsectors]; - if (!surf) - return false; - - // check to see if the point is inside the subsector leaf - for (i = 0; i < surf->numVerts; i++) - { - pt1 = surf->verts[i].ToVec2(); - pt2 = surf->verts[(i + 1) % surf->numVerts].ToVec2(); - - dp1 = pt1 - p; - dp2 = pt2 - p; - - if (dp1.CrossScalar(dp2) < 0) - { - continue; - } - - // this point is outside the subsector leaf - return false; - } - - return true; -} - -bool FLevel::LineIntersectSubSector(const kexVec3 &start, const kexVec3 &end, const MapSubsectorEx *sub, kexVec2 &out) -{ - surface_t *surf; - kexVec2 p1, p2; - kexVec2 s1, s2; - kexVec2 pt; - kexVec2 v; - float d, u; - float newX; - float ab; - int i; - - surf = leafSurfaces[0][sub - GLSubsectors]; - p1 = start.ToVec2(); - p2 = end.ToVec2(); - - for (i = 0; i < surf->numVerts; i++) - { - s1 = surf->verts[i].ToVec2(); - s2 = surf->verts[(i + 1) % surf->numVerts].ToVec2(); - - if ((p1 == p2) || (s1 == s2)) - { - // zero length - continue; - } - - if ((p1 == s1) || (p2 == s1) || (p1 == s2) || (p2 == s2)) - { - // shares end point - continue; - } - - // translate to origin - pt = p2 - p1; - s1 -= p1; - s2 -= p1; - - // normalize - u = pt.UnitSq(); - d = kexMath::InvSqrt(u); - v = (pt * d); - - // rotate points s1 and s2 so they're on the positive x axis - newX = s1.Dot(v); - s1.y = s1.CrossScalar(v); - s1.x = newX; - - newX = s2.Dot(v); - s2.y = s2.CrossScalar(v); - s2.x = newX; - - if ((s1.y < 0 && s2.y < 0) || (s1.y >= 0 && s2.y >= 0)) - { - // s1 and s2 didn't cross - continue; - } - - ab = s2.x + (s1.x - s2.x) * s2.y / (s2.y - s1.y); - - if (ab < 0 || ab >(u * d)) - { - // s1 and s2 crosses but outside of points p1 and p2 - continue; - } - - // intersected - out = p1 + (v * ab); - return true; - } - - return false; -} - FloatVertex FLevel::GetSegVertex(int index) { if (index & 0x8000) @@ -420,19 +163,6 @@ FloatVertex FLevel::GetSegVertex(int index) return v; } -bool FLevel::CheckPVS(MapSubsectorEx *s1, MapSubsectorEx *s2) -{ - uint8_t *vis; - int n1, n2; - - n1 = s1 - GLSubsectors; - n2 = s2 - GLSubsectors; - - vis = &mapPVS[(((NumGLSubsectors + 7) / 8) * n1)]; - - return ((vis[n2 >> 3] & (1 << (n2 & 7))) != 0); -} - void FLevel::CreateLights() { thingLight_t *thingLight; @@ -514,12 +244,9 @@ void FLevel::CreateLights() { surface_t *surface = surfaces[j]; - if (surface->type >= ST_MIDDLESEG && surface->type <= ST_LOWERSEG) + if (surface->type >= ST_MIDDLESIDE && surface->type <= ST_LOWERSIDE) { - IntLineDef *line = nullptr; - if (GLSegs[surface->typeIndex].linedef != NO_LINE_INDEX) - line = &Lines[GLSegs[surface->typeIndex].linedef]; - + IntLineDef *line = Sides[surface->typeIndex].line; if (line) { uint32_t lightcolor = 0xffffff; @@ -547,9 +274,6 @@ void FLevel::CreateLights() { surfaceLightDef desc; desc.tag = 0; - desc.outerCone = 0.0f; - desc.innerCone = 0.0f; - desc.falloff = 1.0f; desc.intensity = lightintensity; desc.distance = lightdistance; desc.bIgnoreCeiling = false; @@ -569,7 +293,7 @@ void FLevel::CreateLights() } else if (surface->type == ST_FLOOR || surface->type == ST_CEILING) { - MapSubsectorEx *sub = surface->subSector; + MapSubsectorEx *sub = &GLSubsectors[surface->typeIndex]; IntSector *sector = GetSectorFromSubSector(sub); if (sector && surface->numVerts > 0) @@ -617,9 +341,6 @@ void FLevel::CreateLights() { surfaceLightDef desc; desc.tag = 0; - desc.outerCone = 0.0f; - desc.innerCone = 0.0f; - desc.falloff = 1.0f; desc.intensity = lightintensity; desc.distance = lightdistance; desc.bIgnoreCeiling = false; diff --git a/src/lightmap/surfaces.cpp b/src/lightmap/surfaces.cpp index 85abc87..79ae109 100644 --- a/src/lightmap/surfaces.cpp +++ b/src/lightmap/surfaces.cpp @@ -36,27 +36,26 @@ kexArray surfaces; -static void Surface_AllocateFromSeg(FLevel &doomMap, MapSegGLEx *seg) +static void Surface_AllocateFromSide(FLevel &doomMap, IntSideDef *side) { - IntSideDef *side; surface_t *surf; IntSector *front; IntSector *back; - if(seg->linedef == NO_LINE_INDEX) - { - return; - } - - side = doomMap.GetSideDef(seg); - front = doomMap.GetFrontSector(seg); - back = doomMap.GetBackSector(seg); + front = doomMap.GetFrontSector(side); + back = doomMap.GetBackSector(side); if (front->controlsector) return; - FloatVertex v1 = doomMap.GetSegVertex(seg->v1); - FloatVertex v2 = doomMap.GetSegVertex(seg->v2); + FloatVertex v1 = doomMap.GetSegVertex(side->line->v1); + FloatVertex v2 = doomMap.GetSegVertex(side->line->v2); + + if (side->line->sidenum[0] != (ptrdiff_t)(side - &doomMap.Sides[0])) + { + std::swap(v1, v2); + } + float v1Top = front->ceilingplane.zAt(v1.x, v1.y); float v1Bottom = front->floorplane.zAt(v1.x, v1.y); float v2Top = front->ceilingplane.zAt(v2.x, v2.y); @@ -94,12 +93,8 @@ static void Surface_AllocateFromSeg(FLevel &doomMap, MapSegGLEx *seg) surf->plane.SetNormal(surf->verts[0], surf->verts[1], surf->verts[2]); surf->plane.SetDistance(surf->verts[0]); - surf->type = ST_LOWERSEG; - surf->typeIndex = seg - doomMap.GLSegs; - surf->subSector = &doomMap.GLSubsectors[doomMap.segLeafLookup[seg - doomMap.GLSegs]]; - - doomMap.segSurfaces[1][surf->typeIndex] = surf; - surf->data = (MapSegGLEx*)seg; + surf->type = ST_LOWERSIDE; + surf->typeIndex = side - &doomMap.Sides[0]; surfaces.Push(surf); } @@ -140,13 +135,9 @@ static void Surface_AllocateFromSeg(FLevel &doomMap, MapSegGLEx *seg) surf->plane.SetNormal(surf->verts[0], surf->verts[1], surf->verts[2]); surf->plane.SetDistance(surf->verts[0]); - surf->type = ST_UPPERSEG; - surf->typeIndex = seg - doomMap.GLSegs; + surf->type = ST_UPPERSIDE; + surf->typeIndex = side - &doomMap.Sides[0]; surf->bSky = bSky; - surf->subSector = &doomMap.GLSubsectors[doomMap.segLeafLookup[seg - doomMap.GLSegs]]; - - doomMap.segSurfaces[2][surf->typeIndex] = surf; - surf->data = (MapSegGLEx*)seg; surfaces.Push(surf); } @@ -174,47 +165,34 @@ static void Surface_AllocateFromSeg(FLevel &doomMap, MapSegGLEx *seg) surf->plane.SetNormal(surf->verts[0], surf->verts[1], surf->verts[2]); surf->plane.SetDistance(surf->verts[0]); - surf->type = ST_MIDDLESEG; - surf->typeIndex = seg - doomMap.GLSegs; - surf->subSector = &doomMap.GLSubsectors[doomMap.segLeafLookup[seg - doomMap.GLSegs]]; - - doomMap.segSurfaces[0][surf->typeIndex] = surf; - surf->data = (MapSegGLEx*)seg; + surf->type = ST_MIDDLESIDE; + surf->typeIndex = side - &doomMap.Sides[0]; surfaces.Push(surf); } } -// -// Surface_AllocateFromLeaf -// -// Plane normals should almost always be known -// unless slopes are involved.... -// - static void Surface_AllocateFromLeaf(FLevel &doomMap) { surface_t *surf; - leaf_t *leaf; IntSector *sector = NULL; int i; int j; - printf("------------- Building leaf surfaces -------------\n"); - - doomMap.leafSurfaces[0] = (surface_t**)Mem_Calloc(sizeof(surface_t*) * doomMap.NumGLSubsectors, hb_static); - doomMap.leafSurfaces[1] = (surface_t**)Mem_Calloc(sizeof(surface_t*) * doomMap.NumGLSubsectors, hb_static); + printf("------------- Building subsector surfaces -------------\n"); for(i = 0; i < doomMap.NumGLSubsectors; i++) { printf("subsectors: %i / %i\r", i+1, doomMap.NumGLSubsectors); - if(doomMap.ssLeafCount[i] < 3) + MapSubsectorEx *sub = &doomMap.GLSubsectors[i]; + + if(sub->numlines < 3) { continue; } - sector = doomMap.GetSectorFromSubSector(&doomMap.GLSubsectors[i]); + sector = doomMap.GetSectorFromSubSector(sub); // I will be NOT surprised if some users tries to do something stupid with // sector hacks @@ -228,17 +206,17 @@ static void Surface_AllocateFromLeaf(FLevel &doomMap) continue; surf = (surface_t*)Mem_Calloc(sizeof(surface_t), hb_static); - surf->numVerts = doomMap.ssLeafCount[i]; + surf->numVerts = sub->numlines; surf->verts = (kexVec3*)Mem_Calloc(sizeof(kexVec3) * surf->numVerts, hb_static); - surf->subSector = &doomMap.GLSubsectors[i]; // floor verts for(j = 0; j < surf->numVerts; j++) { - leaf = &doomMap.leafs[doomMap.ssLeafLookup[i] + (surf->numVerts - 1) - j]; + MapSegGLEx *seg = &doomMap.GLSegs[sub->firstline + (surf->numVerts - 1) - j]; + FloatVertex v1 = doomMap.GetSegVertex(seg->v1); - surf->verts[j].x = leaf->vertex.x; - surf->verts[j].y = leaf->vertex.y; + surf->verts[j].x = v1.x; + surf->verts[j].y = v1.y; surf->verts[j].z = sector->floorplane.zAt(surf->verts[j].x, surf->verts[j].y); } @@ -246,15 +224,11 @@ static void Surface_AllocateFromLeaf(FLevel &doomMap) surf->type = ST_FLOOR; surf->typeIndex = i; - doomMap.leafSurfaces[0][i] = surf; - surf->data = (IntSector*)sector; - surfaces.Push(surf); surf = (surface_t*)Mem_Calloc(sizeof(surface_t), hb_static); - surf->numVerts = doomMap.ssLeafCount[i]; + surf->numVerts = sub->numlines; surf->verts = (kexVec3*)Mem_Calloc(sizeof(kexVec3) * surf->numVerts, hb_static); - surf->subSector = &doomMap.GLSubsectors[i]; if(doomMap.bSkySectors[sector-&doomMap.Sectors[0]]) { @@ -264,10 +238,11 @@ static void Surface_AllocateFromLeaf(FLevel &doomMap) // ceiling verts for(j = 0; j < surf->numVerts; j++) { - leaf = &doomMap.leafs[doomMap.ssLeafLookup[i] + j]; + MapSegGLEx *seg = &doomMap.GLSegs[sub->firstline + j]; + FloatVertex v1 = doomMap.GetSegVertex(seg->v1); - surf->verts[j].x = leaf->vertex.x; - surf->verts[j].y = leaf->vertex.y; + surf->verts[j].x = v1.x; + surf->verts[j].y = v1.y; surf->verts[j].z = sector->ceilingplane.zAt(surf->verts[j].x, surf->verts[j].y); } @@ -275,9 +250,6 @@ static void Surface_AllocateFromLeaf(FLevel &doomMap) surf->type = ST_CEILING; surf->typeIndex = i; - doomMap.leafSurfaces[1][i] = surf; - surf->data = (IntSector*)sector; - surfaces.Push(surf); } @@ -306,20 +278,26 @@ void Surface_AllocateFromMap(FLevel &doomMap) Mem_Free(surfaces[i]); surfaces = {}; - doomMap.segSurfaces[0] = (surface_t**)Mem_Calloc(sizeof(surface_t*) * doomMap.NumGLSegs, hb_static); - doomMap.segSurfaces[1] = (surface_t**)Mem_Calloc(sizeof(surface_t*) * doomMap.NumGLSegs, hb_static); - doomMap.segSurfaces[2] = (surface_t**)Mem_Calloc(sizeof(surface_t*) * doomMap.NumGLSegs, hb_static); - for (unsigned int i = 0; i < doomMap.Sectors.Size(); i++) doomMap.Sectors[i].controlsector = false; + for (unsigned int i = 0; i < doomMap.Sides.Size(); i++) + doomMap.Sides[i].line = nullptr; + for (unsigned int i = 0; i < doomMap.Lines.Size(); i++) { - const auto &line = doomMap.Lines[i]; - if (line.special == 160) // Sector_Set3dFloor + IntLineDef *line = &doomMap.Lines[i]; + + // Link sides to lines + if (line->sidenum[0] < doomMap.Sides.Size()) + doomMap.Sides[line->sidenum[0]].line = line; + if (line->sidenum[1] < doomMap.Sides.Size()) + doomMap.Sides[line->sidenum[1]].line = line; + + if (line->special == 160) // Sector_Set3dFloor { - int sectorTag = line.args[0]; - int type = line.args[1]; + int sectorTag = line->args[0]; + int type = line->args[1]; //int opacity = line.args[3]; IntSector *controlsector = &doomMap.Sectors[doomMap.Sides[doomMap.Lines[i].sidenum[0]].sector]; @@ -337,13 +315,13 @@ void Surface_AllocateFromMap(FLevel &doomMap) printf("------------- Building seg surfaces -------------\n"); - for(int i = 0; i < doomMap.NumGLSegs; i++) + for(unsigned int i = 0; i < doomMap.Sides.Size(); i++) { - Surface_AllocateFromSeg(doomMap, &doomMap.GLSegs[i]); - printf("segs: %i / %i\r", i+1, doomMap.NumGLSegs); + Surface_AllocateFromSide(doomMap, &doomMap.Sides[i]); + printf("sides: %i / %i\r", i+1, doomMap.Sides.Size()); } - printf("\nSeg surfaces: %i\n", surfaces.Length()); + printf("\nSide surfaces: %i\n", surfaces.Length()); Surface_AllocateFromLeaf(doomMap); @@ -373,7 +351,7 @@ void Surface_AllocateFromMap(FLevel &doomMap) } } } - else if (s->type == ST_MIDDLESEG || s->type == ST_UPPERSEG || s->type == ST_LOWERSEG) + else if (s->type == ST_MIDDLESIDE || s->type == ST_UPPERSIDE || s->type == ST_LOWERSIDE) { if (!IsDegenerate(s->verts[0], s->verts[1], s->verts[2])) { diff --git a/src/lightmap/surfaces.h b/src/lightmap/surfaces.h index 2f0754c..f113058 100644 --- a/src/lightmap/surfaces.h +++ b/src/lightmap/surfaces.h @@ -32,9 +32,9 @@ struct MapSubsectorEx; enum surfaceType_t { ST_UNKNOWN = 0, - ST_MIDDLESEG, - ST_UPPERSEG, - ST_LOWERSEG, + ST_MIDDLESIDE, + ST_UPPERSIDE, + ST_LOWERSIDE, ST_CEILING, ST_FLOOR }; @@ -59,9 +59,9 @@ struct surface_t float *lightmapCoords; surfaceType_t type; int typeIndex; - void *data; + //void *data; bool bSky; - MapSubsectorEx *subSector; + //MapSubsectorEx *subSector; }; extern kexArray surfaces; diff --git a/src/lightmap/trace.cpp b/src/lightmap/trace.cpp index 278c2dc..93328c4 100644 --- a/src/lightmap/trace.cpp +++ b/src/lightmap/trace.cpp @@ -35,36 +35,11 @@ #include "mapdata.h" #include "trace.h" -// -// kexTrace::kexTrace -// - -kexTrace::kexTrace() -{ - this->map = NULL; -} - -// -// kexTrace::~kexTrace -// - -kexTrace::~kexTrace() -{ -} - -// -// kexTrace::Init -// - void kexTrace::Init(FLevel &doomMap) { map = &doomMap; } -// -// kexTrace::Trace -// - void kexTrace::Trace(const kexVec3 &startVec, const kexVec3 &endVec) { start = startVec; @@ -76,223 +51,4 @@ void kexTrace::Trace(const kexVec3 &startVec, const kexVec3 &endVec) hitSurface = surfaces[hit.surface]; else hitSurface = nullptr; - -/* - dir = (end - start).Normalize(); - hitNormal.Clear(); - hitVector.Clear(); - hitSurface = NULL; - fraction = 1; - - if(map == NULL) - { - return; - } - - TraceBSPNode(map->NumGLNodes - 1); -*/ } - -#if 0 -// -// kexTrace::TraceSurface -// - -void kexTrace::TraceSurface(surface_t *surface) -{ - kexPlane *plane; - kexVec3 hit; - kexVec3 edge1; - kexVec3 edge2; - kexVec3 normal; - float d1; - float d2; - float d; - float frac; - int i; - kexPluecker r; - - if(surface == NULL) - { - return; - } - - plane = &surface->plane; - - d1 = plane->Distance(start) - plane->d; - d2 = plane->Distance(end) - plane->d; - - if(d1 <= d2 || d1 < 0 || d2 > 0) - { - // trace is either completely in front or behind the plane - return; - } - - frac = (d1 / (d1 - d2)); - - if(frac > 1 || frac < 0) - { - // not a valid contact - return; - } - - if(frac >= fraction) - { - // farther than the current contact - return; - } - - hit = start.Lerp(end, frac); - normal = plane->Normal(); - - r.SetRay(start, dir); - - // segs are always made up of 4 vertices, so its safe to assume 4 edges here - if(surface->type >= ST_MIDDLESEG && surface->type <= ST_LOWERSEG) - { - kexPluecker p1; - kexPluecker p2; - kexPluecker p3; - kexPluecker p4; - byte sideBits = 0; - - p1.SetLine(surface->verts[2], surface->verts[3]); // top edge - p2.SetLine(surface->verts[1], surface->verts[0]); // bottom edge - p3.SetLine(surface->verts[3], surface->verts[1]); // right edge - p4.SetLine(surface->verts[0], surface->verts[2]); // left edge - - // this sucks so much..... I am surprised this even works at all - d = r.InnerProduct(p1)-0.001f; - sideBits |= (FLOATSIGNBIT(d) << 0); - d = r.InnerProduct(p2)-0.001f; - sideBits |= (FLOATSIGNBIT(d) << 1); - d = r.InnerProduct(p3)-0.001f; - sideBits |= (FLOATSIGNBIT(d) << 2); - d = r.InnerProduct(p4)-0.001f; - sideBits |= (FLOATSIGNBIT(d) << 3); - - if(sideBits != 0xF) - { - return; - } - } - else if(surface->type == ST_FLOOR || surface->type == ST_CEILING) - { - kexPluecker p; - kexVec3 v1; - kexVec3 v2; - - for(i = 0; i < surface->numVerts; i++) - { - v1 = surface->verts[i]; - v2 = surface->verts[(i+1)%surface->numVerts]; - - p.SetLine(v2, v1); - - if(r.InnerProduct(p) > 0.01f) - { - return; - } - } - } - - hitNormal = normal; - hitVector = hit; - hitSurface = surface; - fraction = frac; -} - -// -// kexTrace::TraceSubSector -// - -void kexTrace::TraceSubSector(int num) -{ - MapSubsectorEx *sub; - int i; - int j; - - sub = &map->GLSubsectors[num]; - - if(!map->ssLeafBounds[num].LineIntersect(start, end)) - { - return; - } - - // test line segments - for(i = 0; i < (int)sub->numlines; i++) - { - int segnum = sub->firstline + i; - - for(j = 0; j < 3; j++) - { - if(j == 0) - { - int linenum = map->GLSegs[segnum].linedef; - - if(linenum != NO_LINE_INDEX && map->Lines[linenum].flags & (ML_TWOSIDED|ML_TRANSPARENT1|ML_TRANSPARENT2)) - { - // don't trace transparent 2-sided lines - continue; - } - } - TraceSurface(map->segSurfaces[j][segnum]); - } - } - - // test subsector leafs - for(j = 0; j < 2; j++) - { - TraceSurface(map->leafSurfaces[j][num]); - } -} - -// -// kexTrace::TraceBSPNode -// - -void kexTrace::TraceBSPNode(int num) -{ - MapNodeEx *node; - kexVec3 dp1; - kexVec3 dp2; - float d; - byte side; - - if(num & NFX_SUBSECTOR) - { - TraceSubSector(num & (~NFX_SUBSECTOR)); - return; - } - - if(!map->nodeBounds[num & (~NFX_SUBSECTOR)].LineIntersect(start, end)) - { - return; - } - - node = &map->GLNodes[num]; - - kexVec3 pt1(F(node->x), F(node->y), 0); - kexVec3 pt2(F(node->dx), F(node->dy), 0); - //kexVec3 pt1(F(node->x << 16), F(node->y << 16), 0); - //kexVec3 pt2(F(node->dx << 16), F(node->dy << 16), 0); - - dp1 = pt1 - start; - dp2 = (pt2 + pt1) - start; - d = dp1.Cross(dp2).z; - - side = FLOATSIGNBIT(d); - - TraceBSPNode(node->children[side ^ 1]); - - dp1 = pt1 - end; - dp2 = (pt2 + pt1) - end; - d = dp1.Cross(dp2).z; - - // don't trace if both ends of the ray are on the same side - if(side != FLOATSIGNBIT(d)) - { - TraceBSPNode(node->children[side]); - } -} -#endif diff --git a/src/lightmap/trace.h b/src/lightmap/trace.h index 58875de..f4f44ca 100644 --- a/src/lightmap/trace.h +++ b/src/lightmap/trace.h @@ -32,9 +32,6 @@ struct FLevel; class kexTrace { public: - kexTrace(); - ~kexTrace(); - void Init(FLevel &doomMap); void Trace(const kexVec3 &startVec, const kexVec3 &endVec); @@ -44,15 +41,5 @@ public: float fraction; private: - FLevel *map; - -#if 0 - kexVec3 dir; - kexVec3 hitNormal; - kexVec3 hitVector; - - void TraceBSPNode(int num); - void TraceSubSector(int num); - void TraceSurface(surface_t *surface); -#endif + FLevel *map = nullptr; }; diff --git a/src/main.cpp b/src/main.cpp index b30bb1e..5774601 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -763,230 +763,3 @@ const int64_t GetSeconds() { return time(0); } - -#if 0 // Old dlight main function - -int main(int argc, char **argv) -{ - kexWadFile wadFile; - kexWadFile outWadFile; - FLevel doomMap; - lump_t *lmLump; - kexArray ignoreLumps; - kexLightmapBuilder builder; - kexStr configFile("strife_sve.cfg"); - bool bWriteTGA; - int map = 1; - int arg = 1; - - printf("DLight (c) 2013-2014 Samuel Villarreal\n\n"); - - if (argc < 1 || argv[1] == NULL) - { - printf("Usage: dlight [options] [wadfile]\n"); - printf("Use -help for list of options\n"); - return 0; - } - - basePath = argv[0]; - basePath.StripFile(); - - bWriteTGA = false; - - while (1) - { - if (!strcmp(argv[arg], "-help")) - { - printf("Options:\n"); - printf("-help: displays all known options\n"); - printf("-map: process lightmap for MAP##\n"); - printf("-samples: set texel sampling size (lowest = higher quaility but\n"); - printf(" slow compile time) must be in powers of two\n"); - printf("-ambience: set global ambience value for lightmaps (0.0 - 1.0)\n"); - printf("-size: lightmap texture dimentions for width and height\n"); - printf(" must be in powers of two (1, 2, 4, 8, 16, etc)\n"); - printf("-threads: set total number of threads (1 min, 128 max)\n"); - printf("-config: specify a config file to parse (default: strife_sve.cfg)\n"); - printf("-writetga: dumps lightmaps to targa (.TGA) files\n"); - arg++; - return 0; - } - else if (!strcmp(argv[arg], "-map")) - { - if (argv[arg + 1] == NULL) - { - Error("Specify map number for -map\n"); - return 1; - } - - map = atoi(argv[++arg]); - arg++; - } - else if (!strcmp(argv[arg], "-samples")) - { - if (argv[arg + 1] == NULL) - { - Error("Specify value for -samples\n"); - return 1; - } - - builder.samples = atoi(argv[++arg]); - if (builder.samples <= 0) - { - builder.samples = 1; - } - if (builder.samples > 128) - { - builder.samples = 128; - } - - builder.samples = kexMath::RoundPowerOfTwo(builder.samples); - arg++; - } - else if (!strcmp(argv[arg], "-ambience")) - { - if (argv[arg + 1] == NULL) - { - Error("Specify value for -ambience\n"); - return 1; - } - - builder.ambience = (float)atof(argv[++arg]); - if (builder.ambience < 0) - { - builder.ambience = 0; - } - if (builder.ambience > 1) - { - builder.ambience = 1; - } - } - else if (!strcmp(argv[arg], "-size")) - { - int lmDims; - - if (argv[arg + 1] == NULL) - { - Error("Specify value for -size\n"); - return 1; - } - - lmDims = atoi(argv[++arg]); - if (lmDims <= 0) - { - lmDims = 1; - } - if (lmDims > LIGHTMAP_MAX_SIZE) - { - lmDims = LIGHTMAP_MAX_SIZE; - } - - lmDims = kexMath::RoundPowerOfTwo(lmDims); - - builder.textureWidth = lmDims; - builder.textureHeight = lmDims; - arg++; - } - else if (!strcmp(argv[arg], "-threads")) - { - kexWorker::maxWorkThreads = atoi(argv[++arg]); - kexMath::Clamp(kexWorker::maxWorkThreads, 1, MAX_THREADS); - arg++; - } - else if (!strcmp(argv[arg], "-config")) - { - configFile = argv[++arg]; - arg++; - } - else if (!strcmp(argv[arg], "-writetga")) - { - bWriteTGA = true; - arg++; - } - else - { - break; - } - } - - if (argv[arg] == NULL) - { - printf("Usage: dlight [options] [wadfile]\n"); - return 0; - } - - if (!wadFile.Open(argv[arg])) - { - return 1; - } - - // concat the base path to light def file if there is none - if (configFile.IndexOf("\\") == -1 && configFile.IndexOf("/") == -1) - { - configFile = basePath + configFile; - } - - int starttime = (int)GetSeconds(); - - printf("---------------- Parsing config file ----------------\n\n"); - doomMap.ParseConfigFile(configFile.c_str()); - - printf("------------- Building level structures -------------\n\n"); - wadFile.SetCurrentMap(map); - doomMap.BuildMapFromWad(wadFile); - - printf("----------- Allocating surfaces from level ----------\n\n"); - Surface_AllocateFromMap(doomMap); - - printf("---------------- Allocating lights ----------------\n\n"); - doomMap.CreateLights(); - - printf("---------------- Creating lightmaps ---------------\n\n"); - builder.CreateLightmaps(doomMap); - doomMap.CleanupThingLights(); - - if (bWriteTGA) - { - builder.WriteTexturesToTGA(); - } - - printf("------------------ Rebuilding wad ----------------\n\n"); - wadFile.CreateBackup(); - - lmLump = wadFile.GetLumpFromName(Va("LM_MAP%02d", wadFile.currentmap)); - - if (lmLump) - { - int lumpnum = lmLump - wadFile.lumps; - - ignoreLumps.Push(lumpnum + ML_LM_LABEL); - ignoreLumps.Push(lumpnum + ML_LM_CELLS); - ignoreLumps.Push(lumpnum + ML_LM_SUN); - ignoreLumps.Push(lumpnum + ML_LM_SURFS); - ignoreLumps.Push(lumpnum + ML_LM_TXCRD); - ignoreLumps.Push(lumpnum + ML_LM_LMAPS); - } - - outWadFile.InitForWrite(); - outWadFile.CopyLumpsFromWadFile(wadFile, ignoreLumps); - outWadFile.AddLump(Va("LM_MAP%02d", wadFile.currentmap), 0, NULL); - - builder.AddLightGridLump(outWadFile); - builder.AddLightmapLumps(outWadFile); - - printf("------------- Writing %s -------------\n\n", wadFile.wadName.c_str()); - outWadFile.Write(wadFile.wadName); - outWadFile.Close(); - wadFile.Close(); - - printf("----------------- Shutting down -----------------\n\n"); - Mem_Purge(hb_static); - - int proctime = (int)GetSeconds() - starttime; - printf("\nBuild time: %d:%02d:%02d\n", - proctime / 3600, (proctime / 60) % 60, proctime % 60); - - return 0; -} - -#endif