2#include "EntityStore.h"
4#include "Resources/Mesh.h"
5#include "Resources/MaterialInstance.h"
6#include "Resources/MeshManager.h"
8#include "Platform/Instrumentation.h"
10#include "CommandHelpers.h"
19 dst.resize(src.size());
21 std::memcpy(dst.data(), src.data(), src.byteSize());
37 if (prefix.back().index != ~0u)
return;
40 for (
size_t i = 0; i < prefix.size(); i++) {
41 if (prefix[i].index == ~0u) {
42 prefix[i].index = uint32_t(items.transforms.size());
43 items.transforms.emplace_back(
TransformItem{ prefix[i].trComp, i == 0 ? ~0u : prefix[i - 1].index });
48 void getMeshItems_(std::vector<PrefixItem>& prefix,
MeshItems& items,
EntityPtr entity, uint32_t primitiveTypeMask);
50 void descend(std::vector<PrefixItem>& prefix,
MeshItems& items,
EntityPtr entity, uint32_t primitiveTypeMask)
53 if (!sceneComp)
return;
57 if (trComp) prefix.emplace_back(PrefixItem{ trComp, ~0u });
59 for (
auto & child : sceneComp->children) {
60 getMeshItems_(prefix, items, child, primitiveTypeMask);
63 if (trComp) prefix.pop_back();
67 void extract(std::vector<PrefixItem>& prefix,
MeshItems& items,
EntityPtr entity, uint32_t primitiveTypeMask)
70 if (((1 << meshComp->meshHandle->primitiveType) & primitiveTypeMask) != 0) {
73 items.meshes.emplace_back(
MeshItem{ meshComp->meshHandle, meshComp, meshRenderComp, meshRenderComp->material.resolve(), meshRenderComp->startIndex, meshRenderComp->vertexCount, ~0u });
75 if (!prefix.empty()) {
76 recordPrefix(prefix, items);
77 items.meshes.back().parent = prefix.back().index;
85 void getMeshItems_(std::vector<PrefixItem>& prefix,
MeshItems& items,
EntityPtr entity, uint32_t primitiveTypeMask)
87 descend(prefix, items, entity, primitiveTypeMask);
88 extract(prefix, items, entity, primitiveTypeMask);
92 void getMeshItems_(
Context* context, std::vector<PrefixItem>& prefix,
MeshItems& items, EntityIds entities, uint32_t primitiveTypeMask)
94 for (
auto & entity : entities) {
97 getMeshItems_(prefix, items, entityPtr, primitiveTypeMask);
112 hierarchy.resize(transforms.size());
114 for (
size_t i = 0; i < transforms.size(); i++) {
115 auto srcTrComp = transforms[i].trComp;
120 if (transforms[i].parent == ~0u) {
124 assert(transforms[i].parent < i);
125 context->
store->
addChild(hierarchy[transforms[i].parent]->getContainer(), entity);
132 void createMeshResources(
Context* context, std::vector<Cogs::ComponentModel::Entity*>& entities, std::vector<MeshHandle>& originalMeshes, MeshReps& meshes)
134 assert(entities.size() == meshes.size());
135 assert(entities.size() == originalMeshes.size());
137 for (
size_t j = 0; j < meshes.size(); j++) {
138 const auto & meshRep = meshes[j];
140 auto * meshComp = entities[j]->getComponent<
MeshComponent>();
141 if (meshRep.positions.size() == 0) {
145 meshComp->meshHandle = context->meshManager->create();
146 meshComp->setChanged();
148 auto * mesh = meshComp->meshHandle.resolve();
150 auto bbox = Cogs::Geometry::makeEmptyBoundingBox<Cogs::Geometry::BoundingBox>();
151 for (
size_t i = 0; i < meshRep.positions.size(); i++) {
152 bbox.min = glm::min(bbox.min, meshRep.positions[i]);
153 bbox.max = glm::max(bbox.max, meshRep.positions[i]);
155 mesh->setBounds(bbox);
157 mesh->setPositions(meshRep.positions.data(), meshRep.positions.data() + meshRep.positions.size());
158 if (meshRep.normals.size() != 0) {
159 mesh->setNormals(meshRep.normals.data(), meshRep.normals.data() + meshRep.normals.size());
161 if (meshRep.texcoords.size() != 0) {
162 mesh->setTexCoords(meshRep.texcoords.data(), meshRep.texcoords.data() + meshRep.texcoords.size());
164 if (meshRep.tangents.size() != 0) {
165 mesh->setTangents(meshRep.tangents.data(), meshRep.tangents.data() + meshRep.tangents.size());
167 if (meshRep.indices.size() != 0) {
168 mesh->setIndexData(meshRep.indices.data(), meshRep.indices.size());
171 auto * originalMesh = originalMeshes[j].resolve();
179 mesh->primitiveType = originalMesh->primitiveType;
183 meshRndComp->vertexCount = (uint32_t)-1;
184 meshRndComp->setChanged();
191 std::vector<Cogs::ComponentModel::Entity*> entities(meshes.size());
192 for (
size_t i = 0; i < meshItems.size(); i++) {
193 auto & item = meshItems[i];
195 auto * meshEntityParent = parent;
196 if (item.parent != (uint32_t)-1) {
197 assert(item.parent < hierarchy.size());
198 meshEntityParent = hierarchy[item.parent]->getContainer();
201 auto entity = context->
store->
createChildEntity(
"MeshPart", meshEntityParent, item.meshComp->getContainer()->getName());
202 entities[i] = entity.get();
211 createMeshResources(context, entities, originalMeshes, meshes);
224 std::vector<Cogs::ComponentModel::ComponentPtr<SceneComponent>> hierarchy;
225 createNodeHierarchy(context, hierarchy, group, items.transforms);
226 createMeshNodes(context, hierarchy, group.get(), originalMeshes, items.meshes, meshes);
236 meshComp->
meshHandle = context->meshManager->create();
237 meshComp->setChanged();
239 auto * mesh = meshComp->meshHandle.resolve();
246 for(
auto & meshRep : meshes) {
247 Vn += meshRep.positions.size();
248 Nn += meshRep.normals.size();
249 Tn += meshRep.tangents.size();
250 Xn += meshRep.texcoords.size();
251 In += meshRep.indices.size();
255 singleRep.positions.resize(Vn,
false);
256 singleRep.normals.resize(Nn,
false);
257 singleRep.tangents.resize(Tn,
false);
258 singleRep.texcoords.resize(Xn,
false);
259 singleRep.indices.resize(In,
false);
268 for (
size_t j = 0; j < meshes.size(); j++) {
269 const auto & meshRep = meshes[j];
271 if (meshRep.positions.size() == 0)
continue;
273 auto lIn = meshRep.indices.size();
275 for (
size_t i = 0; i < lIn; i++) {
276 singleRep.indices[Io + i] = meshRep.indices[i] + uint32_t(Vo);
281 auto lVn = meshRep.positions.size();
282 std::memcpy(singleRep.positions.data() + Vo, meshRep.positions.data(),
sizeof(glm::vec3)*lVn);
287 auto lNn = meshRep.normals.size();
289 std::memcpy(singleRep.normals.data() + No, meshRep.normals.data(),
sizeof(glm::vec3)*lNn);
293 auto lTn = meshRep.tangents.size();
295 std::memcpy(singleRep.tangents.data() + To, meshRep.tangents.data(),
sizeof(glm::vec3)*lTn);
299 auto lXn = meshRep.texcoords.size();
301 std::memcpy(singleRep.texcoords.data() + Xo, meshRep.texcoords.data(),
sizeof(glm::vec2)*lXn);
307 auto bbox = Cogs::Geometry::makeEmptyBoundingBox<Cogs::Geometry::BoundingBox>();
308 for (
size_t i = 0; i < singleRep.positions.size(); i++) {
309 bbox.min = glm::min(bbox.min, singleRep.positions[i]);
310 bbox.max = glm::max(bbox.max, singleRep.positions[i]);
312 mesh->setBounds(bbox);
314 mesh->setPositions(singleRep.positions.data(), singleRep.positions.data() + singleRep.positions.size());
315 if (singleRep.normals.size() != 0) {
316 mesh->setNormals(singleRep.normals.data(), singleRep.normals.data() + singleRep.normals.size());
318 if (singleRep.texcoords.size() != 0) {
319 mesh->setTexCoords(singleRep.texcoords.data(), singleRep.texcoords.data() + singleRep.texcoords.size());
321 if (singleRep.tangents.size() != 0) {
322 mesh->setTangents(singleRep.tangents.data(), singleRep.tangents.data() + singleRep.tangents.size());
324 if (singleRep.indices.size() != 0) {
325 mesh->setIndexData(singleRep.indices.data(), singleRep.indices.size());
328 auto * originalMesh = originalMeshes[0].resolve();
336 mesh->primitiveType = originalMesh->primitiveType;
339 meshRndComp->
material = items.meshes.front().meshRenderComp->material;
340 meshRndComp->startIndex = 0;
341 meshRndComp->vertexCount = (uint32_t)-1;
342 meshRndComp->setChanged();
348void Cogs::Core::MeshRep::copy(
const MeshRep & other)
350 CpuInstrumentationScope(SCOPE_EDITOR_COMMAND,
"MeshRepCopy");
351 ::copy(positions, other.positions);
352 ::copy(normals, other.normals);
353 ::copy(texcoords, other.texcoords);
354 ::copy(tangents, other.tangents);
355 ::copy(indices, other.indices);
361 std::vector<PrefixItem> prefix;
362 getMeshItems_(prefix, items, entity, primitiveTypeMask);
378void Cogs::Core::getMeshItems(
Context* context,
MeshItems& items, Cogs::Core::EntityIds entities, uint32_t primitiveTypeMask)
380 std::vector<PrefixItem> prefix;
381 getMeshItems_(context, prefix, items, entities, primitiveTypeMask);
388void Cogs::Core::remapVertices(
Context* ,
MeshRep& rep,
const std::vector<uint32_t>& unique)
390 CpuInstrumentationScope(SCOPE_EDITOR_COMMAND,
"remapVertices");
396 if (rep.positions.size() != 0) {
397 auto * P =
reinterpret_cast<glm::vec3*
>(tmp.data());
398 for (
size_t i = 0; i < unique.size(); i++) {
399 P[i] = rep.positions[unique[i]];
401 rep.positions.resize(unique.size(),
false);
402 std::memcpy(rep.positions.data(), tmp.data(), rep.positions.byteSize());
404 if (rep.normals.size()) {
405 auto * N =
reinterpret_cast<glm::vec3*
>(tmp.data());
406 for (
size_t i = 0; i < unique.size(); i++) {
407 N[i] = rep.normals[unique[i]];
409 rep.normals.resize(unique.size(),
false);
410 std::memcpy(rep.normals.data(), tmp.data(), rep.normals.byteSize());
412 if (rep.texcoords.size()) {
413 auto * T =
reinterpret_cast<glm::vec2*
>(tmp.data());
414 for (
size_t i = 0; i < unique.size(); i++) {
415 T[i] = rep.texcoords[unique[i]];
417 rep.texcoords.resize(unique.size(),
false);
418 std::memcpy(rep.texcoords.data(), tmp.data(), rep.texcoords.byteSize());
420 if (rep.tangents.size()) {
421 auto * T =
reinterpret_cast<glm::vec3*
>(tmp.data());
422 for (
size_t i = 0; i < unique.size(); i++) {
423 T[i] = rep.tangents[unique[i]];
425 rep.tangents.resize(unique.size(),
false);
426 std::memcpy(rep.tangents.data(), tmp.data(), rep.tangents.byteSize());
430void Cogs::Core::remapIndices(
Context* ,
MeshRep& rep,
const std::vector<uint32_t>& map)
432 if (rep.indices.size() == 0)
return;
434 CpuInstrumentationScope(SCOPE_EDITOR_COMMAND,
"remapIndices");
437 std::memcpy(tmp.data(), rep.indices.data(), tmp.byteSize());
439 for (
size_t i = 0; i < rep.indices.size(); i++) {
440 rep.indices[i] = map[tmp[i]];
447void Cogs::Core::unpackMeshItems(
Context* context, std::vector<MeshHandle>& originalMeshes, MeshReps& meshes,
MeshItems& items,
UnpackOptions options)
449 CpuInstrumentationScope(SCOPE_EDITOR_COMMAND,
"unpackMeshItems");
451 originalMeshes.clear();
454 for (
auto item : items.meshes) {
457 originalMeshes.push_back(item.mesh);
459 auto srcMesh = item.mesh.resolve();
462 if (options.discardNormals ==
false) {
465 assert(mesh.normals.size() == 0 || mesh.normals.size() == mesh.positions.size());
467 if (options.discardTexCoords ==
false) {
470 assert(mesh.texcoords.size() == 0 || mesh.texcoords.size() == mesh.positions.size());
472 if (options.discardTangents ==
false) {
475 assert(mesh.tangents.size() == 0 || mesh.tangents.size() == mesh.positions.size());
477 uint32_t maxVertexCount =
static_cast<uint32_t
>(mesh.positions.size());
478 uint32_t maxIndex = std::max(uint32_t(1), maxVertexCount) - 1u;
479 auto indexes = srcMesh->getIndexes();
481 if (!indexes.empty()) {
482 uint32_t maxIndexCount =
static_cast<uint32_t
>(indexes.size());
483 uint32_t maxIndexOffset = std::max(uint32_t(1), maxIndexCount) - 1;
484 uint32_t rangeOffset = std::min(maxIndexOffset, item.offset);
485 uint32_t maxRangeCount = std::max(rangeOffset, maxIndexCount) - rangeOffset;
486 uint32_t rangeCount = std::min(maxRangeCount, item.count);
488 mesh.indices.resize(rangeCount,
false);
489 if (rangeOffset != 0 || rangeCount != maxIndexCount) {
492 std::vector<uint32_t> unique;
493 unique.reserve(indexes.size());
495 std::vector<uint32_t> map(indexes.size(), ~0u);
497 for (uint32_t i = 0; i < rangeCount; i++) {
498 auto ix0 = indexes[rangeOffset + i];
501 ix1 =
static_cast<uint32_t
>(unique.size());
502 unique.push_back(ix0);
505 mesh.indices[i] = ix1;
507 remapVertices(context, mesh, unique);
510 std::memcpy(mesh.indices.data(), indexes.data(),
sizeof(uint32_t)*indexes.size());
514 uint32_t rangeOffset = std::min(maxIndex, item.offset);
515 uint32_t maxRangeCount = std::max(rangeOffset, maxVertexCount) - rangeOffset;
516 uint32_t rangeCount = std::min(maxRangeCount, item.count);
519 if (rangeCount != maxVertexCount) {
520 if (rangeOffset != 0) {
521 std::memmove(mesh.positions.data(), mesh.positions.data() + rangeOffset, rangeCount * 3 *
sizeof(
float));
522 if (mesh.normals.size() != 0) std::memmove(mesh.normals.data(), mesh.normals.data() + rangeOffset, rangeCount * 3 *
sizeof(
float));
523 if (mesh.texcoords.size() != 0) std::memmove(mesh.positions.data(), mesh.positions.data() + rangeOffset, rangeCount * 2 *
sizeof(
float));
524 if (mesh.tangents.size() != 0) std::memmove(mesh.tangents.data(), mesh.tangents.data() + rangeOffset, rangeCount * 3 *
sizeof(
float));
526 mesh.positions.resize(rangeCount);
527 if (mesh.normals.size() != 0) mesh.normals.resize(rangeCount);
528 if (mesh.texcoords.size() != 0) mesh.texcoords.resize(rangeCount);
529 if (mesh.tangents.size() != 0) mesh.tangents.resize(rangeCount);
532 if (options.forceIndexed) {
533 mesh.indices.resize(mesh.positions.size(),
false);
534 for (
size_t i = 0; i < mesh.indices.size(); i++) {
535 mesh.indices[i] =
static_cast<uint32_t
>(i);
540 meshes.push_back(std::move(mesh));
545void Cogs::Core::packMeshItems(
Context* context, std::vector<MeshHandle>& originalMeshes, MeshReps& meshes,
MeshItems& items,
bool update)
547 CpuInstrumentationScope(SCOPE_EDITOR_COMMAND,
"packMeshItems");
550 std::vector<Cogs::ComponentModel::Entity*> entities(items.meshes.size());
552 for (
size_t i = 0; i < entities.size(); i++) {
553 entities[i] = items.meshes[i].meshComp->getContainer();
555 createMeshResources(context, entities, originalMeshes, meshes);
558 for (
size_t i = 0; i < items.meshes.size(); i++) {
559 const auto & item = items.meshes[i];
560 const auto & meshRep = meshes[i];
561 auto * originalMesh = originalMeshes[i].resolve();
563 if (meshRep.positions.size() == 0) {
568 item.meshComp->meshHandle = context->meshManager->create();
569 item.meshComp->setChanged();
571 auto * newMesh = items.meshes[i].meshComp->meshHandle.resolve();
573 newMesh->setPositions(meshRep.positions.data(), meshRep.positions.data() + meshRep.positions.size());
574 if (meshRep.normals.size() != 0) {
575 newMesh->setNormals(meshRep.normals.data(), meshRep.normals.data() + meshRep.normals.size());
577 if (meshRep.texcoords.size() != 0) {
578 newMesh->setTexCoords(meshRep.texcoords.data(), meshRep.texcoords.data() + meshRep.texcoords.size());
580 if (meshRep.tangents.size() != 0) {
581 newMesh->setTangents(meshRep.tangents.data(), meshRep.tangents.data() + meshRep.tangents.size());
583 if (meshRep.indices.size() != 0) {
584 newMesh->setIndexData(meshRep.indices.data(), meshRep.indices.size());
593 newMesh->primitiveType = originalMesh->primitiveType;
595 item.meshRenderComp->startIndex = 0;
596 item.meshRenderComp->vertexCount = ~0;
597 item.meshRenderComp->setChanged();
602 else if(!originalMeshes.empty()) {
603 for (
size_t i = 0; i < items.meshes.size(); i++) {
604 const auto & item = items.meshes[i];
606 item.meshComp->meshHandle = originalMeshes[i];
607 item.meshComp->setChanged();
609 item.meshRenderComp->startIndex = item.offset;
610 item.meshRenderComp->vertexCount = item.count;
611 item.meshRenderComp->setChanged();
A shared_pointer type pointer to a component in an entity.
void setChanged()
Sets the component to the ComponentFlags::Changed state with carry.
ComponentType * getComponent() const
class Entity * getContainer() const
Get the container currently owning this component instance.
Container for components, providing composition of dynamic entities.
const std::string & getName() const noexcept
Get the name of this entity.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
class EntityStore * store
Entity store.
EntityPtr getEntity(const StringView &name, bool logIfNotFound=true) const
Retrieve a reference to the shared entity pointer to the Entity with the given name.
void addChild(ComponentModel::Entity *parent, const EntityPtr &entity)
Add a child to the given parent.
EntityPtr createChildEntity(const StringView &type, ComponentModel::Entity *parent, const StringView &name=StringView())
Create a new Entity, parenting it to the given parent.
EntityPtr createEntity(const StringView &name, const StringView &type, bool storeOwnership=true)
Create a new Entity.
Contains a handle to a Mesh resource to use when rendering using the MeshRenderComponent.
MeshHandle meshHandle
Handle to a Mesh resource to use when rendering.
Renders the contents of a MeshComponent using the given materials.
uint32_t startIndex
Start vertex index to render from.
MaterialInstanceHandle material
Material used to render the mesh.
Contains information on how the entity behaves in the scene.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
std::shared_ptr< ComponentModel::Entity > EntityPtr
Smart pointer for Entity access.
@ Position
Position semantic.
@ Tangent
Tangent semantic.
@ TextureCoordinate
Texture coordinate semantic.
@ ClockwiseWinding
The mesh uses clockwise winding order for it's triangles as opposed to the counter-clockwise default.
static const ResourceHandle_t NoHandle
Handle representing a default (or none if default not present) resource.