From caaccee1dd7ff93f72cb7d3f335a3bef2e211d62 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Wed, 1 Feb 2023 13:52:17 +0100 Subject: [PATCH] Export model data for dynamic world objects --- bsp.h | 37 ++++++++++++++++++++++++++++++++++++- common.h | 9 ++++++--- main.cpp | 39 ++++++++++++++++++++++++++++++++------- ps1bsp.h | 10 ++++++++++ 4 files changed, 84 insertions(+), 11 deletions(-) diff --git a/bsp.h b/bsp.h index 3c7e936..e9392ae 100644 --- a/bsp.h +++ b/bsp.h @@ -115,6 +115,25 @@ typedef struct BoundBox // Bounding Box, Float values if (point.z > max.z) max.z = point.z; } + + vec3_t getCenter() const + { + return vec3_t( + (max.x + min.x) * 0.5f, + (max.y + min.y) * 0.5f, + (max.z + min.z) * 0.5f + ); + } + + SVECTOR toBoundingSphere() const + { + Vec3 center = getCenter(); + Vec3 extents = max - center; + + SVECTOR sphere = center.convertWorldPosition(); + sphere.pad = (short)(extents.magnitude() * WORLDSCALE); + return sphere; + } } boundbox_t; typedef struct BBoxShort // Bounding Box, Short values @@ -147,7 +166,7 @@ typedef struct BBoxShort // Bounding Box, Short values Vec3 extents = getMaxs() - center; SVECTOR sphere = center.convertWorldPosition(); - sphere.pad = (short)(extents.magnitude() * 4); + sphere.pad = (short)(extents.magnitude() * WORLDSCALE); return sphere; } } bboxshort_t; @@ -245,6 +264,19 @@ typedef struct unsigned char sndlava; // } dleaf_t; +typedef struct +{ + boundbox_t bound; // The bounding box of the Model + vec3_t origin; // origin of model, usually (0,0,0) + long node_id0; // index of first BSP node + long node_id1; // index of the first Clip node + long node_id2; // index of the second Clip node + long node_id3; // usually zero + long numleafs; // number of BSP leaves + long face_id; // index of Faces + long face_num; // number of Faces +} model_t; + typedef struct World { const char* name; @@ -284,6 +316,9 @@ typedef struct World int numLeaves; dleaf_t* leaves; + int numModels; + model_t* models; + int entitiesLength; char* entities; diff --git a/common.h b/common.h index 4852c15..9aa824f 100644 --- a/common.h +++ b/common.h @@ -12,6 +12,9 @@ #include "ps1types.h" +#define WORLDSHIFT 2 +#define WORLDSCALE 4 // (1 << WORLDSHIFT) + typedef float scalar_t; // Scalar value, typedef struct Vec3 // Vector or Position @@ -109,9 +112,9 @@ typedef struct Vec3 // Vector or Position SVECTOR convertWorldPosition() { SVECTOR outPoint; - outPoint.vx = (short)(x * 4); - outPoint.vy = (short)(y * 4); - outPoint.vz = (short)(z * 4); + outPoint.vx = (short)(x * WORLDSCALE); + outPoint.vy = (short)(y * WORLDSCALE); + outPoint.vz = (short)(z * WORLDSCALE); outPoint.pad = ONE; return outPoint; } diff --git a/main.cpp b/main.cpp index ce6f71b..df7a047 100644 --- a/main.cpp +++ b/main.cpp @@ -105,7 +105,6 @@ int process_faces(const world_t* world, const TextureList& textures) // Sum all vertices to calculate an average center point vertexSum = vertexSum + vertexPoint; - // TODO: compute texture color * light at this vertex ps1bsp_facevertex_t faceVertex = { 0 }; faceVertex.index = (unsigned short)tesselator.addVertex(vertexPoint); outFaceVertices.push_back(faceVertex); @@ -260,9 +259,9 @@ int process_faces(const world_t* world, const TextureList& textures) // Ensure we don't overflow 16-bit short values. Most Quake maps will stay within these bounds so it *should* be fine (for now). if (inVertex.x > -8192 && inVertex.x < 8192 && inVertex.y > -8192 && inVertex.y < 8192 && inVertex.z > -8192 && inVertex.z < 8192) { - outVertex.x = (short)(inVertex.x * 4); - outVertex.y = (short)(inVertex.y * 4); - outVertex.z = (short)(inVertex.z * 4); + outVertex.x = (short)(inVertex.x * WORLDSCALE); + outVertex.y = (short)(inVertex.y * WORLDSCALE); + outVertex.z = (short)(inVertex.z * WORLDSCALE); } else { @@ -289,7 +288,7 @@ int process_faces(const world_t* world, const TextureList& textures) ps1bsp_plane_t outPlane = { 0 }; outPlane.normal = plane->normal.convertNormal(); - outPlane.dist = (short)(plane->dist * 4); + outPlane.dist = (short)(plane->dist * WORLDSCALE); outPlane.type = (short)plane->type; outPlanes.push_back(outPlane); @@ -329,6 +328,21 @@ int process_faces(const world_t* world, const TextureList& textures) outLeaves.push_back(outLeaf); } + // Convert models + std::vector outModels; + for (int modelIdx = 0; modelIdx < world->numModels; ++modelIdx) + { + model_t* model = &world->models[modelIdx]; + + ps1bsp_model_t outModel = { 0 }; + outModel.boundingSphere = model->bound.toBoundingSphere(); + outModel.origin = model->origin.convertWorldPosition(); + outModel.nodeId = (u_short)model->node_id0; + outModel.clipNodeId = (u_short)model->node_id1; + + outModels.push_back(outModel); + } + std::vector outLeafFaces(world->faceList, world->faceList + world->faceListLength); std::vector outVisData(world->visList, world->visList + world->visListLength); @@ -344,15 +358,17 @@ int process_faces(const world_t* world, const TextureList& textures) writeMapData(outLeaves, outHeader.leaves, fbsp); writeMapData(outLeafFaces, outHeader.leafFaces, fbsp); writeMapData(outVisData, outHeader.visData, fbsp); + writeMapData(outModels, outHeader.models, fbsp); // Write final header fseek(fbsp, 0, SEEK_SET); fwrite(&outHeader, sizeof(ps1bsp_header_t), 1, fbsp); fclose(fbsp); - printf("PS1BSP: wrote %d vertices, %d faces, %d polygons, %d planes, %d nodes, %d leaves, %d leaf faces\n", + printf("PS1BSP: wrote %d vertices, %d faces, %d polygons, %d planes, %d nodes, %d leaves, %d leaf faces, %d models\n", outVertices.size(), outFaces.size(), outPolygons.size(), - outPlanes.size(), outNodes.size(), outLeaves.size(), outLeafFaces.size()); + outPlanes.size(), outNodes.size(), outLeaves.size(), outLeafFaces.size(), + outModels.size()); return 1; } @@ -532,6 +548,15 @@ int load_bsp(const char* bspname, world_t* world) fseek(f, header->leaves.offset, SEEK_SET); fread(world->leaves, sizeof(dleaf_t), world->numLeaves, f); + // Load models + world->numModels = header->models.size / sizeof(model_t); + world->models = (model_t*)malloc(header->models.size); + if (world->models == NULL) + return 0; + + fseek(f, header->models.offset, SEEK_SET); + fread(world->models, sizeof(model_t), world->numModels, f); + // Load lightmaps world->lightmapLength = header->lightmaps.size / sizeof(unsigned char); world->lightmap = (unsigned char*)malloc(header->lightmaps.size); diff --git a/ps1bsp.h b/ps1bsp.h index f72cdeb..6e129da 100644 --- a/ps1bsp.h +++ b/ps1bsp.h @@ -39,6 +39,7 @@ typedef struct ps1bsp_dentry_t leaves; ps1bsp_dentry_t leafFaces; ps1bsp_dentry_t visData; + ps1bsp_dentry_t models; } ps1bsp_header_t; typedef struct @@ -142,6 +143,15 @@ typedef struct ps1bsp_leaf_s const struct ps1bsp_leaf_s* nextLeaf; // For chaining leafs in drawing order } ps1bsp_leaf_t; +typedef struct +{ + SVECTOR boundingSphere; + SVECTOR origin; + + u_short nodeId; + u_short clipNodeId; +} ps1bsp_model_t; + // Pre-parsed and encoded entity data (this runs the risk of becoming too bloated) typedef struct {