3#include "Components/Core/SceneComponent.h"
4#include "Components/Core/LodComponent.h"
5#include "Components/Core/TransformComponent.h"
6#include "Components/Core/MeshRenderComponent.h"
7#include "Resources/MaterialInstance.h"
8#include "Resources/MaterialManager.h"
9#include "EntityStore.h"
11#include "Editor/Editor.h"
12#include "Commands/EditorCommand.h"
13#include "Rendering/Common.h"
15#include "RRMultiSimplifyCommand.h"
21Cogs::Core::RRMultiSimplifyCommand::RRMultiSimplifyCommand(
EditorState * state)
24 taskState.context = state->context;
27bool Cogs::Core::RRMultiSimplifyCommand::initTaskData()
30 taskState.items.transforms.clear();
31 taskState.items.meshes.clear();
33 if (taskState.items.meshes.empty())
return false;
36 opts.discardNormals =
true;
37 opts.discardTexCoords =
false;
38 opts.discardTangents =
true;
39 opts.forceIndexed =
false;
41 taskState.meshSets.clear();
42 taskState.meshSets.emplace_back();
43 unpackMeshItems(context, originalMeshes, taskState.meshSets.front().meshes, taskState.items, opts);
53 for (
auto child : sceneComp->children) {
54 descendAndColorize(child.get(), material);
58 mRndComp->material = material;
65void Cogs::Core::RRMultiSimplifyCommand::finishTaskData()
67 if (taskState.cancel)
return;
70 if (
auto * sceneComp = state->getSelected()->getComponent<
SceneComponent>()) {
71 if (sceneComp->parent) {
72 parent = sceneComp->parent.resolve()->getContainer();
78 auto lodGroup = context->store->getEntity(
"LODs");
80 const auto id = lodGroup->
getId();
82 context->store->destroyEntity(
id);
85 lodGroup = context->store->createEntity(
"LODs",
"Lod", parent ==
nullptr);
87 context->store->addChild(parent, lodGroup);
92 lodComp->separateHierarchies =
true;
93 lodComp->thresholds.resize(taskState.meshSets.size());
94 for (
size_t i = 0; i < taskState.meshSets.size(); i++) {
95 auto & meshSet = taskState.meshSets[i];
97 lodComp->thresholds[i] = meshSet.error;
101 hierarchy = createAsSingleMeshItem(context, lodGroup.get(), originalMeshes, meshSet.meshes, taskState.items);
104 hierarchy = createNewMeshItems(context, lodGroup.get(), originalMeshes, meshSet.meshes, taskState.items);
106 hierarchy->setName(
"Level " + std::to_string(i));
109 glm::vec4 c((i >> 2) & 1, (i >> 1) & 1, i & 1, 1);
110 auto material = context->materialInstanceManager->createMaterialInstance(context->materialManager->getDefaultMaterial());
111 material->setProperty(
"diffuseColor", glm::value_ptr(c),
sizeof(c));
112 descendAndColorize(hierarchy.get(), material);
115 lodComp->setChanged();
117 state->selected = EntityIds{ lodGroup->getId() };
122 std::vector<float> thresholds;
124 for (
auto & option : options) {
125 if (option.key ==
"epsilon") option.asFloat(epsilon);
126 else if (option.key ==
"thresholds") {
127 auto & val = option.value;
130 while (a < val.length()) {
131 auto b = val.find(
',', a);
132 thresholds.push_back(std::stof(val.substr(a, b == std::string::npos ? b : b - a)));
133 if (b == std::string::npos)
break;
137 else if (option.key ==
"errorGuided") option.asBool(error_guided);
139 else if (option.key ==
"featureAngle") option.asFloat(normalGenArgs.featureAngle);
140 else if (option.key ==
"protrusionAngle") option.asFloat(normalGenArgs.protrusionAngle);
141 else if (option.key ==
"flip") option.asBool(normalGenArgs.flip);
142 else if (option.key ==
"singleMesh") option.asBool(singleMesh);
147 steps = std::max(1, steps);
164bool Cogs::Core::RRMultiSimplifyCommand::issueTask()
166 if (initTaskData()) {
167 std::vector<float> thresholds(steps);
168 for (
int i = 0; i < steps; i++) {
169 auto t = (i + 1.f) / steps;
171 thresholds[i] = error * t;
173 taskState.cancel =
false;
174 taskState.running =
true;
176 task = context->taskManager->enqueue(context->taskManager->GlobalQueue,
RRMultiMinMaxErrorGuidedTask(&taskState,
false, epsilon, thresholds, normalGenArgs));
179 std::vector<float> thresholds_(steps);
180 for (
int i = 0; i < steps; i++) {
181 auto t = (steps - i - 1.f) / steps;
183 thresholds_[i] = 100.f * t * t * t * t;
185 task = context->taskManager->enqueue(context->taskManager->GlobalQueue,
RRMultiTriangleGuidedTask(&taskState,
false, epsilon, thresholds_, normalGenArgs));
192void Cogs::Core::RRMultiSimplifyCommand::waitForTask()
194 context->taskManager->wait(task);
199void Cogs::Core::RRMultiSimplifyCommand::showParameterGui()
201 const char * label =
"RR multi-level mesh simplification";
203 ImGui::OpenPopup(label);
204 if (ImGui::BeginPopupModal(label, NULL)) {
206 ImGui::InputFloat(
"Vertex merge epsilon", &epsilon);
208 const char* modes[] = {
"Error-driven",
"Triangle count-driven" };
209 int mode_current = error_guided ? 0 : 1;
210 ImGui::Combo(
"Simplification guide", &mode_current, modes, 2);
211 error_guided = mode_current == 0;
214 ImGui::InputFloat(
"Min-max error threhold", &error);
216 ImGui::SliderInt(
"Steps", &steps, 1, 25);
220 ImGui::Checkbox(
"Merge lod level into single mesh", &singleMesh);
221 ImGui::SliderAngle(
"Feature angle", &normalGenArgs.featureAngle, 0.f, 180.f);
222 ImGui::SliderAngle(
"Protrusion angle", &normalGenArgs.protrusionAngle, 0.f, 180.f);
223 ImGui::Checkbox(
"Flip normals", &normalGenArgs.flip);
227 ImGui::Checkbox(
"Debug-colorize levels", &debugColors);
229 if (ImGui::Button(
"Simplify", ImVec2(120, 0))) {
235 if (ImGui::Button(
"Cancel", ImVec2(120, 0))) {
236 taskState.cancel =
true;
238 ImGui::CloseCurrentPopup();
244void Cogs::Core::RRMultiSimplifyCommand::showProgressGui()
246 const char * label =
"Simplification in progress";
248 ImGui::OpenPopup(label);
249 if (ImGui::BeginPopupModal(label, NULL)) {
250 ImGui::ProgressBar(taskState.progress);
253 if (ImGui::Button(
"Cancel", ImVec2(120, 0))) {
254 taskState.cancel =
true;
267 if (taskState.running ==
false) {
277 if (!taskState.running && task.isValid()) {
Container for components, providing composition of dynamic entities.
T * getComponent() const
Get a pointer to the first component implementing the given type in the entity.
constexpr size_t getId() const noexcept
Get the unique identifier of this entity.
Contains data describing level of detail behavior for the entity the component belongs to.
LodPolicy policy
The policy used for determining the level of detail for this entity.
Renders the contents of a MeshComponent using the given materials.
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.
@ GeometricTolerance
Use a geometric error bound to determine how refined geometry needs to be at its current position.
Abstract base class for all editor commands showing GUI in interactive mode.
bool continueModal() override
Shall return true while the GUI should still be shown. False when.
void showGui() override
Display custom ImGUI.
void beginModal() override
Called when the command is initiated.
void apply() override
Run the command.
@ TriangleList
List of triangles.