Skip to content

Commit

Permalink
Merge pull request #2 from DBauer15/buffer
Browse files Browse the repository at this point in the history
Buffer
  • Loading branch information
DBauer15 authored Apr 23, 2024
2 parents 3125c2f + 3dfd858 commit 26b57db
Show file tree
Hide file tree
Showing 24 changed files with 1,278 additions and 252 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,7 @@ build/
build

# Install Folder
install
install

# Except Test Data
!tests/data/**
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ if (NOT WIN32)
endif()

OPTION(STAGE_BUILD_EXAMPLES OFF)
OPTION(STAGE_BUILD_TESTS OFF)

OPTION(STAGE_LOGGING_WARN OFF)
OPTION(STAGE_LOGGING_LOG OFF)
OPTION(STAGE_LOGGING_OFF OFF)
Expand All @@ -21,5 +23,9 @@ if (STAGE_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()

if (STAGE_BUILD_TESTS)
add_subdirectory(tests)
endif()

install(EXPORT stageConfig
DESTINATION lib/cmake/stage)
41 changes: 27 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ int main(int argc, char** argv) {
return -1;
}

stage::Scene scene(argv[1]);
stage::Config config;
stage::Scene scene(argv[1], config);
if (!scene.isValid()) {
std::cout << "Invalid scene" << std::endl;
return -1;
Expand All @@ -47,18 +48,26 @@ int main(int argc, char** argv) {
return -1;
}
stage_scene_t* scene = NULL;
STAGE_STATUS result = stage_load(argv[1], &scene);
stage_error_t error;
stage_config_t config = stage_config_get_default();
stage_scene_t scene = stage_load(argv[1], config, &error);
if (result != STAGE_NO_ERROR) {
if (error != STAGE_NO_ERROR) {
printf("Invalid scene\n");
return -1;
}
size_t n_objects, n_instances;
stage_scene_get_objects(scene, &n_objects);
stage_scene_get_instances(scene, &n_instances);
printf("--- SCENE INFO ---\n");
printf("Objects:\t%i\n", scene->n_objects);
printf("Instances:\t%i\n", scene->n_instances);
printf("Scale:\t%.4f\n", scene_scale);
printf("Objects:\t%i\n", n_objects);
printf("Instances:\t%i\n", n_instances);
stage_free(config);
stage_free(scene);
return 0;
Expand All @@ -78,21 +87,25 @@ A scene is what you'll get when you first load a file. It contains all the data
* List of `Image`, a collection of image data like texture and environment maps
* The `SceneScale` defines the maximum extent of the loaded scene

When creating scenes, you can pass a `Config` to determine the behavior of the parser and the data parsed

* `layout` determines the vertex layout of the parsed data

---
### The `Object`, `Geometry`, and `AlignedVertex`
### The `Object` and `Geometry`
An `Object` represents a single 3D entity in a scene. It can be made up of several `Geometry` instances which, combined, represent the whole object.

A `Geometry` is the smallest building block in the scene and contains:
* A list of `indices`
* A list of `AlignedVertex` instances.
* A buffer of `positions`
* A buffer of `normals`
* A buffer of `uvs`
* A buffer of `material_ids`

The indices index into the list of vertex data.
The indices index into each of the buffer objects.
The memory layout of the underlying buffer that stores vertex data is determined by the `layout` config parameter when loading the scene.

An `AlignedVertex` represents a single vertex entry and contains:
* `position`
* `normal`
* `uv`
* `material_id`
All data within an `Object` is guaranteed to be contiguous and adhere to the chosen memory layout. Blocked layouts are blocked separately for each `Geometry`.

The material ID can be used to locate the `Material` that is associated with this vertex.

Expand Down
12 changes: 12 additions & 0 deletions dependencies/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,16 @@ set(TINYEXR_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/tinyexr CACHE INTERNAL "")
set(STAGE_EXPORTS miniz tinyexr ${STAGE_EXPORTS})
endif()

# GTest
if (STAGE_BUILD_TESTS)
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
endif()

install(TARGETS ${STAGE_EXPORTS} EXPORT stageConfig)
46 changes: 32 additions & 14 deletions examples/scene_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,47 @@ int main(int argc, char** argv) {
return -1;
}

stage_scene_t* scene = NULL;
STAGE_STATUS result = stage_load(argv[1], &scene);
stage_error_t error;
stage_config_t config = stage_config_get_default();
stage_scene_t scene = stage_load(argv[1], config, &error);

if (result != STAGE_NO_ERROR) {
if (error != STAGE_NO_ERROR) {
printf("Invalid scene\n");
return -1;
}

size_t n_objects, n_instances, n_lights, n_materials, n_textures;
float scene_scale;
stage_scene_get_objects(scene, &n_objects);
stage_scene_get_instances(scene, &n_instances);
stage_scene_get_lights(scene, &n_lights);
stage_scene_get_materials(scene, &n_materials);
stage_scene_get_textures(scene, &n_textures);
scene_scale = stage_scene_get_scale(scene);


printf("--- SCENE INFO ---\n");
printf("Scale:\t%.4f\n", scene->scene_scale);
printf("Objects:\t%i\n", scene->n_objects);
printf("Instances:\t%i\n", scene->n_instances);
printf("Lights:\t\t%i\n", scene->n_lights);
printf("Materials:\t%i\n", scene->n_materials);
printf("Textures:\t%i\n", scene->n_textures);
if (scene->camera != NULL) {
printf("Scale:\t%.4f\n", scene_scale);
printf("Objects:\t%i\n", n_objects);
printf("Instances:\t%i\n", n_instances);
printf("Lights:\t\t%i\n", n_lights);
printf("Materials:\t%i\n", n_materials);
printf("Textures:\t%i\n", n_textures);

stage_camera_t camera = stage_scene_get_camera(scene);
if (camera != NULL) {
stage_vec3f_t position = stage_camera_get_position(camera);
stage_vec3f_t lookat = stage_camera_get_lookat(camera);
stage_vec3f_t up = stage_camera_get_up(camera);
float fovy = stage_camera_get_fovy(camera);
printf("Camera:\n");
printf("\tFOV:\t%.4f", scene->camera->fovy);
printf("\tPosition:\t%.4f,\t%.4f,\t%.4f", scene->camera->position.x, scene->camera->position.y, scene->camera->position.z);
printf("\tLook At:\t%.4f,\t%.4f,\t%.4f", scene->camera->lookat.x, scene->camera->lookat.y, scene->camera->lookat.z);
printf("\tUp:\t\t%.4f,\t%.4f,\t%.4f", scene->camera->up.x, scene->camera->up.y, scene->camera->up.z);
printf("\tFOV:\t\t%.4f\n", fovy);
printf("\tPosition:\t%.4f,\t%.4f,\t%.4f\n", position.x, position.y, position.z);
printf("\tLook At:\t%.4f,\t%.4f,\t%.4f\n", lookat.x, lookat.y, lookat.z);
printf("\tUp:\t\t%.4f,\t%.4f,\t%.4f\n", up.x, up.y, up.z);
}

stage_free(config);
stage_free(scene);

return 0;
Expand Down
3 changes: 2 additions & 1 deletion examples/scene_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ int main(int argc, char** argv) {
return -1;
}

stage::Scene scene(argv[1]);
stage::Config config;
stage::Scene scene(argv[1], config);
if (!scene.isValid()) {
std::cout << "Invalid scene" << std::endl;
return -1;
Expand Down
10 changes: 2 additions & 8 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
find_package(TBB REQUIRED)

add_library(stage
backstage/camera.h
backstage/image.h
backstage/buffer.cpp
backstage/mesh.cpp
backstage/image.cpp
backstage/light.h
backstage/material.h
backstage/mesh.h
backstage/scene.h
backstage/scene.cpp
stage.h
stage.cpp
stage_c.h
stage_c.cpp
)

Expand Down
63 changes: 63 additions & 0 deletions src/backstage/buffer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include "buffer.h"

#include <stdexcept>

#include "log.h"

namespace stage {
namespace backstage {


Buffer::Buffer(Buffer& other) {
m_data = other.m_data;
m_size_in_bytes = other.m_size_in_bytes;
m_has_ownership = other.m_has_ownership;

other.m_has_ownership = false;
}

Buffer&
Buffer::operator=(Buffer& other) {
m_data = other.m_data;
m_size_in_bytes = other.m_size_in_bytes;
m_has_ownership = other.m_has_ownership;

other.m_has_ownership = false;
return *this;
}


Buffer::~Buffer() {
if (m_data != nullptr && m_has_ownership) {
std::free(m_data);
}
}

void
Buffer::data(uint8_t* blob, size_t size) {
resize(size);
std::memcpy(m_data, blob, m_size_in_bytes);
}

void
Buffer::data(std::vector<uint8_t> blob) {
resize(blob.size());
std::memcpy(m_data, blob.data(), m_size_in_bytes);
}

void
Buffer::resize(size_t newsize_in_bytes) {
if (newsize_in_bytes == m_size_in_bytes) return;
if (!m_has_ownership)
throw std::runtime_error("Cannot resize buffer that is not owned");

if (m_data != nullptr) {
m_data = (uint8_t*)std::realloc(m_data, newsize_in_bytes);
} else {
m_data = (uint8_t*)std::malloc(newsize_in_bytes);
}
m_size_in_bytes = newsize_in_bytes;
}

}
}
114 changes: 114 additions & 0 deletions src/backstage/buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#pragma once
#include <vector>
#include <memory>
#include <cstdlib>
#include <cstring>

namespace stage {
namespace backstage {

struct Buffer {
Buffer() = default;
Buffer(uint8_t* blob, size_t size) { data(blob, size); }
Buffer(std::vector<uint8_t> blob) { data(blob); }
Buffer(Buffer& other);
Buffer& operator=(Buffer& other);
~Buffer();

uint8_t* data() { return m_data; };
uint8_t* release() {
m_has_ownership = false;
return m_data;
};

void data(uint8_t* blob, size_t size);
void data(std::vector<uint8_t> blob);

void resize(size_t newsize_in_bytes);

size_t size() { return m_size_in_bytes; }

private:
uint8_t* m_data { nullptr };
size_t m_size_in_bytes { 0 };
size_t m_capacity_in_bytes { 0 };

bool m_has_ownership { true };
};

template<typename T>
struct BufferView {

BufferView() = default;
BufferView(std::shared_ptr<Buffer> source, size_t offset, size_t num_elements, size_t stride = sizeof(T)) : m_offset(offset), m_size(num_elements), m_stride(stride) {
m_buffer = source;
}

void setBuffer(std::shared_ptr<Buffer> source) {
m_offset = source->size();
m_size = 0;
m_stride = sizeof(T);
m_buffer = source;
}

void setBuffer(std::shared_ptr<Buffer> source, size_t offset, size_t num_elements, size_t stride = sizeof(T)) {
m_offset = source->size() + offset;
m_size = num_elements;
m_stride = stride;
m_buffer = source;
}

uint8_t* data() const {
if (!m_buffer) return nullptr;
return (m_buffer->data() + m_offset);
}

void push_back(const T& element) {
if (!m_buffer)
return;
size_t oldsize_in_bytes = m_buffer->size();
if (oldsize_in_bytes <= positionInBuffer())
m_buffer->resize(oldsize_in_bytes + m_stride);
std::memcpy(m_buffer->data() + positionInBuffer(), &element, sizeof(T));
m_size += 1;
}

void push_back(std::vector<T>& elements) {
if (!m_buffer)
return;
size_t oldsize_in_bytes = m_buffer->size();
if (oldsize_in_bytes <= positionInBuffer())
m_buffer->resize(positionInBuffer() + m_stride * elements.size());

if (m_stride == sizeof(T)) {
std::memcpy(m_buffer->data() + positionInBuffer(), elements.data(), sizeof(T) * elements.size());
} else {
for (size_t i = 0; i < elements.size(); i++) {
std::memcpy(m_buffer->data() + positionInBuffer() + (i * m_stride), elements.data() + i, sizeof(T));
}
}
m_size += elements.size();
}

size_t sizeInBytes() const { return m_size * sizeof(T); }
size_t size() const { return m_size; }
size_t offset() const { return m_offset; }
size_t stride() const { return m_stride; }

T& operator[](uint32_t id) const {
return *(T*)(data() + (id * m_stride));
}

private:
std::shared_ptr<Buffer> m_buffer;
size_t m_offset;
size_t m_stride;
size_t m_size { 0 };

size_t positionInBuffer() {
return (m_offset + m_size * m_stride);
}
};

}
}
Loading

0 comments on commit 26b57db

Please sign in to comment.