3#include "Foundation/Logging/Logger.h"
5#include "Resources/Buffer.h"
12std::span<const glm::vec3> Cogs::Core::extractSemanticStreamVec3(Memory::MemoryBuffer& backing, MeshHandle mesh,
const Cogs::ElementSemantic semantic,
size_t semanticIndex)
14 for (
size_t i = 0; i < VertexDataType::LastVertexType; ++i) {
15 VertexDataType::EVertexDataType type = VertexDataType::EVertexDataType(i);
16 if (mesh->hasStream(type)) {
28 size_t bufferByteSize = buffer->
size();
30 LOG_ERROR(logger,
"Vertex stream (offset=%u, stride=%u, num=%u) spans outside backing buffer of size %zu",
34 const uint8_t* src =
static_cast<const uint8_t*
>(buffer->
data()) + stream.
offset;
37 backing.resize(
sizeof(glm::vec3) * stream.
numElements,
false);
38 std::span<glm::vec3> dst(
static_cast<glm::vec3*
>(backing.data()), stream.
numElements);
42 case Cogs::DataFormat::X32Y32Z32_FLOAT:
44 if (stream.
stride ==
sizeof(glm::vec3)) {
45 return std::span<const glm::vec3>(
reinterpret_cast<const glm::vec3*
>(src), stream.
numElements);
49 dst[k] = *
reinterpret_cast<const glm::vec3*
>(src + stream.
stride * k);
53 case Cogs::DataFormat::R16G16B16_UNORM:
55 dst[k] = (1.f / 0xffffu) * glm::vec3(*
reinterpret_cast<const glm::u16vec3*
>(src + stream.
stride * k));
60 const FormatInfo* formatInfo = Cogs::getFormatInfo(element.
format);
61 LOG_DEBUG(logger,
"extractSemanticStreamVec3: Unsupported vertex format %s", formatInfo->vName);
70 return std::span<const glm::vec3>();
73std::span<const uint32_t> Cogs::Core::extractIndexStreamUint32(Memory::MemoryBuffer& backing, MeshHandle mesh)
75 if (mesh->hasStream(VertexDataType::Indexes)) {
80 size_t bufferByteSize = buffer->
size();
82 LOG_ERROR(logger,
"Vertex stream (offset=%u, stride=%u, num=%u) spans outside backing buffer of size %zu",
86 const uint8_t* src =
static_cast<const uint8_t*
>(buffer->
data()) + stream.
offset;
90 backing.resize(
sizeof(glm::vec3) * stream.
numElements,
false);
91 std::span<uint32_t> dst(
static_cast<uint32_t*
>(backing.data()), stream.
numElements);
93 dst[k] =
reinterpret_cast<const uint16_t*
>(src)[k];
99 return std::span<const uint32_t>(
reinterpret_cast<const uint32_t*
>(src), stream.
numElements);
102 LOG_ERROR(logger,
"extractIndexStreamUint32: Mesh index stream has illegal stride %u", stream.
stride);
107 return std::span<const uint32_t>();
114 if (!mesh->
hasStream(VertexDataType::EVertexDataType::Positions)) {
115 LOG_ERROR(logger,
"Unable to generate normals (no positions)\n");
120 LOG_ERROR(logger,
"Unable to generate normals (not TriangleList)\n");
126 std::vector<glm::vec3> normals(vertex_count, glm::vec3(0.0));
128 const auto indices = mesh->getIndexes();
129 size_t index_count = indices.size();
131 while (index + 3 <= index_count) {
132 uint32_t i0 = indices[index + 0];
133 uint32_t i1 = indices[index + 1];
134 uint32_t i2 = indices[index + 2];
135 glm::vec3 a = pos[i0];
136 glm::vec3 b = pos[i1];
137 glm::vec3 c = pos[i2];
139 if (mesh->
isCCW()) n = glm::cross(b - a, c - a);
140 else n = glm::cross(c - a, b - a);
148 while (index + 3 <= vertex_count) {
149 uint32_t i0 = index + 0;
150 uint32_t i1 = index + 1;
151 uint32_t i2 = index + 2;
152 glm::vec3 a = pos[i0];
153 glm::vec3 b = pos[i1];
154 glm::vec3 c = pos[i2];
156 if (mesh->
isCCW()) n = glm::cross(b - a, c - a);
157 else n = glm::cross(c - a, b - a);
164 for (uint32_t i = 0; i < vertex_count; i++) {
165 normals[i] = glm::normalize(normals[i]);
173 if (!mesh->
hasStream(VertexDataType::EVertexDataType::Positions)) {
174 LOG_ERROR(logger,
"Unable to generate tangents (no positions)\n");
178 if (!mesh->
hasStream(VertexDataType::EVertexDataType::Normals)) {
182 if (!mesh->
hasStream(VertexDataType::EVertexDataType::TexCoords0)) {
183 LOG_ERROR(logger,
"Unable to generate tangents (no TexCoords)\n");
188 LOG_ERROR(logger,
"Unable to generate tangents (not TriangleList)\n");
192 size_t vertex_count = mesh->
getCount();
197 LOG_ERROR(logger,
"Invalid data in Stream, not enough values\n");
201 std::vector<glm::vec3> tangents(vertex_count, glm::vec3(0.0));
204 const auto indices = mesh->getIndexes();
205 size_t index_count = indices.size();
207 while (index + 3 <= index_count) {
208 uint32_t i0 = indices[index + 0];
209 uint32_t i1 = indices[index + 1];
210 uint32_t i2 = indices[index + 2];
211 glm::vec3 a = pos[i0];
212 glm::vec3 b = pos[i1];
213 glm::vec3 c = pos[i2];
214 glm::vec2 ta = texCoord[i0];
215 glm::vec2 tb = texCoord[i1];
216 glm::vec2 tc = texCoord[i2];
232 float den = 1.f / (u0.x * u1.y - u0.y * u1.x);
233 glm::vec3 t0 = u1.y*den * v0 - u0.y*den * v1;
242 while (index + 3 <= vertex_count) {
243 uint32_t i0 = index + 0;
244 uint32_t i1 = index + 1;
245 uint32_t i2 = index + 2;
246 glm::vec3 a = pos[i0];
247 glm::vec3 b = pos[i1];
248 glm::vec3 c = pos[i2];
249 glm::vec2 ta = texCoord[i0];
250 glm::vec2 tb = texCoord[i1];
251 glm::vec2 tc = texCoord[i2];
267 float den = 1.f / (u0.x * u1.y - u0.y * u1.x);
268 glm::vec3 t0 = u1.y*den * v0 - u0.y*den * v1;
277 for (uint32_t i = 0; i < vertex_count; i++) {
278 tangents[i] = glm::normalize(tangents[i] - glm::dot(normals[i], tangents[i])*normals[i]);
290 auto numPositions = vertexCount !=
static_cast<uint32_t
>(-1) ? vertexCount : mesh->getCount();
292 if (!numPositions)
return {};
294 const auto[pData, pCount, pStride] = mesh->getPositionStream();
297 LOG_ERROR(logger,
"Position data not valid for bounding box calculation.");
301 Geometry::BoundingBox box;
303 if (mesh->isIndexed()) {
304 if (mesh->hasIndexesU16()) {
305 auto indexes = mesh->getIndexesU16();
307 for (
size_t i = 0; i < numPositions; ++i) {
308 const uint16_t index = indexes[startIndex + i];
309 glm::vec3 pos = *
reinterpret_cast<const glm::vec3 *
>(pData + index * pStride);
310 box.min = glm::min(box.min, pos);
311 box.max = glm::max(box.max, pos);
314 auto indexes = mesh->getIndexes();
316 for (
size_t i = 0; i < numPositions; ++i) {
317 const uint32_t index = indexes[startIndex + i];
318 glm::vec3 pos = *
reinterpret_cast<const glm::vec3 *
>(pData + index * pStride);
319 box.min = glm::min(box.min, pos);
320 box.max = glm::max(box.max, pos);
324 for (
size_t i = 0; i < numPositions; ++i) {
325 auto pos = *
reinterpret_cast<const glm::vec3 *
>(pData + i * pStride);
326 box.min = glm::min(box.min, pos);
327 box.max = glm::max(box.max, pos);
Log implementation class.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
void COGSCORE_DLL_API generateMeshNormals(Mesh *mesh)
Generate normals.
void COGSCORE_DLL_API generateMeshTangents(Mesh *mesh)
Generate tangents.
Cogs::Geometry::BoundingBox COGSCORE_DLL_API calculateBounds(Mesh *mesh)
Calculate a bounding box for the given mesh.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
ElementSemantic
Element semantics used to map data to the shader stage.
size_t size() const
Size of the buffer in bytes.
void * data()
Get a pointer to the buffer data.
Contains a stream of data used by Mesh resources.
uint32_t numElements
Number of elements of the type given by format contained in data.
uint32_t offset
Byte offset from the start of the buffer.
VertexFormatHandle format
A pointer to the format describing the contents of the byte buffer.
uint32_t stride
Element stride.
Cogs::Core::ResourceBufferHandle buffer
Data buffer.
Wrapper for read-only access to mapped stream data.
bool isValid() const
Returns true if stream mapping successful.
Meshes contain streams of vertex data in addition to index data and options defining geometry used fo...
void setTangents(std::span< const glm::vec3 > tangents)
Set the tangent data of the Mesh.
bool isCCW() const
If triangles in the mesh are specified counter-clockwise, which is the default.
bool isIndexed() const
If the mesh uses indexed geometry.
bool hasStream(VertexDataType::EVertexDataType type) const
Check if the Mesh has a DataStream for the given type.
MappedStreamReadOnly< glm::vec3 > mapNormalsReadOnly(const size_t start, const size_t end)
Map the normal stream for read access, range between start and end.
void setNormals(std::span< const glm::vec3 > normals)
Set the normal data of the Mesh.
DataStream & getStream(const VertexDataType::EVertexDataType dataType)
Get the stream corresponding to the given dataType.
MappedStreamReadOnly< glm::vec3 > mapPositionsReadOnly(const size_t start, const size_t end)
Map the position stream for read access, range between start and end.
uint32_t getCount() const
Get the vertex count of the mesh.
MappedStreamReadOnly< glm::vec2 > mapTexCoordsReadOnly(const size_t start, const size_t end)
Map the texture coordinate stream for read access, range between start and end.
@ TriangleList
List of triangles.
Vertex element structure used to describe a single data element in a vertex for the input assembler.
DataFormat format
Format of the element.
uint16_t semanticIndex
Index for the semantic mapping.
ElementSemantic semantic
Semantic mapping of the element (position, normal, etc...).