├── .gitignore ├── CMakeLists.txt └── gpua_rad ├── basetypes.h ├── bsp.cpp ├── bsp.h ├── bspfile.h ├── bspflags.h ├── datamap.h ├── loadbsp.cu ├── main.cpp ├── poly.cpp ├── poly.h ├── prettyprint.cpp ├── prettyprint.h ├── rad.cpp ├── rad.h ├── raytrace.cpp ├── raytrace.h ├── script.cpp ├── script.h ├── timer.cpp ├── timer.h ├── trace.cpp ├── trace.h ├── vector.cpp ├── vector.h ├── vmatrix.h └── worldsize.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Files to ignore when considering what GIT should commit. 2 | 3 | # Visual Studio 4 | *.suo 5 | *.user 6 | *.sln.docstates 7 | *.obj 8 | *.pch 9 | *.tlog 10 | *.log 11 | *.scc 12 | *.exp 13 | *.ilk 14 | *.lastbuildstate 15 | vc100.pdb 16 | ipch 17 | *.sdf 18 | *.opensdf 19 | *.idb 20 | *.vcxproj 21 | *.sln 22 | *.sentinel 23 | *.vpc_crc 24 | *.vcxproj.filters 25 | *.pdb 26 | *.lib 27 | 28 | # Visual Studio 2017 29 | *.VC.db 30 | *.VC.opendb 31 | *.VC.db-shm 32 | *.VC.db-wal 33 | 34 | # OSX/Linux build products 35 | *.mak 36 | *.mak.vpc_crc 37 | *.xcodeproj/ 38 | *.project 39 | obj*/ 40 | !devtools/*.mak 41 | !utils/smdlexp/smdlexp.mak 42 | *.a 43 | *.dylib 44 | *.plist 45 | 46 | # Specific Source build products 47 | 48 | Debug/ 49 | Release/ 50 | Release_*momentum/ 51 | Debug_*momentum/ 52 | save/ 53 | cmake*/ 54 | 55 | # files generated by running a mod 56 | *.ain 57 | stats.txt 58 | voice_ban.dt 59 | *.dem 60 | 61 | # shader files 62 | *.tmp 63 | 64 | # Others 65 | *.cache 66 | *.jpg 67 | *.prt 68 | *.vmx 69 | *.lin 70 | *.vdf 71 | *.pch.ib_tag 72 | *.ib_pdb_index 73 | *.cfg 74 | .idea/ 75 | *.exe 76 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | project(GPU_VRAD) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | include_directories(gpua_rad) 7 | 8 | add_executable(GPU_VRAD 9 | gpua_rad/basetypes.h 10 | gpua_rad/bsp.cpp 11 | gpua_rad/bsp.h 12 | gpua_rad/bspfile.h 13 | gpua_rad/bspflags.h 14 | gpua_rad/datamap.h 15 | gpua_rad/main.cpp 16 | gpua_rad/poly.cpp 17 | gpua_rad/poly.h 18 | gpua_rad/prettyprint.cpp 19 | gpua_rad/prettyprint.h 20 | gpua_rad/rad.cpp 21 | gpua_rad/rad.h 22 | gpua_rad/raytrace.cpp 23 | gpua_rad/raytrace.h 24 | gpua_rad/script.cpp 25 | gpua_rad/script.h 26 | gpua_rad/timer.cpp 27 | gpua_rad/timer.h 28 | gpua_rad/trace.cpp 29 | gpua_rad/trace.h 30 | gpua_rad/vector.cpp 31 | gpua_rad/vector.h 32 | gpua_rad/vmatrix.h 33 | gpua_rad/worldsize.h) 34 | -------------------------------------------------------------------------------- /gpua_rad/basetypes.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPUARAD_BASETYPES_H 2 | #define _GPUARAD_BASETYPES_H 3 | 4 | typedef int qboolean; 5 | 6 | #endif // _GPUARAD_BASETYPES_H 7 | -------------------------------------------------------------------------------- /gpua_rad/bsp.cpp: -------------------------------------------------------------------------------- 1 | #include "bsp.h" 2 | 3 | CBSP::CBSP(const char * filename) 4 | { 5 | pp::Info("CBSP::CBSP(const char * filename)"); 6 | memset(&m_Lumps, 0, sizeof(m_Lumps)); 7 | 8 | std::ifstream ifs(filename, std::ios::ate | std::ios::binary); 9 | 10 | if (!ifs) 11 | { 12 | pp::Error("Couldn't open bsp file %s.", filename); 13 | } 14 | 15 | std::streamsize size = ifs.tellg(); 16 | ifs.seekg(0, std::ios::beg); 17 | 18 | m_bspData = new uint8_t[size]; 19 | m_bspHdr = (dheader_t*)m_bspData; 20 | 21 | if (ifs.read((char*)m_bspData, size)) 22 | { 23 | pp::Success("Loaded %lli bytes from %s", size, filename); 24 | } 25 | 26 | m_szFilename = filename; 27 | ifs.close(); 28 | } 29 | 30 | CBSP::~CBSP() 31 | { 32 | pp::Info("CBSP::~CBSP()"); 33 | delete[] m_bspData; 34 | } 35 | 36 | void CBSP::LoadBSP() 37 | { 38 | pp::Info("LoadBSP()"); 39 | m_iMapRevision = m_bspHdr->mapRevision; 40 | 41 | if (!ValidateHeader(m_bspHdr)) 42 | { 43 | return; 44 | } 45 | 46 | pp::Success("Found valid BSP header - map revision %i", m_iMapRevision); 47 | 48 | CopyLump(LUMP_ENTITIES, m_vEntData); // 0 49 | m_iNumPlanes = CopyLump(LUMP_PLANES, m_dPlanes, sizeof(*m_dPlanes), MAX_MAP_PLANES); // 1 50 | m_iNumTexData = CopyLump(LUMP_TEXDATA, m_dTexData, sizeof(*m_dTexData), MAX_MAP_TEXDATA); // 1 51 | m_iNumVertexes = CopyLump(LUMP_VERTEXES, m_dVertexes, sizeof(*m_dVertexes), MAX_MAP_VERTS); // 3 52 | m_iVisDataSize = CopyLump(LUMP_VISIBILITY, m_dVisData, sizeof(*m_dVisData), MAX_MAP_VISIBILITY); // 4 53 | m_dVis = (dvis_t *)m_dVisData; 54 | m_iNumNodes = CopyLump(LUMP_NODES, m_dNodes, sizeof(*m_dNodes), MAX_MAP_NODES); // 5 55 | m_iNumTexInfos = CopyLump(LUMP_TEXINFO, m_dTexInfos, sizeof(*m_dTexInfos), MAX_MAP_TEXINFO); // 6 56 | m_iNumFaces = CopyLump(LUMP_FACES, m_dFaces, sizeof(*m_dFaces), MAX_MAP_FACES); // 7 57 | CopyLump(LUMP_LIGHTING, m_vLightDataLDR); // 8 58 | 59 | m_iNumLeafs = CopyLump(LUMP_LEAFS, m_dLeafs, sizeof(*m_dLeafs), MAX_MAP_LEAFS); // 10 60 | CopyLump(LUMP_FACEIDS, m_vFaceIds); // 11 61 | m_iNumEdges = CopyLump(LUMP_EDGES, m_dEdges, sizeof(*m_dEdges), MAX_MAP_EDGES); // 12 62 | m_iNumSurfEdges = CopyLump(LUMP_SURFEDGES, m_dSurfEdges, sizeof(*m_dSurfEdges), MAX_MAP_SURFEDGES); // 13 63 | m_iNumModels = CopyLump(LUMP_MODELS, m_dModels, sizeof(*m_dModels), MAX_MAP_MODELS); // 14 64 | m_iNumWorldLightsLDR = CopyLump(LUMP_WORLDLIGHTS, m_dWorldLightsLDR, sizeof(*m_dWorldLightsLDR), MAX_MAP_WORLDLIGHTS); // 15 65 | m_iNumLeafFaces = CopyLump(LUMP_LEAFFACES, m_dLeafFaces, sizeof(*m_dLeafFaces), MAX_MAP_LEAFFACES); // 16 66 | m_iNumLeafBrushes = CopyLump(LUMP_LEAFBRUSHES, m_dLeafBrushes, sizeof(*m_dLeafBrushes), MAX_MAP_LEAFBRUSHES); // 17 67 | m_iNumBrushes = CopyLump(LUMP_BRUSHES, m_dBrushes, sizeof(*m_dBrushes), MAX_MAP_BRUSHES); // 18 68 | m_iNumBrushSides = CopyLump(LUMP_BRUSHSIDES, m_dBrushSides, sizeof(*m_dBrushSides), MAX_MAP_BRUSHSIDES); // 19 69 | m_iNumAreas = CopyLump(LUMP_AREAS, m_dAreas, sizeof(*m_dAreas), MAX_MAP_AREAS); // 20 70 | m_iNumAreaPortals = CopyLump(LUMP_AREAPORTALS, m_dAreaPortals, sizeof(*m_dAreaPortals), MAX_MAP_AREAPORTALS); // 21 71 | 72 | CopyLump(LUMP_DISPINFO, m_vDispInfos); // 26 73 | 74 | m_iNumOrigFaces = CopyLump(LUMP_ORIGINALFACES, m_dOrigFaces, sizeof(*m_dOrigFaces), MAX_MAP_FACES); // 27 75 | 76 | CopyLump(LUMP_PHYSDISP, m_vPhysDisp); // 28 77 | CopyLump(LUMP_PHYSCOLLIDE, m_vPhysCollide); // 29 78 | m_iNumVertNormals = CopyLump(LUMP_VERTNORMALS, m_dVertNormals, sizeof(*m_dVertNormals), MAX_MAP_VERTNORMALS); // 30 79 | m_iNumVertNormalIndices = CopyLump(LUMP_VERTNORMALINDICES, m_dVertNormalIndices, sizeof(*m_dVertNormalIndices), MAX_MAP_VERTNORMALS); // 31 80 | 81 | CopyLump(LUMP_DISP_VERTS, m_vDispVerts); // 33 82 | CopyLump(LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS, m_vNumDispLightmapSamplePositions); // 34 83 | 84 | m_iNumLeafWaterData = CopyLump(LUMP_LEAFWATERDATA, m_dLeafWaterData, sizeof(*m_dLeafWaterData), MAX_MAP_LEAFWATERDATA); // 36 85 | m_iNumPrimitives = CopyLump(LUMP_PRIMITIVES, m_dPrimitives, sizeof(*m_dPrimitives), MAX_MAP_PRIMITIVES); // 37 86 | m_iNumPrimverts = CopyLump(LUMP_PRIMVERTS, m_dPrimverts, sizeof(*m_dPrimverts), MAX_MAP_PRIMVERTS); // 38 87 | m_iNumPrimindices = CopyLump(LUMP_PRIMINDICES, m_dPrimindices, sizeof(*m_dPrimindices), MAX_MAP_PRIMINDICES); // 39 88 | // LUMP_PAKFILE TODO 89 | m_iNumClipPortalVerts = CopyLump(LUMP_CLIPPORTALVERTS, m_dClipPortalVerts, sizeof(*m_dClipPortalVerts), MAX_MAP_PORTALVERTS); // 41 90 | m_iNumCubemapSamples = CopyLump(LUMP_CUBEMAPS, m_dCubemapSamples, sizeof(*m_dCubemapSamples), MAX_MAP_CUBEMAPSAMPLES); // 42 91 | CopyLump(LUMP_TEXDATA_STRING_DATA, m_vTexDataStringData); // 43 92 | CopyLump(LUMP_TEXDATA_STRING_TABLE, m_vTexDataStringTable); // 44 93 | m_iNumOverlayCount = CopyLump(LUMP_OVERLAYS, m_dOverlays, sizeof(*m_dOverlays), MAX_MAP_OVERLAYS); // 45 94 | m_iNumLeafMinDistToWater = CopyLump(LUMP_LEAFMINDISTTOWATER, m_dLeafMinDistToWater, sizeof(*m_dLeafMinDistToWater), MAX_MAP_LEAFS); // 46 95 | 96 | CopyLump(LUMP_FACE_MACRO_TEXTURE_INFO, m_vFaceMacroTextureInfos); // 47 97 | CopyLump(LUMP_DISP_TRIS, m_vDispTris); // 48 98 | 99 | m_iNumWaterOverlayCount = CopyLump(LUMP_WATEROVERLAYS, m_dWaterOverlays, sizeof(*m_dWaterOverlays), MAX_MAP_WATEROVERLAYS); // 50 100 | CopyLump(LUMP_LEAF_AMBIENT_INDEX_HDR, m_vLeafAmbientIndexHDR); // 51 101 | CopyLump(LUMP_LEAF_AMBIENT_INDEX, m_vLeafAmbientIndexLDR); // 52 102 | CopyLump(LUMP_LIGHTING_HDR, m_vLightDataHDR); // 53 103 | m_iNumWorldLightsHDR = CopyLump(LUMP_WORLDLIGHTS_HDR, m_dWorldLightsHDR, sizeof(*m_dWorldLightsHDR), MAX_MAP_WORLDLIGHTS); // 39 104 | CopyLump(LUMP_LEAF_AMBIENT_LIGHTING_HDR, m_vLeafAmbientLightingHDR); // 55 105 | CopyLump(LUMP_LEAF_AMBIENT_LIGHTING, m_vLeafAmbientLightingLDR); // 56 106 | 107 | m_iNumFacesHDR = CopyLump(LUMP_FACES_HDR, m_dFacesHDR, sizeof(*m_dFacesHDR), MAX_MAP_FACES); // 58 108 | CopyLump(LUMP_MAP_FLAGS, &m_fLevelFlags, sizeof(uint32_t), 1); 109 | m_iNumOverlayFades = CopyLump(LUMP_OVERLAY_FADES, m_dOverlayFades, sizeof(*m_dOverlayFades), MAX_MAP_OVERLAYS); // 60 110 | 111 | // Gather unparsed lumps 112 | for (int i = 0; i < HEADER_LUMPS; i++) 113 | { 114 | if (!m_Lumps.bLumpParsed[i] && m_bspHdr->lumps[i].filelen) 115 | { 116 | m_Lumps.size[i] = CopyVariableLump(i, &m_Lumps.pLumps[i]); 117 | pp::Warning("Unsaved lump index %i (%i bytes)", i, m_Lumps.size[i]); 118 | } 119 | } 120 | } 121 | 122 | bool CBSP::ValidateHeader(dheader_t* hdr) 123 | { 124 | if (hdr->ident != IDBSPHEADER) 125 | { 126 | pp::Error("%s is not a IBSP file", m_szFilename); 127 | return false; 128 | } 129 | if (hdr->version < MINBSPVERSION || hdr->version > BSPVERSION) 130 | { 131 | pp::Error("%s is version %i, not %i", m_szFilename, hdr->version, BSPVERSION); 132 | return false; 133 | } 134 | return true; 135 | } 136 | 137 | int CBSP::CopyLump(int lump, void * out, size_t element_size, size_t max_count, int force_version) 138 | { 139 | if (lump >= MAX_LUMPS || lump < 0) 140 | { 141 | pp::Error("Lump index out of bounds"); 142 | return 0; 143 | } 144 | 145 | m_Lumps.bLumpParsed[lump] = true; 146 | 147 | if (!HasLump(lump)) 148 | { 149 | memset(out, 0, max_count * element_size); 150 | pp::Warning("[%s] Missing lump index %i", g_szLumpNames[lump], lump); 151 | return 0; 152 | } 153 | 154 | size_t length = m_bspHdr->lumps[lump].filelen; 155 | size_t ofs = m_bspHdr->lumps[lump].fileofs; 156 | size_t count = length / element_size; 157 | 158 | if (max_count < count) 159 | { 160 | pp::Error("[%s] Lump index %i is using %i/%i elements", g_szLumpNames[lump], lump, count, max_count); 161 | return 0; 162 | } 163 | if (length % element_size) 164 | { 165 | pp::Error("[%s] Lump index %i has incorrect file length", g_szLumpNames[lump], lump); 166 | return 0; 167 | } 168 | if (force_version >= 0 && force_version != m_bspHdr->lumps[lump].version) 169 | { 170 | pp::Error("[%s] Old version for lump %i", g_szLumpNames[lump], lump); 171 | return 0; 172 | } 173 | 174 | pp::Success("[%s] Loaded lump index %i (Size: %i, File offset: %i, Items: %i, Item size: %i)", g_szLumpNames[lump], lump, length, ofs, count, element_size); 175 | 176 | memcpy(out, (byte*)m_bspData + ofs, length); 177 | 178 | return count; 179 | } 180 | 181 | bool CBSP::HasLump(int lump) 182 | { 183 | return m_bspHdr->lumps[lump].filelen > 0; 184 | } 185 | 186 | int CBSP::LumpVersion(int lump) 187 | { 188 | return m_bspHdr->lumps[lump].version; 189 | } 190 | 191 | void CBSP::ParseEntities() 192 | { 193 | m_iNumEntities = 0; 194 | ParseFromMemory(m_vEntData.data(), m_vEntData.size()); 195 | 196 | while (ParseEntity()) 197 | { 198 | } 199 | 200 | pp::Success("Found %i entities", m_iNumEntities); 201 | } 202 | 203 | qboolean CBSP::ParseEntity() 204 | { 205 | epair_t *e; 206 | entity_t *mapent; 207 | 208 | if (!GetToken(true)) 209 | return false; 210 | 211 | if (_stricmp(token, "{")) 212 | pp::Error("ParseEntity: { not found"); 213 | 214 | if (m_iNumEntities > MAX_MAP_ENTITIES) 215 | pp::Error("num_entities > MAX_MAP_ENTITIES"); 216 | 217 | mapent = &m_Entities[m_iNumEntities]; 218 | m_iNumEntities++; 219 | 220 | do 221 | { 222 | if (!GetToken(true)) 223 | pp::Error("ParseEntity: EOF without closing brace"); 224 | 225 | if (!_stricmp(token, "}")) 226 | break; 227 | 228 | e = ParseEpair(); 229 | e->next = mapent->epairs; 230 | mapent->epairs = e; 231 | } while (1); 232 | 233 | return true; 234 | } 235 | 236 | 237 | epair_t * CBSP::ParseEpair() 238 | { 239 | epair_t *e; 240 | 241 | e = (epair_t*)malloc(sizeof(epair_t)); 242 | memset(e, 0, sizeof(epair_t)); 243 | 244 | if (strlen(token) >= MAX_KEY - 1) 245 | pp::Error("ParseEpar: token too long"); 246 | e->key = _strdup(token); 247 | 248 | GetToken(false); 249 | if (strlen(token) >= MAX_VALUE - 1) 250 | pp::Error("ParseEpar: token too long"); 251 | e->value = _strdup(token); 252 | 253 | // strip trailing spaces 254 | StripTrailing(e->key); 255 | StripTrailing(e->value); 256 | 257 | return e; 258 | } 259 | 260 | void CBSP::StripTrailing(char *e) 261 | { 262 | char *s; 263 | 264 | s = e + strlen(e) - 1; 265 | while (s >= e && *s <= 32) 266 | { 267 | *s = 0; 268 | s--; 269 | } 270 | } -------------------------------------------------------------------------------- /gpua_rad/bsp.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPUA_BSP_H_ 2 | #define _GPUA_BSP_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "script.h" 13 | 14 | #include "prettyprint.h" 15 | 16 | #include "vector.h" 17 | #include "bspfile.h" 18 | 19 | #define MAX_TEXLIGHTS 128 20 | #define MAX_TEXLIGHT_NAME 256 21 | 22 | class CBSP : public CScript 23 | { 24 | public: 25 | CBSP(const char* filename); 26 | ~CBSP(); 27 | void LoadBSP(); 28 | bool ValidateHeader(dheader_t* hdr); 29 | int CopyLump(int lump, void* out, size_t element_size, size_t max_count, int force_version = -1); 30 | 31 | template 32 | int CopyLump(int lump, std::vector &vec, int force_version = -1) 33 | { 34 | size_t count = m_bspHdr->lumps[lump].filelen / sizeof(T); 35 | vec.resize(count); 36 | return CopyLump(lump, vec.data(), sizeof(T), count, force_version); 37 | } 38 | 39 | template 40 | int CopyVariableLump(int lump, void** dest, int force_version = -1) 41 | { 42 | size_t count = m_bspHdr->lumps[lump].filelen / sizeof(T); 43 | *dest = malloc(count * sizeof(T)); 44 | 45 | return CopyLump(lump, *dest, sizeof(T), count, force_version); 46 | } 47 | 48 | void ParseEntities(); 49 | qboolean ParseEntity(); 50 | epair_t* ParseEpair(); 51 | void StripTrailing(char *e); 52 | 53 | bool HasLump(int lump); 54 | int LumpVersion(int lump); 55 | // Filename 56 | const char* m_szFilename; 57 | 58 | // Bsp stuff 59 | lumps_t m_Lumps; 60 | uint8_t* m_bspData; 61 | dheader_t* m_bspHdr; 62 | int m_iMapRevision; 63 | uint32_t m_fLevelFlags; 64 | 65 | /// Lumps 66 | // lump 0 67 | std::vector m_vEntData; 68 | 69 | // lump 1 70 | int m_iNumPlanes; 71 | dplane_t m_dPlanes[MAX_MAP_PLANES]; 72 | 73 | // lump 2 74 | int m_iNumTexData; 75 | dtexdata_t m_dTexData[MAX_MAP_TEXDATA]; 76 | 77 | // lump 3 78 | int m_iNumVertexes; 79 | dvertex_t m_dVertexes[MAX_MAP_VERTS]; 80 | 81 | // lump 4 82 | int m_iVisDataSize; 83 | uint8_t m_dVisData[MAX_MAP_VISIBILITY]; 84 | dvis_t *m_dVis; 85 | 86 | // lump 5 87 | int m_iNumNodes; 88 | dnode_t m_dNodes[MAX_MAP_NODES]; 89 | 90 | // lump 6 91 | int m_iNumTexInfos; 92 | texinfo_t m_dTexInfos[MAX_MAP_TEXINFO]; 93 | 94 | // lump 7 95 | int m_iNumFaces; 96 | dface_t m_dFaces[MAX_MAP_FACES]; 97 | 98 | // lump 8 99 | std::vector m_vLightDataLDR; 100 | 101 | // lump 10 102 | int m_iNumLeafs; 103 | dleaf_t m_dLeafs[MAX_MAP_LEAFS]; 104 | 105 | // lump 11 106 | std::vector m_vFaceIds; 107 | 108 | // lump 12 109 | int m_iNumEdges; 110 | dedge_t m_dEdges[MAX_MAP_EDGES]; 111 | 112 | // lump 13 113 | int m_iNumSurfEdges; 114 | int m_dSurfEdges[MAX_MAP_SURFEDGES]; 115 | 116 | // lump 14 117 | int m_iNumModels; 118 | dmodel_t m_dModels[MAX_MAP_MODELS]; 119 | 120 | // lump 15 121 | int m_iNumWorldLightsLDR; 122 | dworldlight_t m_dWorldLightsLDR[MAX_MAP_WORLDLIGHTS]; 123 | 124 | // lump 16 125 | int m_iNumLeafFaces; 126 | unsigned short m_dLeafFaces[MAX_MAP_LEAFFACES]; 127 | 128 | // lump 17 129 | int m_iNumLeafBrushes; 130 | unsigned short m_dLeafBrushes[MAX_MAP_LEAFBRUSHES]; 131 | 132 | // lump 18 133 | int m_iNumBrushes; 134 | dbrush_t m_dBrushes[MAX_MAP_BRUSHES]; 135 | 136 | // lump 19 137 | int m_iNumBrushSides; 138 | dbrushside_t m_dBrushSides[MAX_MAP_BRUSHSIDES]; 139 | 140 | // lump 20 141 | int m_iNumAreas; 142 | darea_t m_dAreas[MAX_MAP_AREAS]; 143 | 144 | // lump 21 145 | int m_iNumAreaPortals; 146 | dareaportal_t m_dAreaPortals[MAX_MAP_AREAPORTALS]; 147 | 148 | // lump 26 149 | std::vector m_vDispInfos; 150 | 151 | // lump 27 152 | int m_iNumOrigFaces; 153 | dface_t m_dOrigFaces[MAX_MAP_FACES]; 154 | 155 | // lump 28 156 | std::vector m_vPhysDisp; 157 | 158 | // lump 29 159 | std::vector m_vPhysCollide; 160 | 161 | // lump 30 162 | int m_iNumVertNormals; 163 | Vector m_dVertNormals[MAX_MAP_VERTNORMALS]; 164 | 165 | // lump 31 166 | int m_iNumVertNormalIndices; // dfaces reference these. These index g_vertnormals. 167 | unsigned short m_dVertNormalIndices[MAX_MAP_VERTNORMALS]; 168 | 169 | // lump 33 170 | std::vector m_vDispVerts; 171 | 172 | // lump 34 173 | std::vector m_vNumDispLightmapSamplePositions; 174 | 175 | // lump 36 176 | int m_iNumLeafWaterData; 177 | dleafwaterdata_t m_dLeafWaterData[MAX_MAP_LEAFWATERDATA]; 178 | 179 | // lump 37 180 | int m_iNumPrimitives; 181 | dprimitive_t m_dPrimitives[MAX_MAP_PRIMITIVES]; 182 | 183 | // lump 38 184 | int m_iNumPrimverts; 185 | dprimvert_t m_dPrimverts[MAX_MAP_PRIMVERTS]; 186 | 187 | // lump 39 188 | int m_iNumPrimindices; 189 | unsigned short m_dPrimindices[MAX_MAP_PRIMINDICES]; 190 | 191 | // lump 41 192 | int m_iNumClipPortalVerts; 193 | Vector m_dClipPortalVerts[MAX_MAP_PORTALVERTS]; 194 | 195 | // lump 42 196 | int m_iNumCubemapSamples = 0; 197 | dcubemapsample_t m_dCubemapSamples[MAX_MAP_CUBEMAPSAMPLES]; 198 | 199 | // lump 43 200 | std::vector m_vTexDataStringData; 201 | 202 | // lump 44 203 | std::vector m_vTexDataStringTable; 204 | 205 | // lump 45 206 | int m_iNumOverlayCount; 207 | doverlay_t m_dOverlays[MAX_MAP_OVERLAYS]; 208 | 209 | // lump 46 210 | int m_iNumLeafMinDistToWater; 211 | unsigned short m_dLeafMinDistToWater[MAX_MAP_LEAFS]; 212 | 213 | // lump 47 214 | std::vector m_vFaceMacroTextureInfos; 215 | 216 | // lump 48 217 | std::vector m_vDispTris; 218 | 219 | // lump 50 220 | int m_iNumWaterOverlayCount; 221 | dwateroverlay_t m_dWaterOverlays[MAX_MAP_WATEROVERLAYS]; 222 | 223 | // lump 51 224 | std::vector m_vLeafAmbientIndexHDR; 225 | 226 | // lump 52 227 | std::vector m_vLeafAmbientIndexLDR; 228 | 229 | // lump 53 230 | std::vector m_vLightDataHDR; 231 | 232 | // lump 54 233 | int m_iNumWorldLightsHDR; 234 | dworldlight_t m_dWorldLightsHDR[MAX_MAP_WORLDLIGHTS]; 235 | 236 | // lump 55 237 | std::vector m_vLeafAmbientLightingHDR; 238 | 239 | // lump 56 240 | std::vector m_vLeafAmbientLightingLDR; 241 | 242 | // lump 58 243 | int m_iNumFacesHDR; 244 | dface_t m_dFacesHDR[MAX_MAP_FACES]; 245 | 246 | // lump 60 247 | int m_iNumOverlayFades; 248 | doverlayfade_t m_dOverlayFades[MAX_MAP_OVERLAYS]; 249 | 250 | int m_iNumEntities; 251 | entity_t m_Entities[MAX_MAP_ENTITIES]; 252 | }; 253 | 254 | #endif // _GPUA_BSP_H_ -------------------------------------------------------------------------------- /gpua_rad/bspfile.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPUA_BSPFILE_H_ 2 | #define _GPUA_BSPFILE_H_ 3 | 4 | #include "datamap.h" 5 | 6 | //#pragma pack(1) 7 | 8 | #define IDBSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'V') 9 | 10 | #define MINBSPVERSION 19 11 | #define BSPVERSION 20 12 | 13 | // key / value pair sizes 14 | #define MAX_KEY 32 15 | #define MAX_VALUE 1024 16 | 17 | // level feature flags 18 | #define LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_NONHDR 0x00000001 // was processed by vrad with -staticproplighting, no hdr data 19 | #define LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_HDR 0x00000002 // was processed by vrad with -staticproplighting, in hdr 20 | 21 | // upper design bounds 22 | #define MIN_MAP_DISP_POWER 2 // Minimum and maximum power a displacement can be. 23 | #define MAX_MAP_DISP_POWER 4 24 | 25 | // Max # of neighboring displacement touching a displacement's corner. 26 | #define MAX_DISP_CORNER_NEIGHBORS 4 27 | 28 | #define NUM_DISP_POWER_VERTS(power) ( ((1 << (power)) + 1) * ((1 << (power)) + 1) ) 29 | #define NUM_DISP_POWER_TRIS(power) ( (1 << (power)) * (1 << (power)) * 2 ) 30 | 31 | #define MAX_MAP_DISP_VERTS ( MAX_MAP_DISPINFO * ((1< 64k edges 304 | short numedges; 305 | short texinfo; 306 | // This is a union under the assumption that a fog volume boundary (ie. water surface) 307 | // isn't a displacement map. 308 | // FIXME: These should be made a union with a flags or type field for which one it is 309 | // if we can add more to this. 310 | // union 311 | // { 312 | short dispinfo; 313 | // This is only for surfaces that are the boundaries of fog volumes 314 | // (ie. water surfaces) 315 | // All of the rest of the surfaces can look at their leaf to find out 316 | // what fog volume they are in. 317 | short surfaceFogVolumeID; 318 | // }; 319 | 320 | // lighting info 321 | byte styles[MAXLIGHTMAPS]; 322 | int lightofs; // start of [numstyles*surfsize] samples 323 | float area; 324 | 325 | // TODO: make these unsigned chars? 326 | int m_LightmapTextureMinsInLuxels[2]; 327 | int m_LightmapTextureSizeInLuxels[2]; 328 | 329 | int origFace; // reference the original face this face was derived from 330 | 331 | 332 | public: 333 | 334 | unsigned short GetNumPrims() const; 335 | void SetNumPrims(unsigned short nPrims); 336 | bool AreDynamicShadowsEnabled(); 337 | void SetDynamicShadowsEnabled(bool bEnabled); 338 | 339 | // non-polygon primitives (strips and lists) 340 | private: 341 | unsigned short m_NumPrims; // Top bit, if set, disables shadows on this surface (this is why there are accessors). 342 | 343 | public: 344 | unsigned short firstPrimID; 345 | 346 | unsigned int smoothingGroups; 347 | }; 348 | 349 | inline unsigned short dface_t::GetNumPrims() const 350 | { 351 | return m_NumPrims & 0x7FFF; 352 | } 353 | 354 | inline void dface_t::SetNumPrims(unsigned short nPrims) 355 | { 356 | m_NumPrims &= ~0x7FFF; 357 | m_NumPrims |= (nPrims & 0x7FFF); 358 | } 359 | 360 | inline bool dface_t::AreDynamicShadowsEnabled() 361 | { 362 | return (m_NumPrims & 0x8000) == 0; 363 | } 364 | 365 | inline void dface_t::SetDynamicShadowsEnabled(bool bEnabled) 366 | { 367 | if (bEnabled) 368 | m_NumPrims &= ~0x8000; 369 | else 370 | m_NumPrims |= 0x8000; 371 | } 372 | 373 | struct dleaf_t // lump 10 374 | { 375 | int contents; // OR of all brushes (not needed?) 376 | 377 | short cluster; 378 | 379 | BEGIN_BITFIELD(bf); 380 | short area : 9; 381 | short flags : 7; // Per leaf flags. 382 | END_BITFIELD(); 383 | 384 | short mins[3]; // for frustum culling 385 | short maxs[3]; 386 | 387 | unsigned short firstleafface; 388 | unsigned short numleaffaces; 389 | 390 | unsigned short firstleafbrush; 391 | unsigned short numleafbrushes; 392 | short leafWaterDataID; // -1 for not in water 393 | 394 | // NOTE: removed this for version 1 and moved into separate lump "LUMP_LEAF_AMBIENT_LIGHTING" or "LUMP_LEAF_AMBIENT_LIGHTING_HDR" 395 | // Precaculated light info for entities. 396 | // CompressedLightCube m_AmbientLighting; 397 | }; 398 | 399 | struct dfaceid_t // lump 11 400 | { 401 | unsigned short hammerfaceid; 402 | }; 403 | 404 | struct dedge_t // lump 12 405 | { 406 | unsigned short v[2]; // vertex numbers 407 | }; 408 | 409 | struct dmodel_t // lump 14 410 | { 411 | Vector mins, maxs; 412 | Vector origin; // for sounds or lights 413 | int headnode; 414 | int firstface, numfaces; // submodels just draw faces without walking the bsp tree 415 | }; 416 | 417 | // lights that were used to illuminate the world 418 | enum emittype_t 419 | { 420 | emit_surface, // 90 degree spotlight 421 | emit_point, // simple point light source 422 | emit_spotlight, // spotlight with penumbra 423 | emit_skylight, // directional light with no falloff (surface must trace to SKY texture) 424 | emit_quakelight, // linear falloff, non-lambertian 425 | emit_skyambient, // spherical light source with no falloff (surface must trace to SKY texture) 426 | }; 427 | 428 | // Flags for dworldlight_t::flags 429 | #define DWL_FLAGS_INAMBIENTCUBE 0x0001 // This says that the light was put into the per-leaf ambient cubes. 430 | 431 | struct dworldlight_t // lump 15 432 | { 433 | Vector origin; 434 | Vector intensity; 435 | Vector normal; // for surfaces and spotlights 436 | int cluster; 437 | emittype_t type; 438 | int style; 439 | float stopdot; // start of penumbra for emit_spotlight 440 | float stopdot2; // end of penumbra for emit_spotlight 441 | float exponent; // 442 | float radius; // cutoff distance 443 | // falloff for emit_spotlight + emit_point: 444 | // 1 / (constant_attn + linear_attn * dist + quadratic_attn * dist^2) 445 | float constant_attn; 446 | float linear_attn; 447 | float quadratic_attn; 448 | int flags; // Uses a combination of the DWL_FLAGS_ defines. 449 | int texinfo; // 450 | int owner; // entity that this light it relative to 451 | }; 452 | struct dbrush_t // lump 18 453 | { 454 | int firstside; 455 | int numsides; 456 | int contents; 457 | }; 458 | 459 | struct dbrushside_t // lump 19 460 | { 461 | unsigned short planenum; // facing out of the leaf 462 | short texinfo; 463 | short dispinfo; // displacement info (BSPVERSION 7) 464 | short bevel; // is the side a bevel plane? (BSPVERSION 7) 465 | }; 466 | 467 | struct darea_t // lump 20 468 | { 469 | int numareaportals; 470 | int firstareaportal; 471 | }; 472 | 473 | // each area has a list of portals that lead into other areas 474 | // when portals are closed, other areas may not be visible or 475 | // hearable even if the vis info says that it should be 476 | struct dareaportal_t // lump 21 477 | { 478 | unsigned short m_PortalKey; // Entities have a key called portalnumber (and in vbsp a variable 479 | // called areaportalnum) which is used 480 | // to bind them to the area portals by comparing with this value. 481 | 482 | unsigned short otherarea; // The area this portal looks into. 483 | 484 | unsigned short m_FirstClipPortalVert; // Portal geometry. 485 | unsigned short m_nClipPortalVerts; 486 | 487 | int planenum; 488 | }; 489 | 490 | // These denote where one dispinfo fits on another. 491 | // Note: tables are generated based on these indices so make sure to update 492 | // them if these indices are changed. 493 | typedef enum 494 | { 495 | CORNER_TO_CORNER = 0, 496 | CORNER_TO_MIDPOINT = 1, 497 | MIDPOINT_TO_CORNER = 2 498 | } NeighborSpan; 499 | 500 | 501 | // These define relative orientations of displacement neighbors. 502 | typedef enum 503 | { 504 | ORIENTATION_CCW_0 = 0, 505 | ORIENTATION_CCW_90 = 1, 506 | ORIENTATION_CCW_180 = 2, 507 | ORIENTATION_CCW_270 = 3 508 | } NeighborOrientation; 509 | 510 | // NOTE: see the section above titled "displacement neighbor rules". 511 | struct CDispSubNeighbor 512 | { 513 | public: 514 | unsigned short GetNeighborIndex() const { return m_iNeighbor; } 515 | NeighborSpan GetSpan() const { return (NeighborSpan)m_Span; } 516 | NeighborSpan GetNeighborSpan() const { return (NeighborSpan)m_NeighborSpan; } 517 | NeighborOrientation GetNeighborOrientation() const { return (NeighborOrientation)m_NeighborOrientation; } 518 | 519 | bool IsValid() const { return m_iNeighbor != 0xFFFF; } 520 | void SetInvalid() { m_iNeighbor = 0xFFFF; } 521 | 522 | 523 | public: 524 | unsigned short m_iNeighbor; // This indexes into ddispinfos. 525 | // 0xFFFF if there is no neighbor here. 526 | 527 | unsigned char m_NeighborOrientation; // (CCW) rotation of the neighbor wrt this displacement. 528 | 529 | // These use the NeighborSpan type. 530 | unsigned char m_Span; // Where the neighbor fits onto this side of our displacement. 531 | unsigned char m_NeighborSpan; // Where we fit onto our neighbor. 532 | }; 533 | 534 | // NOTE: see the section above titled "displacement neighbor rules". 535 | class CDispNeighbor 536 | { 537 | public: 538 | void SetInvalid() { m_SubNeighbors[0].SetInvalid(); m_SubNeighbors[1].SetInvalid(); } 539 | 540 | // Returns false if there isn't anything touching this edge. 541 | bool IsValid() { return m_SubNeighbors[0].IsValid() || m_SubNeighbors[1].IsValid(); } 542 | 543 | 544 | public: 545 | // Note: if there is a neighbor that fills the whole side (CORNER_TO_CORNER), 546 | // then it will always be in CDispNeighbor::m_Neighbors[0] 547 | CDispSubNeighbor m_SubNeighbors[2]; 548 | }; 549 | 550 | class CDispCornerNeighbors 551 | { 552 | public: 553 | void SetInvalid() { m_nNeighbors = 0; } 554 | 555 | 556 | public: 557 | unsigned short m_Neighbors[MAX_DISP_CORNER_NEIGHBORS]; // indices of neighbors. 558 | unsigned char m_nNeighbors; 559 | }; 560 | 561 | class ddispinfo_t // lump 26 562 | { 563 | public: 564 | int NumVerts() const { return NUM_DISP_POWER_VERTS(power); } 565 | int NumTris() const { return NUM_DISP_POWER_TRIS(power); } 566 | 567 | public: 568 | Vector startPosition; // start position used for orientation -- (added BSPVERSION 6) 569 | int m_iDispVertStart; // Index into LUMP_DISP_VERTS. 570 | int m_iDispTriStart; // Index into LUMP_DISP_TRIS. 571 | 572 | int power; // power - indicates size of map (2^power + 1) 573 | int minTess; // minimum tesselation allowed 574 | float smoothingAngle; // lighting smoothing angle 575 | int contents; // surface contents 576 | 577 | unsigned short m_iMapFace; // Which map face this displacement comes from. 578 | 579 | int m_iLightmapAlphaStart; // Index into ddisplightmapalpha. 580 | // The count is m_pParent->lightmapTextureSizeInLuxels[0]*m_pParent->lightmapTextureSizeInLuxels[1]. 581 | 582 | int m_iLightmapSamplePositionStart; // Index into LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS. 583 | 584 | CDispNeighbor m_EdgeNeighbors[4]; // Indexed by NEIGHBOREDGE_ defines. 585 | CDispCornerNeighbors m_CornerNeighbors[4]; // Indexed by CORNER_ defines. 586 | 587 | enum unnamed { ALLOWEDVERTS_SIZE = PAD_NUMBER(MAX_DISPVERTS, 32) / 32 }; 588 | unsigned long m_AllowedVerts[ALLOWEDVERTS_SIZE]; // This is built based on the layout and sizes of our neighbors 589 | // and tells us which vertices are allowed to be active. 590 | }; 591 | 592 | class CDispVert // lump 33 593 | { 594 | public: 595 | Vector m_vVector; // Vector field defining displacement volume. 596 | float m_flDist; // Displacement distances. 597 | float m_flAlpha; // "per vertex" alpha values. 598 | }; 599 | 600 | struct dleafwaterdata_t // lump 36 601 | { 602 | float surfaceZ; 603 | float minZ; 604 | short surfaceTexInfoID; 605 | }; 606 | 607 | struct dprimitive_t // lump 37 608 | { 609 | unsigned char type; 610 | unsigned short firstIndex; 611 | unsigned short indexCount; 612 | unsigned short firstVert; 613 | unsigned short vertCount; 614 | }; 615 | 616 | struct dprimvert_t // lump 38 617 | { 618 | Vector pos; 619 | }; 620 | 621 | struct dcubemapsample_t // lump 42 622 | { 623 | int origin[3]; // position of light snapped to the nearest integer 624 | // the filename for the vtf file is derived from the position 625 | unsigned char size; // 0 - default 626 | // otherwise, 1<<(size-1) 627 | }; 628 | 629 | #define OVERLAY_BSP_FACE_COUNT 64 630 | 631 | #define OVERLAY_NUM_RENDER_ORDERS (1<> (16 - OVERLAY_RENDER_ORDER_NUM_BITS)); 679 | } 680 | 681 | class CFaceMacroTextureInfo // lump 47 682 | { 683 | public: 684 | // This looks up into g_TexDataStringTable, which looks up into g_TexDataStringData. 685 | // 0xFFFF if the face has no macro texture. 686 | unsigned short m_MacroTextureNameID; 687 | }; 688 | 689 | class CDispTri // lump 48 690 | { 691 | public: 692 | unsigned short m_uiTags; // Displacement triangle tags. 693 | }; 694 | 695 | #define WATEROVERLAY_BSP_FACE_COUNT 256 696 | #define WATEROVERLAY_RENDER_ORDER_NUM_BITS 2 697 | #define WATEROVERLAY_NUM_RENDER_ORDERS (1<> (16 - WATEROVERLAY_RENDER_ORDER_NUM_BITS)); 745 | } 746 | 747 | struct dleafambientindex_t 748 | { 749 | unsigned short ambientSampleCount; 750 | unsigned short firstAmbientSample; 751 | }; 752 | 753 | // compressed color format 754 | struct ColorRGBExp32 755 | { 756 | byte r, g, b; 757 | signed char exponent; 758 | }; 759 | 760 | struct CompressedLightCube 761 | { 762 | ColorRGBExp32 m_Color[6]; 763 | }; 764 | 765 | struct dleafambientlighting_t 766 | { 767 | CompressedLightCube cube; 768 | byte x; // fixed point fraction of leaf bounds 769 | byte y; // fixed point fraction of leaf bounds 770 | byte z; // fixed point fraction of leaf bounds 771 | byte pad; // unused 772 | }; 773 | 774 | struct doverlayfade_t // lump 60 775 | { 776 | float flFadeDistMinSq; 777 | float flFadeDistMaxSq; 778 | }; 779 | 780 | struct plane_t : public dplane_t 781 | { 782 | plane_t *hash_chain; 783 | 784 | plane_t() { normal.Init(); } 785 | }; 786 | 787 | struct epair_t 788 | { 789 | epair_t *next; 790 | char *key; 791 | char *value; 792 | }; 793 | 794 | struct portal_t; 795 | 796 | struct entity_t 797 | { 798 | Vector origin; 799 | int firstbrush; 800 | int numbrushes; 801 | epair_t *epairs; 802 | 803 | // only valid for func_areaportals 804 | int areaportalnum; 805 | int portalareas[2]; 806 | portal_t *m_pPortalsLeadingIntoAreas[2]; // portals leading into portalareas 807 | }; 808 | 809 | #endif // _GPUA_BSPFILE_H_ -------------------------------------------------------------------------------- /gpua_rad/bspflags.h: -------------------------------------------------------------------------------- 1 | //========= Copyright Valve Corporation, All rights reserved. ============// 2 | // 3 | // Purpose: 4 | // 5 | // $Workfile: $ 6 | // $Date: $ 7 | // $NoKeywords: $ 8 | //=============================================================================// 9 | 10 | #ifndef BSPFLAGS_H 11 | #define BSPFLAGS_H 12 | 13 | #ifdef _WIN32 14 | #pragma once 15 | #endif 16 | 17 | // contents flags are seperate bits 18 | // a given brush can contribute multiple content bits 19 | // multiple brushes can be in a single leaf 20 | 21 | // these definitions also need to be in q_shared.h! 22 | 23 | // lower bits are stronger, and will eat weaker brushes completely 24 | #define CONTENTS_EMPTY 0 // No contents 25 | 26 | #define CONTENTS_SOLID 0x1 // an eye is never valid in a solid 27 | #define CONTENTS_WINDOW 0x2 // translucent, but not watery (glass) 28 | #define CONTENTS_AUX 0x4 29 | #define CONTENTS_GRATE 0x8 // alpha-tested "grate" textures. Bullets/sight pass through, but solids don't 30 | #define CONTENTS_SLIME 0x10 31 | #define CONTENTS_WATER 0x20 32 | #define CONTENTS_BLOCKLOS 0x40 // block AI line of sight 33 | #define CONTENTS_OPAQUE 0x80 // things that cannot be seen through (may be non-solid though) 34 | #define LAST_VISIBLE_CONTENTS 0x80 35 | 36 | #define ALL_VISIBLE_CONTENTS (LAST_VISIBLE_CONTENTS | (LAST_VISIBLE_CONTENTS-1)) 37 | 38 | #define CONTENTS_TESTFOGVOLUME 0x100 39 | #define CONTENTS_UNUSED 0x200 40 | 41 | // unused 42 | // NOTE: If it's visible, grab from the top + update LAST_VISIBLE_CONTENTS 43 | // if not visible, then grab from the bottom. 44 | #define CONTENTS_UNUSED6 0x400 45 | 46 | #define CONTENTS_TEAM1 0x800 // per team contents used to differentiate collisions 47 | #define CONTENTS_TEAM2 0x1000 // between players and objects on different teams 48 | 49 | // ignore CONTENTS_OPAQUE on surfaces that have SURF_NODRAW 50 | #define CONTENTS_IGNORE_NODRAW_OPAQUE 0x2000 51 | 52 | // hits entities which are MOVETYPE_PUSH (doors, plats, etc.) 53 | #define CONTENTS_MOVEABLE 0x4000 54 | 55 | // remaining contents are non-visible, and don't eat brushes 56 | #define CONTENTS_AREAPORTAL 0x8000 57 | 58 | #define CONTENTS_PLAYERCLIP 0x10000 59 | #define CONTENTS_MONSTERCLIP 0x20000 60 | 61 | // currents can be added to any other contents, and may be mixed 62 | #define CONTENTS_CURRENT_0 0x40000 63 | #define CONTENTS_CURRENT_90 0x80000 64 | #define CONTENTS_CURRENT_180 0x100000 65 | #define CONTENTS_CURRENT_270 0x200000 66 | #define CONTENTS_CURRENT_UP 0x400000 67 | #define CONTENTS_CURRENT_DOWN 0x800000 68 | 69 | #define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity 70 | 71 | #define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game 72 | #define CONTENTS_DEBRIS 0x4000000 73 | #define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs 74 | #define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans 75 | #define CONTENTS_LADDER 0x20000000 76 | #define CONTENTS_HITBOX 0x40000000 // use accurate hitboxes on trace 77 | 78 | 79 | // NOTE: These are stored in a short in the engine now. Don't use more than 16 bits 80 | #define SURF_LIGHT 0x0001 // value will hold the light strength 81 | #define SURF_SKY2D 0x0002 // don't draw, indicates we should skylight + draw 2d sky but not draw the 3D skybox 82 | #define SURF_SKY 0x0004 // don't draw, but add to skybox 83 | #define SURF_WARP 0x0008 // turbulent water warp 84 | #define SURF_TRANS 0x0010 85 | #define SURF_NOPORTAL 0x0020 // the surface can not have a portal placed on it 86 | #define SURF_TRIGGER 0x0040 // FIXME: This is an xbox hack to work around elimination of trigger surfaces, which breaks occluders 87 | #define SURF_NODRAW 0x0080 // don't bother referencing the texture 88 | 89 | #define SURF_HINT 0x0100 // make a primary bsp splitter 90 | 91 | #define SURF_SKIP 0x0200 // completely ignore, allowing non-closed brushes 92 | #define SURF_NOLIGHT 0x0400 // Don't calculate light 93 | #define SURF_BUMPLIGHT 0x0800 // calculate three lightmaps for the surface for bumpmapping 94 | #define SURF_NOSHADOWS 0x1000 // Don't receive shadows 95 | #define SURF_NODECALS 0x2000 // Don't receive decals 96 | #define SURF_NOCHOP 0x4000 // Don't subdivide patches on this surface 97 | #define SURF_HITBOX 0x8000 // surface is part of a hitbox 98 | 99 | 100 | 101 | // ----------------------------------------------------- 102 | // spatial content masks - used for spatial queries (traceline,etc.) 103 | // ----------------------------------------------------- 104 | #define MASK_ALL (0xFFFFFFFF) 105 | // everything that is normally solid 106 | #define MASK_SOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE) 107 | // everything that blocks player movement 108 | #define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE) 109 | // blocks npc movement 110 | #define MASK_NPCSOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE) 111 | // water physics in these contents 112 | #define MASK_WATER (CONTENTS_WATER|CONTENTS_MOVEABLE|CONTENTS_SLIME) 113 | // everything that blocks lighting 114 | #define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_OPAQUE) 115 | // everything that blocks lighting, but with monsters added. 116 | #define MASK_OPAQUE_AND_NPCS (MASK_OPAQUE|CONTENTS_MONSTER) 117 | // everything that blocks line of sight for AI 118 | #define MASK_BLOCKLOS (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_BLOCKLOS) 119 | // everything that blocks line of sight for AI plus NPCs 120 | #define MASK_BLOCKLOS_AND_NPCS (MASK_BLOCKLOS|CONTENTS_MONSTER) 121 | // everything that blocks line of sight for players 122 | #define MASK_VISIBLE (MASK_OPAQUE|CONTENTS_IGNORE_NODRAW_OPAQUE) 123 | // everything that blocks line of sight for players, but with monsters added. 124 | #define MASK_VISIBLE_AND_NPCS (MASK_OPAQUE_AND_NPCS|CONTENTS_IGNORE_NODRAW_OPAQUE) 125 | // bullets see these as solid 126 | #define MASK_SHOT (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_HITBOX) 127 | // non-raycasted weapons see this as solid (includes grates) 128 | #define MASK_SHOT_HULL (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_GRATE) 129 | // hits solids (not grates) and passes through everything else 130 | #define MASK_SHOT_PORTAL (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER) 131 | // everything normally solid, except monsters (world+brush only) 132 | #define MASK_SOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_GRATE) 133 | // everything normally solid for player movement, except monsters (world+brush only) 134 | #define MASK_PLAYERSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_PLAYERCLIP|CONTENTS_GRATE) 135 | // everything normally solid for npc movement, except monsters (world+brush only) 136 | #define MASK_NPCSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE) 137 | // just the world, used for route rebuilding 138 | #define MASK_NPCWORLDSTATIC (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE) 139 | // These are things that can split areaportals 140 | #define MASK_SPLITAREAPORTAL (CONTENTS_WATER|CONTENTS_SLIME) 141 | 142 | // UNDONE: This is untested, any moving water 143 | #define MASK_CURRENT (CONTENTS_CURRENT_0|CONTENTS_CURRENT_90|CONTENTS_CURRENT_180|CONTENTS_CURRENT_270|CONTENTS_CURRENT_UP|CONTENTS_CURRENT_DOWN) 144 | 145 | // everything that blocks corpse movement 146 | // UNDONE: Not used yet / may be deleted 147 | #define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_GRATE) 148 | 149 | #endif // BSPFLAGS_H 150 | -------------------------------------------------------------------------------- /gpua_rad/datamap.h: -------------------------------------------------------------------------------- 1 | //========= Copyright Valve Corporation, All rights reserved. ============// 2 | // 3 | // Purpose: 4 | // 5 | // $NoKeywords: $ 6 | //=============================================================================// 7 | 8 | #ifndef DATAMAP_H 9 | #define DATAMAP_H 10 | #ifdef _WIN32 11 | #pragma once 12 | #endif 13 | 14 | #include "vector.h" 15 | 16 | // SINGLE_INHERITANCE restricts the size of CBaseEntity pointers-to-member-functions to 4 bytes 17 | //class SINGLE_INHERITANCE CBaseEntity; 18 | struct inputdata_t; 19 | 20 | #define INVALID_TIME (FLT_MAX * -1.0) // Special value not rebased on save/load 21 | 22 | typedef enum _fieldtypes 23 | { 24 | FIELD_VOID = 0, // No type or value 25 | FIELD_FLOAT, // Any floating point value 26 | FIELD_STRING, // A string ID (return from ALLOC_STRING) 27 | FIELD_VECTOR, // Any vector, QAngle, or AngularImpulse 28 | FIELD_QUATERNION, // A quaternion 29 | FIELD_INTEGER, // Any integer or enum 30 | FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint for compression 31 | FIELD_SHORT, // 2 byte integer 32 | FIELD_CHARACTER, // a byte 33 | FIELD_COLOR32, // 8-bit per channel r,g,b,a (32bit color) 34 | FIELD_EMBEDDED, // an embedded object with a datadesc, recursively traverse and embedded class/structure based on an additional typedescription 35 | FIELD_CUSTOM, // special type that contains function pointers to it's read/write/parse functions 36 | 37 | FIELD_CLASSPTR, // CBaseEntity * 38 | FIELD_EHANDLE, // Entity handle 39 | FIELD_EDICT, // edict_t * 40 | 41 | FIELD_POSITION_VECTOR, // A world coordinate (these are fixed up across level transitions automagically) 42 | FIELD_TIME, // a floating point time (these are fixed up automatically too!) 43 | FIELD_TICK, // an integer tick count( fixed up similarly to time) 44 | FIELD_MODELNAME, // Engine string that is a model name (needs precache) 45 | FIELD_SOUNDNAME, // Engine string that is a sound name (needs precache) 46 | 47 | FIELD_INPUT, // a list of inputed data fields (all derived from CMultiInputVar) 48 | FIELD_FUNCTION, // A class function pointer (Think, Use, etc) 49 | 50 | FIELD_VMATRIX, // a vmatrix (output coords are NOT worldspace) 51 | 52 | // NOTE: Use float arrays for local transformations that don't need to be fixed up. 53 | FIELD_VMATRIX_WORLDSPACE,// A VMatrix that maps some local space to world space (translation is fixed up on level transitions) 54 | FIELD_MATRIX3X4_WORLDSPACE, // matrix3x4_t that maps some local space to world space (translation is fixed up on level transitions) 55 | 56 | FIELD_INTERVAL, // a start and range floating point interval ( e.g., 3.2->3.6 == 3.2 and 0.4 ) 57 | FIELD_MODELINDEX, // a model index 58 | FIELD_MATERIALINDEX, // a material index (using the material precache string table) 59 | 60 | FIELD_VECTOR2D, // 2 floats 61 | 62 | FIELD_TYPECOUNT, // MUST BE LAST 63 | } fieldtype_t; 64 | 65 | 66 | //----------------------------------------------------------------------------- 67 | // Field sizes... 68 | //----------------------------------------------------------------------------- 69 | template 70 | class CDatamapFieldSizeDeducer 71 | { 72 | public: 73 | enum 74 | { 75 | SIZE = 0 76 | }; 77 | 78 | static int FieldSize() 79 | { 80 | return 0; 81 | } 82 | }; 83 | 84 | #define DECLARE_FIELD_SIZE( _fieldType, _fieldSize ) \ 85 | template< > class CDatamapFieldSizeDeducer<_fieldType> { public: enum { SIZE = _fieldSize }; static int FieldSize() { return _fieldSize; } }; 86 | #define FIELD_SIZE( _fieldType ) CDatamapFieldSizeDeducer<_fieldType>::SIZE 87 | #define FIELD_BITS( _fieldType ) (FIELD_SIZE( _fieldType ) * 8) 88 | 89 | DECLARE_FIELD_SIZE(FIELD_FLOAT, sizeof(float)) 90 | DECLARE_FIELD_SIZE(FIELD_STRING, sizeof(int)) 91 | DECLARE_FIELD_SIZE(FIELD_VECTOR, 3 * sizeof(float)) 92 | DECLARE_FIELD_SIZE(FIELD_VECTOR2D, 2 * sizeof(float)) 93 | DECLARE_FIELD_SIZE(FIELD_QUATERNION, 4 * sizeof(float)) 94 | DECLARE_FIELD_SIZE(FIELD_INTEGER, sizeof(int)) 95 | DECLARE_FIELD_SIZE(FIELD_BOOLEAN, sizeof(char)) 96 | DECLARE_FIELD_SIZE(FIELD_SHORT, sizeof(short)) 97 | DECLARE_FIELD_SIZE(FIELD_CHARACTER, sizeof(char)) 98 | DECLARE_FIELD_SIZE(FIELD_COLOR32, sizeof(int)) 99 | DECLARE_FIELD_SIZE(FIELD_CLASSPTR, sizeof(int)) 100 | DECLARE_FIELD_SIZE(FIELD_EHANDLE, sizeof(int)) 101 | DECLARE_FIELD_SIZE(FIELD_EDICT, sizeof(int)) 102 | DECLARE_FIELD_SIZE(FIELD_POSITION_VECTOR, 3 * sizeof(float)) 103 | DECLARE_FIELD_SIZE(FIELD_TIME, sizeof(float)) 104 | DECLARE_FIELD_SIZE(FIELD_TICK, sizeof(int)) 105 | DECLARE_FIELD_SIZE(FIELD_MODELNAME, sizeof(int)) 106 | DECLARE_FIELD_SIZE(FIELD_SOUNDNAME, sizeof(int)) 107 | DECLARE_FIELD_SIZE(FIELD_INPUT, sizeof(int)) 108 | #ifdef POSIX 109 | // pointer to members under gnuc are 8bytes if you have a virtual func 110 | DECLARE_FIELD_SIZE(FIELD_FUNCTION, sizeof(uint64)) 111 | #else 112 | DECLARE_FIELD_SIZE(FIELD_FUNCTION, sizeof(int *)) 113 | #endif 114 | DECLARE_FIELD_SIZE(FIELD_VMATRIX, 16 * sizeof(float)) 115 | DECLARE_FIELD_SIZE(FIELD_VMATRIX_WORLDSPACE, 16 * sizeof(float)) 116 | DECLARE_FIELD_SIZE(FIELD_MATRIX3X4_WORLDSPACE, 12 * sizeof(float)) 117 | DECLARE_FIELD_SIZE(FIELD_INTERVAL, 2 * sizeof(float)) // NOTE: Must match interval.h definition 118 | DECLARE_FIELD_SIZE(FIELD_MODELINDEX, sizeof(int)) 119 | DECLARE_FIELD_SIZE(FIELD_MATERIALINDEX, sizeof(int)) 120 | 121 | 122 | #define ARRAYSIZE2D(p) (sizeof(p)/sizeof(p[0][0])) 123 | #define SIZE_OF_ARRAY(p) _ARRAYSIZE(p) 124 | 125 | #define _FIELD(name,fieldtype,count,flags,mapname,tolerance) { fieldtype, #name, { offsetof(classNameTypedef, name), 0 }, count, flags, mapname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, tolerance } 126 | #define DEFINE_FIELD_NULL { FIELD_VOID,0, {0,0},0,0,0,0,0,0} 127 | #define DEFINE_FIELD(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_SAVE, NULL, 0 ) 128 | #define DEFINE_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 ) 129 | #define DEFINE_KEYFIELD_NOT_SAVED(name,fieldtype, mapname)_FIELD(name, fieldtype, 1, FTYPEDESC_KEY, mapname, 0 ) 130 | #define DEFINE_AUTO_ARRAY(name,fieldtype) _FIELD(name, fieldtype, SIZE_OF_ARRAY(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 ) 131 | #define DEFINE_AUTO_ARRAY_KEYFIELD(name,fieldtype,mapname) _FIELD(name, fieldtype, SIZE_OF_ARRAY(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, mapname, 0 ) 132 | #define DEFINE_ARRAY(name,fieldtype, count) _FIELD(name, fieldtype, count, FTYPEDESC_SAVE, NULL, 0 ) 133 | #define DEFINE_ENTITY_FIELD(name,fieldtype) _FIELD(edict_t, name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, #name, 0 ) 134 | #define DEFINE_ENTITY_GLOBAL_FIELD(name,fieldtype) _FIELD(edict_t, name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE | FTYPEDESC_GLOBAL, #name, 0 ) 135 | #define DEFINE_GLOBAL_FIELD(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_GLOBAL | FTYPEDESC_SAVE, NULL, 0 ) 136 | #define DEFINE_GLOBAL_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1, FTYPEDESC_GLOBAL | FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 ) 137 | #define DEFINE_CUSTOM_FIELD(name,datafuncs) { FIELD_CUSTOM, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, datafuncs, NULL } 138 | #define DEFINE_CUSTOM_KEYFIELD(name,datafuncs,mapname) { FIELD_CUSTOM, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_KEY, mapname, datafuncs, NULL } 139 | #define DEFINE_AUTO_ARRAY2D(name,fieldtype) _FIELD(name, fieldtype, ARRAYSIZE2D(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 ) 140 | // Used by byteswap datadescs 141 | #define DEFINE_BITFIELD(name,fieldtype,bitcount) DEFINE_ARRAY(name,fieldtype,((bitcount+FIELD_BITS(fieldtype)-1)&~(FIELD_BITS(fieldtype)-1)) / FIELD_BITS(fieldtype) ) 142 | #define DEFINE_INDEX(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_INDEX, NULL, 0 ) 143 | 144 | #define DEFINE_EMBEDDED( name ) \ 145 | { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name.m_DataMap), sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f } 146 | 147 | #define DEFINE_EMBEDDED_OVERRIDE( name, overridetype ) \ 148 | { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &((overridetype *)0)->m_DataMap, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f } 149 | 150 | #define DEFINE_EMBEDDEDBYREF( name ) \ 151 | { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( *(((classNameTypedef *)0)->name) ), NULL, 0, 0.0f } 152 | 153 | #define DEFINE_EMBEDDED_ARRAY( name, count ) \ 154 | { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, count, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f } 155 | 156 | #define DEFINE_EMBEDDED_AUTO_ARRAY( name ) \ 157 | { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, SIZE_OF_ARRAY( ((classNameTypedef *)0)->name ), FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f } 158 | 159 | #ifndef NO_ENTITY_PREDICTION 160 | 161 | #define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype ) \ 162 | { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &fieldtype::m_PredMap } 163 | 164 | #define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype ) \ 165 | { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &fieldtype::m_PredMap } 166 | 167 | #else 168 | 169 | #define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype ) DEFINE_FIELD_NULL 170 | #define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype ) DEFINE_FIELD_NULL 171 | 172 | #endif 173 | 174 | // Extensions to datamap.h macros for predicted entities only 175 | #define DEFINE_PRED_FIELD(name,fieldtype, flags) _FIELD(name, fieldtype, 1, flags, NULL, 0.0f ) 176 | #define DEFINE_PRED_ARRAY(name,fieldtype, count,flags) _FIELD(name, fieldtype, count, flags, NULL, 0.0f ) 177 | #define DEFINE_FIELD_NAME(localname,netname,fieldtype) _FIELD(localname, fieldtype, 1, 0, #netname, 0.0f ) 178 | // Predictable macros, which include a tolerance for floating point values... 179 | #define DEFINE_PRED_FIELD_TOL(name,fieldtype, flags,tolerance) _FIELD(name, fieldtype, 1, flags, NULL, tolerance ) 180 | #define DEFINE_PRED_ARRAY_TOL(name,fieldtype, count,flags,tolerance) _FIELD(name, fieldtype, count, flags, NULL, tolerance) 181 | #define DEFINE_FIELD_NAME_TOL(localname,netname,fieldtolerance) _FIELD(localname, fieldtype, 1, 0, #netname, tolerance ) 182 | 183 | //#define DEFINE_DATA( name, fieldextname, flags ) _FIELD(name, fieldtype, 1, flags, extname ) 184 | 185 | // INPUTS 186 | #define DEFINE_INPUT( name, fieldtype, inputname ) { fieldtype, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_INPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, inputname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ) } 187 | #define DEFINE_INPUTFUNC( fieldtype, inputname, inputfunc ) { fieldtype, #inputfunc, { NULL, NULL }, 1, FTYPEDESC_INPUT, inputname, NULL, static_cast (&classNameTypedef::inputfunc) } 188 | 189 | // OUTPUTS 190 | // the variable 'name' MUST BE derived from CBaseOutput 191 | // we know the output type from the variable itself, so it doesn't need to be specified here 192 | class ISaveRestoreOps; 193 | extern ISaveRestoreOps *eventFuncs; 194 | #define DEFINE_OUTPUT( name, outputname ) { FIELD_CUSTOM, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_OUTPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, outputname, eventFuncs } 195 | 196 | // replaces EXPORT table for portability and non-DLL based systems (xbox) 197 | #define DEFINE_FUNCTION_RAW( function, func_type ) { FIELD_VOID, nameHolder.GenerateName(#function), { NULL, NULL }, 1, FTYPEDESC_FUNCTIONTABLE, NULL, NULL, (inputfunc_t)((func_type)(&classNameTypedef::function)) } 198 | #define DEFINE_FUNCTION( function ) DEFINE_FUNCTION_RAW( function, inputfunc_t ) 199 | 200 | 201 | #define FTYPEDESC_GLOBAL 0x0001 // This field is masked for global entity save/restore 202 | #define FTYPEDESC_SAVE 0x0002 // This field is saved to disk 203 | #define FTYPEDESC_KEY 0x0004 // This field can be requested and written to by string name at load time 204 | #define FTYPEDESC_INPUT 0x0008 // This field can be written to by string name at run time, and a function called 205 | #define FTYPEDESC_OUTPUT 0x0010 // This field propogates it's value to all targets whenever it changes 206 | #define FTYPEDESC_FUNCTIONTABLE 0x0020 // This is a table entry for a member function pointer 207 | #define FTYPEDESC_PTR 0x0040 // This field is a pointer, not an embedded object 208 | #define FTYPEDESC_OVERRIDE 0x0080 // The field is an override for one in a base class (only used by prediction system for now) 209 | 210 | // Flags used by other systems (e.g., prediction system) 211 | #define FTYPEDESC_INSENDTABLE 0x0100 // This field is present in a network SendTable 212 | #define FTYPEDESC_PRIVATE 0x0200 // The field is local to the client or server only (not referenced by prediction code and not replicated by networking) 213 | #define FTYPEDESC_NOERRORCHECK 0x0400 // The field is part of the prediction typedescription, but doesn't get compared when checking for errors 214 | 215 | #define FTYPEDESC_MODELINDEX 0x0800 // The field is a model index (used for debugging output) 216 | 217 | #define FTYPEDESC_INDEX 0x1000 // The field is an index into file data, used for byteswapping. 218 | 219 | // These flags apply to C_BasePlayer derived objects only 220 | #define FTYPEDESC_VIEW_OTHER_PLAYER 0x2000 // By default you can only view fields on the local player (yourself), 221 | // but if this is set, then we allow you to see fields on other players 222 | #define FTYPEDESC_VIEW_OWN_TEAM 0x4000 // Only show this data if the player is on the same team as the local player 223 | #define FTYPEDESC_VIEW_NEVER 0x8000 // Never show this field to anyone, even the local player (unusual) 224 | 225 | #define TD_MSECTOLERANCE 0.001f // This is a FIELD_FLOAT and should only be checked to be within 0.001 of the networked info 226 | 227 | struct typedescription_t; 228 | 229 | 230 | class ISaveRestoreOps; 231 | 232 | // 233 | // Function prototype for all input handlers. 234 | // 235 | //typedef void (CBaseEntity::*inputfunc_t)(inputdata_t &data); 236 | 237 | struct datamap_t; 238 | struct typedescription_t; 239 | 240 | enum 241 | { 242 | TD_OFFSET_NORMAL = 0, 243 | TD_OFFSET_PACKED = 1, 244 | 245 | // Must be last 246 | TD_OFFSET_COUNT, 247 | }; 248 | 249 | struct typedescription_t 250 | { 251 | fieldtype_t fieldType; 252 | const char *fieldName; 253 | int fieldOffset[TD_OFFSET_COUNT]; // 0 == normal, 1 == packed offset 254 | unsigned short fieldSize; 255 | short flags; 256 | // the name of the variable in the map/fgd data, or the name of the action 257 | const char *externalName; 258 | // pointer to the function set for save/restoring of custom data types 259 | ISaveRestoreOps *pSaveRestoreOps; 260 | // for associating function with string names 261 | //inputfunc_t inputFunc; 262 | void* inputFunc; 263 | // For embedding additional datatables inside this one 264 | datamap_t *td; 265 | 266 | // Stores the actual member variable size in bytes 267 | int fieldSizeInBytes; 268 | 269 | // FTYPEDESC_OVERRIDE point to first baseclass instance if chains_validated has occurred 270 | struct typedescription_t *override_field; 271 | 272 | // Used to track exclusion of baseclass fields 273 | int override_count; 274 | 275 | // Tolerance for field errors for float fields 276 | float fieldTolerance; 277 | }; 278 | 279 | 280 | //----------------------------------------------------------------------------- 281 | // Purpose: stores the list of objects in the hierarchy 282 | // used to iterate through an object's data descriptions 283 | //----------------------------------------------------------------------------- 284 | struct datamap_t 285 | { 286 | typedescription_t *dataDesc; 287 | int dataNumFields; 288 | char const *dataClassName; 289 | datamap_t *baseMap; 290 | 291 | bool chains_validated; 292 | // Have the "packed" offsets been computed 293 | bool packed_offsets_computed; 294 | int packed_size; 295 | 296 | #if defined( _DEBUG ) 297 | bool bValidityChecked; 298 | #endif // _DEBUG 299 | }; 300 | 301 | 302 | //----------------------------------------------------------------------------- 303 | // 304 | // Macros used to implement datadescs 305 | // 306 | #define DECLARE_SIMPLE_DATADESC() \ 307 | static datamap_t m_DataMap; \ 308 | static datamap_t *GetBaseMap(); \ 309 | template friend void DataMapAccess(T *, datamap_t **p); \ 310 | template friend datamap_t *DataMapInit(T *); 311 | 312 | #define DECLARE_DATADESC() \ 313 | DECLARE_SIMPLE_DATADESC() \ 314 | virtual datamap_t *GetDataDescMap( void ); 315 | 316 | #define BEGIN_DATADESC( className ) \ 317 | datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \ 318 | datamap_t *className::GetDataDescMap( void ) { return &m_DataMap; } \ 319 | datamap_t *className::GetBaseMap() { datamap_t *pResult; DataMapAccess((BaseClass *)NULL, &pResult); return pResult; } \ 320 | BEGIN_DATADESC_GUTS( className ) 321 | 322 | #define BEGIN_DATADESC_NO_BASE( className ) \ 323 | datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \ 324 | datamap_t *className::GetDataDescMap( void ) { return &m_DataMap; } \ 325 | datamap_t *className::GetBaseMap() { return NULL; } \ 326 | BEGIN_DATADESC_GUTS( className ) 327 | 328 | #define BEGIN_SIMPLE_DATADESC( className ) \ 329 | datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \ 330 | datamap_t *className::GetBaseMap() { return NULL; } \ 331 | BEGIN_DATADESC_GUTS( className ) 332 | 333 | #define BEGIN_SIMPLE_DATADESC_( className, BaseClass ) \ 334 | datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \ 335 | datamap_t *className::GetBaseMap() { datamap_t *pResult; DataMapAccess((BaseClass *)NULL, &pResult); return pResult; } \ 336 | BEGIN_DATADESC_GUTS( className ) 337 | 338 | #define BEGIN_DATADESC_GUTS( className ) \ 339 | template datamap_t *DataMapInit(T *); \ 340 | template <> datamap_t *DataMapInit( className * ); \ 341 | namespace className##_DataDescInit \ 342 | { \ 343 | datamap_t *g_DataMapHolder = DataMapInit( (className *)NULL ); /* This can/will be used for some clean up duties later */ \ 344 | } \ 345 | \ 346 | template <> datamap_t *DataMapInit( className * ) \ 347 | { \ 348 | typedef className classNameTypedef; \ 349 | static CDatadescGeneratedNameHolder nameHolder(#className); \ 350 | className::m_DataMap.baseMap = className::GetBaseMap(); \ 351 | static typedescription_t dataDesc[] = \ 352 | { \ 353 | { FIELD_VOID,0, {0,0},0,0,0,0,0,0}, /* so you can define "empty" tables */ 354 | 355 | #define END_DATADESC() \ 356 | }; \ 357 | \ 358 | if ( sizeof( dataDesc ) > sizeof( dataDesc[0] ) ) \ 359 | { \ 360 | classNameTypedef::m_DataMap.dataNumFields = SIZE_OF_ARRAY( dataDesc ) - 1; \ 361 | classNameTypedef::m_DataMap.dataDesc = &dataDesc[1]; \ 362 | } \ 363 | else \ 364 | { \ 365 | classNameTypedef::m_DataMap.dataNumFields = 1; \ 366 | classNameTypedef::m_DataMap.dataDesc = dataDesc; \ 367 | } \ 368 | return &classNameTypedef::m_DataMap; \ 369 | } 370 | 371 | // used for when there is no data description 372 | #define IMPLEMENT_NULL_SIMPLE_DATADESC( derivedClass ) \ 373 | BEGIN_SIMPLE_DATADESC( derivedClass ) \ 374 | END_DATADESC() 375 | 376 | #define IMPLEMENT_NULL_SIMPLE_DATADESC_( derivedClass, baseClass ) \ 377 | BEGIN_SIMPLE_DATADESC_( derivedClass, baseClass ) \ 378 | END_DATADESC() 379 | 380 | #define IMPLEMENT_NULL_DATADESC( derivedClass ) \ 381 | BEGIN_DATADESC( derivedClass ) \ 382 | END_DATADESC() 383 | 384 | // helps get the offset of a bitfield 385 | #define BEGIN_BITFIELD( name ) \ 386 | union \ 387 | { \ 388 | char name; \ 389 | struct \ 390 | { 391 | 392 | #define END_BITFIELD() \ 393 | }; \ 394 | }; 395 | 396 | //----------------------------------------------------------------------------- 397 | // Forward compatability with potential seperate byteswap datadescs 398 | 399 | #define DECLARE_BYTESWAP_DATADESC() DECLARE_SIMPLE_DATADESC() 400 | #define BEGIN_BYTESWAP_DATADESC(name) BEGIN_SIMPLE_DATADESC(name) 401 | #define BEGIN_BYTESWAP_DATADESC_(name,base) BEGIN_SIMPLE_DATADESC_(name,base) 402 | #define END_BYTESWAP_DATADESC() END_DATADESC() 403 | 404 | //----------------------------------------------------------------------------- 405 | 406 | template 407 | inline void DataMapAccess(T *ignored, datamap_t **p) 408 | { 409 | *p = &T::m_DataMap; 410 | } 411 | 412 | //----------------------------------------------------------------------------- 413 | 414 | /*class CDatadescGeneratedNameHolder 415 | { 416 | public: 417 | CDatadescGeneratedNameHolder(const char *pszBase) 418 | : m_pszBase(pszBase) 419 | { 420 | m_nLenBase = strlen(m_pszBase); 421 | } 422 | 423 | ~CDatadescGeneratedNameHolder() 424 | { 425 | for (int i = 0; i < m_Names.Count(); i++) 426 | { 427 | delete m_Names[i]; 428 | } 429 | } 430 | 431 | const char *GenerateName(const char *pszIdentifier) 432 | { 433 | char *pBuf = new char[m_nLenBase + strlen(pszIdentifier) + 1]; 434 | strcpy(pBuf, m_pszBase); 435 | strcat(pBuf, pszIdentifier); 436 | m_Names.AddToTail(pBuf); 437 | return pBuf; 438 | } 439 | 440 | private: 441 | const char *m_pszBase; 442 | size_t m_nLenBase; 443 | CUtlVector m_Names; 444 | };*/ 445 | 446 | //----------------------------------------------------------------------------- 447 | 448 | //#include "tier0/memdbgoff.h" 449 | 450 | #endif // DATAMAP_H 451 | -------------------------------------------------------------------------------- /gpua_rad/loadbsp.cu: -------------------------------------------------------------------------------- 1 | #include "cuda_runtime.h" 2 | #include "device_launch_parameters.h" 3 | #include 4 | 5 | 6 | 7 | 8 | /* 9 | cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size); 10 | 11 | __global__ void addKernel(int *c, const int *a, const int *b) 12 | { 13 | int i = threadIdx.x; 14 | c[i] = a[i] + b[i]; 15 | } 16 | 17 | int main() 18 | { 19 | const int arraySize = 5; 20 | const int a[arraySize] = { 1, 2, 3, 4, 5 }; 21 | const int b[arraySize] = { 10, 20, 30, 40, 50 }; 22 | int c[arraySize] = { 0 }; 23 | 24 | // Add vectors in parallel. 25 | cudaError_t cudaStatus = addWithCuda(c, a, b, arraySize); 26 | if (cudaStatus != cudaSuccess) { 27 | fprintf(stderr, "addWithCuda failed!"); 28 | return 1; 29 | } 30 | 31 | printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n", 32 | c[0], c[1], c[2], c[3], c[4]); 33 | 34 | // cudaDeviceReset must be called before exiting in order for profiling and 35 | // tracing tools such as Nsight and Visual Profiler to show complete traces. 36 | cudaStatus = cudaDeviceReset(); 37 | if (cudaStatus != cudaSuccess) { 38 | fprintf(stderr, "cudaDeviceReset failed!"); 39 | return 1; 40 | } 41 | 42 | return 0; 43 | } 44 | 45 | // Helper function for using CUDA to add vectors in parallel. 46 | cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size) 47 | { 48 | int *dev_a = 0; 49 | int *dev_b = 0; 50 | int *dev_c = 0; 51 | cudaError_t cudaStatus; 52 | 53 | // Choose which GPU to run on, change this on a multi-GPU system. 54 | cudaStatus = cudaSetDevice(0); 55 | if (cudaStatus != cudaSuccess) { 56 | fprintf(stderr, "cudaSetDevice failed! Do you have a CUDA-capable GPU installed?"); 57 | goto Error; 58 | } 59 | 60 | // Allocate GPU buffers for three vectors (two input, one output) . 61 | cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(int)); 62 | if (cudaStatus != cudaSuccess) { 63 | fprintf(stderr, "cudaMalloc failed!"); 64 | goto Error; 65 | } 66 | 67 | cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(int)); 68 | if (cudaStatus != cudaSuccess) { 69 | fprintf(stderr, "cudaMalloc failed!"); 70 | goto Error; 71 | } 72 | 73 | cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(int)); 74 | if (cudaStatus != cudaSuccess) { 75 | fprintf(stderr, "cudaMalloc failed!"); 76 | goto Error; 77 | } 78 | 79 | // Copy input vectors from host memory to GPU buffers. 80 | cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(int), cudaMemcpyHostToDevice); 81 | if (cudaStatus != cudaSuccess) { 82 | fprintf(stderr, "cudaMemcpy failed!"); 83 | goto Error; 84 | } 85 | 86 | cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(int), cudaMemcpyHostToDevice); 87 | if (cudaStatus != cudaSuccess) { 88 | fprintf(stderr, "cudaMemcpy failed!"); 89 | goto Error; 90 | } 91 | 92 | // Launch a kernel on the GPU with one thread for each element. 93 | addKernel<<<1, size>>>(dev_c, dev_a, dev_b); 94 | 95 | // Check for any errors launching the kernel 96 | cudaStatus = cudaGetLastError(); 97 | if (cudaStatus != cudaSuccess) { 98 | fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus)); 99 | goto Error; 100 | } 101 | 102 | // cudaDeviceSynchronize waits for the kernel to finish, and returns 103 | // any errors encountered during the launch. 104 | cudaStatus = cudaDeviceSynchronize(); 105 | if (cudaStatus != cudaSuccess) { 106 | fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus); 107 | goto Error; 108 | } 109 | 110 | // Copy output vector from GPU buffer to host memory. 111 | cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost); 112 | if (cudaStatus != cudaSuccess) { 113 | fprintf(stderr, "cudaMemcpy failed!"); 114 | goto Error; 115 | } 116 | 117 | Error: 118 | cudaFree(dev_c); 119 | cudaFree(dev_a); 120 | cudaFree(dev_b); 121 | 122 | return cudaStatus; 123 | } 124 | */ -------------------------------------------------------------------------------- /gpua_rad/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "prettyprint.h" 7 | 8 | #include "rad.h" 9 | 10 | int main(int argc, char** argv) 11 | { 12 | CTimer timer("Main"); 13 | CRAD* rad = new CRAD(argv[2]); 14 | 15 | rad->ReadLights(argv[1]); 16 | rad->LoadBSP(); 17 | rad->Setup(); 18 | rad->ParseEntities(); 19 | //rad->ExtractBrushEntityShadowCasters(); 20 | rad->AddBrushesForRayTrace(); 21 | delete rad; 22 | 23 | timer.End(); 24 | getchar(); 25 | 26 | return 0; 27 | } -------------------------------------------------------------------------------- /gpua_rad/poly.cpp: -------------------------------------------------------------------------------- 1 | #include "poly.h" 2 | #include "math.h" 3 | 4 | // doesn't seem to need to be here? -- in threads.h 5 | //extern int numthreads; 6 | 7 | // counters are only bumped when running single threaded, 8 | // because they are an awefull coherence problem 9 | int c_active_windings; 10 | int c_peak_windings; 11 | int c_winding_allocs; 12 | int c_winding_points; 13 | 14 | winding_t *winding_pool[MAX_POINTS_ON_WINDING + 4]; 15 | 16 | winding_t *AllocWinding(int points) 17 | { 18 | winding_t *w; 19 | 20 | c_winding_allocs++; 21 | c_winding_points += points; 22 | c_active_windings++; 23 | if (c_active_windings > c_peak_windings) 24 | c_peak_windings = c_active_windings; 25 | 26 | if (winding_pool[points]) 27 | { 28 | w = winding_pool[points]; 29 | winding_pool[points] = w->next; 30 | } 31 | else 32 | { 33 | w = (winding_t *)malloc(sizeof(*w)); 34 | w->p = (Vector *)calloc(points, sizeof(Vector)); 35 | } 36 | 37 | w->numpoints = 0; // None are occupied yet even though allocated. 38 | w->maxpoints = points; 39 | w->next = NULL; 40 | return w; 41 | } 42 | 43 | void FreeWinding(winding_t *w) 44 | { 45 | if (w->numpoints == 0xdeaddead) 46 | pp::Error("FreeWinding: freed a freed winding"); 47 | 48 | w->numpoints = 0xdeaddead; // flag as freed 49 | w->next = winding_pool[w->maxpoints]; 50 | winding_pool[w->maxpoints] = w; 51 | } 52 | 53 | /* 54 | ================= 55 | BaseWindingForPlane 56 | ================= 57 | */ 58 | winding_t *BaseWindingForPlane(Vector &normal, float dist) 59 | { 60 | int i, x; 61 | float max, v; 62 | Vector org, vright, vup; 63 | winding_t *w; 64 | 65 | // find the major axis 66 | 67 | max = -1; 68 | x = -1; 69 | for (i = 0; i<3; i++) 70 | { 71 | v = fabs(normal[i]); 72 | if (v > max) 73 | { 74 | x = i; 75 | max = v; 76 | } 77 | } 78 | 79 | if (x == -1) 80 | pp::Error("BaseWindingForPlane: no axis found"); 81 | 82 | vup.Init(); 83 | 84 | switch (x) 85 | { 86 | case 0: 87 | case 1: 88 | vup[2] = 1; 89 | break; 90 | case 2: 91 | vup[0] = 1; 92 | break; 93 | } 94 | 95 | v = DotProduct(vup, normal); 96 | VectorMA(vup, -v, normal, vup); 97 | VectorNormalize(vup); 98 | 99 | VectorScale(normal, dist, org); 100 | 101 | CrossProduct(vup, normal, vright); 102 | 103 | VectorScale(vup, (MAX_COORD_INTEGER * 4), vup); 104 | VectorScale(vright, (MAX_COORD_INTEGER * 4), vright); 105 | 106 | // project a really big axis aligned box onto the plane 107 | w = AllocWinding(4); 108 | 109 | VectorSubtract(org, vright, w->p[0]); 110 | VectorAdd(w->p[0], vup, w->p[0]); 111 | 112 | VectorAdd(org, vright, w->p[1]); 113 | VectorAdd(w->p[1], vup, w->p[1]); 114 | 115 | VectorAdd(org, vright, w->p[2]); 116 | VectorSubtract(w->p[2], vup, w->p[2]); 117 | 118 | VectorSubtract(org, vright, w->p[3]); 119 | VectorSubtract(w->p[3], vup, w->p[3]); 120 | 121 | w->numpoints = 4; 122 | 123 | return w; 124 | } 125 | 126 | /* 127 | ============= 128 | ChopWindingInPlace 129 | ============= 130 | */ 131 | void ChopWindingInPlace(winding_t **inout, Vector &normal, float dist, float epsilon) 132 | { 133 | winding_t *in; 134 | float dists[MAX_POINTS_ON_WINDING + 4]; 135 | int sides[MAX_POINTS_ON_WINDING + 4]; 136 | int counts[3]; 137 | float dot; 138 | int i, j; 139 | Vector mid(0.0f, 0.0f, 0.0f); 140 | winding_t *f; 141 | int maxpts; 142 | 143 | in = *inout; 144 | counts[0] = counts[1] = counts[2] = 0; 145 | // determine sides for each point 146 | for (i = 0; inumpoints; i++) 147 | { 148 | dot = DotProduct(in->p[i], normal); 149 | dot -= dist; 150 | dists[i] = dot; 151 | if (dot > epsilon) 152 | { 153 | sides[i] = SIDE_FRONT; 154 | } 155 | else if (dot < -epsilon) 156 | { 157 | sides[i] = SIDE_BACK; 158 | } 159 | else 160 | { 161 | sides[i] = SIDE_ON; 162 | } 163 | counts[sides[i]]++; 164 | } 165 | sides[i] = sides[0]; 166 | dists[i] = dists[0]; 167 | 168 | if (!counts[0]) 169 | { 170 | FreeWinding(in); 171 | *inout = NULL; 172 | return; 173 | } 174 | if (!counts[1]) 175 | return; // inout stays the same 176 | 177 | maxpts = in->numpoints + 4; // cant use counts[0]+2 because 178 | // of fp grouping errors 179 | 180 | f = AllocWinding(maxpts); 181 | 182 | for (i = 0; inumpoints; i++) 183 | { 184 | Vector& p1 = in->p[i]; 185 | 186 | if (sides[i] == SIDE_ON) 187 | { 188 | VectorCopy(p1, f->p[f->numpoints]); 189 | f->numpoints++; 190 | continue; 191 | } 192 | 193 | if (sides[i] == SIDE_FRONT) 194 | { 195 | VectorCopy(p1, f->p[f->numpoints]); 196 | f->numpoints++; 197 | } 198 | 199 | if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i]) 200 | continue; 201 | 202 | // generate a split point 203 | Vector& p2 = in->p[(i + 1) % in->numpoints]; 204 | 205 | dot = dists[i] / (dists[i] - dists[i + 1]); 206 | for (j = 0; j<3; j++) 207 | { // avoid round off error when possible 208 | if (normal[j] == 1) 209 | mid[j] = dist; 210 | else if (normal[j] == -1) 211 | mid[j] = -dist; 212 | else 213 | mid[j] = p1[j] + dot*(p2[j] - p1[j]); 214 | } 215 | 216 | VectorCopy(mid, f->p[f->numpoints]); 217 | f->numpoints++; 218 | } 219 | 220 | if (f->numpoints > maxpts) 221 | pp::Error("ClipWinding: points exceeded estimate"); 222 | if (f->numpoints > MAX_POINTS_ON_WINDING) 223 | pp::Error("ClipWinding: MAX_POINTS_ON_WINDING"); 224 | 225 | FreeWinding(in); 226 | *inout = f; 227 | } -------------------------------------------------------------------------------- /gpua_rad/poly.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPUARAD_POLY_H_ 2 | #define _GPUARAD_POLY_H_ 3 | 4 | #include "prettyprint.h" 5 | 6 | #include "worldsize.h" 7 | #include "vector.h" 8 | 9 | #define MAX_POINTS_ON_WINDING 64 10 | 11 | // you can define on_epsilon in the makefile as tighter 12 | // point on plane side epsilon 13 | // todo: need a world-space epsilon, a lightmap-space epsilon, and a texture space epsilon 14 | // or at least convert from a world-space epsilon to lightmap and texture space epsilons 15 | #ifndef ON_EPSILON 16 | #define ON_EPSILON 0.1 17 | #endif 18 | 19 | // Used to represent sides of things like planes. 20 | #define SIDE_FRONT 0 21 | #define SIDE_BACK 1 22 | #define SIDE_ON 2 23 | #define SIDE_CROSS -2 // necessary for polylib.c 24 | 25 | class winding_t 26 | { 27 | public: 28 | int numpoints; 29 | Vector *p; // variable sized 30 | int maxpoints; 31 | winding_t *next; 32 | }; 33 | 34 | void ChopWindingInPlace(winding_t **inout, Vector &normal, float dist, float epsilon); 35 | winding_t *BaseWindingForPlane(Vector &normal, float dist); 36 | 37 | winding_t *AllocWinding(int points); 38 | void FreeWinding(winding_t *w); 39 | 40 | #endif // _GPUARAD_POLY_H_ -------------------------------------------------------------------------------- /gpua_rad/prettyprint.cpp: -------------------------------------------------------------------------------- 1 | #include "prettyprint.h" 2 | 3 | namespace pp 4 | { 5 | size_t color_printf(eConsoleColor color, const char * format, ...) 6 | { 7 | HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 8 | CONSOLE_SCREEN_BUFFER_INFO info; 9 | WORD new_colors; 10 | char* out; 11 | va_list args; 12 | size_t ret; 13 | 14 | va_start(args, format); 15 | ret = _vscprintf(format, args); 16 | out = new char[ret + 1]; 17 | ret = vsnprintf(out, ret + 1, format, args); 18 | va_end(args); 19 | 20 | if (GetConsoleScreenBufferInfo(hConsole, &info)) 21 | { 22 | new_colors = info.wAttributes; 23 | new_colors &= ~eConsoleColor::ALL; 24 | new_colors |= color; 25 | 26 | SetConsoleTextAttribute(hConsole, new_colors); 27 | printf("%s", out); 28 | SetConsoleTextAttribute(hConsole, info.wAttributes); 29 | } 30 | else 31 | { 32 | printf("%s", out); 33 | } 34 | delete out; 35 | return ret; 36 | } 37 | 38 | void print_prefix(eConsoleColor color, const char* prefix) 39 | { 40 | HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 41 | CONSOLE_SCREEN_BUFFER_INFO info; 42 | WORD new_colors; 43 | 44 | printf("["); 45 | if (GetConsoleScreenBufferInfo(hConsole, &info)) 46 | { 47 | new_colors = info.wAttributes; 48 | new_colors &= ~eConsoleColor::ALL; 49 | new_colors |= color; 50 | 51 | SetConsoleTextAttribute(hConsole, new_colors); 52 | printf("%s", prefix); 53 | SetConsoleTextAttribute(hConsole, info.wAttributes); 54 | } 55 | else 56 | { 57 | printf("%s", prefix); 58 | } 59 | printf("] "); 60 | } 61 | 62 | size_t Success(const char * format, ...) 63 | { 64 | char* out; 65 | va_list args; 66 | size_t ret; 67 | 68 | va_start(args, format); 69 | ret = _vscprintf(format, args); 70 | out = new char[ret + 1]; 71 | ret = vsnprintf(out, ret + 1, format, args); 72 | va_end(args); 73 | 74 | print_prefix(eConsoleColor::GREEN, "+"); 75 | 76 | printf("%s\n", out); 77 | delete out; 78 | return ret; 79 | } 80 | 81 | size_t Info(const char * format, ...) 82 | { 83 | char* out; 84 | va_list args; 85 | size_t ret; 86 | 87 | va_start(args, format); 88 | ret = _vscprintf(format, args); 89 | out = new char[ret + 1]; 90 | ret = vsnprintf(out, ret + 1, format, args); 91 | va_end(args); 92 | 93 | print_prefix(eConsoleColor::BLUE, "*"); 94 | 95 | printf("%s\n", out); 96 | delete out; 97 | return ret; 98 | } 99 | 100 | size_t Warning(const char * format, ...) 101 | { 102 | char* out; 103 | va_list args; 104 | size_t ret; 105 | 106 | va_start(args, format); 107 | ret = _vscprintf(format, args); 108 | out = new char[ret + 1]; 109 | ret = vsnprintf(out, ret + 1, format, args); 110 | va_end(args); 111 | 112 | print_prefix(eConsoleColor::YELLOW, "!"); 113 | 114 | printf("%s\n", out); 115 | delete out; 116 | return ret; 117 | } 118 | 119 | size_t Error(const char * format, ...) 120 | { 121 | char* out; 122 | va_list args; 123 | size_t ret; 124 | 125 | va_start(args, format); 126 | ret = _vscprintf(format, args); 127 | out = new char[ret + 1]; 128 | ret = vsnprintf(out, ret + 1, format, args); 129 | va_end(args); 130 | 131 | print_prefix(eConsoleColor::RED, "-"); 132 | 133 | printf("%s\n", out); 134 | delete out; 135 | 136 | getchar(); 137 | exit(1); 138 | 139 | return ret; 140 | } 141 | 142 | size_t Fatal(const char * format, ...) 143 | { 144 | char* out; 145 | va_list args; 146 | size_t ret; 147 | 148 | va_start(args, format); 149 | ret = _vscprintf(format, args); 150 | out = new char[ret + 1]; 151 | ret = vsnprintf(out, ret + 1, format, args); 152 | va_end(args); 153 | 154 | print_prefix(eConsoleColor::RED, "FATAL"); 155 | 156 | printf("%s\n", out); 157 | delete out; 158 | return ret; 159 | } 160 | 161 | size_t Hexdump(const unsigned char * base, size_t len) 162 | { 163 | size_t i, j, h; 164 | for (i = 0; i < (len / 0x10) + 1; i++) 165 | { 166 | for (j = 0; j < 0x10; j++) 167 | { 168 | h = (i * 0x10) + j; 169 | 170 | if (h >= len) 171 | { 172 | break; 173 | } 174 | 175 | if (h % 16 == 0) 176 | { 177 | if (h % 0x80 == 0) 178 | { 179 | if (i != 0) 180 | { 181 | printf("\n"); 182 | } 183 | 184 | color_printf(eConsoleColor::DARKMAGENTA, "%- 6X", h); 185 | printf(" -> "); 186 | } 187 | else 188 | { 189 | printf("\n%- 6X -> ", (unsigned int)h); 190 | } 191 | } 192 | else 193 | { 194 | #ifndef _WIN64 195 | if (h % 4 == 0) 196 | { 197 | printf(" "); 198 | } 199 | #else 200 | if (h % 8 == 0) 201 | { 202 | printf(" "); 203 | } 204 | #endif 205 | } 206 | 207 | if (base[h] >= 0x0 && base[h] <= 0x1F) // 0x0 - 0x1F 208 | color_printf(eConsoleColor::DARKRED, "%02X ", base[h]); 209 | else if (base[h] >= 0x20 && base[h] <= 0x7E) // 0x20 - 0x7E 210 | color_printf(eConsoleColor::WHITE, "%02X ", base[h]); 211 | else if (base[h] >= 0x7F && base[h] <= 0xFF) // 0x20 - 0x7E 212 | color_printf(eConsoleColor::GRAY, "%02X ", base[h]); 213 | } 214 | printf(" "); 215 | for (j = 0; j < 0x10; j++) 216 | { 217 | h = (i * 0x10) + j; 218 | 219 | if (h >= len) 220 | { 221 | break; 222 | } 223 | 224 | if (base[h] >= 0x0 && base[h] <= 0x1F) // 0x0 - 0x1F 225 | color_printf(eConsoleColor::DARKRED, "."); 226 | else if (base[h] >= 0x20 && base[h] <= 0x7E) // 0x20 - 0x7E 227 | { 228 | switch (base[h]) 229 | { 230 | case 0x25: // Weird stuff with this char 231 | color_printf(eConsoleColor::WHITE, "%%%%"); 232 | break; 233 | default: 234 | color_printf(eConsoleColor::WHITE, "%c", base[h]); 235 | break; 236 | } 237 | } 238 | else if (base[h] >= 0x7F && base[h] <= 0xFF) // 0x20 - 0x7E 239 | color_printf(eConsoleColor::GRAY, "."); 240 | } 241 | } 242 | printf("\n"); 243 | return i; 244 | } 245 | 246 | bool GetColor(short &ret) 247 | { 248 | CONSOLE_SCREEN_BUFFER_INFO info; 249 | if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info)) 250 | return false; 251 | ret = info.wAttributes; 252 | return true; 253 | } 254 | } -------------------------------------------------------------------------------- /gpua_rad/prettyprint.h: -------------------------------------------------------------------------------- 1 | #ifndef _PRETTYPRINT_H_ 2 | #define _PRETTYPRINT_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace pp 10 | { 11 | enum eConsoleColor 12 | { 13 | BLACK = 0, 14 | DARKBLUE = FOREGROUND_BLUE, 15 | DARKGREEN = FOREGROUND_GREEN, 16 | DARKCYAN = FOREGROUND_GREEN | FOREGROUND_BLUE, 17 | DARKRED = FOREGROUND_RED, 18 | DARKMAGENTA = FOREGROUND_RED | FOREGROUND_BLUE, 19 | DARKYELLOW = FOREGROUND_RED | FOREGROUND_GREEN, 20 | DARKGRAY = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, 21 | GRAY = FOREGROUND_INTENSITY, 22 | BLUE = FOREGROUND_INTENSITY | FOREGROUND_BLUE, 23 | GREEN = FOREGROUND_INTENSITY | FOREGROUND_GREEN, 24 | CYAN = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE, 25 | RED = FOREGROUND_INTENSITY | FOREGROUND_RED, 26 | MAGENTA = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE, 27 | YELLOW = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN, 28 | WHITE = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, 29 | ALL = FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED 30 | }; 31 | 32 | extern size_t Success(const char* format, ...); 33 | extern size_t Info(const char* format, ...); 34 | extern size_t Warning(const char* format, ...); 35 | extern size_t Error(const char* format, ...); 36 | extern size_t Fatal(const char* format, ...); 37 | extern size_t Hexdump(const unsigned char* base, size_t len); 38 | } 39 | 40 | #endif // _PRETTYPRINT_H_ -------------------------------------------------------------------------------- /gpua_rad/rad.cpp: -------------------------------------------------------------------------------- 1 | #include "rad.h" 2 | 3 | CRAD::CRAD(const char * filename) : CTrace(filename) 4 | { 5 | m_bHDR = true; 6 | m_iNumBounce = 100; 7 | m_vecAmbient.Init(); 8 | m_flLightscale = 1.0f; 9 | m_bStaticPropLighting = false; 10 | } 11 | 12 | CRAD::~CRAD() 13 | { 14 | m_vTexLights.clear(); 15 | m_vSzNoShadowMaterialNames.clear(); 16 | m_vSzForcedTextureShadowsOnModel.clear(); 17 | } 18 | 19 | void CRAD::ReadLights(const char * filename) 20 | { 21 | Vector v; 22 | texlight_t tl; 23 | 24 | std::string s; 25 | std::ifstream ifs(filename); 26 | 27 | char sztl[MAX_TEXLIGHT_NAME]; 28 | int file_texlights = 0; 29 | 30 | if (!ifs) 31 | { 32 | pp::Warning("Couldn't open texlight file %s.", filename); 33 | } 34 | 35 | pp::Info("Reading texlights from %s", filename); 36 | 37 | while (std::getline(ifs, s)) 38 | { 39 | size_t start_off; 40 | size_t off; 41 | 42 | // empty line 43 | if (!s.length()) 44 | { 45 | continue; 46 | } 47 | 48 | if (s.rfind("hdr:", 0) == 0) 49 | { 50 | start_off = 5; 51 | if (!m_bHDR) 52 | { 53 | continue; 54 | } 55 | } 56 | else if (s.rfind("ldr:", 0) == 0) 57 | { 58 | start_off = 5; 59 | if (m_bHDR) 60 | { 61 | continue; 62 | } 63 | } 64 | else if (s.rfind("noshadow ", 0) == 0) 65 | { 66 | off = GetNextColumn(s, " \t", start_off); 67 | 68 | if (off < 0 && off != std::string::npos) 69 | { 70 | pp::Warning("Could not find delimeter"); 71 | continue; 72 | } 73 | 74 | off++; 75 | 76 | m_vSzNoShadowMaterialNames.push_back(_strdup(s.c_str() + off)); 77 | //pp::Info("Found noshadow: %s", s.c_str() + off); 78 | continue; 79 | } 80 | else if (s.rfind("forcetextureshadow ", 0) == 0) 81 | { 82 | off = GetNextColumn(s, " \t", start_off); 83 | 84 | if (off < 0 && off != std::string::npos) 85 | { 86 | pp::Warning("Could not find delimeter"); 87 | continue; 88 | } 89 | 90 | off++; 91 | 92 | m_vSzForcedTextureShadowsOnModel.push_back(_strdup(s.c_str() + off)); 93 | //pp::Info("Found forced shadow: %s", s.c_str() + off); 94 | continue; 95 | } 96 | 97 | off = GetNextColumn(s, " \t", start_off); 98 | 99 | if (off < 0 && off != std::string::npos) 100 | { 101 | pp::Warning("Could not find delimeter"); 102 | continue; 103 | } 104 | 105 | if (!LightForString(s.c_str() + off, v)) 106 | { 107 | continue; 108 | } 109 | 110 | if (m_vTexLights.size() > MAX_TEXLIGHTS) 111 | { 112 | pp::Error("Too many texlights, max = %d", MAX_TEXLIGHTS); 113 | } 114 | 115 | size_t len = ((off - start_off) >= MAX_TEXLIGHT_NAME) ? (MAX_TEXLIGHT_NAME - 1) : (off - start_off); 116 | strncpy_s(sztl, s.c_str() + start_off, len); 117 | sztl[len] = '\0'; 118 | 119 | for (auto texlight : m_vTexLights) 120 | { 121 | if (strcmp(texlight.name, sztl) == 0) 122 | { 123 | if (strcmp(texlight.filename, filename) == 0) 124 | { 125 | pp::Error("ERROR\a: Duplication of '%s' in file '%s'!\n", 126 | texlight.name, texlight.filename); 127 | } 128 | else if (texlight.value[0] != v[0] 129 | || texlight.value[1] != v[1] 130 | || texlight.value[2] != v[2]) 131 | { 132 | pp::Warning("Warning: Overriding '%s' from '%s' with '%s'!\n", 133 | texlight.name, texlight.filename, filename); 134 | } 135 | else 136 | { 137 | pp::Warning("Warning: Redundant '%s' def in '%s' AND '%s'!\n", 138 | texlight.name, texlight.filename, filename); 139 | } 140 | break; 141 | } 142 | } 143 | 144 | strncpy_s(tl.name, sztl, MAX_TEXLIGHT_NAME); 145 | tl.value = v; 146 | tl.filename = filename; 147 | file_texlights++; 148 | m_vTexLights.push_back(tl); 149 | //pp::Info("Found texlight: %s, %f, %f, %f", tl.name, tl.value.x, tl.value.y, tl.value.z); 150 | } 151 | 152 | pp::Success("Parsed %i texlights from %s\n", file_texlights, filename); 153 | 154 | ifs.close(); 155 | } 156 | 157 | int CRAD::LightForString(const char * light, Vector & intensity) 158 | { 159 | double r, g, b, scaler; 160 | int argCnt; 161 | 162 | intensity.Init(); 163 | 164 | // scanf into doubles, then assign, so it is vec_t size independent 165 | r = g = b = scaler = 0; 166 | double r_hdr, g_hdr, b_hdr, scaler_hdr; 167 | argCnt = sscanf_s(light, "%lf %lf %lf %lf %lf %lf %lf %lf", 168 | &r, &g, &b, &scaler, &r_hdr, &g_hdr, &b_hdr, &scaler_hdr); 169 | 170 | if (argCnt == 8) // 2 4-tuples 171 | { 172 | if (m_bHDR) 173 | { 174 | r = r_hdr; 175 | g = g_hdr; 176 | b = b_hdr; 177 | scaler = scaler_hdr; 178 | } 179 | argCnt = 4; 180 | } 181 | 182 | // make sure light is legal 183 | if (r < 0.0f || g < 0.0f || b < 0.0f || scaler < 0.0f) 184 | { 185 | pp::Warning("Invalid light\n"); 186 | intensity.Init(0.0f, 0.0f, 0.0f); 187 | return false; 188 | } 189 | 190 | intensity[0] = float(pow(r / 255.0, 2.2) * 255.0); // convert to linear 191 | 192 | switch (argCnt) 193 | { 194 | case 1: 195 | // The R,G,B values are all equal. 196 | intensity[1] = intensity[2] = intensity[0]; 197 | break; 198 | 199 | case 3: 200 | case 4: 201 | // Save the other two G,B values. 202 | intensity[1] = float(pow(g / 255.0, 2.2) * 255); 203 | intensity[2] = float(pow(b / 255.0, 2.2) * 255); 204 | 205 | // Did we also get an "intensity" scaler value too? 206 | if (argCnt == 4) 207 | { 208 | // Scale the normalized 0-255 R,G,B values by the intensity scaler 209 | VectorScale(intensity, float(scaler / 255.0f), intensity); 210 | } 211 | break; 212 | 213 | default: 214 | pp::Warning("Unknown light specifier type - %s\n", light); 215 | return false; 216 | } 217 | // scale up source lights by scaling factor 218 | VectorScale(intensity, m_flLightscale, intensity); 219 | return true; 220 | } 221 | 222 | size_t CRAD::GetNextColumn(std::string s, const char * delims, size_t start) 223 | { 224 | size_t tmp_off = start; 225 | size_t off; 226 | 227 | off = s.find_first_of(" \t", tmp_off); 228 | 229 | while (off != std::string::npos && (off - tmp_off) < 0) 230 | { 231 | tmp_off = off + 1; 232 | off = s.find_first_of(" \t", tmp_off); 233 | } 234 | 235 | return off; 236 | } 237 | 238 | void CRAD::Setup() 239 | { 240 | if (m_bStaticPropLighting) 241 | { 242 | m_fLevelFlags |= m_bHDR ? LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_HDR : LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_NONHDR; 243 | } 244 | else 245 | { 246 | m_fLevelFlags &= ~(LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_HDR | LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_NONHDR); 247 | } 248 | 249 | // now, we need to set our face ptr depending upon hdr, and if hdr, init it 250 | if (m_bHDR) 251 | { 252 | m_pFaces = m_dFacesHDR; 253 | if (m_iNumFacesHDR == 0) 254 | { 255 | m_iNumFacesHDR = m_iNumFaces; 256 | memcpy(m_dFacesHDR, m_dFaces, m_iNumFaces * sizeof(*m_dFaces)); 257 | } 258 | } 259 | else 260 | { 261 | m_pFaces = m_dFaces; 262 | } 263 | 264 | if (!m_iVisDataSize) 265 | { 266 | pp::Info("No vis information, direct lighting only.\n"); 267 | m_iNumBounce = 0; 268 | m_vecAmbient[0] = m_vecAmbient[1] = m_vecAmbient[2] = 0.1f; 269 | m_dVis->numclusters = CountClusters(); 270 | } 271 | 272 | m_vFacePatches.resize(MAX_MAP_FACES); 273 | m_vFaceParents.resize(MAX_MAP_FACES); 274 | m_vClusterChildren.resize(MAX_MAP_CLUSTERS); 275 | 276 | for (int i = 0; i < MAX_MAP_FACES; i++) 277 | { 278 | m_vFacePatches[i] = INVALID_INDEX; 279 | m_vFaceParents[i] = INVALID_INDEX; 280 | } 281 | 282 | for (int i = 0; i < MAX_MAP_CLUSTERS; i++) 283 | { 284 | m_vClusterChildren[i] = INVALID_INDEX; 285 | } 286 | } 287 | 288 | int CRAD::CountClusters() 289 | { 290 | int cluster_count = 0; 291 | 292 | for (int i = 0; i < m_iNumLeafs; i++) 293 | { 294 | if (m_dLeafs[i].cluster > cluster_count) 295 | cluster_count = m_dLeafs[i].cluster; 296 | } 297 | 298 | return cluster_count + 1; 299 | } 300 | -------------------------------------------------------------------------------- /gpua_rad/rad.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPUA_RAD_H_ 2 | #define _GPUA_RAD_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "prettyprint.h" 10 | 11 | #include "trace.h" 12 | 13 | #define INVALID_INDEX -1 14 | 15 | struct texlight_t 16 | { 17 | char name[MAX_TEXLIGHT_NAME]; 18 | Vector value; 19 | const char* filename; 20 | }; 21 | 22 | class CRAD : public CTrace 23 | { 24 | public: 25 | CRAD(const char* filename); 26 | ~CRAD(); 27 | void ReadLights(const char* filename); 28 | int LightForString(const char* light, Vector &intensity); 29 | size_t GetNextColumn(std::string s, const char* delims, size_t start); 30 | void Setup(); 31 | int CountClusters(); 32 | 33 | private: 34 | // Settings 35 | bool m_bHDR; 36 | Vector m_vecAmbient; 37 | float m_flLightscale; 38 | bool m_bStaticPropLighting; 39 | unsigned int m_iNumBounce; // 25; /* Originally this was 8 */ 40 | // Important stuff 41 | 42 | /* TODO SetHdrMode() */ 43 | std::vector* m_pvLightData; 44 | std::vector* m_pvLeafAmbientIndex; 45 | std::vector* m_pvLeafAmbientLighting; 46 | /* 47 | int *pNumWorldLights = &numworldlightsLDR; 48 | dworldlight_t *m_pdWorldLights = dworldlightsLDR; 49 | */ 50 | /* TODO SetHdrMode() */ 51 | 52 | std::vector m_vFacePatches; 53 | std::vector m_vFaceParents; 54 | std::vector m_vClusterChildren; 55 | 56 | std::vector m_vTexLights; 57 | std::vector m_vSzNoShadowMaterialNames; 58 | std::vector m_vSzForcedTextureShadowsOnModel; 59 | }; 60 | #endif -------------------------------------------------------------------------------- /gpua_rad/raytrace.cpp: -------------------------------------------------------------------------------- 1 | #include "raytrace.h" 2 | #include "math.h" 3 | 4 | CRayTracingEnvironment RTEnv; 5 | 6 | void CRayTracingEnvironment::AddTriangle(int32_t id, const Vector & v1, const Vector & v2, const Vector & v3, const Vector & color) 7 | { 8 | AddTriangle(id, v1, v2, v3, color, 0, 0); 9 | } 10 | 11 | void CRayTracingEnvironment::AddTriangle(int32_t id, const Vector & v1, const Vector & v2, const Vector & v3, const Vector & color, uint16_t flags, int32_t materialIndex) 12 | { 13 | CacheOptimizedTriangle tmptri; 14 | tmptri.m_Data.m_GeometryData.m_nTriangleID = id; 15 | tmptri.Vertex(0) = v1; 16 | tmptri.Vertex(1) = v2; 17 | tmptri.Vertex(2) = v3; 18 | tmptri.m_Data.m_GeometryData.m_nFlags = flags; 19 | OptimizedTriangleList.push_back(tmptri); 20 | if (!(Flags & RTE_FLAGS_DONT_STORE_TRIANGLE_COLORS)) 21 | TriangleColors.push_back(color); 22 | if (!(Flags & RTE_FLAGS_DONT_STORE_TRIANGLE_MATERIALS)) 23 | TriangleMaterials.push_back(materialIndex); 24 | } 25 | 26 | static Vector GetEdgeEquation(const Vector &p1, const Vector &p2, int c1, int c2, Vector InsidePoint) 27 | { 28 | float nx = p1[c2] - p2[c2]; 29 | float ny = p2[c1] - p1[c1]; 30 | float d = -(nx*p1[c1] + ny*p1[c2]); 31 | // assert(fabs(nx*p1[c1]+ny*p1[c2]+d)<0.01); 32 | // assert(fabs(nx*p2[c1]+ny*p2[c2]+d)<0.01); 33 | 34 | // use the convention that negative is "outside" 35 | float trial_dist = InsidePoint[c1] * nx + InsidePoint[c2] * ny + d; 36 | if (trial_dist<0) 37 | { 38 | nx = -nx; 39 | ny = -ny; 40 | d = -d; 41 | trial_dist = -trial_dist; 42 | } 43 | nx /= trial_dist; // scale so that it will be =1.0 at the oppositve vertex 44 | ny /= trial_dist; 45 | d /= trial_dist; 46 | 47 | return Vector(nx, ny, d); 48 | } 49 | 50 | void CacheOptimizedTriangle::ChangeIntoIntersectionFormat(void) 51 | { 52 | // lose the vertices and use edge equations instead 53 | 54 | // grab the whole original triangle to we don't overwrite it 55 | TriGeometryData_t srcTri = m_Data.m_GeometryData; 56 | 57 | m_Data.m_IntersectData.m_nFlags = srcTri.m_nFlags; 58 | m_Data.m_IntersectData.m_nTriangleID = srcTri.m_nTriangleID; 59 | 60 | Vector p1 = srcTri.Vertex(0); 61 | Vector p2 = srcTri.Vertex(1); 62 | Vector p3 = srcTri.Vertex(2); 63 | 64 | Vector e1 = p2 - p1; 65 | Vector e2 = p3 - p1; 66 | 67 | Vector N = e1.Cross(e2); 68 | N.NormalizeInPlace(); 69 | // now, determine which axis to drop 70 | int drop_axis = 0; 71 | for (int c = 1; c<3; c++) 72 | if (fabs(N[c]) > fabs(N[drop_axis])) 73 | drop_axis = c; 74 | 75 | m_Data.m_IntersectData.m_flD = N.Dot(p1); 76 | m_Data.m_IntersectData.m_flNx = N.x; 77 | m_Data.m_IntersectData.m_flNy = N.y; 78 | m_Data.m_IntersectData.m_flNz = N.z; 79 | 80 | // decide which axes to keep 81 | int nCoordSelect0 = (drop_axis + 1) % 3; 82 | int nCoordSelect1 = (drop_axis + 2) % 3; 83 | 84 | m_Data.m_IntersectData.m_nCoordSelect0 = nCoordSelect0; 85 | m_Data.m_IntersectData.m_nCoordSelect1 = nCoordSelect1; 86 | 87 | 88 | Vector edge1 = GetEdgeEquation(p1, p2, nCoordSelect0, nCoordSelect1, p3); 89 | m_Data.m_IntersectData.m_ProjectedEdgeEquations[0] = edge1.x; 90 | m_Data.m_IntersectData.m_ProjectedEdgeEquations[1] = edge1.y; 91 | m_Data.m_IntersectData.m_ProjectedEdgeEquations[2] = edge1.z; 92 | 93 | Vector edge2 = GetEdgeEquation(p2, p3, nCoordSelect0, nCoordSelect1, p1); 94 | m_Data.m_IntersectData.m_ProjectedEdgeEquations[3] = edge2.x; 95 | m_Data.m_IntersectData.m_ProjectedEdgeEquations[4] = edge2.y; 96 | m_Data.m_IntersectData.m_ProjectedEdgeEquations[5] = edge2.z; 97 | } 98 | 99 | int CacheOptimizedTriangle::ClassifyAgainstAxisSplit(int split_plane, float split_value) 100 | { 101 | // classify a triangle against an axis-aligned plane 102 | float minc = Vertex(0)[split_plane]; 103 | float maxc = minc; 104 | for (int v = 1; v<3; v++) 105 | { 106 | minc = fmin(minc, Vertex(v)[split_plane]); 107 | maxc = fmax(maxc, Vertex(v)[split_plane]); 108 | } 109 | 110 | if (minc >= split_value) 111 | return PLANECHECK_POSITIVE; 112 | if (maxc <= split_value) 113 | return PLANECHECK_NEGATIVE; 114 | if (minc == maxc) 115 | return PLANECHECK_POSITIVE; 116 | return PLANECHECK_STRADDLING; 117 | } 118 | -------------------------------------------------------------------------------- /gpua_rad/raytrace.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPUARAD_RAYTRACE_H_ 2 | #define _GPUARAD_RAYTRACE_H_ 3 | 4 | #define RTE_FLAGS_FAST_TREE_GENERATION 1 5 | #define RTE_FLAGS_DONT_STORE_TRIANGLE_COLORS 2 // saves memory if not needed 6 | #define RTE_FLAGS_DONT_STORE_TRIANGLE_MATERIALS 4 7 | 8 | #define PLANECHECK_POSITIVE 1 9 | #define PLANECHECK_NEGATIVE -1 10 | #define PLANECHECK_STRADDLING 0 11 | 12 | #define KDNODE_STATE_XSPLIT 0 // this node is an x split 13 | #define KDNODE_STATE_YSPLIT 1 // this node is a ysplit 14 | #define KDNODE_STATE_ZSPLIT 2 // this node is a zsplit 15 | #define KDNODE_STATE_LEAF 3 // this node is a leaf 16 | 17 | #include 18 | 19 | #include 20 | 21 | #include "vector.h" 22 | 23 | struct TriIntersectData_t 24 | { 25 | // this structure is 16longs=64 bytes for cache line packing. 26 | float m_flNx, m_flNy, m_flNz; // plane equation 27 | float m_flD; 28 | 29 | int32_t m_nTriangleID; // id of the triangle. 30 | 31 | float m_ProjectedEdgeEquations[6]; // A,B,C for each edge equation. a 32 | // point is inside the triangle if 33 | // a*c1+b*c2+c is negative for all 3 34 | // edges. 35 | 36 | uint8_t m_nCoordSelect0, m_nCoordSelect1; // the triangle is projected onto a 2d 37 | // plane for edge testing. These are 38 | // the indices (0..2) of the 39 | // coordinates preserved in the 40 | // projection 41 | 42 | uint8_t m_nFlags; // triangle flags 43 | uint8_t m_unused0; // no longer used 44 | }; 45 | 46 | 47 | struct TriGeometryData_t 48 | { 49 | int32_t m_nTriangleID; // id of the triangle. 50 | 51 | float m_VertexCoordData[9]; // can't use a vector in a union 52 | 53 | uint8_t m_nFlags; // triangle flags 54 | signed char m_nTmpData0; // used by kd-tree builder 55 | signed char m_nTmpData1; // used by kd-tree builder 56 | 57 | 58 | // accessors to get around union annoyance 59 | FORCEINLINE Vector &Vertex(int idx) 60 | { 61 | return *(reinterpret_cast (m_VertexCoordData + 3 * idx)); 62 | } 63 | 64 | }; 65 | 66 | struct CacheOptimizedTriangle 67 | { 68 | 69 | union 70 | { 71 | TriIntersectData_t m_IntersectData; 72 | TriGeometryData_t m_GeometryData; 73 | } m_Data; 74 | 75 | // accessors to get around union annoyance 76 | FORCEINLINE Vector &Vertex(int idx) 77 | { 78 | return *(reinterpret_cast (m_Data.m_GeometryData.m_VertexCoordData + 3 * idx)); 79 | } 80 | 81 | FORCEINLINE const Vector &Vertex(int idx) const 82 | { 83 | return *(reinterpret_cast (m_Data.m_GeometryData.m_VertexCoordData + 3 * idx)); 84 | } 85 | 86 | void ChangeIntoIntersectionFormat(void); // change information storage format for 87 | // computing intersections. 88 | 89 | int ClassifyAgainstAxisSplit(int split_plane, float split_value); // PLANECHECK_xxx below 90 | 91 | }; 92 | 93 | class CRayTracingEnvironment 94 | { 95 | public: 96 | uint32_t Flags; // RTE_F 97 | std::vector OptimizedTriangleList; //< the packed trianglesLAGS_xxx above 98 | std::vector TriangleColors; //< color of tries 99 | std::vector TriangleMaterials; //< material index of tries 100 | 101 | 102 | CRayTracingEnvironment() 103 | { 104 | Flags = 0; 105 | } 106 | 107 | // call AddTriangle to set up the world 108 | void AddTriangle(int32_t id, const Vector &v1, const Vector &v2, const Vector &v3, 109 | const Vector &color); 110 | 111 | // Adds a triangle with flags & material 112 | void AddTriangle(int32_t id, const Vector &v1, const Vector &v2, const Vector &v3, 113 | const Vector &color, uint16_t flags, int32_t materialIndex); 114 | 115 | }; 116 | 117 | extern CRayTracingEnvironment RTEnv; 118 | 119 | #endif // _GPUARAD_RAYTRACE_H_ -------------------------------------------------------------------------------- /gpua_rad/script.cpp: -------------------------------------------------------------------------------- 1 | #include "script.h" 2 | 3 | void CScript::ParseFromMemory(char * buffer, int size) 4 | { 5 | script = scriptstack; 6 | script++; 7 | if (script == &scriptstack[MAX_INCLUDES]) 8 | pp::Error("Script file exceeded MAX_INCLUDES"); 9 | strcpy(script->filename, "memory buffer"); 10 | 11 | script->buffer = buffer; 12 | script->line = 1; 13 | script->script_p = script->buffer; 14 | script->end_p = script->buffer + size; 15 | 16 | endofscript = false; 17 | tokenready = false; 18 | } 19 | 20 | qboolean CScript::GetToken(qboolean crossline) 21 | { 22 | char *token_p; 23 | 24 | if (tokenready) // is a token allready waiting? 25 | { 26 | tokenready = false; 27 | return true; 28 | } 29 | 30 | // printf("script_p %x (%x)\n", script->script_p, script->end_p ); fflush( stdout ); 31 | 32 | if (script->script_p >= script->end_p) 33 | { 34 | return EndOfScript(crossline); 35 | } 36 | 37 | tokenready = false; 38 | 39 | // skip space, ctrl chars 40 | skipspace: 41 | while (*script->script_p <= 32) 42 | { 43 | if (script->script_p >= script->end_p) 44 | { 45 | return EndOfScript(crossline); 46 | } 47 | if (*(script->script_p++) == '\n') 48 | { 49 | if (!crossline) 50 | { 51 | pp::Error("Line %i is incomplete\n", scriptline); 52 | } 53 | scriptline = ++script->line; 54 | } 55 | } 56 | 57 | if (script->script_p >= script->end_p) 58 | { 59 | return EndOfScript(crossline); 60 | } 61 | 62 | // strip single line comments 63 | if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field 64 | (*script->script_p == '/' && *((script->script_p) + 1) == '/')) // also make // a comment field 65 | { 66 | if (!crossline) 67 | pp::Error("Line %i is incomplete\n", scriptline); 68 | while (*script->script_p++ != '\n') 69 | { 70 | if (script->script_p >= script->end_p) 71 | { 72 | return EndOfScript(crossline); 73 | } 74 | } 75 | scriptline = ++script->line; 76 | goto skipspace; 77 | } 78 | 79 | // strip out matching /* */ comments 80 | if (*script->script_p == '/' && *((script->script_p) + 1) == '*') 81 | { 82 | script->script_p += 2; 83 | while (*script->script_p != '*' || *((script->script_p) + 1) != '/') 84 | { 85 | if (*script->script_p++ != '\n') 86 | { 87 | if (script->script_p >= script->end_p) 88 | { 89 | return EndOfScript(crossline); 90 | } 91 | 92 | scriptline = ++script->line; 93 | } 94 | } 95 | script->script_p += 2; 96 | goto skipspace; 97 | } 98 | 99 | // copy token to buffer 100 | token_p = token; 101 | 102 | if (*script->script_p == '"') 103 | { 104 | // quoted token 105 | script->script_p++; 106 | while (*script->script_p != '"') 107 | { 108 | *token_p++ = *script->script_p++; 109 | if (script->script_p == script->end_p) 110 | break; 111 | if (token_p == &token[MAX_TOKEN]) 112 | pp::Error("Token too large on line %i\n", scriptline); 113 | } 114 | script->script_p++; 115 | } 116 | else // regular token 117 | while (*script->script_p > 32 && *script->script_p != ';') 118 | { 119 | if (!ExpandMacroToken(token_p)) 120 | { 121 | if (!ExpandVariableToken(token_p)) 122 | { 123 | *token_p++ = *script->script_p++; 124 | if (script->script_p == script->end_p) 125 | break; 126 | if (token_p == &token[MAX_TOKEN]) 127 | pp::Error("Token too large on line %i\n", scriptline); 128 | 129 | } 130 | } 131 | } 132 | 133 | // add null to end of token 134 | *token_p = 0; 135 | 136 | // check for other commands 137 | if (!stricmp(token, "$include")) 138 | { 139 | pp::Error("Trying to use non implemented feature"); 140 | /*GetToken(false); 141 | 142 | bool bFallbackToToken = true; 143 | 144 | CUtlVector< CUtlString > expandedPathList; 145 | 146 | if (CmdLib_ExpandWithBasePaths(expandedPathList, token) > 0) 147 | { 148 | for (int i = 0; i < expandedPathList.Count(); ++i) 149 | { 150 | CUtlVector< CUtlString > findFileList; 151 | FindFileAbsoluteList(findFileList, expandedPathList[i].String()); 152 | 153 | if (findFileList.Count() > 0) 154 | { 155 | bFallbackToToken = false; 156 | 157 | // Only add the first set of glob matches from the first base path 158 | for (int j = 0; j < findFileList.Count(); ++j) 159 | { 160 | AddScriptToStack(const_cast< char * >(findFileList[j].String())); 161 | } 162 | 163 | break; 164 | } 165 | } 166 | } 167 | 168 | if (bFallbackToToken) 169 | { 170 | AddScriptToStack(token); 171 | } 172 | 173 | return GetToken(crossline);*/ 174 | } 175 | else if (!stricmp(token, "$definemacro")) 176 | { 177 | GetToken(false); 178 | DefineMacro(token); 179 | return GetToken(crossline); 180 | } 181 | else if (!stricmp(token, "$definevariable")) 182 | { 183 | GetToken(false); 184 | DefineVariable(token); 185 | return GetToken(crossline); 186 | } 187 | else if (AddMacroToStack(token)) 188 | { 189 | return GetToken(crossline); 190 | } 191 | 192 | return true; 193 | } 194 | 195 | qboolean CScript::EndOfScript(qboolean crossline) 196 | { 197 | if (!crossline) 198 | pp::Error("Line %i is incomplete\n", scriptline); 199 | 200 | if (!strcmp(script->filename, "memory buffer")) 201 | { 202 | endofscript = true; 203 | return false; 204 | } 205 | 206 | free(script->buffer); 207 | script->buffer = NULL; 208 | if (script == scriptstack + 1) 209 | { 210 | endofscript = true; 211 | return false; 212 | } 213 | script--; 214 | scriptline = script->line; 215 | // printf ("returning to %s\n", script->filename); 216 | return GetToken(crossline); 217 | } 218 | 219 | bool CScript::ExpandMacroToken(char *&token_p) 220 | { 221 | if (script->nummacroparams && *script->script_p == '$') 222 | { 223 | char *cp = script->script_p + 1; 224 | 225 | while (*cp > 32 && *cp != '$') 226 | { 227 | cp++; 228 | } 229 | 230 | // found a word with $'s on either end? 231 | if (*cp != '$') 232 | return false; 233 | 234 | // get token pointer 235 | char *tp = script->script_p + 1; 236 | int len = (cp - tp); 237 | *(tp + len) = '\0'; 238 | 239 | // lookup macro parameter 240 | int index = 0; 241 | for (index = 0; index < script->nummacroparams; index++) 242 | { 243 | if (stricmp(script->macroparam[index], tp) == 0) 244 | break; 245 | } 246 | if (index >= script->nummacroparams) 247 | { 248 | pp::Error("unknown macro token \"%s\" in %s\n", tp, script->filename); 249 | } 250 | 251 | // paste token into 252 | len = strlen(script->macrovalue[index]); 253 | strcpy(token_p, script->macrovalue[index]); 254 | token_p += len; 255 | 256 | script->script_p = cp + 1; 257 | 258 | if (script->script_p >= script->end_p) 259 | pp::Error("Macro expand overflow\n"); 260 | 261 | if (token_p >= &token[MAX_TOKEN]) 262 | pp::Error("Token too large on line %i\n", scriptline); 263 | 264 | return true; 265 | } 266 | return false; 267 | } 268 | 269 | /* 270 | ============== 271 | ============== 272 | */ 273 | // FIXME: this should create a new script context so the individual tokens in the variable can be parsed 274 | bool CScript::ExpandVariableToken(char *&token_p) 275 | { 276 | if (*script->script_p == '$') 277 | { 278 | char *cp = script->script_p + 1; 279 | 280 | while (*cp > 32 && *cp != '$') 281 | { 282 | cp++; 283 | } 284 | 285 | // found a word with $'s on either end? 286 | if (*cp != '$') 287 | return false; 288 | 289 | // get token pointer 290 | char *tp = script->script_p + 1; 291 | int len = (cp - tp); 292 | *(tp + len) = '\0'; 293 | 294 | // lookup macro parameter 295 | 296 | int index; 297 | for (index = 0; index < m_vDefineVariable.size(); index++) 298 | { 299 | if (strnicmp(m_vDefineVariable[index].param, tp, len) == 0) 300 | break; 301 | } 302 | 303 | if (index >= m_vDefineVariable.size()) 304 | { 305 | pp::Error("unknown variable token \"%s\" in %s\n", tp, script->filename); 306 | } 307 | 308 | // paste token into 309 | len = strlen(m_vDefineVariable[index].value); 310 | strcpy(token_p, m_vDefineVariable[index].value); 311 | token_p += len; 312 | 313 | script->script_p = cp + 1; 314 | 315 | if (script->script_p >= script->end_p) 316 | pp::Error("Macro expand overflow\n"); 317 | 318 | if (token_p >= &token[MAX_TOKEN]) 319 | pp::Error("Token too large on line %i\n", scriptline); 320 | 321 | return true; 322 | } 323 | return false; 324 | } 325 | 326 | void CScript::DefineMacro(char *macroname) 327 | { 328 | script_t *pmacro = (script_t *)malloc(sizeof(script_t)); 329 | 330 | strcpy(pmacro->filename, macroname); 331 | pmacro->line = script->line; 332 | pmacro->nummacroparams = 0; 333 | 334 | char *mp = pmacro->macrobuffer; 335 | char *cp = script->script_p; 336 | 337 | while (TokenAvailable()) 338 | { 339 | GetToken(false); 340 | 341 | if (token[0] == '\\' && token[1] == '\\') 342 | { 343 | break; 344 | } 345 | cp = script->script_p; 346 | 347 | pmacro->macroparam[pmacro->nummacroparams++] = mp; 348 | 349 | strcpy(mp, token); 350 | mp += strlen(token) + 1; 351 | 352 | if (mp >= pmacro->macrobuffer + sizeof(pmacro->macrobuffer)) 353 | pp::Error("Macro buffer overflow\n"); 354 | } 355 | // roll back script_p to previous valid location 356 | script->script_p = cp; 357 | 358 | // find end of macro def 359 | while (*cp && *cp != '\n') 360 | { 361 | //Msg("%d ", *cp ); 362 | if (*cp == '\\' && *(cp + 1) == '\\') 363 | { 364 | // skip till end of line 365 | while (*cp && *cp != '\n') 366 | { 367 | *cp = ' '; // replace with spaces 368 | cp++; 369 | } 370 | 371 | if (*cp) 372 | { 373 | cp++; 374 | } 375 | } 376 | else 377 | { 378 | cp++; 379 | } 380 | } 381 | 382 | int size = (cp - script->script_p); 383 | 384 | pmacro->buffer = (char *)malloc(size + 1); 385 | memcpy(pmacro->buffer, script->script_p, size); 386 | pmacro->buffer[size] = '\0'; 387 | pmacro->end_p = &pmacro->buffer[size]; 388 | 389 | macrolist[nummacros++] = pmacro; 390 | 391 | script->script_p = cp; 392 | } 393 | 394 | qboolean CScript::TokenAvailable() 395 | { 396 | char *search_p; 397 | 398 | if (tokenready) // is a token allready waiting? 399 | { 400 | return true; 401 | } 402 | 403 | search_p = script->script_p; 404 | 405 | if (search_p >= script->end_p) 406 | return false; 407 | 408 | while (*search_p <= 32) 409 | { 410 | if (*search_p == '\n') 411 | return false; 412 | search_p++; 413 | if (search_p == script->end_p) 414 | return false; 415 | 416 | } 417 | 418 | if (*search_p == ';' || *search_p == '#' || // semicolon and # is comment field 419 | (*search_p == '/' && *((search_p)+1) == '/')) // also make // a comment field 420 | return false; 421 | 422 | return true; 423 | } 424 | 425 | void CScript::DefineVariable(char *variablename) 426 | { 427 | variable_t v; 428 | 429 | v.param = strdup(variablename); 430 | 431 | GetToken(false); 432 | 433 | v.value = strdup(token); 434 | 435 | m_vDefineVariable.push_back(v); 436 | } 437 | 438 | /* 439 | ============== 440 | ============== 441 | */ 442 | bool CScript::AddMacroToStack(char *macroname) 443 | { 444 | // lookup macro 445 | if (macroname[0] != '$') 446 | return false; 447 | 448 | int i; 449 | for (i = 0; i < nummacros; i++) 450 | { 451 | if (strcmpi(macrolist[i]->filename, ¯oname[1]) == 0) 452 | { 453 | break; 454 | } 455 | } 456 | if (i == nummacros) 457 | return false; 458 | 459 | script_t *pmacro = macrolist[i]; 460 | 461 | // get tokens 462 | script_t *pnext = script + 1; 463 | 464 | pnext++; 465 | if (pnext == &scriptstack[MAX_INCLUDES]) 466 | pp::Error("script file exceeded MAX_INCLUDES"); 467 | 468 | // get tokens 469 | char *cp = pnext->macrobuffer; 470 | 471 | pnext->nummacroparams = pmacro->nummacroparams; 472 | 473 | for (i = 0; i < pnext->nummacroparams; i++) 474 | { 475 | GetToken(false); 476 | 477 | strcpy(cp, token); 478 | pnext->macroparam[i] = pmacro->macroparam[i]; 479 | pnext->macrovalue[i] = cp; 480 | 481 | cp += strlen(token) + 1; 482 | 483 | if (cp >= pnext->macrobuffer + sizeof(pnext->macrobuffer)) 484 | pp::Error("Macro buffer overflow\n"); 485 | } 486 | 487 | script = pnext; 488 | strcpy(script->filename, pmacro->filename); 489 | 490 | int size = pmacro->end_p - pmacro->buffer; 491 | script->buffer = (char *)malloc(size + 1); 492 | memcpy(script->buffer, pmacro->buffer, size); 493 | pmacro->buffer[size] = '\0'; 494 | script->script_p = script->buffer; 495 | script->end_p = script->buffer + size; 496 | script->line = pmacro->line; 497 | 498 | return true; 499 | } 500 | -------------------------------------------------------------------------------- /gpua_rad/script.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPUARAD_SCRIPT_H_ 2 | #define _GPUARAD_SCRIPT_H_ 3 | 4 | #define MAX_INCLUDES 64 5 | #define MAX_TOKEN 1024 6 | 7 | #include 8 | 9 | #include "prettyprint.h" 10 | 11 | #include "basetypes.h" 12 | 13 | struct script_t 14 | { 15 | char filename[1024]; 16 | char *buffer, *script_p, *end_p; 17 | int line; 18 | 19 | char macrobuffer[4096]; 20 | char *macroparam[64]; 21 | char *macrovalue[64]; 22 | int nummacroparams; 23 | }; 24 | 25 | typedef struct 26 | { 27 | char *param; 28 | char *value; 29 | } variable_t; 30 | 31 | enum ScriptPathMode_t 32 | { 33 | SCRIPT_USE_ABSOLUTE_PATH, 34 | SCRIPT_USE_RELATIVE_PATH 35 | }; 36 | 37 | class CScript 38 | { 39 | public: 40 | void ParseFromMemory(char* buffer, int size); 41 | qboolean GetToken(qboolean crossline); 42 | qboolean EndOfScript(qboolean crossline); 43 | bool ExpandMacroToken(char *&token_p); 44 | bool ExpandVariableToken(char *&token_p); 45 | void DefineMacro(char *macroname); 46 | qboolean TokenAvailable(); 47 | void DefineVariable(char *variablename); 48 | bool AddMacroToStack(char *macroname); 49 | 50 | script_t scriptstack[MAX_INCLUDES]; 51 | script_t *script = nullptr; 52 | int scriptline; 53 | 54 | char token[MAX_TOKEN]; 55 | qboolean endofscript; 56 | qboolean tokenready; // only true if UnGetToken was just called 57 | 58 | script_t *macrolist[256]; 59 | int nummacros; 60 | 61 | std::vector m_vDefineVariable; 62 | }; 63 | 64 | #endif // _GPUARAD_SCRIPT_H_ -------------------------------------------------------------------------------- /gpua_rad/timer.cpp: -------------------------------------------------------------------------------- 1 | #include "timer.h" 2 | 3 | CTimer::CTimer(const char * identifier) : m_szIdentifier(identifier) 4 | { 5 | m_tpscStart = std::chrono::high_resolution_clock::now(); 6 | m_bEnded = false; 7 | } 8 | 9 | CTimer::~CTimer() 10 | { 11 | if (!m_bEnded) 12 | { 13 | std::chrono::duration elapsed = std::chrono::high_resolution_clock::now() - m_tpscStart; 14 | pp::Info("[Performance Timer] %s has ended, elapsed time: %f seconds", m_szIdentifier, elapsed.count()); 15 | m_bEnded = true; 16 | } 17 | } 18 | 19 | void CTimer::End() 20 | { 21 | if (!m_bEnded) 22 | { 23 | std::chrono::duration elapsed = std::chrono::high_resolution_clock::now() - m_tpscStart; 24 | pp::Info("[Performance Timer] %s has ended, elapsed time: %f seconds", m_szIdentifier, elapsed.count()); 25 | m_bEnded = true; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /gpua_rad/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPUARAD_TIMER_H_ 2 | #define _GPUARAD_TIMER_H_ 3 | 4 | #include 5 | 6 | #include "prettyprint.h" 7 | 8 | class CTimer 9 | { 10 | public: 11 | CTimer(const char* identifier); 12 | ~CTimer(); 13 | void End(); 14 | private: 15 | std::chrono::time_point m_tpscStart; 16 | const char* m_szIdentifier; 17 | bool m_bEnded; 18 | }; 19 | 20 | #endif // _GPUARAD_TIMER_H_ -------------------------------------------------------------------------------- /gpua_rad/trace.cpp: -------------------------------------------------------------------------------- 1 | #include "trace.h" 2 | #include 3 | 4 | CTrace::CTrace(const char * filename) : CBSP(filename) 5 | { 6 | 7 | } 8 | 9 | void CTrace::AddBrushesForRayTrace() 10 | { 11 | CTimer timer("AddBrushesForRayTrace"); 12 | 13 | if (!m_iNumModels) 14 | { 15 | pp::Warning("No models found!"); 16 | return; 17 | } 18 | 19 | VMatrix identity; 20 | identity.Identity(); 21 | 22 | std::vectorbrush_list; 23 | GetBrushesRecursively(m_dModels[0].headnode, brush_list); 24 | 25 | for (int i = 0; i < brush_list.size() && i < MAX_MAP_BRUSHES; i++) 26 | { 27 | dbrush_t *brush = &m_dBrushes[brush_list[i]]; 28 | AddBrushToRaytraceEnvironment(brush, identity); 29 | } 30 | 31 | for (int i = 0; i < m_dModels[0].numfaces; i++) 32 | { 33 | int ndxFace = m_dModels[0].firstface + i; 34 | 35 | if (ndxFace < 0 || ndxFace > MAX_MAP_FACES) 36 | { 37 | pp::Error("Invalid face index %i", ndxFace); 38 | return; 39 | } 40 | 41 | dface_t *face = &m_pFaces[ndxFace]; 42 | 43 | int texinfo_index = face->texinfo; 44 | 45 | if (texinfo_index < 0 || texinfo_index > MAX_MAP_TEXINFO) 46 | { 47 | pp::Error("Invalid texinfo index %i", texinfo_index); 48 | return; 49 | } 50 | 51 | texinfo_t *tx = &m_dTexInfos[face->texinfo]; 52 | if (!(tx->flags & SURF_SKY)) 53 | continue; 54 | 55 | Vector points[MAX_POINTS_ON_WINDING]; 56 | 57 | for (int j = 0; j < face->numedges; j++) 58 | { 59 | int surf_edge_index = face->firstedge + j; 60 | if (j >= MAX_POINTS_ON_WINDING || j < 0) 61 | { 62 | pp::Error("MAX_POINTS_ON_WINDING reached!"); 63 | return; 64 | } 65 | 66 | if (surf_edge_index > MAX_MAP_SURFEDGES || surf_edge_index < 0) 67 | { 68 | pp::Error("Invalid surf edge index %i", surf_edge_index); 69 | return; 70 | } 71 | 72 | int surf_edge = m_dSurfEdges[surf_edge_index]; 73 | 74 | unsigned short v; 75 | 76 | if (surf_edge < 0) 77 | v = m_dEdges[-surf_edge].v[1]; 78 | else 79 | v = m_dEdges[surf_edge].v[0]; 80 | 81 | if (v > MAX_MAP_VERTS || v < 0) 82 | { 83 | pp::Error("Invalid vertex index %i", v); 84 | return; 85 | } 86 | 87 | dvertex_t *dv = &m_dVertexes[v]; 88 | points[j] = dv->point; 89 | } 90 | 91 | for (int j = 2; j < face->numedges; j++) 92 | { 93 | Vector fullCoverage; 94 | fullCoverage.x = 1.0f; 95 | RTEnv.AddTriangle(TRACE_ID_SKY, points[0], points[j - 1], points[j], fullCoverage); 96 | } 97 | } 98 | } 99 | 100 | void CTrace::GetBrushesRecursively(int node, std::vector& list) 101 | { 102 | if (node < 0) 103 | { 104 | int leaf_index = -1 - node; 105 | 106 | if (leaf_index < 0 || leaf_index > MAX_MAP_LEAFS) 107 | { 108 | pp::Error("Invalid leaf index %i", leaf_index); 109 | return; 110 | } 111 | 112 | for (int i = 0; i < m_dLeafs[leaf_index].numleafbrushes; i++) 113 | { 114 | int leaf_brush_index = m_dLeafs[leaf_index].firstleafbrush + i; 115 | 116 | if (leaf_brush_index < 0 || leaf_brush_index > MAX_MAP_LEAFBRUSHES) 117 | { 118 | pp::Error("Invalid leaf brush index index %i", leaf_index); 119 | return; 120 | } 121 | 122 | int brush_index = m_dLeafBrushes[leaf_brush_index]; 123 | 124 | if (brush_index < 0 || brush_index > MAX_MAP_BRUSHES) 125 | { 126 | pp::Error("Invalid brush index index %i", brush_index); 127 | return; 128 | } 129 | 130 | if (std::find(list.begin(), list.end(), brush_index) == list.end()) 131 | { 132 | list.push_back(brush_index); 133 | } 134 | } 135 | } 136 | else 137 | { 138 | // recurse 139 | dnode_t *pnode = m_dNodes + node; 140 | 141 | GetBrushesRecursively(pnode->children[0], list); 142 | GetBrushesRecursively(pnode->children[1], list); 143 | } 144 | } 145 | 146 | void CTrace::AddBrushToRaytraceEnvironment(dbrush_t * brush, VMatrix & xform) 147 | { 148 | if (!(brush->contents & MASK_OPAQUE)) 149 | return; 150 | 151 | Vector v0, v1, v2; 152 | 153 | for (int i = 0; i < brush->numsides; i++) 154 | { 155 | int brush_side_index = brush->firstside + i; 156 | 157 | if (brush_side_index < 0 || brush_side_index > MAX_MAP_BRUSHSIDES) 158 | { 159 | pp::Error("Invalid brush side index index %i", brush_side_index); 160 | return; 161 | } 162 | 163 | dbrushside_t *side = &m_dBrushSides[brush->firstside + i]; 164 | 165 | int plane_index = side->planenum; 166 | 167 | if (plane_index < 0 || plane_index > MAX_MAP_PLANES) 168 | { 169 | pp::Error("Invalid plade index index %i", plane_index); 170 | return; 171 | } 172 | 173 | dplane_t *plane = &m_dPlanes[side->planenum]; 174 | 175 | int texinfo_index = side->texinfo; 176 | 177 | if (texinfo_index < 0 || texinfo_index > MAX_MAP_TEXINFO) 178 | { 179 | pp::Error("Invalid texinfo index index %i", texinfo_index); 180 | return; 181 | } 182 | 183 | texinfo_t *tx = &m_dTexInfos[side->texinfo]; 184 | 185 | winding_t *w = BaseWindingForPlane(plane->normal, plane->dist); 186 | 187 | if (tx->flags & SURF_SKY || side->dispinfo) 188 | continue; 189 | 190 | for (int j = 0; jnumsides && w; j++) 191 | { 192 | if (i == j) 193 | continue; 194 | dbrushside_t *pOtherSide = &m_dBrushSides[brush->firstside + j]; 195 | if (pOtherSide->bevel) 196 | continue; 197 | plane = &m_dPlanes[pOtherSide->planenum ^ 1]; 198 | ChopWindingInPlace(&w, plane->normal, plane->dist, 0); 199 | } 200 | if (w) 201 | { 202 | for (int j = 2; j < w->numpoints; j++) 203 | { 204 | v0 = xform.VMul4x3(w->p[0]); 205 | v1 = xform.VMul4x3(w->p[j - 1]); 206 | v2 = xform.VMul4x3(w->p[j]); 207 | Vector fullCoverage; 208 | fullCoverage.x = 1.0f; 209 | RTEnv.AddTriangle(TRACE_ID_OPAQUE, v0, v1, v2, fullCoverage); 210 | } 211 | FreeWinding(w); 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /gpua_rad/trace.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPUARAD_TRACE_H_ 2 | #define _GPUARAD_TRACE_H_ 3 | 4 | #include 5 | 6 | #include "timer.h" 7 | #include "vmatrix.h" 8 | 9 | #include "raytrace.h" 10 | 11 | #include "bsp.h" 12 | #include "poly.h" 13 | #include "bspflags.h" 14 | 15 | // Raytracing 16 | #define TRACE_ID_SKY 0x01000000 // sky face ray blocker 17 | #define TRACE_ID_OPAQUE 0x02000000 // everyday light blocking face 18 | #define TRACE_ID_STATICPROP 0x04000000 // static prop - lower bits are prop ID 19 | 20 | class CTrace : public CBSP 21 | { 22 | public: 23 | CTrace(const char* filename); 24 | 25 | void AddBrushesForRayTrace(); 26 | void GetBrushesRecursively(int node, std::vector &list); 27 | void AddBrushToRaytraceEnvironment(dbrush_t* brush, VMatrix &identity); 28 | 29 | dface_t *m_pFaces; 30 | }; 31 | 32 | #endif // _GPUARAD_TRACE_H_ -------------------------------------------------------------------------------- /gpua_rad/vector.cpp: -------------------------------------------------------------------------------- 1 | #include "vector.h" 2 | 3 | Vector::Vector() 4 | { 5 | Init(); 6 | } 7 | 8 | inline void Vector::Init(float ix, float iy, float iz) 9 | { 10 | x = ix; 11 | y = iy; 12 | z = iz; 13 | } 14 | 15 | void Vector::dump() 16 | { 17 | pp::Info("Vector(%f, %f, %f)", x, y, z); 18 | } 19 | 20 | Vector Vector::operator+(const Vector & v) const 21 | { 22 | Vector res; 23 | VectorAdd(*this, v, res); 24 | return res; 25 | } 26 | 27 | Vector Vector::operator-(const Vector & v) const 28 | { 29 | Vector res; 30 | VectorSubtract(*this, v, res); 31 | return res; 32 | } 33 | 34 | Vector Vector::operator*(const Vector & v) const 35 | { 36 | Vector res; 37 | VectorMultiply(*this, v, res); 38 | return res; 39 | } 40 | 41 | Vector Vector::operator/(const Vector & v) const 42 | { 43 | Vector res; 44 | VectorDivide(*this, v, res); 45 | return res; 46 | } 47 | 48 | Vector Vector::operator*(float fl) const 49 | { 50 | Vector res; 51 | VectorMultiply(*this, fl, res); 52 | return res; 53 | } 54 | 55 | Vector Vector::operator/(float fl) const 56 | { 57 | Vector res; 58 | VectorDivide(*this, fl, res); 59 | return res; 60 | } 61 | 62 | Vector Vector::Cross(const Vector & vOther) const 63 | { 64 | Vector res; 65 | CrossProduct(*this, vOther, res); 66 | return res; 67 | } 68 | 69 | float Vector::NormalizeInPlace() 70 | { 71 | return VectorNormalize(*this); 72 | } 73 | 74 | float Vector::Dot(const Vector & vOther) const 75 | { 76 | return DotProduct(*this, vOther); 77 | } 78 | -------------------------------------------------------------------------------- /gpua_rad/vector.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPUA_MATH_VECTOR_H_ 2 | #define _GPUA_MATH_VECTOR_H_ 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include "prettyprint.h" 9 | #include 10 | #include 11 | #include 12 | 13 | class VectorByValue; 14 | 15 | class Vector 16 | { 17 | public: 18 | float x, y, z; 19 | 20 | // Construction/destruction: 21 | Vector(); 22 | Vector(float ix, float iy, float iz) 23 | { 24 | x = ix; 25 | y = iy; 26 | z = iz; 27 | } 28 | 29 | void Init(float ix = 0.f, float iy = 0.f, float iz = 0.f); 30 | 31 | void dump(); 32 | 33 | // operators 34 | bool operator==(const Vector& src) const 35 | { 36 | return (src.x == x) && (src.y == y) && (src.z == z); 37 | } 38 | bool operator!=(const Vector& src) const 39 | { 40 | return (src.x != x) || (src.y != y) || (src.z != z); 41 | } 42 | 43 | // arithmetic operations 44 | FORCEINLINE Vector& operator+=(const Vector &v) 45 | { 46 | x += v.x; y += v.y; z += v.z; 47 | return *this; 48 | } 49 | 50 | FORCEINLINE Vector& operator-=(const Vector &v) 51 | { 52 | x -= v.x; y -= v.y; z -= v.z; 53 | return *this; 54 | } 55 | 56 | FORCEINLINE Vector& operator*=(const Vector &v) 57 | { 58 | x *= v.x; 59 | y *= v.y; 60 | z *= v.z; 61 | return *this; 62 | } 63 | 64 | FORCEINLINE Vector& operator*=(float fl) 65 | { 66 | x *= fl; 67 | y *= fl; 68 | z *= fl; 69 | return *this; 70 | } 71 | 72 | FORCEINLINE Vector& operator/=(const Vector &v) 73 | { 74 | if (v.x == 0.0f || v.y == 0.0f || v.z == 0.0f) 75 | return *this; 76 | x /= v.x; 77 | y /= v.y; 78 | z /= v.z; 79 | return *this; 80 | } 81 | 82 | FORCEINLINE Vector& operator/=(float fl) 83 | { 84 | if(fl == 0.0f) 85 | return *this; 86 | float oofl = 1.0f / fl; 87 | x *= oofl; 88 | y *= oofl; 89 | z *= oofl; 90 | return *this; 91 | } 92 | 93 | FORCEINLINE Vector& operator+=(float fl) 94 | { 95 | x += fl; 96 | y += fl; 97 | z += fl; 98 | return *this; 99 | } 100 | 101 | FORCEINLINE Vector& operator-=(float fl) 102 | { 103 | x -= fl; 104 | y -= fl; 105 | z -= fl; 106 | return *this; 107 | } 108 | 109 | Vector& operator=(const Vector &vOther) 110 | { 111 | x = vOther.x; y = vOther.y; z = vOther.z; 112 | return *this; 113 | } 114 | 115 | Vector operator-(void) const 116 | { 117 | return Vector(-x, -y, -z); 118 | } 119 | 120 | Vector operator+(const Vector& v) const; 121 | Vector operator-(const Vector& v) const; 122 | Vector operator*(const Vector& v) const; 123 | Vector operator/(const Vector& v) const; 124 | Vector operator*(float fl) const; 125 | Vector operator/(float fl) const; 126 | 127 | FORCEINLINE float& operator[](int i) const 128 | { 129 | return ((float*)this)[i]; 130 | } 131 | 132 | operator VectorByValue &() { return *((VectorByValue *)(this)); } 133 | operator const VectorByValue &() const { return *((const VectorByValue *)(this)); } 134 | 135 | FORCEINLINE float LengthSqr(void) const 136 | { 137 | return (x*x + y*y + z*z); 138 | } 139 | 140 | Vector Cross(const Vector& vOther) const; 141 | 142 | float NormalizeInPlace(); 143 | 144 | // for backwards compatability 145 | float Dot(const Vector& vOther) const; 146 | }; 147 | 148 | FORCEINLINE float DotProduct(const Vector& a, const Vector& b) 149 | { 150 | return(a.x*b.x + a.y*b.y + a.z*b.z); 151 | } 152 | 153 | FORCEINLINE void VectorCopy(const Vector& src, Vector& dst) 154 | { 155 | dst.x = src.x; 156 | dst.y = src.y; 157 | dst.z = src.z; 158 | } 159 | 160 | FORCEINLINE void VectorSubtract(const Vector& a, const Vector& b, Vector& c) 161 | { 162 | c.x = a.x - b.x; 163 | c.y = a.y - b.y; 164 | c.z = a.z - b.z; 165 | } 166 | 167 | FORCEINLINE void VectorAdd(const Vector& a, const Vector& b, Vector& c) 168 | { 169 | c.x = a.x + b.x; 170 | c.y = a.y + b.y; 171 | c.z = a.z + b.z; 172 | } 173 | 174 | FORCEINLINE void VectorDivide(const Vector& a, float b, Vector& c) 175 | { 176 | float oob = 1.0f / b; 177 | c.x = a.x * oob; 178 | c.y = a.y * oob; 179 | c.z = a.z * oob; 180 | } 181 | 182 | FORCEINLINE void VectorDivide(const Vector& a, const Vector& b, Vector& c) 183 | { 184 | c.x = a.x / b.x; 185 | c.y = a.y / b.y; 186 | c.z = a.z / b.z; 187 | } 188 | 189 | FORCEINLINE void VectorMultiply(const Vector& a, float b, Vector& c) 190 | { 191 | c.x = a.x * b; 192 | c.y = a.y * b; 193 | c.z = a.z * b; 194 | } 195 | 196 | FORCEINLINE void VectorMultiply(const Vector& a, const Vector& b, Vector& c) 197 | { 198 | c.x = a.x * b.x; 199 | c.y = a.y * b.y; 200 | c.z = a.z * b.z; 201 | } 202 | 203 | inline void VectorScale(const Vector& in, float scale, Vector& result) 204 | { 205 | VectorMultiply(in, scale, result); 206 | } 207 | 208 | inline void VectorScale(const Vector& in, Vector &scale, Vector& result) 209 | { 210 | VectorMultiply(in, scale, result); 211 | } 212 | 213 | FORCEINLINE void VectorMAInline(const float* start, float scale, const float* direction, float* dest) 214 | { 215 | dest[0] = start[0] + direction[0] * scale; 216 | dest[1] = start[1] + direction[1] * scale; 217 | dest[2] = start[2] + direction[2] * scale; 218 | } 219 | 220 | FORCEINLINE void VectorMAInline(const Vector& start, float scale, const Vector& direction, Vector& dest) 221 | { 222 | dest.x = start.x + direction.x*scale; 223 | dest.y = start.y + direction.y*scale; 224 | dest.z = start.z + direction.z*scale; 225 | } 226 | 227 | FORCEINLINE void VectorMA(const Vector& start, float scale, const Vector& direction, Vector& dest) 228 | { 229 | VectorMAInline(start, scale, direction, dest); 230 | } 231 | 232 | FORCEINLINE void VectorMA(const float * start, float scale, const float *direction, float *dest) 233 | { 234 | VectorMAInline(start, scale, direction, dest); 235 | } 236 | 237 | #if defined(__i386__) || defined(_M_IX86) 238 | inline void _SSE_RSqrtInline(float a, float* out) 239 | { 240 | __m128 xx = _mm_load_ss(&a); 241 | __m128 xr = _mm_rsqrt_ss(xx); 242 | __m128 xt; 243 | xt = _mm_mul_ss(xr, xr); 244 | xt = _mm_mul_ss(xt, xx); 245 | xt = _mm_sub_ss(_mm_set_ss(3.f), xt); 246 | xt = _mm_mul_ss(xt, _mm_set_ss(0.5f)); 247 | xr = _mm_mul_ss(xr, xt); 248 | _mm_store_ss(out, xr); 249 | } 250 | #endif 251 | 252 | FORCEINLINE float FASTCALL _VectorNormalize (Vector& vec) 253 | { 254 | float radius = sqrtf(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z); 255 | 256 | // FLT_EPSILON is added to the radius to eliminate the possibility of divide by zero. 257 | float iradius = 1.f / ( radius + FLT_EPSILON ); 258 | 259 | vec.x *= iradius; 260 | vec.y *= iradius; 261 | vec.z *= iradius; 262 | 263 | return radius; 264 | } 265 | 266 | FORCEINLINE float VectorNormalize(Vector& vec) 267 | { 268 | #ifndef DEBUG // stop crashing my edit-and-continue! 269 | #if defined(__i386__) || defined(_M_IX86) 270 | #define DO_SSE_OPTIMIZATION 271 | #endif 272 | #endif 273 | 274 | #if defined( DO_SSE_OPTIMIZATION ) 275 | float sqrlen = vec.LengthSqr() + 1.0e-10f, invlen; 276 | _SSE_RSqrtInline(sqrlen, &invlen); 277 | vec.x *= invlen; 278 | vec.y *= invlen; 279 | vec.z *= invlen; 280 | return sqrlen * invlen; 281 | #else 282 | return _VectorNormalize(vec); 283 | #endif 284 | } 285 | 286 | inline void CrossProduct(const Vector& a, const Vector& b, Vector& result) 287 | { 288 | result.x = a.y*b.z - a.z*b.y; 289 | result.y = a.z*b.x - a.x*b.z; 290 | result.z = a.x*b.y - a.y*b.x; 291 | } 292 | 293 | //----------------------------------------------------------------------------- 294 | // Allows us to specifically pass the vector by value when we need to 295 | //----------------------------------------------------------------------------- 296 | class VectorByValue : public Vector 297 | { 298 | public: 299 | // Construction/destruction: 300 | VectorByValue(void) : Vector() {} 301 | VectorByValue(float X, float Y, float Z) : Vector(X, Y, Z) {} 302 | VectorByValue(const VectorByValue& vOther) { *this = vOther; } 303 | }; 304 | 305 | #endif // _GPUA_MATH_VECTOR_H_ -------------------------------------------------------------------------------- /gpua_rad/vmatrix.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPUARAD_VMATRIX_H_ 2 | #define _GPUARAD_VMATRIX_H_ 3 | 4 | #include "math.h" 5 | 6 | #include "vector.h" 7 | 8 | struct matrix3x4_t 9 | { 10 | matrix3x4_t() {} 11 | matrix3x4_t( 12 | float m00, float m01, float m02, float m03, 13 | float m10, float m11, float m12, float m13, 14 | float m20, float m21, float m22, float m23) 15 | { 16 | m_flMatVal[0][0] = m00; m_flMatVal[0][1] = m01; m_flMatVal[0][2] = m02; m_flMatVal[0][3] = m03; 17 | m_flMatVal[1][0] = m10; m_flMatVal[1][1] = m11; m_flMatVal[1][2] = m12; m_flMatVal[1][3] = m13; 18 | m_flMatVal[2][0] = m20; m_flMatVal[2][1] = m21; m_flMatVal[2][2] = m22; m_flMatVal[2][3] = m23; 19 | } 20 | 21 | //----------------------------------------------------------------------------- 22 | // Creates a matrix where the X axis = forward 23 | // the Y axis = left, and the Z axis = up 24 | //----------------------------------------------------------------------------- 25 | void Init(const Vector& xAxis, const Vector& yAxis, const Vector& zAxis, const Vector &vecOrigin) 26 | { 27 | m_flMatVal[0][0] = xAxis.x; m_flMatVal[0][1] = yAxis.x; m_flMatVal[0][2] = zAxis.x; m_flMatVal[0][3] = vecOrigin.x; 28 | m_flMatVal[1][0] = xAxis.y; m_flMatVal[1][1] = yAxis.y; m_flMatVal[1][2] = zAxis.y; m_flMatVal[1][3] = vecOrigin.y; 29 | m_flMatVal[2][0] = xAxis.z; m_flMatVal[2][1] = yAxis.z; m_flMatVal[2][2] = zAxis.z; m_flMatVal[2][3] = vecOrigin.z; 30 | } 31 | 32 | //----------------------------------------------------------------------------- 33 | // Creates a matrix where the X axis = forward 34 | // the Y axis = left, and the Z axis = up 35 | //----------------------------------------------------------------------------- 36 | matrix3x4_t(const Vector& xAxis, const Vector& yAxis, const Vector& zAxis, const Vector &vecOrigin) 37 | { 38 | Init(xAxis, yAxis, zAxis, vecOrigin); 39 | } 40 | 41 | inline void Invalidate(void) 42 | { 43 | for (int i = 0; i < 3; i++) 44 | { 45 | for (int j = 0; j < 4; j++) 46 | { 47 | m_flMatVal[i][j] = nanf(""); 48 | } 49 | } 50 | } 51 | 52 | float *operator[](int i) { return m_flMatVal[i]; } 53 | const float *operator[](int i) const { return m_flMatVal[i]; } 54 | float *Base() { return &m_flMatVal[0][0]; } 55 | const float *Base() const { return &m_flMatVal[0][0]; } 56 | 57 | float m_flMatVal[3][4]; 58 | }; 59 | 60 | class VMatrix 61 | { 62 | public: 63 | float m[4][4]; 64 | 65 | VMatrix(); 66 | VMatrix( 67 | float m00, float m01, float m02, float m03, 68 | float m10, float m11, float m12, float m13, 69 | float m20, float m21, float m22, float m23, 70 | float m30, float m31, float m32, float m33 71 | ); 72 | 73 | // Creates a matrix where the X axis = forward 74 | // the Y axis = left, and the Z axis = up 75 | VMatrix(const Vector& forward, const Vector& left, const Vector& up); 76 | VMatrix(const Vector& forward, const Vector& left, const Vector& up, const Vector& translation); 77 | 78 | // Construct from a 3x4 matrix 79 | VMatrix(const matrix3x4_t& matrix3x4); 80 | 81 | // Set the values in the matrix. 82 | void Init( 83 | float m00, float m01, float m02, float m03, 84 | float m10, float m11, float m12, float m13, 85 | float m20, float m21, float m22, float m23, 86 | float m30, float m31, float m32, float m33 87 | ); 88 | 89 | // array access 90 | inline float* operator[](int i) 91 | { 92 | return m[i]; 93 | } 94 | 95 | inline const float* operator[](int i) const 96 | { 97 | return m[i]; 98 | } 99 | 100 | // Initialize from a 3x4 101 | void Init(const matrix3x4_t& matrix3x4); 102 | 103 | inline void Identity(); 104 | inline Vector VMul4x3(const Vector &vVec) const; 105 | }; 106 | 107 | //----------------------------------------------------------------------------- 108 | // Sets matrix to identity 109 | //----------------------------------------------------------------------------- 110 | inline void MatrixSetIdentity(VMatrix &dst) 111 | { 112 | dst[0][0] = 1.0f; dst[0][1] = 0.0f; dst[0][2] = 0.0f; dst[0][3] = 0.0f; 113 | dst[1][0] = 0.0f; dst[1][1] = 1.0f; dst[1][2] = 0.0f; dst[1][3] = 0.0f; 114 | dst[2][0] = 0.0f; dst[2][1] = 0.0f; dst[2][2] = 1.0f; dst[2][3] = 0.0f; 115 | dst[3][0] = 0.0f; dst[3][1] = 0.0f; dst[3][2] = 0.0f; dst[3][3] = 1.0f; 116 | } 117 | 118 | inline void Vector3DMultiplyPosition(const VMatrix& src1, const VectorByValue src2, Vector& dst) 119 | { 120 | dst[0] = src1[0][0] * src2.x + src1[0][1] * src2.y + src1[0][2] * src2.z + src1[0][3]; 121 | dst[1] = src1[1][0] * src2.x + src1[1][1] * src2.y + src1[1][2] * src2.z + src1[1][3]; 122 | dst[2] = src1[2][0] * src2.x + src1[2][1] * src2.y + src1[2][2] * src2.z + src1[2][3]; 123 | } 124 | 125 | inline VMatrix::VMatrix() 126 | { 127 | } 128 | 129 | inline VMatrix::VMatrix( 130 | float m00, float m01, float m02, float m03, 131 | float m10, float m11, float m12, float m13, 132 | float m20, float m21, float m22, float m23, 133 | float m30, float m31, float m32, float m33) 134 | { 135 | Init( 136 | m00, m01, m02, m03, 137 | m10, m11, m12, m13, 138 | m20, m21, m22, m23, 139 | m30, m31, m32, m33 140 | ); 141 | } 142 | 143 | 144 | inline VMatrix::VMatrix(const matrix3x4_t& matrix3x4) 145 | { 146 | Init(matrix3x4); 147 | } 148 | 149 | 150 | //----------------------------------------------------------------------------- 151 | // Creates a matrix where the X axis = forward 152 | // the Y axis = left, and the Z axis = up 153 | //----------------------------------------------------------------------------- 154 | inline VMatrix::VMatrix(const Vector& xAxis, const Vector& yAxis, const Vector& zAxis) 155 | { 156 | Init( 157 | xAxis.x, yAxis.x, zAxis.x, 0.0f, 158 | xAxis.y, yAxis.y, zAxis.y, 0.0f, 159 | xAxis.z, yAxis.z, zAxis.z, 0.0f, 160 | 0.0f, 0.0f, 0.0f, 1.0f 161 | ); 162 | } 163 | 164 | inline VMatrix::VMatrix(const Vector& xAxis, const Vector& yAxis, const Vector& zAxis, const Vector& translation) 165 | { 166 | Init( 167 | xAxis.x, yAxis.x, zAxis.x, translation.x, 168 | xAxis.y, yAxis.y, zAxis.y, translation.y, 169 | xAxis.z, yAxis.z, zAxis.z, translation.z, 170 | 0.0f, 0.0f, 0.0f, 1.0f 171 | ); 172 | } 173 | 174 | 175 | inline void VMatrix::Init( 176 | float m00, float m01, float m02, float m03, 177 | float m10, float m11, float m12, float m13, 178 | float m20, float m21, float m22, float m23, 179 | float m30, float m31, float m32, float m33 180 | ) 181 | { 182 | m[0][0] = m00; 183 | m[0][1] = m01; 184 | m[0][2] = m02; 185 | m[0][3] = m03; 186 | 187 | m[1][0] = m10; 188 | m[1][1] = m11; 189 | m[1][2] = m12; 190 | m[1][3] = m13; 191 | 192 | m[2][0] = m20; 193 | m[2][1] = m21; 194 | m[2][2] = m22; 195 | m[2][3] = m23; 196 | 197 | m[3][0] = m30; 198 | m[3][1] = m31; 199 | m[3][2] = m32; 200 | m[3][3] = m33; 201 | } 202 | 203 | //----------------------------------------------------------------------------- 204 | // Initialize from a 3x4 205 | //----------------------------------------------------------------------------- 206 | inline void VMatrix::Init(const matrix3x4_t& matrix3x4) 207 | { 208 | memcpy(m, matrix3x4.Base(), sizeof(matrix3x4_t)); 209 | 210 | m[3][0] = 0.0f; 211 | m[3][1] = 0.0f; 212 | m[3][2] = 0.0f; 213 | m[3][3] = 1.0f; 214 | } 215 | 216 | //----------------------------------------------------------------------------- 217 | // Other random stuff 218 | //----------------------------------------------------------------------------- 219 | inline void VMatrix::Identity() 220 | { 221 | MatrixSetIdentity(*this); 222 | } 223 | 224 | inline Vector VMatrix::VMul4x3(const Vector &vVec) const 225 | { 226 | Vector vResult; 227 | Vector3DMultiplyPosition(*this, vVec, vResult); 228 | return vResult; 229 | } 230 | #endif // _GPUARAD_VMATRIX_H_ 231 | -------------------------------------------------------------------------------- /gpua_rad/worldsize.h: -------------------------------------------------------------------------------- 1 | //========= Copyright Valve Corporation, All rights reserved. ============// 2 | // 3 | // Purpose: 4 | // 5 | // $NoKeywords: $ 6 | // 7 | //=============================================================================// 8 | // worldsize.h -- extent of world and resolution/size of coordinate messages used in engine 9 | 10 | #ifndef WORLDSIZE_H 11 | #define WORLDSIZE_H 12 | #pragma once 13 | 14 | 15 | // These definitions must match the coordinate message sizes in coordsize.h 16 | 17 | // Following values should be +16384, -16384, +15/16, -15/16 18 | // NOTE THAT IF THIS GOES ANY BIGGER THEN DISK NODES/LEAVES CANNOT USE SHORTS TO STORE THE BOUNDS 19 | #define MAX_COORD_INTEGER (16384) 20 | #define MIN_COORD_INTEGER (-MAX_COORD_INTEGER) 21 | #define MAX_COORD_FRACTION (1.0-(1.0/16.0)) 22 | #define MIN_COORD_FRACTION (-1.0+(1.0/16.0)) 23 | 24 | #define MAX_COORD_FLOAT (16384.0f) 25 | #define MIN_COORD_FLOAT (-MAX_COORD_FLOAT) 26 | 27 | // Width of the coord system, which is TOO BIG to send as a client/server coordinate value 28 | #define COORD_EXTENT (2*MAX_COORD_INTEGER) 29 | 30 | // Maximum traceable distance ( assumes cubic world and trace from one corner to opposite ) 31 | // COORD_EXTENT * sqrt(3) 32 | #define MAX_TRACE_LENGTH ( 1.732050807569 * COORD_EXTENT ) 33 | 34 | // This value is the LONGEST possible range (limited by max valid coordinate number, not 2x) 35 | #define MAX_COORD_RANGE (MAX_COORD_INTEGER) 36 | 37 | #define ASSERT_COORD( v ) Assert( (v.x>=MIN_COORD_INTEGER*2) && (v.x<=MAX_COORD_INTEGER*2) && \ 38 | (v.y>=MIN_COORD_INTEGER*2) && (v.y<=MAX_COORD_INTEGER*2) && \ 39 | (v.z>=MIN_COORD_INTEGER*2) && (v.z<=MAX_COORD_INTEGER*2) ); \ 40 | 41 | 42 | #endif // WORLDSIZE_H 43 | --------------------------------------------------------------------------------