1#include "TerrainSystem.h"
7#include "Components/Core/RenderComponent.h"
9#include "Systems/Core/CameraSystem.h"
10#include "Systems/Core/TransformSystem.h"
12#include "Resources/ResourceStore.h"
13#include "Resources/MaterialManager.h"
15#include "TerrainRenderer.h"
16#include "OceanSystem.h"
18#include "Foundation/Logging/Logger.h"
19#include "Foundation/Platform/IO.h"
32 terrainFormat = VertexFormats::createVertexFormat(format);
34 if (!terrainRenderer) {
39 const auto dependencyDir = IO::expandEnvironmentVariable(
"CogsDir");
51 assert(terrainRenderer);
55 delete terrainRenderer;
56 terrainRenderer =
nullptr;
64 auto & terrainData = getData(&terrain);
66 if (!terrainData.initialized) {
68 terrainInitializeInstance(terrainData.context, context->device);
70 terrainData.getBounds = std::make_unique<TerrainBounds>(&terrain, &terrainData);
71 context->
bounds->addBoundsExtension(terrainData.getBounds.get());
73 terrainData.initialized =
true;
76 terrainData.terrainStreamsLayout.numStreams = 1;
77 terrainData.terrainStreamsLayout.vertexFormats[0] = terrainFormat;
78 terrainData.terrainStreamsLayout.updateHash();
81 if (terrainData.initialized) {
82 bool materialChanged = terrainData.depthMaterial != terrain.depthMaterial || terrainData.material != terrain.material;
84 auto customTextureKey = terrain.material->material->getTextureKey(
"customTexture");
85 terrain.material->setTextureProperty(customTextureKey, terrain.customTexture);
86 terrain.material->setTextureAddressMode(customTextureKey, terrain.addressMode);
90 terrainUpdate(terrainData.context);
93 terrainGetEffectParameters(terrainData.context, &p);
95 if (p.changed || materialChanged) {
96 terrainData.depthMaterial = terrain.depthMaterial;
97 terrainData.material = terrain.material;
99 terrain.material->setVariant(
"NumTextures", p.numTextures);
100 terrainData.depthMaterial->setVariant(
"NumTextures", p.numTextures);
101 terrain.material->setVariant(
"NumActiveTextures", p.numActiveImagery);
102 terrainData.depthMaterial->setVariant(
"NumActiveTextures", p.numActiveImagery);
104 if (terrainData.customComputeColor.size()) {
105 terrain.material->setVariant(
"CustomComputeColor", terrainData.customComputeColor);
106 terrainData.depthMaterial->setVariant(
"CustomComputeColor", terrainData.customComputeColor);
109 if (p.precomputeNormals) {
110 terrain.material->setVariant(
"PrecomputeNormals", p.precomputeNormals);
111 terrainData.depthMaterial->setVariant(
"PrecomputeNormals", p.precomputeNormals);
115 float nearPlaneLimit = terrainGetNearestSample(terrainData.context);
117 terrainData.nearPlaneLimit = nearPlaneLimit;
126 auto & terrainData = getData(terrainPtr);
127 terrainData.context = terrainCreate();
130 context->materialManager->processLoading();
133 terrainComponent.
material = context->materialInstanceManager->createMaterialInstance(terrainMaterial);
134 terrainComponent.
material->setPermutation(
"Normal");
135 terrainComponent.
depthMaterial = context->materialInstanceManager->createMaterialInstance(terrainMaterial);
138 if (pool.size() == 1) {
139 assert(picker ==
nullptr);
141 context->rayPicking->addPickable(picker);
143 LOG_DEBUG(logger,
"Registered terrain picker extension");
153 if (terrainData.initialized) {
154 terrainDestroy(terrainData.context);
156 context->bounds->removeBoundsExtension(terrainData.getBounds.get());
161 if (pool.size() == 0) {
162 assert(picker !=
nullptr);
163 context->rayPicking->removePickable(picker);
167 LOG_DEBUG(logger,
"Last component destroyed, unregistered terrain picker extension");
173 const glm::vec2& normPosition,
179 std::vector<RayPicking::RayPickHit>& hits)
182 glm::vec2 screenPos = normPosition * .5f + .5f;
184 auto & cameraData = context->cameraSystem->getData(&camera);
187 auto& terrainData = terrainSystem->getData(&terrain);
189 if (!terrainData.initialized) {
198 glm::vec4 pickedCoordinates;
199 if (cameraData.rayPickId == -1 && &camera != context->cameraSystem->getMainCamera())
205 if (terrainRayPick(terrainData.context, glm::value_ptr(screenPos), glm::value_ptr(cameraData.inverseViewProjectionMatrix), glm::value_ptr(pickedCoordinates), cameraData.rayPickId)) {
206 glm::vec3 coordinates = glm::vec3(pickedCoordinates);
207 glm::vec4 clipPos = cameraData.rawViewProjection * glm::vec4(coordinates, 1.f);
208 if ((-clipPos.w <= clipPos.z) && (clipPos.z <= clipPos.w)) {
210 glm::vec4 viewPos = cameraData.viewMatrix * glm::vec4(glm::vec3(coordinates), 1.f);
211 float viewDist = -viewPos.z;
214 if (viewDist < hits[0].distance) {
235 if (!renderComponent->isVisible()) {
236 if (terrainData->oceanData) {
239 if (!renderComponent_->isVisible())
return;
245 if (terrainData->initialized) {
248 glm::dvec3 globalBounds[2];
249 terrainGetBounds(terrainData->context, (
double *)globalBounds);
251 Cogs::BoundingBox terrainBounds = {
252 glm::vec3(globalBounds[0] + offsetFromOrigin),
253 glm::vec3(globalBounds[1] + offsetFromOrigin),
256 if (!isEmpty(terrainBounds)) {
258 nearPlaneLimit = terrainData->nearPlaneLimit * 0.85f;
259 bounds += terrainBounds;
ComponentType * getComponent() const
virtual void cleanup(Context *)
Provided for custom cleanup logic in derived systems.
virtual ComponentHandle createComponent()
Create a new component instance.
Context * context
Pointer to the Context instance the system lives in.
virtual void initialize(Context *context)
Initialize the system.
virtual void destroyComponent(ComponentHandle)
Destroy the component held by the given handle.
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.
class IRenderer * renderer
Renderer.
std::unique_ptr< class Bounds > bounds
Bounds service instance.
std::unique_ptr< class ResourceStore > resourceStore
ResourceStore service instance.
virtual void registerExtension(IRendererExtension *extension)=0
Register an extension with the renderer.
virtual void unregisterExtension(IRendererExtension *extension)=0
Unregister an extension with the renderer.
Base component for all rendering content.
constexpr bool isVisibleInLayer(RenderLayers layerMask) const
Check if the entity should be visible in the given layer mask.
void getBounds(Context *context, Cogs::Geometry::BoundingBox &bounds, float &nearPlaneLimit) final
bool pickCamera(Context *context, const CameraComponent &camera, const glm::vec2 &normPosition, float, float, PickingFlags pickingFlags, PicksReturned returnFlag, const RayPicking::RayPickFilter &filter, std::vector< RayPicking::RayPickHit > &hits) override
Do a ray pick from a normalized screen space position in the camera direction and return all hits.
ComponentModel::ComponentHandle createComponent() override
void cleanup(Context *context) override
Provided for custom cleanup logic in derived systems.
void destroyComponent(ComponentHandle component) override
void initialize(Context *context) override
Initialize the system.
Log implementation class.
PicksReturned
* Options for returning picking hits.
@ Closest
Return just the closest hit.
PickingFlags
Options for COGS picking.
@ ReturnChildEntity
Return ID if sub-entity picked, not set: return root parent entity.
@ DelayVariantLoading
Do not load any material variants, will be specified later.
Contains geometry calculations and generation.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
@ Direct3D12
Graphics device using the Direct3D 12 API.
@ Direct3D11
Graphics device using the Direct3D 11 API.
@ OpenGL20
Graphics device using OpenGL, supporting at least OpenGL 2.0.
@ Position
Position semantic.
Handle to a Component instance.
ComponentType * resolveComponent() const
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.
MaterialInstanceHandle depthMaterial
The terrain material instance used for the depth buffer.
MaterialInstanceHandle material
The terrain material instance.
Vertex element structure used to describe a single data element in a vertex for the input assembler.