diff --git a/examples/models/models_first_person_maze.cpp b/examples/models/models_first_person_maze.cpp index 32d1a175..4910aa79 100644 --- a/examples/models/models_first_person_maze.cpp +++ b/examples/models/models_first_person_maze.cpp @@ -25,7 +25,7 @@ int main(void) raylib::Image imMap("resources/cubicmap.png"); // Load cubicmap image (RAM) raylib::Texture cubicmap(imMap); // Convert image to texture to display (VRAM) - Mesh mesh = raylib::Mesh::Cubicmap(imMap, Vector3{ 1.0f, 1.0f, 1.0f }); + raylib::MeshUnmanaged mesh = raylib::MeshUnmanaged::Cubicmap(imMap, Vector3{ 1.0f, 1.0f, 1.0f }); // Use MeshUnmanaged, Mesh will be handled by Model raylib::Model model(mesh); // NOTE: By default each cube is mapped to one part of texture atlas diff --git a/include/Mesh.hpp b/include/Mesh.hpp index 38d9daec..60bd11fa 100644 --- a/include/Mesh.hpp +++ b/include/Mesh.hpp @@ -8,28 +8,33 @@ #include "./raylib-cpp-utils.hpp" #include "./BoundingBox.hpp" #include "./Model.hpp" +#include "./MeshUnmanaged.hpp" namespace raylib { /** - * Vertex data definning a mesh + * Vertex data defining a mesh + * + * The Mesh will be unloaded on object destruction. + * + * @see raylib::MeshUnmanaged */ -class Mesh : public ::Mesh { +class Mesh : public MeshUnmanaged { public: - Mesh(const ::Mesh& mesh) { - set(mesh); - } + using MeshUnmanaged::MeshUnmanaged; /** - * Load meshes from model file + * Explicitly forbid the copy constructor. */ - // static std::vector Load(const std::string& fileName) { - // int count = 0; - // ::Mesh* meshes = LoadMeshes(fileName.c_str(), &count); - // return std::vector(meshes, meshes + count); - // } - Mesh(const Mesh&) = delete; + /** + * Explicitly forbid copy assignment. + */ + Mesh& operator=(const Mesh&) = delete; + + /** + * Move constructor. + */ Mesh(Mesh&& other) { set(other); @@ -50,106 +55,6 @@ class Mesh : public ::Mesh { other.vboId = nullptr; } - /** - * Generate polygonal mesh - */ - static ::Mesh Poly(int sides, float radius) { - return ::GenMeshPoly(sides, radius); - } - - /** - * Generate plane mesh (with subdivisions) - */ - static ::Mesh Plane(float width, float length, int resX, int resZ) { - return ::GenMeshPlane(width, length, resX, resZ); - } - - /** - * Generate cuboid mesh - */ - static ::Mesh Cube(float width, float height, float length) { - return ::GenMeshCube(width, height, length); - } - - /** - * Generate sphere mesh (standard sphere) - */ - static ::Mesh Sphere(float radius, int rings, int slices) { - return ::GenMeshSphere(radius, rings, slices); - } - - /** - * Generate half-sphere mesh (no bottom cap) - */ - static ::Mesh HemiSphere(float radius, int rings, int slices) { - return ::GenMeshHemiSphere(radius, rings, slices); - } - - /** - * Generate cylinder mesh - */ - static ::Mesh Cylinder(float radius, float height, int slices) { - return ::GenMeshCylinder(radius, height, slices); - } - - /** - * Generate cone/pyramid mesh - */ - static ::Mesh Cone(float radius, float height, int slices) { - return ::GenMeshCone(radius, height, slices); - } - - /** - * Generate torus mesh - */ - static ::Mesh Torus(float radius, float size, int radSeg, int sides) { - return ::GenMeshTorus(radius, size, radSeg, sides); - } - - /** - * Generate trefoil knot mesh - */ - static ::Mesh Knot(float radius, float size, int radSeg, int sides) { - return ::GenMeshKnot(radius, size, radSeg, sides); - } - - /** - * Generate heightmap mesh from image data - */ - static ::Mesh Heightmap(const ::Image& heightmap, ::Vector3 size) { - return ::GenMeshHeightmap(heightmap, size); - } - - /** - * Generate cubes-based map mesh from image data - */ - static ::Mesh Cubicmap(const ::Image& cubicmap, ::Vector3 cubeSize) { - return ::GenMeshCubicmap(cubicmap, cubeSize); - } - - GETTERSETTER(int, VertexCount, vertexCount) - GETTERSETTER(int, TriangleCount, triangleCount) - GETTERSETTER(float*, Vertices, vertices) - GETTERSETTER(float *, TexCoords, texcoords) - GETTERSETTER(float *, TexCoords2, texcoords2) - GETTERSETTER(float *, Normals, normals) - GETTERSETTER(float *, Tangents, tangents) - GETTERSETTER(unsigned char *, Colors, colors) - GETTERSETTER(unsigned short *, Indices, indices) // NOLINT - GETTERSETTER(float *, AnimVertices, animVertices) - GETTERSETTER(float *, AnimNormals, animNormals) - GETTERSETTER(unsigned char *, BoneIds, boneIds) - GETTERSETTER(float *, BoneWeights, boneWeights) - GETTERSETTER(unsigned int, VaoId, vaoId) - GETTERSETTER(unsigned int *, VboId, vboId) - - Mesh& operator=(const ::Mesh& mesh) { - set(mesh); - return *this; - } - - Mesh& operator=(const Mesh&) = delete; - Mesh& operator=(Mesh&& other) noexcept { if (this == &other) { return *this; @@ -180,110 +85,6 @@ class Mesh : public ::Mesh { ~Mesh() { Unload(); } - - /** - * Upload mesh vertex data to GPU (VRAM) - */ - void Upload(bool dynamic = false) { - ::UploadMesh(this, dynamic); - } - - /** - * Upload mesh vertex data to GPU (VRAM) - */ - void UpdateBuffer(int index, void *data, int dataSize, int offset = 0) { - ::UpdateMeshBuffer(*this, index, data, dataSize, offset); - } - - /** - * Draw a 3d mesh with material and transform - */ - void Draw(const ::Material& material, const ::Matrix& transform) const { - ::DrawMesh(*this, material, transform); - } - - /** - * Draw multiple mesh instances with material and different transforms - */ - void Draw(const ::Material& material, ::Matrix* transforms, int instances) const { - ::DrawMeshInstanced(*this, material, transforms, instances); - } - - /** - * Export mesh data to file - * - * @throws raylib::RaylibException Throws if failed to export the Mesh. - */ - void Export(const std::string& fileName) { - if (!::ExportMesh(*this, fileName.c_str())) { - throw RaylibException("Failed to export the Mesh"); - } - } - - /** - * Unload mesh from memory (RAM and/or VRAM) - */ - void Unload() { - if (vboId != nullptr) { - ::UnloadMesh(*this); - vboId = nullptr; - } - } - - /** - * Compute mesh bounding box limits - */ - raylib::BoundingBox BoundingBox() const { - return ::GetMeshBoundingBox(*this); - } - - /** - * Compute mesh bounding box limits - */ - operator raylib::BoundingBox() { - return BoundingBox(); - } - - /** - * Compute mesh tangents - */ - Mesh& GenTangents() { - ::GenMeshTangents(this); - return *this; - } - - /** - * Load model from generated mesh - */ - raylib::Model LoadModelFrom() const { - return ::LoadModelFromMesh(*this); - } - - /** - * Load model from generated mesh - */ - operator raylib::Model() { - return ::LoadModelFromMesh(*this); - } - - protected: - void set(const ::Mesh& mesh) { - vertexCount = mesh.vertexCount; - triangleCount = mesh.triangleCount; - vertices = mesh.vertices; - texcoords = mesh.texcoords; - texcoords2 = mesh.texcoords2; - normals = mesh.normals; - tangents = mesh.tangents; - colors = mesh.colors; - indices = mesh.indices; - animVertices = mesh.animVertices; - animNormals = mesh.animNormals; - boneIds = mesh.boneIds; - boneWeights = mesh.boneWeights; - vaoId = mesh.vaoId; - vboId = mesh.vboId; - } }; } // namespace raylib diff --git a/include/MeshUnmanaged.hpp b/include/MeshUnmanaged.hpp new file mode 100644 index 00000000..6ecbd181 --- /dev/null +++ b/include/MeshUnmanaged.hpp @@ -0,0 +1,267 @@ +#ifndef RAYLIB_CPP_INCLUDE_MESHUNMANAGED_HPP_ +#define RAYLIB_CPP_INCLUDE_MESHUNMANAGED_HPP_ + +#include +#include + +#include "./raylib.hpp" +#include "./raylib-cpp-utils.hpp" +#include "./BoundingBox.hpp" +#include "./Model.hpp" + +namespace raylib { + +/** + * Vertex data defining a mesh, not managed by C++ RAII. + * + * Make sure to Unload() this if needed, otherwise use raylib::Mesh. + * + * @see raylib::Mesh + */ +class MeshUnmanaged : public ::Mesh { + public: + /** + * Default texture constructor. + */ + MeshUnmanaged() { + vertexCount = 0; + triangleCount = 0; + vertices = nullptr; + texcoords = nullptr; + texcoords2 = nullptr; + normals = nullptr; + tangents = nullptr; + colors = nullptr; + indices = nullptr; + animVertices = nullptr; + animNormals = nullptr; + boneIds = nullptr; + boneWeights = nullptr; + vaoId = 0; + vboId = nullptr; + } + + MeshUnmanaged(const ::Mesh& mesh) { + set(mesh); + } + + MeshUnmanaged(::Mesh&& mesh) { + set(mesh); + } + + /** + * Load meshes from model file + */ + // static std::vector Load(const std::string& fileName) { + // int count = 0; + // ::Mesh* meshes = LoadMeshes(fileName.c_str(), &count); + // return std::vector(meshes, meshes + count); + // } + + /** + * Generate polygonal mesh + */ + static ::Mesh Poly(int sides, float radius) { + return ::GenMeshPoly(sides, radius); + } + + /** + * Generate plane mesh (with subdivisions) + */ + static ::Mesh Plane(float width, float length, int resX, int resZ) { + return ::GenMeshPlane(width, length, resX, resZ); + } + + /** + * Generate cuboid mesh + */ + static ::Mesh Cube(float width, float height, float length) { + return ::GenMeshCube(width, height, length); + } + + /** + * Generate sphere mesh (standard sphere) + */ + static ::Mesh Sphere(float radius, int rings, int slices) { + return ::GenMeshSphere(radius, rings, slices); + } + + /** + * Generate half-sphere mesh (no bottom cap) + */ + static ::Mesh HemiSphere(float radius, int rings, int slices) { + return ::GenMeshHemiSphere(radius, rings, slices); + } + + /** + * Generate cylinder mesh + */ + static ::Mesh Cylinder(float radius, float height, int slices) { + return ::GenMeshCylinder(radius, height, slices); + } + + /** + * Generate cone/pyramid mesh + */ + static ::Mesh Cone(float radius, float height, int slices) { + return ::GenMeshCone(radius, height, slices); + } + + /** + * Generate torus mesh + */ + static ::Mesh Torus(float radius, float size, int radSeg, int sides) { + return ::GenMeshTorus(radius, size, radSeg, sides); + } + + /** + * Generate trefoil knot mesh + */ + static ::Mesh Knot(float radius, float size, int radSeg, int sides) { + return ::GenMeshKnot(radius, size, radSeg, sides); + } + + /** + * Generate heightmap mesh from image data + */ + static ::Mesh Heightmap(const ::Image& heightmap, ::Vector3 size) { + return ::GenMeshHeightmap(heightmap, size); + } + + /** + * Generate cubes-based map mesh from image data + */ + static ::Mesh Cubicmap(const ::Image& cubicmap, ::Vector3 cubeSize) { + return ::GenMeshCubicmap(cubicmap, cubeSize); + } + + GETTERSETTER(int, VertexCount, vertexCount) + GETTERSETTER(int, TriangleCount, triangleCount) + GETTERSETTER(float*, Vertices, vertices) + GETTERSETTER(float *, TexCoords, texcoords) + GETTERSETTER(float *, TexCoords2, texcoords2) + GETTERSETTER(float *, Normals, normals) + GETTERSETTER(float *, Tangents, tangents) + GETTERSETTER(unsigned char *, Colors, colors) + GETTERSETTER(unsigned short *, Indices, indices) // NOLINT + GETTERSETTER(float *, AnimVertices, animVertices) + GETTERSETTER(float *, AnimNormals, animNormals) + GETTERSETTER(unsigned char *, BoneIds, boneIds) + GETTERSETTER(float *, BoneWeights, boneWeights) + GETTERSETTER(unsigned int, VaoId, vaoId) + GETTERSETTER(unsigned int *, VboId, vboId) + + MeshUnmanaged& operator=(const ::Mesh& mesh) { + set(mesh); + return *this; + } + + /** + * Unload mesh from memory (RAM and/or VRAM) + */ + void Unload() { + if (vboId != nullptr) { + ::UnloadMesh(*this); + vboId = nullptr; + } + } + + /** + * Upload mesh vertex data to GPU (VRAM) + */ + void Upload(bool dynamic = false) { + ::UploadMesh(this, dynamic); + } + + /** + * Upload mesh vertex data to GPU (VRAM) + */ + void UpdateBuffer(int index, void *data, int dataSize, int offset = 0) { + ::UpdateMeshBuffer(*this, index, data, dataSize, offset); + } + + /** + * Draw a 3d mesh with material and transform + */ + void Draw(const ::Material& material, const ::Matrix& transform) const { + ::DrawMesh(*this, material, transform); + } + + /** + * Draw multiple mesh instances with material and different transforms + */ + void Draw(const ::Material& material, ::Matrix* transforms, int instances) const { + ::DrawMeshInstanced(*this, material, transforms, instances); + } + + /** + * Export mesh data to file + * + * @throws raylib::RaylibException Throws if failed to export the Mesh. + */ + void Export(const std::string& fileName) { + if (!::ExportMesh(*this, fileName.c_str())) { + throw RaylibException("Failed to export the Mesh"); + } + } + + /** + * Compute mesh bounding box limits + */ + raylib::BoundingBox BoundingBox() const { + return ::GetMeshBoundingBox(*this); + } + + /** + * Compute mesh bounding box limits + */ + operator raylib::BoundingBox() { + return BoundingBox(); + } + + /** + * Compute mesh tangents + */ + Mesh& GenTangents() { + ::GenMeshTangents(this); + return *this; + } + + /** + * Load model from generated mesh + */ + raylib::Model LoadModelFrom() const { + return ::LoadModelFromMesh(*this); + } + + /** + * Load model from generated mesh + */ + operator raylib::Model() { + return ::LoadModelFromMesh(*this); + } + + protected: + void set(const ::Mesh& mesh) { + vertexCount = mesh.vertexCount; + triangleCount = mesh.triangleCount; + vertices = mesh.vertices; + texcoords = mesh.texcoords; + texcoords2 = mesh.texcoords2; + normals = mesh.normals; + tangents = mesh.tangents; + colors = mesh.colors; + indices = mesh.indices; + animVertices = mesh.animVertices; + animNormals = mesh.animNormals; + boneIds = mesh.boneIds; + boneWeights = mesh.boneWeights; + vaoId = mesh.vaoId; + vboId = mesh.vboId; + } +}; +} // namespace raylib + +using RMeshUnmanaged = raylib::MeshUnmanaged; + +#endif // RAYLIB_CPP_INCLUDE_MESHUNMANAGED_HPP_ diff --git a/include/TextureUnmanaged.hpp b/include/TextureUnmanaged.hpp index 38994c0f..01e48271 100644 --- a/include/TextureUnmanaged.hpp +++ b/include/TextureUnmanaged.hpp @@ -12,7 +12,7 @@ namespace raylib { /** - * A Texture that is not managed by the C++ garbage collector. + * A Texture that is not managed by C++ RAII. * * Make sure to Unload() this if needed, otherwise use raylib::Texture. *