Skip to content

Commit

Permalink
fix: Move RMesh to a namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
AWildErin committed Jun 27, 2024
1 parent caf7a4d commit 631dd81
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 129 deletions.
266 changes: 138 additions & 128 deletions include/cbreader/rmesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,167 +7,177 @@

class BufferStream;

constexpr std::uint32_t MAX_SOUND_EMITTERS = 16;

struct Header
namespace rmesh
{
// Length prefixed string
std::string header;

/** Defines whether or not the RMesh file has any triggers embedded within the file. */
bool hasTriggerBox = false;
constexpr std::uint32_t MAX_SOUND_EMITTERS = 16;

/** NTF Mod specific property. */
bool hasNoColl = false;
};
struct Header
{
// Length prefixed string
std::string header;

struct Texture
{
std::byte blendType;
/** Defines whether or not the RMesh file has any triggers embedded within the file. */
bool hasTriggerBox = false;

std::string textureName;
};
/** NTF Mod specific property. */
bool hasNoColl = false;
};

struct Vertex
{
Vector3 vertex;
Vector2 uv;
struct Texture
{
std::byte blendType;

float unk1{};
float unk2{};
std::string textureName;
};

std::byte r{};
std::byte g{};
std::byte b{};
};
struct Vertex
{
Vector3 vertex;
Vector2 uv;

struct Surface
{
Texture textures[2];
float unk1{};
float unk2{};

std::vector<Vertex> vertices;
std::byte r{};
std::byte g{};
std::byte b{};
};

std::vector<Triangle> triangles;
};
struct Surface
{
Texture textures[2];

struct Mesh
{
std::vector<Surface> surfaces;

/** Only valid for TriggerBoxes */
std::string name;
};

/**
* @class Entity
*
* Root entity class embedded in RMesh files
*/
struct Entity
{
std::string className;
std::vector<Vertex> vertices;

/** 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. */
Vector3 position;
Vector3 rotation;
Vector3 scale;
std::vector<Triangle> triangles;
};

virtual ~Entity() = default;
/**
* @class Mesh
*
* A collection of surfaces that make up the visual and collision mesh for RMesh
*/
struct Mesh
{
std::vector<Surface> surfaces;

virtual void Read(BufferStream& stream, std::string _className);
};
/** Only valid for TriggerBoxes */
std::string name;
};

struct EntityScreen : public Entity
{
std::string imgPath;
/**
* @class Entity
*
* Root entity class embedded in RMesh files
*/
struct Entity
{
std::string className;

void Read(BufferStream& stream, std::string _className) override;
};
/** 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. */
Vector3 position;
Vector3 rotation;
Vector3 scale;

struct EntityWaypoint : public Entity
{
void Read(BufferStream& stream, std::string _className) override;
};
virtual ~Entity() = default;

struct EntityLight : public Entity
{
/** SCP:CB calculates this as range/2000.0 in the RMesh code*/
float range = 0.f;
virtual void Read(BufferStream& stream, std::string _className);
};

/** Space delimited color string. Color is 3 ints, and multiplied by intensity when reading. */
std::string color;
struct EntityScreen : public Entity
{
std::string imgPath;

/** SCP:CB calculates this as Min(intensity*0.8,1)*/
float intensity = 0.f;
void Read(BufferStream& stream, std::string _className) override;
};

void Read(BufferStream& stream, std::string _className) override;
};
struct EntityWaypoint : public Entity
{
void Read(BufferStream& stream, std::string _className) override;
};

