Initial commit

This commit is contained in:
Joshua Ashton 2022-06-12 16:33:55 +01:00
commit 4e86a20238
18 changed files with 584 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
build
.cache

View File

@ -0,0 +1,12 @@
#pragma once
#include <Orange/Core/Types.h>
namespace orange
{
template <size_t Length, size_t Alignment>
struct AlignedStorage
{
alignas(Alignment) unsigned char data[Length];
};
}

View File

@ -0,0 +1,12 @@
#pragma once
#include <Orange/Core/Result.h>
namespace orange::fs
{
class File
{
};
//Result<File>
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <Orange/Core/Types.h>
namespace orange
{
constexpr uint32_t HashString(const char* s, size_t count)
{
return ((count ? HashString(s, count - 1) : 2166136261u) ^ s[count]) * 16777619u;
}
constexpr uint32_t operator"" _hash(const char* s, size_t count)
{
return HashString(s, count);
}
}

View File

@ -0,0 +1,6 @@
#pragma once
namespace orange
{
#define Assert(...)
}

View File

@ -0,0 +1,82 @@
#pragma once
#include <Orange/Core/Log.h>
#include <Orange/Core/AlignedStorage.h>
#include <Orange/Core/Traits.h>
namespace orange
{
enum class BasicErrorCode : int32_t
{
Invalid = -1,
Failed = -2,
Success = 0,
};
template <typename T, typename ErrorCode = BasicErrorCode>
class Result
{
public:
~Result() { Destroy(); }
T* Get()
{
Assert(IsSuccess());
if (!IsSuccess())
return nullptr;
return &RefUnsafe();
}
const T* Get() const
{
Assert(IsSuccess());
if (!IsSuccess())
return nullptr;
return &RefUnsafe();
}
bool IsSuccess() const { return static_cast<int32_t>(m_error) >= 0; }
operator bool() const { return IsSuccess(); }
T* operator ->() { return Get(); }
const T* operator ->() const { return Get(); }
T& operator *() { return *Get(); }
const T& operator *() const { return *Get(); }
protected:
Result() = default;
template <typename... Args>
T& Create(Args&&... args)
{
Assert(!m_created);
m_created = true;
new(&m_data) T(Forward<Args>(args)...);
return RefUnsafe();
}
void Destroy()
{
if (m_created)
{
RefUnsafe().~T();
m_created = false;
}
}
Result& Error(ErrorCode code) { m_error = code; return *this; }
Result& Success() { m_error = ErrorCode::Success; return *this; }
T& RefUnsafe() { return *reinterpret_cast< T*>(&m_data); }
const T& RefUnsafe() const { return *reinterpret_cast<const T*>(&m_data); }
friend T;
AlignedStorage<sizeof(T), alignof(T)> m_data;
ErrorCode m_error = ErrorCode::Invalid;
bool m_created = false;
};
}

View File

@ -0,0 +1,148 @@
#pragma once
#include <Orange/Core/AlignedStorage.h>
namespace orange
{
template <typename T, size_t N>
class SmallVector
{
public:
SmallVector() {}
SmallVector(size_t size) { Resize(size); }
SmallVector (const SmallVector&) = delete;
SmallVector& operator = (const SmallVector&) = delete;
~SmallVector()
{
for (size_t i = 0; i < m_size; i++)
Ptr(i)->~T();
if (m_capacity > N)
delete[] u.m_ptr;
}
size_t Size() const
{
return m_size;
}
void Reserve(size_t n)
{
n = PickCapacity(n);
if (n <= m_capacity)
return;
Storage* data = new Storage[n];
for (size_t i = 0; i < m_size; i++)
{
new (&data[i]) T(Move(*Ptr(i)));
Ptr(i)->~T();
}
if (m_capacity > N)
delete[] u.m_ptr;
m_capacity = n;
u.m_ptr = data;
}
const T* Data() const { return Ptr(0); }
T* Data() { return Ptr(0); }
void Resize(size_t n)
{
Reserve(n);
for (size_t i = n; i < m_size; i++)
Ptr(i)->~T();
for (size_t i = m_size; i < n; i++)
new (Ptr(i)) T();
}
void PushBack(const T& object)
{
Reserve(m_size + 1);
new (Ptr(m_size++)) T(object);
}
void PushBack(T&& object)
{
Reserve(m_size + 1);
new (Ptr(m_size++)) T(Move(object));
}
template<typename... Args>
void EmplaceBack(Args... args)
{
Reserve(m_size + 1);
new (Ptr(m_size++)) T(Forward<Args>(args)...);
}
void Erase(size_t idx)
{
Ptr(idx)->~T();
for (size_t i = idx; i < m_size - 1; i++)
{
new (Ptr(i)) T(Move(*Ptr(i + 1)));
Ptr(i + 1)->~T();
}
}
void PopBack()
{
Ptr(--m_size)->~T();
}
T& operator [] (size_t idx) { return *Ptr(idx); }
const T& operator [] (size_t idx) const { return *Ptr(idx); }
T& front() { return *Ptr(0); }
const T& front() const { return *Ptr(0); }
T& back() { return *Ptr(m_size - 1); }
const T& back() const { return *Ptr(m_size - 1); }
private:
using Storage = AlignedStorage<sizeof(T), alignof(T)>;
size_t m_capacity = N;
size_t m_size = 0;
union
{
Storage* m_ptr;
Storage m_data[sizeof(T) * N];
} u;
size_t PickCapacity(size_t n) {
size_t capacity = m_capacity;
while (capacity < n)
capacity *= 2;
return capacity;
}
T* Ptr(size_t idx) {
return m_capacity == N
? reinterpret_cast<T*>(&u.m_data[idx])
: reinterpret_cast<T*>(&u.m_ptr[idx]);
}
const T* Ptr(size_t idx) const
{
return m_capacity == N
? reinterpret_cast<const T*>(&u.m_data[idx])
: reinterpret_cast<const T*>(&u.m_ptr[idx]);
}
};
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <Orange/Core/Types.h>
namespace orange
{
template <typename T>
struct Span
{
Span(T* data, size_t size) : data(data), size(size) {}
template <size_t Count>
Span(T (&array)[Count]) : data(array), size(Count) {}
explicit Span(T* data) : data(data), size(1) {}
explicit Span(T& data) : data(&data), size(1) {}
T& operator [] (size_t idx) { return data[idx]; }
const T& operator [] (size_t idx) const { return data[idx]; }
bool IsEmpty() const { return size == 0; }
T& front() { return *data[idx]; }
const T& front() const { return *data[idx]; }
T& back() { return *data[size - 1]; }
const T& back() const { return *data[size - 1]; }
T* data;
size_t size;
};
}

View File

@ -0,0 +1,33 @@
#pragma once
namespace orange
{
struct FalseType { static constexpr bool Value = false; };
struct TrueType { static constexpr bool Value = true; };
template <typename T> struct IsLValueReference : FalseType {};
template <typename T> struct IsLValueReference<T&> : TrueType {};
template <typename T> struct RemoveReference_ { using Type = T; };
template <typename T> struct RemoveReference_<T&> { using Type = T; };
template <typename T> struct RemoveReference_<T&&> { using Type = T; };
template <typename T>
using RemoveReference = typename RemoveReference_<T>::Type;
template <typename T>
constexpr T&& Forward(RemoveReference<T>& t) { return static_cast<T&&>(t); }
template <typename T>
constexpr T&& Forward(RemoveReference<T>&& t)
{
static_assert(!IsLValueReference<T>::Value, "Can not forward an rvalue as an lvalue.");
return static_cast<T&&>(t);
}
template <typename T>
constexpr RemoveReference<T>&& Move(T&& arg)
{
return static_cast<RemoveReference<T>&&>(arg);
}
}

View File

@ -0,0 +1,4 @@
#pragma once
#include <cstdint>
#include <cstddef>

View File

@ -0,0 +1,109 @@
#pragma once
#include <Orange/Core/Types.h>
namespace orange
{
class Quake2BSP
{
public:
Quake2BSP(const void* data, size_t size);
private:
static constexpr uint32_t LumpCount = 19;
static constexpr uint32_t MaxLightmapStyles = 4;
struct LumpType
{
enum
{
Entities,
Planes,
Vertices,
Visibility,
Nodes,
TextureInfo,
Faces,
Lightmaps,
Leaves,
LeafFaceTable,
LeafBrushTable,
Edges,
FaceEdgeTable,
Models,
Brushes,
BrushSides,
Pop,
Areas,
AreaPortals,
};
};
struct LumpPointer
{
uint32_t offset;
uint32_t length;
};
struct BSPHeader
{
uint32_t magic;
uint32_t version;
LumpPointer lumps[LumpCount];
};
struct BSPFace
{
uint16_t plane;
uint16_t planeSide;
uint32_t firstEdge;
uint16_t numEdges;
uint16_t textureInfoIdx;
uint8_t lightmapStyles[MaxLightmapStyles];
uint32_t lightmapOffset;
};
struct BSPPlane
{
float normal[3];
float distance;
uint32_t type;
};
struct BSPNode
{
uint32_t plane;
int32_t frontChild;
int32_t backChild;
int16_t bboxMins[3];
int16_t bboxMaxs[3];
uint16_t firstLeafFace;
uint16_t numLeafFaces;
uint16_t firstLeafBrush;
uint16_t numLeafBrushes;
};
struct BSPTexInfo
{
float uAxis[3];
float uOffset;
float vAxis[3];
float vOffset;
uint32_t flags;
uint32_t value;
char textureName[32];
uint32_t nextTexInfo;
};
};
}

View File

@ -0,0 +1,28 @@
#pragma once
#include <Orange/Core/Result.h>
#include <Orange/Render/Renderer.h>
namespace orange
{
class ForwardRenderer : public Renderer
{
public:
~ForwardRenderer() = default;
static Result<ForwardRenderer> create(SDL_Window* window, const char* name)
{
Result<ForwardRenderer> result;
ForwardRenderer& renderer = result.Create();
if ((renderer.m_instance = createInstance(window, name)) == VK_NULL_HANDLE)
return result.Error(BasicErrorCode::Failed);
return result.Success();
}
protected:
friend Result<ForwardRenderer>;
ForwardRenderer() = default;
};
}

View File

@ -0,0 +1,71 @@
#pragma once
#include <Orange/Core/Types.h>
#include <Orange/Core/SmallVector.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_vulkan.h>
#include <vulkan/vulkan_core.h>
namespace orange
{
class Renderer
{
public:
~Renderer() = default;
protected:
Renderer() = default;
static VkInstance createInstance(SDL_Window* window, const char* name)
{
uint32_t instanceExtensionCount = {};
if (SDL_Vulkan_GetInstanceExtensions(window, &instanceExtensionCount, nullptr) != SDL_TRUE)
{
//std::cerr << "Failed to get SDL instance extension count.\n";
return VK_NULL_HANDLE;
}
SmallVector<const char *, 8> instanceExtensions{ instanceExtensionCount };
if (SDL_Vulkan_GetInstanceExtensions(window, &instanceExtensionCount, instanceExtensions.Data()) != SDL_TRUE)
{
//std::cerr << "Failed to get SDL instance extensions.\n";
return VK_NULL_HANDLE;
}
VkApplicationInfo appInfo =
{
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pApplicationName = name,
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.pEngineName = "Orange",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = VK_API_VERSION_1_3,
};
VkInstanceCreateInfo instanceInfo =
{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &appInfo,
.enabledExtensionCount = instanceExtensionCount,
.ppEnabledExtensionNames = instanceExtensions.Data(),
};
VkResult result = VK_SUCCESS;
VkInstance instance;
if ((result = vkCreateInstance(&instanceInfo, nullptr, &instance)) != VK_SUCCESS)
{
//std::cerr << "Failed to create Vulkan instance.\n";
return VK_NULL_HANDLE;
}
return instance;
}
VkInstance m_instance = VK_NULL_HANDLE;
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
VkDevice m_device = VK_NULL_HANDLE;
};
}

16
meson.build Normal file
View File

@ -0,0 +1,16 @@
project('orange', ['cpp'], version : '0.0.1', meson_version : '>= 0.49', default_options : [
'warning_level=2',
'c_std=c11',
'cpp_std=c++20'
])
orange_compiler = meson.get_compiler('cpp')
add_project_arguments(orange_compiler.get_supported_arguments([
'-Wno-missing-field-initializers',
]), language : 'cpp')
orange_include = include_directories(['include'])
sdl2_dep = dependency('SDL2')
vulkan_dep = dependency('vulkan') # get rid of me!
subdir('src')

View File

@ -0,0 +1,7 @@
#include <Orange/Core/Result.h>
#include <Orange/Render/ForwardRenderer.h>
int main(int argc, char** argv)
{
}

View File

@ -0,0 +1,3 @@
executable('BSPViewer', 'BSPViewer.cpp',
dependencies : [sdl2_dep, vulkan_dep],
include_directories : [orange_include])

1
src/Apps/meson.build Normal file
View File

@ -0,0 +1 @@
subdir('Tools')

1
src/meson.build Normal file
View File

@ -0,0 +1 @@
subdir('Apps')