From 8c2c919bfdf4c946ce16672764386fce50db6126 Mon Sep 17 00:00:00 2001 From: craftablescience Date: Fri, 24 May 2024 02:18:43 -0400 Subject: [PATCH] fix: remove unnecessary length fields from structs --- include/cbreader/rmesh.h | 58 ++++------- src/rmesh.cpp | 220 ++++++++++++++++++--------------------- test/test_rmesh.cpp | 22 ++-- 3 files changed, 133 insertions(+), 167 deletions(-) diff --git a/include/cbreader/rmesh.h b/include/cbreader/rmesh.h index 4720f56..b3468e9 100644 --- a/include/cbreader/rmesh.h +++ b/include/cbreader/rmesh.h @@ -12,7 +12,6 @@ constexpr std::uint32_t MAX_SOUND_EMITTERS = 16; struct Header { // Length prefixed string - std::uint32_t header_length = 0; std::string header; /** Defines whether or not the RMesh file has any triggers embedded within the file. */ @@ -26,7 +25,6 @@ struct Texture { std::byte blendType; - std::uint32_t textureNameLength = 0; std::string textureName; }; @@ -35,31 +33,27 @@ struct Vertex Vector3 vertex; Vector2 uv; - float unk1; - float unk2; + float unk1{}; + float unk2{}; - std::byte r; - std::byte g; - std::byte b; + std::byte r{}; + std::byte g{}; + std::byte b{}; }; struct Surface { Texture textures[2]; - std::uint32_t vertexCount = 0; std::vector vertices; - std::uint32_t trianglesCount = 0; std::vector triangles; }; struct Mesh { - std::int32_t surfaceCount; std::vector surfaces; - std::uint32_t nameLength = 0; std::string name; }; @@ -70,7 +64,6 @@ struct Mesh */ struct Entity { - std::uint32_t classNameLength = 0; std::string className; /** This is read per entity. It would be ideal to read it in Entity, but EntityModel is special in that it has the model file name THEN the position. */ @@ -78,67 +71,62 @@ struct Entity Vector3 rotation; Vector3 scale; - virtual void Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className); + virtual void Read(BufferStream& stream, std::string _className); }; -struct EntityScreen : Entity +struct EntityScreen : public Entity { - std::uint32_t imgPathLength = 0; std::string imgPath; - virtual void Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className); + void Read(BufferStream& stream, std::string _className) override; }; -struct EntityWaypoint : Entity +struct EntityWaypoint : public Entity { - virtual void Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className); + void Read(BufferStream& stream, std::string _className) override; }; -struct EntityLight : Entity +struct EntityLight : public Entity { /** SCP:CB calculates this as range/2000.0 in the RMesh code*/ float range = 0.f; /** Space delimited color string. Color is 3 ints, and multiplied by intensity when reading. */ - std::uint32_t colorLength = 0; std::string color; /** SCP:CB calculates this as Min(intensity*0.8,1)*/ float intensity = 0.f; - virtual void Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className); + void Read(BufferStream& stream, std::string _className) override; }; -struct EntitySpotLight : EntityLight +struct EntitySpotLight : public EntityLight { - std::uint32_t anglesLength = 0; std::string angles; std::uint32_t innerConeAngle = 0; std::uint32_t outerConeAngle = 0; - virtual void Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className); + void Read(BufferStream& stream, std::string _className) override; }; -struct EntitySoundEmitter : Entity +struct EntitySoundEmitter : public Entity { - virtual void Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className); + void Read(BufferStream& stream, std::string _className) override; }; -struct EntityPlayerStart : Entity +struct EntityPlayerStart : public Entity { - std::uint32_t anglesLength = 0; std::string angles; - virtual void Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className); + void Read(BufferStream& stream, std::string _className) override; }; -struct EntityModel : Entity +struct EntityModel : public Entity { - std::uint32_t pathLength = 0; std::string path; - void Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className) override; + void Read(BufferStream& stream, std::string _className) override; }; /** @@ -154,10 +142,8 @@ struct RMesh Mesh drawnMesh; Mesh collisionMesh; - std::uint32_t triggerBoxCount = 0; std::vector triggerBoxes; - std::uint32_t entityCount = 0; std::vector entities; /** @@ -169,6 +155,6 @@ struct RMesh */ bool Read(const std::string& path); - Mesh ReadDrawnMesh(BufferStream& stream); - Mesh ReadCollisionMesh(BufferStream& stream); + static Mesh ReadDrawnMesh(BufferStream& stream); + static Mesh ReadCollisionMesh(BufferStream& stream); }; \ No newline at end of file diff --git a/src/rmesh.cpp b/src/rmesh.cpp index 819356f..81473ef 100644 --- a/src/rmesh.cpp +++ b/src/rmesh.cpp @@ -4,6 +4,7 @@ #include #include +#include bool RMesh::Read(const std::string& path) { @@ -13,7 +14,7 @@ bool RMesh::Read(const std::string& path) return false; } - int length = file.tellg(); + std::streamsize length = file.tellg(); std::vector buffer(length); file.seekg(0, std::ios::beg); @@ -22,8 +23,7 @@ bool RMesh::Read(const std::string& path) BufferStream stream(reinterpret_cast(buffer.data()), buffer.size()); - header.header_length = stream.read(); - header.header = stream.read_string(header.header_length, false); + stream.read(header.header, stream.read(), false); if (header.header.find("RoomMesh") == std::string::npos) { @@ -42,12 +42,11 @@ bool RMesh::Read(const std::string& path) if (header.hasTriggerBox) { - triggerBoxCount = stream.read(); + std::uint32_t triggerBoxCount = stream.read(); for (int i = 0; i < triggerBoxCount; i++) { Mesh mesh = ReadCollisionMesh(stream); - mesh.nameLength = stream.read(); - mesh.name = stream.read_string(mesh.nameLength, false); + stream.read(mesh.name, stream.read(), false); triggerBoxes.push_back(mesh); } @@ -114,60 +113,51 @@ Mesh RMesh::ReadDrawnMesh(BufferStream& stream) { Mesh mesh; - mesh.surfaceCount = stream.read(); - - for (int i = 0; i < mesh.surfaceCount; i++) + std::uint32_t surfaceCount = stream.read(); + for (int i = 0; i < surfaceCount; i++) { - Surface surf; + Surface& surf = mesh.surfaces.emplace_back(); // Read textures - for (int j = 0; j < 2; j++) + for (Texture& texture : surf.textures) { - Texture texture; - texture.blendType = stream.read(); + stream.read(texture.blendType); if (texture.blendType != std::byte(0)) { - texture.textureNameLength = stream.read(); - texture.textureName = stream.read_string(texture.textureNameLength, false); + stream.read(texture.textureName, stream.read(), false); } - - surf.textures[j] = texture; } - surf.vertexCount = stream.read(); - for (int j = 0; j < surf.vertexCount; j++) + std::uint32_t vertexCount = stream.read(); + for (int j = 0; j < vertexCount; j++) { - Vertex vert{}; - - vert.vertex.x = stream.read(); - vert.vertex.y = stream.read(); - vert.vertex.z = stream.read(); + Vertex& vert = surf.vertices.emplace_back(); + stream + .read(vert.vertex.x) + .read(vert.vertex.y) + .read(vert.vertex.z) - vert.uv.x = stream.read(); - vert.uv.y = stream.read(); + .read(vert.uv.x) + .read(vert.uv.y) - vert.unk1 = stream.read(); - vert.unk2 = stream.read(); + .read(vert.unk1) + .read(vert.unk2) - vert.r = stream.read(); - vert.g = stream.read(); - vert.b = stream.read(); - - surf.vertices.push_back(vert); + .read(vert.r) + .read(vert.g) + .read(vert.b); } - surf.trianglesCount = stream.read(); - for (int j = 0; j < surf.trianglesCount; j++) + std::uint32_t triangleCount = stream.read(); + for (int j = 0; j < triangleCount; j++) { - Triangle triangle{}; - triangle.index1 = stream.read(); - triangle.index2 = stream.read(); - triangle.index3 = stream.read(); - surf.triangles.push_back(triangle); + Triangle& triangle = surf.triangles.emplace_back(); + stream + .read(triangle.index1) + .read(triangle.index2) + .read(triangle.index3); } - - mesh.surfaces.push_back(surf); } return mesh; @@ -177,24 +167,23 @@ Mesh RMesh::ReadCollisionMesh(BufferStream& stream) { Mesh mesh; - mesh.surfaceCount = stream.read(); - - for (int i = 0; i < mesh.surfaceCount; i++) + std::uint32_t surfaceCount = stream.read(); + for (int i = 0; i < surfaceCount; i++) { - Surface surf; + Surface& surf = mesh.surfaces.emplace_back(); - surf.vertexCount = stream.read(); - for (int j = 0; j < surf.vertexCount; j++) + std::uint32_t vertexCount = stream.read(); + for (int j = 0; j < vertexCount; j++) { - Vertex vert{}; - vert.vertex.x = stream.read(); - vert.vertex.y = stream.read(); - vert.vertex.z = stream.read(); - surf.vertices.push_back(vert); + Vertex& vert = surf.vertices.emplace_back(); + stream + .read(vert.vertex.x) + .read(vert.vertex.y) + .read(vert.vertex.z); } - surf.trianglesCount = stream.read(); - for (int j = 0; j < surf.trianglesCount; j++) + std::uint32_t triangleCount = stream.read(); + for (int j = 0; j < triangleCount; j++) { Triangle triangle{}; triangle.index1 = stream.read(); @@ -202,108 +191,99 @@ Mesh RMesh::ReadCollisionMesh(BufferStream& stream) triangle.index3 = stream.read(); surf.triangles.push_back(triangle); } - - mesh.surfaces.push_back(surf); } return mesh; } -void Entity::Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className) +void Entity::Read(BufferStream& stream, std::string _className) { - classNameLength = _classNameLength; - className = _className; + className = std::move(_className); } -void EntityScreen::Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className) +void EntityScreen::Read(BufferStream& stream, std::string _className) { - Entity::Read(stream, _classNameLength, _className); + Entity::Read(stream, std::move(_className)); + stream + .read(position.x) + .read(position.y) + .read(position.z) - position.x = stream.read(); - position.y = stream.read(); - position.z = stream.read(); - - imgPathLength = stream.read(); - imgPath = stream.read_string(imgPathLength, false); + .read(imgPath, stream.read(), false); } -void EntityWaypoint::Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className) +void EntityWaypoint::Read(BufferStream& stream, std::string _className) { - Entity::Read(stream, _classNameLength, _className); - - position.x = stream.read(); - position.y = stream.read(); - position.z = stream.read(); + Entity::Read(stream, std::move(_className)); + stream + .read(position.x) + .read(position.y) + .read(position.z); } -void EntityLight::Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className) +void EntityLight::Read(BufferStream& stream, std::string _className) { - Entity::Read(stream, _classNameLength, _className); + Entity::Read(stream, _className); + stream + .read(position.x) + .read(position.y) + .read(position.z) - position.x = stream.read(); - position.y = stream.read(); - position.z = stream.read(); + .read(range) - range = stream.read(); + .read(color, stream.read(), false) - colorLength = stream.read(); - color = stream.read_string(colorLength, false); - - intensity = stream.read(); + .read(intensity); } -void EntitySpotLight::Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className) +void EntitySpotLight::Read(BufferStream& stream, std::string _className) { - EntityLight::Read(stream, _classNameLength, _className); - - anglesLength = stream.read(); - angles = stream.read_string(anglesLength, false); + EntityLight::Read(stream, _className); + stream + .read(angles, stream.read(), false) - innerConeAngle = stream.read(); - outerConeAngle = stream.read(); + .read(innerConeAngle) + .read(outerConeAngle); } -void EntitySoundEmitter::Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className) +void EntitySoundEmitter::Read(BufferStream& stream, std::string _className) { - Entity::Read(stream, _classNameLength, _className); + Entity::Read(stream, _className); /// @todo Handle sound emitters, will need to look more into the SCP:CB code to /// determine how to read these correctly. for now we will just skip over them - stream.read(); - stream.read(); - stream.read(); - stream.read(); - stream.read(); + stream + .skip(3) + .skip() + .skip(); } -void EntityPlayerStart::Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className) +void EntityPlayerStart::Read(BufferStream& stream, std::string _className) { - Entity::Read(stream, _classNameLength, _className); + Entity::Read(stream, _className); + stream + .read(position.x) + .read(position.y) + .read(position.z) - position.x = stream.read(); - position.y = stream.read(); - position.z = stream.read(); - - anglesLength = stream.read(); - angles = stream.read_string(anglesLength, false); + .read(angles, stream.read(), false); } -void EntityModel::Read(BufferStream stream, std::uint32_t _classNameLength, std::string _className) +void EntityModel::Read(BufferStream& stream, std::string _className) { - Entity::Read(stream, _classNameLength, _className); - - pathLength = stream.read(); - path = stream.read_string(pathLength, false); + Entity::Read(stream, _className); + stream + .read(path, stream.read(), false) - position.x = stream.read(); - position.y = stream.read(); - position.z = stream.read(); + .read(position.x) + .read(position.y) + .read(position.z) - rotation.x = stream.read(); - rotation.y = stream.read(); - rotation.z = stream.read(); + .read(rotation.x) + .read(rotation.y) + .read(rotation.z) - scale.x = stream.read(); - scale.y = stream.read(); - scale.z = stream.read(); + .read(scale.x) + .read(scale.y) + .read(scale.z); } \ No newline at end of file diff --git a/test/test_rmesh.cpp b/test/test_rmesh.cpp index eec3b11..a5c7164 100644 --- a/test/test_rmesh.cpp +++ b/test/test_rmesh.cpp @@ -17,33 +17,33 @@ TEST(RMesh, read_triggerboxes) EXPECT_STREQ(rmesh.header.header.data(), "RoomMesh.HasTriggerBox"); // Length of the header string. - EXPECT_EQ(rmesh.header.header_length, 22); + EXPECT_EQ(rmesh.header.header.size(), 22); // This RMesh file should have trigger boxes but not "hasNoColl" EXPECT_TRUE(rmesh.header.hasTriggerBox); EXPECT_FALSE(rmesh.header.hasNoColl); - EXPECT_EQ(rmesh.drawnMesh.surfaceCount, 22); + EXPECT_EQ(rmesh.drawnMesh.surfaces.size(), 22); // Test both the first and second index, if these pass the rest should be fine // The first texture index usually contains the texture. Each "surface" is a section of the mesh that all uses the same texture - EXPECT_EQ(rmesh.drawnMesh.surfaces[0].textures[1].textureNameLength, 21); + EXPECT_EQ(rmesh.drawnMesh.surfaces[0].textures[1].textureName.size(), 21); EXPECT_STREQ(rmesh.drawnMesh.surfaces[0].textures[1].textureName.data(), "containment_doors.jpg"); - EXPECT_EQ(rmesh.drawnMesh.surfaces[0].vertexCount, 318); - EXPECT_EQ(rmesh.drawnMesh.surfaces[0].trianglesCount, 352); + EXPECT_EQ(rmesh.drawnMesh.surfaces[0].vertices.size(), 318); + EXPECT_EQ(rmesh.drawnMesh.surfaces[0].triangles.size(), 352); - EXPECT_EQ(rmesh.drawnMesh.surfaces[1].textures[1].textureNameLength, 9); + EXPECT_EQ(rmesh.drawnMesh.surfaces[1].textures[1].textureName.size(), 9); EXPECT_STREQ(rmesh.drawnMesh.surfaces[1].textures[1].textureName.data(), "metal.jpg"); - EXPECT_EQ(rmesh.drawnMesh.surfaces[1].vertexCount, 9994); - EXPECT_EQ(rmesh.drawnMesh.surfaces[1].trianglesCount, 5104); + EXPECT_EQ(rmesh.drawnMesh.surfaces[1].vertices.size(), 9994); + EXPECT_EQ(rmesh.drawnMesh.surfaces[1].triangles.size(), 5104); // Test the collision model, if we got this passes then it's safe to assume the drawn mesh was read fine. - EXPECT_EQ(rmesh.collisionMesh.surfaceCount, 1); - EXPECT_EQ(rmesh.collisionMesh.surfaces[0].vertexCount, 18); - EXPECT_EQ(rmesh.collisionMesh.surfaces[0].trianglesCount, 8); + EXPECT_EQ(rmesh.collisionMesh.surfaces.size(), 1); + EXPECT_EQ(rmesh.collisionMesh.surfaces[0].vertices.size(), 18); + EXPECT_EQ(rmesh.collisionMesh.surfaces[0].triangles.size(), 8); } /** Reads an RMesh file from the SCP: NTF Mod. This file incorporates hasNoColl in the header. */