struct EntitySpotLight : public EntityLight
{
std::string angles;
struct EntityLight : public Entity
{
/** SCP:CB calculates this as range/2000.0 in the RMesh code*/
float range = 0.f;

std::uint32_t innerConeAngle = 0;
std::uint32_t outerConeAngle = 0;
/** Space delimited color string. Color is 3 ints, and multiplied by intensity when reading. */
std::string color;

void Read(BufferStream& stream, std::string _className) override;
};
/** SCP:CB calculates this as Min(intensity*0.8,1)*/
float intensity = 0.f;

struct EntitySoundEmitter : public Entity
{
void Read(BufferStream& stream, std::string _className) override;
void Read(BufferStream& stream, std::string _className) override;
};

// https://github.com/Regalis11/scpcb/blob/edb8fe0840b78f14d1aef3a0bf6174630e7be296/MapSystem.bb#L181
std::uint32_t sound = 0;
float range = 0.f;
};
struct EntitySpotLight : public EntityLight
{
std::string angles;

struct EntityPlayerStart : public Entity
{
std::string angles;
std::uint32_t innerConeAngle = 0;
std::uint32_t outerConeAngle = 0;

void Read(BufferStream& stream, std::string _className) override;
};
void Read(BufferStream& stream, std::string _className) override;
};

struct EntityModel : public Entity
{
std::string path;

void Read(BufferStream& stream, std::string _className) override;
};

/**
* @class RMesh
* RMesh is the main room mesh format in SCP: Containment Breach
*
* @todo Maybe move Read to the constructor instead
*/
struct RMesh
{
Header header;
struct EntitySoundEmitter : public Entity
{
void Read(BufferStream& stream, std::string _className) override;

// https://github.com/Regalis11/scpcb/blob/edb8fe0840b78f14d1aef3a0bf6174630e7be296/MapSystem.bb#L181
std::uint32_t sound = 0;
float range = 0.f;
};

Mesh drawnMesh;
Mesh collisionMesh;
struct EntityPlayerStart : public Entity
{
std::string angles;

std::vector<Mesh> triggerBoxes;
void Read(BufferStream& stream, std::string _className) override;
};

std::vector<EntityScreen> screenEntities;
std::vector<EntityWaypoint> waypointEntities;
std::vector<EntityLight> lightEntities;
std::vector<EntitySpotLight> spotlightEntities;
std::vector<EntitySoundEmitter> soundEmitterEntities;
std::vector<EntityPlayerStart> playerStartEntities;
std::vector<EntityModel> modelEntities;
struct EntityModel : public Entity
{
std::string path;

void Read(BufferStream& stream, std::string _className) override;
};

/**
* Reads the specified RMesh file
*
* @param path The file path you wish to open
*
* @returns Whether the RMesh file was read correctly.
* @class RMesh
* RMesh is the main room mesh format in SCP: Containment Breach
*
* @todo Maybe move Read to the constructor instead
*/
bool Read(const std::string& path);

static Mesh ReadDrawnMesh(BufferStream& stream);
static Mesh ReadCollisionMesh(BufferStream& stream);
};
struct RMesh
{
Header header;

Mesh drawnMesh;
Mesh collisionMesh;

std::vector<Mesh> triggerBoxes;

std::vector<EntityScreen> screenEntities;
std::vector<EntityWaypoint> waypointEntities;
std::vector<EntityLight> lightEntities;
std::vector<EntitySpotLight> spotlightEntities;
std::vector<EntitySoundEmitter> soundEmitterEntities;
std::vector<EntityPlayerStart> playerStartEntities;
std::vector<EntityModel> modelEntities;

/**
* Reads the specified RMesh file
*
* @param path The file path you wish to open
*
* @returns Whether the RMesh file was read correctly.
*/
bool Read(const std::string& path);

static Mesh ReadDrawnMesh(BufferStream& stream);
static Mesh ReadCollisionMesh(BufferStream& stream);
};

}
2 changes: 2 additions & 0 deletions src/rmesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <iostream>
#include <utility>

using namespace rmesh;

bool RMesh::Read(const std::string& path)
{
std::ifstream file(path, std::ios::binary | std::ios::ate);
Expand Down
2 changes: 1 addition & 1 deletion test/test_rmesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ TEST(RMesh, read_triggerboxes)
{
std::string path = RESOURCES_ROOT_PATH "/173_opt.rmesh";

RMesh rmesh;
rmesh::RMesh rmesh;

// Check if the RMesh file loaded
EXPECT_TRUE(rmesh.Read(path));
Expand Down

0 comments on commit 631dd81

Please sign in to comment.