3#include "Foundation/Logging/Logger.h"
5#include "MeshManager.h"
17void Cogs::Core::Mesh::clearStream(
DataStream & stream)
22 streamsUpdated |= toFlag(stream.
type);
36 for (
auto & si : streamIndexes) {
38 clearStream(streams[si]);
42 boundingBox = Geometry::BoundingBox();
50 const size_t elementSize,
53 auto & stream = getStream(type);
58 return mapStream(type, start, count, elementSize, resize);
67 auto & stream = getStream(type);
69 const size_t neededCapacity = size_t(start + count) * stride;
71 if (stream.size() < neededCapacity || (resize && stream.size() != neededCapacity)) {
75 stream.
numElements =
static_cast<uint32_t
>(start + count);
76 stream.
stride =
static_cast<uint32_t
>(stride);
78 if (type == VertexDataType::Positions && !isIndexed()) {
79 setCount(start + count);
82 return static_cast<uint8_t *
>(stream.data()) + (start * stride);
87 assert(streams.size() < MaxStreams &&
"Vertex stream limit reached.");
89 if (streamIndexes[dataType] == NoStream) {
90 streamIndexes[dataType] =
static_cast<int8_t
>(streams.size());
92 auto & stream = streams.emplace_back();
93 stream.
type = dataType;
97 stream.
buffer = getManager()->createBuffer();
99 if (dataType < VertexDataType::LastVertexType) {
101 }
else if (dataType == VertexDataType::Indexes) {
108 return streams[streamIndexes[dataType]];
113 assert(streamIndexes[dataType] != NoStream &&
"Invalid stream type.");
115 return streams[streamIndexes[dataType]];
120 if (streamIndexes[dataType] != NoStream) {
121 return &streams[streamIndexes[dataType]];
129 if (streamIndexes[dataType] != NoStream) {
130 return &streams[streamIndexes[dataType]];
139 if (vec3Ref.ptr)
return vec3Ref;
146 for (
auto & stream : streams) {
147 if (!stream.
format)
continue;
149 auto vertexFormat = Cogs::VertexFormats::getVertexFormat(stream.
format);
151 auto & elements = vertexFormat->elements;
153 auto found = std::find_if(elements.begin(), elements.end(), [semantic, format](
const VertexElement & element) {
154 return element.semantic == semantic && element.format == format;
157 if (found != elements.end()) {
158 auto offset = (*found).offset;
160 return {
static_cast<uint8_t*
>(stream.data()) + offset, stream.
numElements, Cogs::getSize(*vertexFormat) };
172std::span<uint32_t> Cogs::Core::Mesh::mapPoseIndexes(uint32_t count)
174 void* poseData = mapStream(VertexDataType::PoseIndexes, 0, count,
sizeof(uint32_t),
true);
175 return std::span(
static_cast<uint32_t *
>(poseData), count);
178std::span<const uint32_t> Cogs::Core::Mesh::getPoseIndexes()
const
180 auto stream = getAllocatedStream(VertexDataType::PoseIndexes);
183 return std::span(
static_cast<const uint32_t *
>(stream->data()), stream->
numElements);
191 assert(submeshCount != uint16_t{ 0xffff });
192 uint32_t indexCount =
static_cast<uint32_t
>(getIndexes().size());
193 if (submeshCount == 0 && isIndexed() && !getIndexes().empty()) {
195 auto subMeshes = mapSubMeshes(submeshCount + 1);
196 auto & indexStream = getStream(VertexDataType::Indexes);
197 subMeshes[0] = { 0, indexStream.numElements, this->primitiveType };
198 indexCount = indexStream.numElements;
201 auto subMeshes = mapSubMeshes(submeshCount + 1);
203 subMeshes[submeshCount - 1] = { indexCount,
static_cast<uint32_t
>(collection.size()), primitiveType };
205 auto indexData = mapStream(VertexDataType::Indexes, 0, indexCount + collection.size(),
sizeof(uint32_t));
207 memcpy(indexData + indexCount *
sizeof(uint32_t), collection.data(),
sizeof(uint32_t) * collection.size());
209 count =
static_cast<uint32_t
>(indexCount + collection.size());
218 uint32_t numElements,
223 if (streamIndexes[type] == NoStream) {
224 streams.emplace_back();
225 streamIndexes[type] = (uint8_t)streams.size() - 1;
228 auto & stream = streams[streamIndexes[type]];
237 streamsUpdated |= toFlag(type);
241std::span<Cogs::Core::SubMesh> Cogs::Core::Mesh::mapSubMeshes(uint32_t count)
243 assert(count < uint16_t{ 0xffff });
244 void* data = mapStream(VertexDataType::SubMeshes, 0, count,
sizeof(SubMesh));
245 submeshCount = (uint16_t)count;
247 return std::span(
static_cast<SubMesh *
>(data), count);
250std::span<Cogs::Core::SubMesh> Cogs::Core::Mesh::getSubMeshes()
253 auto & stream = getStream(VertexDataType::SubMeshes);
254 return std::span(
static_cast<SubMesh *
>(stream.data()), stream.
numElements);
260std::span<const uint32_t> Cogs::Core::Mesh::getIndexes()
const
262 if (!isIndexed())
return {};
264 auto & indexStream = getStream(VertexDataType::Indexes);
266 if (indexStream.stride !=
sizeof(uint32_t))
return {};
268 return std::span(
static_cast<const uint32_t *
>(indexStream.data()), indexStream.numElements);
271std::span<const uint16_t> Cogs::Core::Mesh::getIndexesU16()
const
273 if (!hasIndexesU16())
return {};
275 auto & indexStream = getStream(VertexDataType::Indexes);
277 if (indexStream.stride !=
sizeof(uint16_t))
return {};
279 return std::span(
static_cast<const uint16_t *
>(indexStream.data()), indexStream.numElements);
282bool Cogs::Core::Mesh::hasIndexesU16()
const
284 return isIndexed() && getStream(VertexDataType::Indexes).stride ==
sizeof(uint16_t);
287void* Cogs::Core::DataStream::data() {
return buffer ?
static_cast<uint8_t*
>(buffer->
data()) + offset :
nullptr; }
288const void* Cogs::Core::DataStream::data()
const {
return buffer ?
static_cast<const uint8_t*
>(buffer->
data()) + offset :
nullptr; }
289size_t Cogs::Core::DataStream::size()
const {
return buffer ? buffer->
size() : 0; }
294 MeshStreamsLayout streamsLayout;
296 for (
size_t i = 0; i < VertexDataType::LastVertexType; ++i) {
298 if (hasStream(type)) {
299 const DataStream& stream = getStream(type);
300 streamsLayout.vertexFormats[streamsLayout.numStreams++] = stream.format;
303 streamsLayout.updateHash();
304 return streamsLayout;
Mesh manager handling the creation, processing and lifetime of Mesh resources.
Log implementation class.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
ElementSemantic
Element semantics used to map data to the shader stage.
@ Position
Position semantic.
@ VertexBuffer
Buffer can be bound as vertex buffer.
@ IndexBuffer
Buffer can be bound as index buffer.
void setBindFlags(uint16_t flags)
Set the bind flags for the buffer determining how the buffer data may be uploaded to GPU.
void resize(size_t size)
Resize the buffer to accomodate the given number of bytes.
size_t size() const
Size of the buffer in bytes.
void clear()
Clear the buffer contents. Note that the buffer may retain reserved storage after clearing.
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.
VertexDataType::EVertexDataType type
Type index used to index streams in a Mesh resource.
uint32_t stride
Element stride.
Cogs::Core::ResourceBufferHandle buffer
Data buffer.
@ Instanced
Mesh contains instance data.
@ StreamsChanged
One or more of the data streams in the mesh changed.
@ IndexesChanged
The index data of the mesh changed.
@ Indexed
The mesh should be drawn indexed, using index data to order the triangle vertexes.
@ BoundingBoxSet
Custom bounding box set, no automatic calculation of bounds should be performed.
Utility structure containing reference to a data stream in a mesh.
uint8_t * mapStream(const VertexDataType::EVertexDataType type, VertexFormatHandle format, const size_t start, const size_t count, const size_t elementSize, bool resize=false)
Raw stream mapping method.
StreamReference getPositionStream()
Get the data of the stream containing positions.
StreamReference getSemanticStream(ElementSemantic semantic, DataFormat format)
Get the data of the stream containing data with the given semantic, format and minimum element size.
void clear()
Clear all data from the Mesh, returning it to its initial non-indexed state with no streams and no su...
static constexpr int NoStream
Used to indicate no stream.
void addSubMesh(std::span< uint32_t > collection, PrimitiveType::EPrimitiveType primitiveType)
Add a sub-mesh to the Mesh.
DataStream & getStream(const VertexDataType::EVertexDataType dataType)
Get the stream corresponding to the given dataType.
Mesh()
Construct a default mesh instance.
EVertexDataType
Contains data types.
EPrimitiveType
Primitive type enumeration.
Vertex element structure used to describe a single data element in a vertex for the input assembler.