178 lines
4.7 KiB
C++
178 lines
4.7 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include "Geometry.hpp"
|
|
#include "Base/Utils.hpp"
|
|
#include "Base/Logger.hpp"
|
|
#include <stdexcept>
|
|
|
|
namespace OpenVulkano::Scene
|
|
{
|
|
Geometry::Geometry(const Geometry& other)
|
|
: vertexCount(other.vertexCount), indexCount(other.indexCount)
|
|
, vertices(other.vertices ? new Vertex[other.vertexCount] : nullptr)
|
|
, indices(other.indices ? malloc(static_cast<size_t>(Utils::EnumAsInt(other.indexType)) * other.indexCount) : nullptr)
|
|
, indexType(other.indexType)
|
|
, ownsMemory(other.ownsMemory), freeAfterUpload(other.freeAfterUpload)
|
|
, aabb(other.aabb)
|
|
{
|
|
if (other.vertices)
|
|
{
|
|
std::copy(other.vertices, other.vertices + other.vertexCount, this->vertices);
|
|
}
|
|
if (other.indices)
|
|
{
|
|
if (other.indexType == VertexIndexType::UINT16)
|
|
{
|
|
std::copy(static_cast<uint16_t*>(other.indices),
|
|
static_cast<uint16_t*>(other.indices) + other.indexCount,
|
|
static_cast<uint16_t*>(this->indices));
|
|
}
|
|
else
|
|
{
|
|
std::copy(static_cast<uint32_t*>(other.indices),
|
|
static_cast<uint32_t*>(other.indices) + other.indexCount,
|
|
static_cast<uint32_t*>(this->indices));
|
|
}
|
|
}
|
|
}
|
|
|
|
Geometry& Geometry::operator=(const Geometry& other)
|
|
{
|
|
Geometry tmp(other);
|
|
this->Swap(tmp);
|
|
return *this;
|
|
}
|
|
|
|
Geometry::Geometry(Geometry&& other) noexcept
|
|
: RenderResourceHolder<Geometry>(std::move(other)), vertexCount(other.vertexCount), indexCount(other.indexCount)
|
|
, vertices(other.vertices), indices(other.indices), indexType(other.indexType)
|
|
, ownsMemory(other.ownsMemory), freeAfterUpload(other.freeAfterUpload), aabb(other.aabb)
|
|
{
|
|
other.vertexCount = other.indexCount = 0;
|
|
other.vertices = nullptr;
|
|
other.indices = nullptr;
|
|
}
|
|
|
|
Geometry& Geometry::operator=(Geometry&& other) noexcept
|
|
{
|
|
if (this != &other)
|
|
{
|
|
Close();
|
|
this->vertexCount = other.vertexCount;
|
|
this->indexCount = other.indexCount;
|
|
this->indexType = other.indexType;
|
|
this->ownsMemory = other.ownsMemory;
|
|
this->freeAfterUpload = other.freeAfterUpload;
|
|
this->aabb = std::move(other.aabb);
|
|
this->vertices = other.vertices;
|
|
this->indices = other.indices;
|
|
RenderResourceHolder<Geometry>::operator=(std::move(other));
|
|
other.vertexCount = other.indexCount = 0;
|
|
other.vertices = nullptr;
|
|
other.indices = nullptr;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
Geometry::~Geometry()
|
|
{
|
|
Geometry::Close();
|
|
}
|
|
|
|
void Geometry::CalculateAABB()
|
|
{
|
|
if (vertexCount == 0 || !vertices)
|
|
{
|
|
return;
|
|
}
|
|
for (uint32_t i = 0; i < vertexCount; i++)
|
|
{
|
|
aabb.Grow(vertices[i].position);
|
|
}
|
|
}
|
|
|
|
void Geometry::Swap(Geometry& other) noexcept
|
|
{
|
|
RenderResourceHolder<Geometry>::Swap(other);
|
|
std::swap(this->vertexCount, other.vertexCount);
|
|
std::swap(this->indexCount, other.indexCount);
|
|
std::swap(this->aabb, other.aabb);
|
|
std::swap(this->indexType, other.indexType);
|
|
std::swap(this->vertices, other.vertices);
|
|
std::swap(this->indices, other.indices);
|
|
std::swap(this->ownsMemory, other.ownsMemory);
|
|
std::swap(this->freeAfterUpload, other.freeAfterUpload);
|
|
}
|
|
|
|
void Geometry::Init(uint32_t vertexCount, uint32_t indexCount)
|
|
{
|
|
if (HasRenderResource() || this->vertexCount || this->indexCount) throw std::runtime_error("Geometry is already initialized.");
|
|
this->vertexCount = vertexCount;
|
|
this->indexCount = indexCount;
|
|
indexType = (vertexCount > UINT16_MAX) ? VertexIndexType::UINT32 : VertexIndexType::UINT16;
|
|
vertices = new Vertex[vertexCount];
|
|
indices = malloc(static_cast<size_t>(Utils::EnumAsInt(indexType)) * indexCount);
|
|
}
|
|
|
|
void Geometry::SetIndices(const uint32_t* data, uint32_t size, uint32_t dstOffset) const
|
|
{
|
|
for(uint32_t i = 0; i < size; i++)
|
|
{
|
|
if (indexType == VertexIndexType::UINT16)
|
|
{
|
|
static_cast<uint16_t*>(indices)[i + dstOffset] = static_cast<uint16_t>(data[i]);
|
|
}
|
|
else
|
|
{ static_cast<uint32_t*>(indices)[i + dstOffset] = data[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
void Geometry::Close()
|
|
{
|
|
if (ownsMemory)
|
|
{
|
|
vertexCount = 0;
|
|
indexCount = 0;
|
|
Free();
|
|
}
|
|
if (HasRenderResource())
|
|
{
|
|
GetRenderResource().Release();
|
|
}
|
|
}
|
|
|
|
void Geometry::Free()
|
|
{
|
|
delete[] vertices;
|
|
free(indices);
|
|
vertices = nullptr;
|
|
indices = nullptr;
|
|
}
|
|
|
|
uint32_t Geometry::GetIndex(size_t index) const
|
|
{
|
|
uint32_t result = 0;
|
|
|
|
if (index >= indexCount) [[unlikely]]
|
|
throw std::out_of_range("Index is out of range");
|
|
|
|
if (indexType == OpenVulkano::Scene::VertexIndexType::UINT16)
|
|
{
|
|
uint16_t* indices = GetIndices16();
|
|
result = indices[index];
|
|
}
|
|
else if (indexType == OpenVulkano::Scene::VertexIndexType::UINT32)
|
|
{
|
|
uint32_t* indices = GetIndices32();
|
|
result = indices[index];
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|