1#include "SubMeshRenderSystem.h"
5#include "Components/Core/TransformComponent.h"
6#include "Components/Core/MeshComponent.h"
7#include "Components/Core/NearLimitComponent.h"
8#include "Components/Core/ClipShapeComponent.h"
10#include "Systems/Core/TransformSystem.h"
11#include "Systems/Core/CameraSystem.h"
12#include "Systems/Core/ClipShapeSystem.h"
14#include "Resources/Mesh.h"
15#include "Resources/MeshManager.h"
17#include "Services/Variables.h"
18#include "Services/TaskManager.h"
20#include "Utilities/Parallel.h"
21#include "Math/RayIntersection.h"
23#include "Scene/GetBounds.h"
37 const bool workParallel = context->
engine->workParallel();
47 auto & data = this->getData<SubMeshRenderData>(&renderComponent);
48 auto & localBounds = getLocalBounds(&renderComponent);
50 if (!data.transformComponent) {
55 if (data.flags)
return;
59 auto meshComponent = data.meshComponent.resolveComponent<
MeshComponent>();
61 if (!meshComponent->meshHandle)
return;
65 if (meshComponent->hasChanged() || data.meshBoundsGeneration != mesh->getGeneration() || mesh->boundsDirty()) {
67 if (mesh->boundsDirty()) {
70 if (!isEmpty(mesh->boundingBox) && !mesh->isInitialized()) {
75 localBounds = mesh->boundingBox;
76 data.meshBoundsGeneration = (uint8_t)mesh->getGeneration();
77 ++data.localBoundsGeneration;
85 if (data.localBoundsGeneration != data.worldBoundsGeneration || context->transformSystem->hasChanged(transform)) {
86 data.localToWorld = context->transformSystem->getLocalToWorld(transform);
88 if (!isEmpty(localBounds)) {
89 getWorldBounds(&renderComponent) = Bounds::getTransformedBounds(localBounds, data.localToWorld);
91 getWorldBounds(&renderComponent) = localBounds;
94 data.worldBoundsGeneration = data.localBoundsGeneration;
100 CpuInstrumentationScope(SCOPE_SYSTEMS,
"SubMeshRenderSystem::update");
102 Parallel::processComponents(context, pool,
"SubMeshRenderSystem::updateComponent", updateComponent, geometryGroup);
106 Serial::processComponents(pool, updateComponent);
119 if (geometryGroup.isValid()) {
129 if (pool.size() == 1u) {
130 assert(picker ==
nullptr);
131 picker = std::make_unique<SubMeshPicker>(
this);
132 context->rayPicking->addPickable(picker.get());
139 base_type::destroyComponent(component);
141 if (pool.size() == 0u) {
142 context->rayPicking->removePickable(picker.get());
147void Cogs::Core::SubMeshRenderSystem::initializeCulling(
CullingSource * cullSource)
149 const size_t offset = cullSource->count;
150 const size_t count = pool.size();
151 const size_t total = offset + count;
155 cullSource->count = total;
156 cullSource->bbMinWorld.resize(total);
157 cullSource->bbMaxWorld.resize(total);
160 for (
SizeType i = 0; i < count; ++i) {
161 auto & meshData = this->getData<SubMeshRenderData>(&pool[i]);
163 meshData.cullingIndex = j;
164 cullSource->bbMinWorld[j] = getWorldBounds(&pool[i]).min;
165 cullSource->bbMaxWorld[j] = getWorldBounds(&pool[i]).max;
169 auto scope = Parallel::forEach(context, count, [
this, offset, cullSource](
size_t i) {
170 auto & meshData = this->getData<SubMeshRenderData>(&pool[(
SizeType)i]);
172 meshData.cullingIndex = j;
173 cullSource->bbMinWorld[j] = getWorldBounds(&pool[(
SizeType)i]).min;
174 cullSource->bbMaxWorld[j] = getWorldBounds(&pool[(
SizeType)i]).max;
175 },
"SubMeshRenderSystem::initializeCulling");
182 const glm::mat4& worldPickMatrix,
183 const glm::mat4& rawViewProjection,
184 const glm::mat4& viewMatrix,
188 std::vector<RayPicking::RayPickHit>& hits)
192 bool hitSomething =
false;
206 if (!renderData.meshComponent) {
210 const Geometry::BoundingBox& bboxWorld = system->getWorldBounds(&comp);
222 if (isEmpty(bboxWorld)) {
226 if (frustumClassifyBoundingBox(worldPickMatrix, bboxWorld.min, bboxWorld.max) != FrustumPlanes::InsideAll) {
232 glm::mat4 localPickMatrix = worldPickMatrix * renderData.localToWorld;
234 std::vector<RayIntersectionHit> meshHits;
235 std::vector<FrustumPlanes> scratch;
236 if (!intersectMesh(meshHits,
241 static_cast<uint32_t
>(-1),
246 if (meshHits.empty()) {
251 const glm::vec4 position = renderData.localToWorld * glm::vec4(meshHit.pos_, 1.f);
254 const ClipShapeData& clipData = context->clipShapeSystem->getData(clipComp);
255 if (clippedByClipComp(clipData, position)) {
260 const glm::vec4 clipPos = rawViewProjection * glm::vec4(position.x, position.y, position.z, 1.f);
261 if ((-clipPos.w < clipPos.z) && (clipPos.z < clipPos.w)) {
263 glm::vec4 viewPos = viewMatrix * position;
264 float viewDist = -viewPos.z;
267 if (viewDist < hits[0].distance) {
268 glm::vec2 textureCoords = getTextureCoords(texcoordInfo, meshHit, pickingFlags);
269 hits[0] = {comp, returnChildEntity, position, viewDist, textureCoords};
275 glm::vec2 textureCoords = getTextureCoords(texcoordInfo, meshHit, pickingFlags);
276 hits.emplace_back(comp, returnChildEntity, position, viewDist, textureCoords);
284 std::sort(hits.begin(), hits.end());
ComponentHandle getComponentHandle() const
Sets up a clipping shape that can be used by multiple entities.
Context * context
Pointer to the Context instance the system lives in.
void postUpdate()
Perform post update logic in the system.
virtual void initialize(Context *context)
Initialize the system.
void update()
Updates the system state to that of the current frame.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
std::unique_ptr< class TaskManager > taskManager
TaskManager service instance.
std::unique_ptr< class Engine > engine
Engine instance.
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.
ComponentModel::ComponentHandle clipShapeComponent
Handle to the currently active clip component, if any.
constexpr bool isVisibleInLayer(RenderLayers layerMask) const
Check if the entity should be visible in the given layer mask.
constexpr bool isVisible() const
Check if the entity is visible or not.
constexpr bool isRenderFlagSet(RenderFlags flag) const
Check if the given flag is currently set.
constexpr bool isPickable() const
Check if the entity is pickable or not.
Renders a mesh with flexible submesh usage.
int subMesh
Sub mesh index.
void initialize(Context *context) override
Initialize the system.
void destroyComponent(ComponentHandle component) override
Destroy the component held by the given handle.
void cleanup(Context *context) override
Provided for custom cleanup logic in derived systems.
ComponentHandle createComponent() override
Create a new component instance.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
PicksReturned
* Options for returning picking hits.
@ Closest
Return just the closest hit.
@ AllSorted
Return all hits sorted based on distance from the ray start, closest first.
@ ForcePickable
Ensure component is pickable though it is not rendered.
PickingFlags
Options for COGS picking.
@ ReturnChildEntity
Return ID if sub-entity picked, not set: return root parent entity.
Cogs::Geometry::BoundingBox COGSCORE_DLL_API calculateBounds(Mesh *mesh)
Calculate a bounding box for the given mesh.
Contains geometry calculations and generation.
ComponentIndex SizeType
Type used to track the size of pools.
Handle to a Component instance.
ComponentType * resolveComponent() const
Meshes contain streams of vertex data in addition to index data and options defining geometry used fo...
bool isUnwantedType(const ComponentModel::Component &comp) const
Helper function used to determine if a given component belongs to an accepted entity type.
RenderLayers layerMask
Limit picking to the specified render layers. Pick all layers by default.
uint8_t currentLod
The assigned LoD of the current component.
uint8_t selectedLod
The selected LoD of the composite entity.
ResourceType * resolve() const
Resolve the handle, returning a pointer to the actual resource.
bool pickImpl(Context *context, const glm::mat4 &worldPickMatrix, const glm::mat4 &rawViewProjection, const glm::mat4 &viewMatrix, const RayPicking::RayPickFilter &filter, PickingFlags pickingFlags, PicksReturned returnFlag, std::vector< RayPicking::RayPickHit > &hits) override
Each mesh rendering system should implement this function that goes through all components and calls ...