From 9e2b08970ffc641f0a43b0df22a2316dab876ceb Mon Sep 17 00:00:00 2001 From: tom Date: Wed, 11 Mar 2026 13:51:15 +0000 Subject: [PATCH 1/4] implement arena that can be used with std containers and move back to using those --- events.cpp | 1 - index.cpp | 4 +- lib/CMakeLists.txt | 4 +- lib/arena.cpp | 50 +++++++++++++ lib/include/arena.h | 33 +++++++++ lib/include/arena.hpp | 62 ++++++++++++++++ lib/include/loaders.h | 3 +- lib/include/material.h | 6 +- lib/include/mesh.h | 8 +- lib/include/mystl.hpp | 135 ---------------------------------- lib/include/raycast.h | 10 +-- lib/include/scene.h | 6 +- lib/loaders.cpp | 6 +- lib/raycast.cpp | 18 ++--- lib/scene.cpp | 4 +- mygl/include/render_program.h | 4 +- mygl/render_program.cpp | 12 +-- tests/tests.cpp | 4 +- 18 files changed, 190 insertions(+), 180 deletions(-) create mode 100644 lib/arena.cpp create mode 100644 lib/include/arena.h create mode 100644 lib/include/arena.hpp delete mode 100644 lib/include/mystl.hpp diff --git a/events.cpp b/events.cpp index 1421e1e..5ed7d3e 100644 --- a/events.cpp +++ b/events.cpp @@ -2,7 +2,6 @@ #include #include #include "math.h" -#include #include "events.h" #include "mat4.h" diff --git a/index.cpp b/index.cpp index 5ffe7ac..3ac44f1 100644 --- a/index.cpp +++ b/index.cpp @@ -1,4 +1,5 @@ +#include "arena.hpp" #include "mat4.h" #include "math_utils.h" #include "camera.h" @@ -36,6 +37,7 @@ void updateScene(Scene& scene, float dt) { int main(int argc, char** argv) { + Arena app_arena(4096); InputState input = { .pointer_down = false, @@ -174,7 +176,7 @@ int main(int argc, char** argv) "floor" ); - auto scene_nodes = DArray(); + std::vector> scene_nodes(&app_arena); scene_nodes.push_back(&green_tree); scene_nodes.push_back(&floor_model); diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 77b4dd0..29ecfdb 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.24) project(NativeRendererLib) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set (CMAKE_CXX_STANDARD 20) # find_package(OpenGL REQUIRED) set(SDL_ALSA OFF) @@ -25,7 +26,8 @@ add_library(lib SHARED scene.cpp raycast.cpp loaders.cpp - include/mystl.hpp + arena.cpp + include/arena.hpp ) target_include_directories(lib PUBLIC include) diff --git a/lib/arena.cpp b/lib/arena.cpp new file mode 100644 index 0000000..1285837 --- /dev/null +++ b/lib/arena.cpp @@ -0,0 +1,50 @@ +#include "arena.h" +#include + +Arena::Chunk* Arena::_make_chunk(size_t size) { + Chunk* chunk = static_cast(malloc(sizeof(Chunk))); + if (!chunk) throw std::bad_alloc(); + chunk->buffer = static_cast(malloc(size)); + if (!chunk->buffer) { free(chunk); throw std::bad_alloc(); } + chunk->capacity = size; + chunk->offset = 0; + chunk->next = nullptr; + return chunk; +} + +Arena::Arena(std::size_t chunk_size) + : _chunk_size(chunk_size) { + _first = _make_chunk(chunk_size); + _current = _first; +} + +char* Arena::allocate(std::size_t size) { + if (_current->capacity - _current->offset < size) { + size_t new_size = size > _chunk_size ? size : _chunk_size; + Chunk* next = _make_chunk(new_size); + _current->next = next; + _current = next; + } + char* ptr = _current->buffer + _current->offset; + _current->offset += size; + return ptr; +} + +void Arena::reset() { + Chunk* chunk = _first; + while (chunk) { + chunk->offset = 0; + chunk = chunk->next; + } + _current = _first; +} + +Arena::~Arena() { + Chunk* chunk = _first; + while (chunk) { + Chunk* next = chunk->next; + free(chunk->buffer); + free(chunk); + chunk = next; + } +} diff --git a/lib/include/arena.h b/lib/include/arena.h new file mode 100644 index 0000000..8911f02 --- /dev/null +++ b/lib/include/arena.h @@ -0,0 +1,33 @@ +#pragma once +#include +#include + +class Arena { + + struct Chunk { + char* buffer; + size_t capacity; + size_t offset; + Chunk* next; + }; + + Chunk* _make_chunk(size_t size); + + Chunk* _first; + Chunk* _current; + size_t _chunk_size; + +public: + explicit Arena(std::size_t chunk_size); + + // Allocate `size` raw bytes, returns a stable pointer + char* allocate(std::size_t size); + + // Reset all chunks to reuse memory from the start + void reset(); + + // Non-copyable, non-movable + Arena(const Arena&) = delete; + Arena(Arena&&) = delete; + ~Arena(); +}; \ No newline at end of file diff --git a/lib/include/arena.hpp b/lib/include/arena.hpp new file mode 100644 index 0000000..30acc9a --- /dev/null +++ b/lib/include/arena.hpp @@ -0,0 +1,62 @@ +#pragma once +#include +#include + +class Arena { + + struct Chunk { + char* buffer; + size_t capacity; + size_t offset; + Chunk* next; + }; + + Chunk* _make_chunk(size_t size); + + Chunk* _first; + Chunk* _current; + size_t _chunk_size; + +public: + explicit Arena(std::size_t chunk_size); + + // Allocate `size` raw bytes, returns a stable pointer + char* allocate(std::size_t size); + + // Reset all chunks to reuse memory from the start + void reset(); + + // Non-copyable, non-movable + Arena(const Arena&) = delete; + Arena(Arena&&) = delete; + ~Arena(); +}; + +template +class ArenaAllocator { +public: + using value_type = T; + + ArenaAllocator(Arena* arena) noexcept : _arena(arena) {} + + // Rebind constructor - lets std::vector create allocators for other types internally + template + ArenaAllocator(const ArenaAllocator& other) noexcept : _arena(other._arena) {} + + T* allocate(std::size_t n) { + return reinterpret_cast(_arena->allocate(sizeof(T) * n)); + } + + void deallocate(T*, std::size_t) noexcept {} + + template + bool operator==(const ArenaAllocator& other) const noexcept { return _arena == other._arena; } + + template + bool operator!=(const ArenaAllocator& other) const noexcept { return _arena != other._arena; } + +private: + Arena* _arena; + + template friend class ArenaAllocator; +}; diff --git a/lib/include/loaders.h b/lib/include/loaders.h index 4c1f335..3f5654e 100644 --- a/lib/include/loaders.h +++ b/lib/include/loaders.h @@ -2,11 +2,10 @@ #define LOADER_H #include "scene.h" -#include "mystl.hpp" char* get_shader_content(const char* fileName); -DArray read_csv(const char* filename); +std::vector read_csv(const char* filename); SceneNode load_glb(const std::string&); diff --git a/lib/include/material.h b/lib/include/material.h index a57e55d..70cae5e 100644 --- a/lib/include/material.h +++ b/lib/include/material.h @@ -3,7 +3,7 @@ #include "vec.h" #include -#include "mystl.hpp" +#include #include #include @@ -32,8 +32,8 @@ struct BasicColorMaterial { struct BasicTextureMaterial { - DArray texture; - DArray uvMap; + std::vector texture; + std::vector uvMap; std::string texture_path; // path reported by Assimp (may be embedded like "*0") TextureData texture_data; // loaded texture data (pixels, dimensions, etc.) GLuint texture_id; // OpenGL texture ID once created by renderer diff --git a/lib/include/mesh.h b/lib/include/mesh.h index 0f4609a..bba528d 100644 --- a/lib/include/mesh.h +++ b/lib/include/mesh.h @@ -4,13 +4,13 @@ #include #include #include "material.h" -#include "mystl.hpp" +#include struct Vertices { size_t vertex_count; - DArray positions; - DArray normals; - DArray indices; + std::vector positions; + std::vector normals; + std::vector indices; size_t index_count; }; diff --git a/lib/include/mystl.hpp b/lib/include/mystl.hpp deleted file mode 100644 index 0d86634..0000000 --- a/lib/include/mystl.hpp +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef MYSTL_H -#define MYSTL_H - -#include - -template -class DArray { - private: - size_t _capacity; - size_t _size; - T* data; - - void resize(const size_t new_capacity) { - T* new_data = new T[new_capacity]; - - for (size_t i = 0; i < _size; i++) { - new_data[i] = data[i]; - } - - // free old buffer and take ownership of new buffer - delete[] data; - data = new_data; - _capacity = new_capacity; - } - - public: - DArray() : _capacity(0), _size(0), data(nullptr) {} - - // Copy constructor (deep copy) - DArray(const DArray& other) - : _capacity(other._capacity), - _size(other._size), - data(other._capacity ? new T[other._capacity] : nullptr) - { - for (size_t i = 0; i < _size; ++i) - data[i] = other.data[i]; - } - - // Copy assignment (deep copy, strong exception safety) - DArray& operator=(const DArray& other) { - if (this != &other) { - // Make a temporary deep copy first - DArray temp(other); - // Swap with *this* (strong guarantee) - std::swap(_capacity, temp._capacity); - std::swap(_size, temp._size); - std::swap(data, temp.data); - } - return *this; - } - - // Move constructor - take ownership of other's buffer - DArray(DArray&& other) noexcept - : _capacity(other._capacity), - _size(other._size), - data(other.data) - { - // leave other in a valid empty state - other._capacity = 0; - other._size = 0; - other.data = nullptr; - } - - // Move assignment - free current storage, take ownership of other's storage - DArray& operator=(DArray&& other) noexcept { - if (this != &other) { - delete[] data; - _capacity = other._capacity; - _size = other._size; - data = other.data; - - other._capacity = 0; - other._size = 0; - other.data = nullptr; - } - return *this; - } - - void erase(const size_t index) { - if (index >= _size) { - throw std::out_of_range("erase index out of range"); - } - - // Move elements left by one - for (size_t i = index; i < _size - 1; ++i) { - data[i] = data[i + 1]; - } - - --_size; - } - - - void push_back(const T& value) { - if (_size == _capacity) { - size_t new_capacity = 10; - if ( _capacity > 0 ) { - new_capacity = _capacity * 2; - } - resize(new_capacity); - } - - data[_size++] = value; - } - - void pop_back() { - if (_size > 0) { - --_size; - } - } - - T* begin() { return data; } - T* end() { return data + _size; } - const T* begin() const { return data; } - const T* end() const { return data + _size; } - - T* addr(size_t index) { - return &data[index]; - } - - size_t size() const { return _size; } - - T& operator[](size_t index) { - if (index >= _size) { - throw std::out_of_range("index out of range"); - } - return data[index]; - } - - ~DArray() { - delete[] data; - } - -}; - -#endif \ No newline at end of file diff --git a/lib/include/raycast.h b/lib/include/raycast.h index 9efda59..5160338 100644 --- a/lib/include/raycast.h +++ b/lib/include/raycast.h @@ -6,7 +6,7 @@ #include "vec.h" #include "mesh.h" #include "scene.h" -#include "mystl.hpp" +#include #include "camera.h" @@ -44,14 +44,14 @@ struct NodeIntersection { Vec3Result rayIntersectsTriangle(Ray ray, Triangle triangle); -DArray rayIntersectsVertices(Ray ray, Vertices vertices); +std::vector rayIntersectsVertices(Ray ray, Vertices vertices); -DArray rayIntersectsSceneNode(Ray ray, const SceneNode& node); +std::vector rayIntersectsSceneNode(Ray ray, const SceneNode& node); -DArray rayIntersectsScene(const Ray &ray, const Scene& scene); +std::vector rayIntersectsScene(const Ray &ray, const Scene& scene); void sortBySceneDepth( - DArray& intersections, + std::vector& intersections, Camera camera ); diff --git a/lib/include/scene.h b/lib/include/scene.h index 85bb02c..2130781 100644 --- a/lib/include/scene.h +++ b/lib/include/scene.h @@ -4,16 +4,16 @@ #include #include +#include "arena.hpp" #include "light.h" #include "mesh.h" -#include "mystl.hpp" #include "mat4.h" typedef struct SceneNode { size_t id; Mat4 local_transform; Mat4 world_transform; - DArray children; // empty if no children + std::vector children; // empty if no children std::optional mesh; std::optional parent; std::optional name; @@ -24,7 +24,7 @@ typedef struct SceneNode { void setParent(SceneNode& node, SceneNode& parent); typedef struct Scene { - DArray nodes; + std::vector> nodes; AmbientLight ambient_light; DirectionalLight directional_light; PointLight point_light; diff --git a/lib/loaders.cpp b/lib/loaders.cpp index 1fd01de..44844d1 100644 --- a/lib/loaders.cpp +++ b/lib/loaders.cpp @@ -41,7 +41,7 @@ char* get_shader_content(const char* fileName) } // reads something that is not really a csv, because it has no line endings -DArray read_csv(const char* filename) { +std::vector read_csv(const char* filename) { FILE* fptr = fopen(filename, "r"); @@ -55,7 +55,7 @@ DArray read_csv(const char* filename) { number_of_floats++; const size_t number = number_of_floats; - DArray floats; + std::vector floats; size_t float_cursor = 0; char number_string[10] = { 0 }; // it wont be longer than this @@ -161,7 +161,7 @@ static TextureData loadEmbeddedTexture(const aiTexture* aiTex) { return data; } - // Helper: convert aiMesh -> Mesh (fills Vertices.positions and Vertices.normals using DArray) + // Helper: convert aiMesh -> Mesh (fills Vertices.positions and Vertices.normals using std::vector) // convert a single aiMesh into our Mesh representation Mesh convertAiMesh(const aiMesh* aMesh, const aiScene* scene) { Mesh m; diff --git a/lib/raycast.cpp b/lib/raycast.cpp index 0afbd73..5e4490f 100644 --- a/lib/raycast.cpp +++ b/lib/raycast.cpp @@ -5,7 +5,7 @@ #include "scene.h" #include #include -#include "mystl.hpp" + Vec2 getPointerClickInClipSpace(const int mouse_x, const int mouse_y, const int canvas_width, const int canvas_height) { // Convert from window coordinates to normalized device coordinates (clip space) @@ -84,11 +84,11 @@ Vec3Result rayIntersectsTriangle(Ray ray, Triangle triangle) { } -DArray rayIntersectsVertices(Ray ray, Vertices vertices) { +std::vector rayIntersectsVertices(Ray ray, Vertices vertices) { - DArray intersections; + std::vector intersections; - float * positions = vertices.positions.begin(); + float * positions = vertices.positions.data(); for (size_t i = 0; i < vertices.vertex_count * 3; i += 9) { @@ -117,9 +117,9 @@ DArray rayIntersectsVertices(Ray ray, Vertices vertices) { } -DArray rayIntersectsSceneNode(Ray ray, const SceneNode& node) { +std::vector rayIntersectsSceneNode(Ray ray, const SceneNode& node) { - DArray intersections; + std::vector intersections; std::stack node_stack; @@ -185,8 +185,8 @@ DArray rayIntersectsSceneNode(Ray ray, const SceneNode& node) return intersections; } -DArray rayIntersectsScene(const Ray &ray, const Scene& scene) { - DArray intersections; +std::vector rayIntersectsScene(const Ray &ray, const Scene& scene) { + std::vector intersections; for (const auto& node: scene.nodes) { auto rayNodeIntersections = rayIntersectsSceneNode(ray, *node); @@ -202,7 +202,7 @@ DArray rayIntersectsScene(const Ray &ray, const Scene& scene) void sortBySceneDepth( - DArray& intersections, + std::vector& intersections, Camera camera ) { diff --git a/lib/scene.cpp b/lib/scene.cpp index 1cc3c44..a1417ad 100644 --- a/lib/scene.cpp +++ b/lib/scene.cpp @@ -15,7 +15,7 @@ void setParent(SceneNode& node, SceneNode& parent) { const SceneNode * existing_child = oldParent->children[i]; if (existing_child->id == node.id) { - oldParent->children.erase(i); + oldParent->children.erase(oldParent->children.begin() + i); } } @@ -56,7 +56,7 @@ SceneNode createSceneNode(const Mat4 &transform, const std::optional &mesh .id = sceneNodeCounter, .local_transform = transform, .world_transform = transform, // actually valid since there's no parent - .children = DArray(), // empty array if no children + .children = std::vector(), // empty array if no children .mesh = mesh, .name = name }; diff --git a/mygl/include/render_program.h b/mygl/include/render_program.h index dab5532..8b0a18d 100644 --- a/mygl/include/render_program.h +++ b/mygl/include/render_program.h @@ -5,8 +5,6 @@ #include #include "scene.h" #include "mesh.h" -#include -#include "mystl.hpp" GLuint guaranteeUniformLocation(const GLuint program, const GLchar *name); @@ -82,7 +80,7 @@ BasicColorRenderProgram initShader(void); TextureRenderProgram initTextureShader(void); typedef struct GlState { - DArray vaos; + std::vector vaos; } GlState; diff --git a/mygl/render_program.cpp b/mygl/render_program.cpp index 39617b3..62bc5cf 100644 --- a/mygl/render_program.cpp +++ b/mygl/render_program.cpp @@ -1,11 +1,11 @@ #include "render_program.h" #include "loaders.h" #include "mesh.h" -#include "mystl.hpp" #include #include #include +#include GLuint guaranteeUniformLocation(const GLuint program, const GLchar *name) { @@ -37,7 +37,7 @@ void initMesh(Mesh &mesh) { glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*mesh.vertices.vertex_count*3, - mesh.vertices.positions.begin(), GL_STATIC_DRAW); + mesh.vertices.positions.data(), GL_STATIC_DRAW); // Specify the layout of the shader vertex data (positions only, 3 floats) GLint posAttrib = 0; @@ -48,7 +48,7 @@ void initMesh(Mesh &mesh) { glGenBuffers(1, &vbo_norm); glBindBuffer(GL_ARRAY_BUFFER, vbo_norm); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*mesh.vertices.vertex_count*3, - mesh.vertices.normals.begin(), GL_STATIC_DRAW); + mesh.vertices.normals.data(), GL_STATIC_DRAW); // Specify the layout of the shader vertex data (normals only, 3 floats) @@ -63,7 +63,7 @@ void initMesh(Mesh &mesh) { glGenBuffers(1, &vbo_uv); glBindBuffer(GL_ARRAY_BUFFER, vbo_uv); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * texMat.uvMap.size(), - texMat.uvMap.begin(), GL_STATIC_DRAW); + texMat.uvMap.data(), GL_STATIC_DRAW); GLint uvAttrib = 2; glEnableVertexAttribArray(uvAttrib); @@ -77,7 +77,7 @@ void initMesh(Mesh &mesh) { glGenBuffers(1, &ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * mesh.vertices.index_count, - mesh.vertices.indices.begin(), GL_STATIC_DRAW); + mesh.vertices.indices.data(), GL_STATIC_DRAW); } // unbind array buffer (but keep EBO bound to VAO) and VAO to avoid accidental state changes @@ -132,7 +132,7 @@ ShadowMap createShadowMap() { ShadowRenderProgram initShadowRenderProgram() { - DArray attribBindings; + std::vector attribBindings; attribBindings.push_back({ .name = "a_position", .location = 0}); diff --git a/tests/tests.cpp b/tests/tests.cpp index db917f7..2c57b4f 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -1,12 +1,12 @@ #include #include +#include -#include "mystl.hpp" #include "test_helpers.h" int main(int argc, char** argv) { - DArray results; + std::vector results; // triangle tests for (const auto &result : runTriangleTests()) { From 27beb16a7d246ea1209568d04aaa80cfcff81d9e Mon Sep 17 00:00:00 2001 From: tom Date: Wed, 11 Mar 2026 16:52:06 +0000 Subject: [PATCH 2/4] use frame arena --- events.cpp | 5 +++-- include/events.h | 2 +- index.cpp | 7 +++++-- lib/arena.cpp | 15 ++++++++++----- lib/include/raycast.h | 8 ++++---- lib/raycast.cpp | 21 ++++++++++++--------- mygl/gl_renderer.cpp | 6 +++--- mygl/include/gl_renderer.h | 6 +++--- 8 files changed, 41 insertions(+), 29 deletions(-) diff --git a/events.cpp b/events.cpp index 5ed7d3e..3701748 100644 --- a/events.cpp +++ b/events.cpp @@ -1,6 +1,7 @@ #include #include +#include "arena.hpp" #include "math.h" #include "events.h" @@ -12,7 +13,7 @@ using namespace mym; -void processEvents(WindowState& window, Camera& camera, InputState& input, Scene& scene) +void processEvents(WindowState& window, Camera& camera, InputState& input, Scene& scene, Arena& frame_arena) { ZoneScoped; // Handle events @@ -70,7 +71,7 @@ void processEvents(WindowState& window, Camera& camera, InputState& input, Scene ); // intersect scene - auto hits = rayIntersectsScene(worldRay, scene); + auto hits = rayIntersectsScene(worldRay, scene, frame_arena); if (hits.size() == 0) break; diff --git a/include/events.h b/include/events.h index 09cdd03..b73075f 100644 --- a/include/events.h +++ b/include/events.h @@ -17,4 +17,4 @@ typedef struct InputState { } InputState; -void processEvents(WindowState& window, Camera& camera, InputState& input, Scene& scene); +void processEvents(WindowState& window, Camera& camera, InputState& input, Scene& scene, Arena& frame_arena); diff --git a/index.cpp b/index.cpp index 3ac44f1..514de4a 100644 --- a/index.cpp +++ b/index.cpp @@ -38,6 +38,7 @@ int main(int argc, char** argv) { Arena app_arena(4096); + Arena frame_arena(4096); InputState input = { .pointer_down = false, @@ -262,7 +263,8 @@ int main(int argc, char** argv) &next_update_time, &scene_mutex, &camera_mutex, - &window_mutex + &window_mutex, + &frame_arena ] { while(!window.should_close) { @@ -275,9 +277,10 @@ int main(int argc, char** argv) std::lock_guard camera_guard(camera_mutex); std::lock_guard window_guard(window_mutex); // event is forwarded to imgui in here - processEvents(window, camera, input, scene); + processEvents(window, camera, input, scene, frame_arena); } + frame_arena.reset(); next_update_time += std::chrono::milliseconds(UPDATE_INTERVAL); std::this_thread::sleep_until(next_update_time); } diff --git a/lib/arena.cpp b/lib/arena.cpp index 1285837..c0d3d3d 100644 --- a/lib/arena.cpp +++ b/lib/arena.cpp @@ -19,11 +19,16 @@ Arena::Arena(std::size_t chunk_size) } char* Arena::allocate(std::size_t size) { - if (_current->capacity - _current->offset < size) { - size_t new_size = size > _chunk_size ? size : _chunk_size; - Chunk* next = _make_chunk(new_size); - _current->next = next; - _current = next; + while (_current->capacity - _current->offset < size) { + if (_current->next) { + // reuse existing chunk left over from before last reset + _current = _current->next; + } else { + size_t new_size = size > _chunk_size ? size : _chunk_size; + Chunk* next = _make_chunk(new_size); + _current->next = next; + _current = next; + } } char* ptr = _current->buffer + _current->offset; _current->offset += size; diff --git a/lib/include/raycast.h b/lib/include/raycast.h index 5160338..09c5ec4 100644 --- a/lib/include/raycast.h +++ b/lib/include/raycast.h @@ -44,14 +44,14 @@ struct NodeIntersection { Vec3Result rayIntersectsTriangle(Ray ray, Triangle triangle); -std::vector rayIntersectsVertices(Ray ray, Vertices vertices); +std::vector> rayIntersectsVertices(Ray ray, Vertices vertices, Arena& arena); -std::vector rayIntersectsSceneNode(Ray ray, const SceneNode& node); +std::vector> rayIntersectsSceneNode(Ray ray, const SceneNode& node, Arena& arena); -std::vector rayIntersectsScene(const Ray &ray, const Scene& scene); +std::vector> rayIntersectsScene(const Ray &ray, const Scene& scene, Arena& arena); void sortBySceneDepth( - std::vector& intersections, + std::vector>& intersections, Camera camera ); diff --git a/lib/raycast.cpp b/lib/raycast.cpp index 5e4490f..c990ff5 100644 --- a/lib/raycast.cpp +++ b/lib/raycast.cpp @@ -1,4 +1,5 @@ #include "raycast.h" +#include "arena.hpp" #include "float.h" #include "mesh.h" #include "vec.h" @@ -84,9 +85,9 @@ Vec3Result rayIntersectsTriangle(Ray ray, Triangle triangle) { } -std::vector rayIntersectsVertices(Ray ray, Vertices vertices) { +std::vector> rayIntersectsVertices(Ray ray, Vertices vertices, Arena& arena) { - std::vector intersections; + std::vector> intersections(&arena); float * positions = vertices.positions.data(); @@ -117,9 +118,9 @@ std::vector rayIntersectsVertices(Ray ray, Vertices vertices } -std::vector rayIntersectsSceneNode(Ray ray, const SceneNode& node) { +std::vector> rayIntersectsSceneNode(Ray ray, const SceneNode& node, Arena& arena) { - std::vector intersections; + std::vector> intersections(&arena); std::stack node_stack; @@ -149,7 +150,8 @@ std::vector rayIntersectsSceneNode(Ray ray, const SceneNode& n auto rayNodeIntersections = rayIntersectsVertices( newRay, - nodeUnderTest->mesh.value().vertices); + nodeUnderTest->mesh.value().vertices, + arena); if (rayNodeIntersections.size() > 0) { for (const auto& intersection : rayNodeIntersections) { @@ -185,11 +187,12 @@ std::vector rayIntersectsSceneNode(Ray ray, const SceneNode& n return intersections; } -std::vector rayIntersectsScene(const Ray &ray, const Scene& scene) { - std::vector intersections; +std::vector> rayIntersectsScene(const Ray &ray, const Scene& scene, Arena& arena) { + + std::vector> intersections(&arena); for (const auto& node: scene.nodes) { - auto rayNodeIntersections = rayIntersectsSceneNode(ray, *node); + auto rayNodeIntersections = rayIntersectsSceneNode(ray, *node, arena); if (rayNodeIntersections.size() > 0) { for (const auto& intersection : rayNodeIntersections) { intersections.push_back(intersection); @@ -202,7 +205,7 @@ std::vector rayIntersectsScene(const Ray &ray, const Scene& sc void sortBySceneDepth( - std::vector& intersections, + std::vector>& intersections, Camera camera ) { diff --git a/mygl/gl_renderer.cpp b/mygl/gl_renderer.cpp index 42b1f1e..8681ee4 100644 --- a/mygl/gl_renderer.cpp +++ b/mygl/gl_renderer.cpp @@ -61,9 +61,9 @@ GlRenderer::GlRenderer() { void GlRenderer::drawGl( - WindowState window, - Camera camera, - Scene scene + const WindowState& window, + const Camera& camera, + const Scene& scene ) { diff --git a/mygl/include/gl_renderer.h b/mygl/include/gl_renderer.h index 3b95360..c5d516c 100644 --- a/mygl/include/gl_renderer.h +++ b/mygl/include/gl_renderer.h @@ -20,9 +20,9 @@ class GlRenderer { public: GlRenderer(); void drawGl( - WindowState window, - Camera camera, - Scene scene + const WindowState& window, + const Camera& camera, + const Scene& scene ); }; From c5d8557e6f4707c3c9975500f73a151d654a2ef3 Mon Sep 17 00:00:00 2001 From: tom Date: Wed, 11 Mar 2026 17:19:55 +0000 Subject: [PATCH 3/4] remove tracyh from normal debug builds --- CMakeLists.txt | 7 ++++++- index.cpp | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 71c2d9f..0aadf9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,12 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(OpenGL REQUIRED) -option( TRACY_ENABLE "" ON) +if(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + set(TRACY_ENABLE ON CACHE BOOL "" FORCE) +else() + set(TRACY_ENABLE OFF CACHE BOOL "" FORCE) +endif() + add_subdirectory(third_party/tracy) add_subdirectory(lib lib) add_subdirectory(mym mym) diff --git a/index.cpp b/index.cpp index 514de4a..cfdd3a6 100644 --- a/index.cpp +++ b/index.cpp @@ -13,6 +13,7 @@ #include "backends/imgui_impl_sdl3.h" #include "backends/imgui_impl_opengl3.h" #include +#include using namespace mym; #define UPDATE_INTERVAL 10 From 24c2168bc73bebc2eb39aa08744148483d1d3daa Mon Sep 17 00:00:00 2001 From: tom Date: Thu, 12 Mar 2026 10:06:17 +0000 Subject: [PATCH 4/4] fix tests --- tests/raycast_scene_tests.cpp | 9 ++++++--- tests/raycast_vertices_tests.cpp | 8 ++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/raycast_scene_tests.cpp b/tests/raycast_scene_tests.cpp index 8c14926..e0b9b07 100644 --- a/tests/raycast_scene_tests.cpp +++ b/tests/raycast_scene_tests.cpp @@ -50,6 +50,7 @@ const BasicColorMaterial irrelevant = { TestResult intersect_node_with_position_transform() { + Arena test_arena(4096); auto vertices = setupVertices(); Mat4 transform = fromPositionAndEuler( @@ -70,7 +71,7 @@ TestResult intersect_node_with_position_transform() { .direction = {0.f, -1.f, 0.f} }; - auto result = rayIntersectsSceneNode(ray, node); + auto result = rayIntersectsSceneNode(ray, node, test_arena); const VertexIntersection expected = { .point = { -11.f, 0.f, 0.f}, @@ -105,6 +106,7 @@ TestResult intersect_node_with_position_transform() { TestResult intersect_node_with_multiple_position_transform() { + Arena test_arena(4096); auto vertices = setupVertices(); Mat4 transform = fromPositionAndEuler( @@ -135,7 +137,7 @@ TestResult intersect_node_with_multiple_position_transform() { }; - auto result = rayIntersectsSceneNode(ray, parentNode); + auto result = rayIntersectsSceneNode(ray, parentNode, test_arena); const VertexIntersection expected = { .point = { -11.f, 0.f, 0.f}, @@ -170,6 +172,7 @@ TestResult intersect_node_with_multiple_position_transform() { TestResult intersect_node_with_roation_transform() { + Arena test_arena(4096); auto vertices = setupVertices(); Mat4 transform = fromPositionAndEuler( @@ -190,7 +193,7 @@ TestResult intersect_node_with_roation_transform() { .direction = {0.f, -1.f, 0.f} }; - auto result = rayIntersectsSceneNode(ray, node); + auto result = rayIntersectsSceneNode(ray, node, test_arena); const VertexIntersection expected = { .point = { -1.f, -1.f, 0.f}, diff --git a/tests/raycast_vertices_tests.cpp b/tests/raycast_vertices_tests.cpp index b194c82..70c715b 100644 --- a/tests/raycast_vertices_tests.cpp +++ b/tests/raycast_vertices_tests.cpp @@ -1,3 +1,4 @@ +#include "arena.hpp" #include "mesh.h" #include "test_helpers.h" #include @@ -40,6 +41,8 @@ Vertices setupData() { TestResult intersect_vertices_first() { + Arena test_arena(4096); + auto meshVertices = setupData(); // triangle is symmetrical x-y and just a bit back from origin z @@ -48,7 +51,7 @@ TestResult intersect_vertices_first() { .direction = {0.f, -1.f, 0.f} }; - auto result = rayIntersectsVertices(ray, meshVertices); + auto result = rayIntersectsVertices(ray, meshVertices, test_arena); const VertexIntersection expected = { .point = { -1.f, 0.f, 0.f}, @@ -81,6 +84,7 @@ TestResult intersect_vertices_first() { TestResult intersect_vertices_last() { + Arena test_arena(4096); auto meshVertices = setupData(); // triangle is symmetrical x-y and just a bit back from origin z @@ -90,7 +94,7 @@ TestResult intersect_vertices_last() { .direction = {0.f, -1.f, 0.f} }; - auto result = rayIntersectsVertices(ray, meshVertices); + auto result = rayIntersectsVertices(ray, meshVertices, test_arena); const VertexIntersection expected = { .point = { 1.f, 0.f, 0.f},