1#include "OceanSystem.h"
6#include "ViewContext.h"
7#include "EntityStore.h"
9#include "Services/Variables.h"
11#include "Components/Core/RenderComponent.h"
12#include "Components/Core/NearLimitComponent.h"
13#include "Components/Behavior/ReflectionComponent.h"
14#include "Components/Appearance/MaterialComponent.h"
16#include "Systems/Core/CameraSystem.h"
18#include "Resources/ResourceStore.h"
19#include "Resources/MaterialManager.h"
20#include "Resources/TextureManager.h"
22#include "TerrainSystem.h"
24#include "Foundation/ComponentModel/Entity.h"
28Cogs::Core::OceanPicker::OceanPicker(OceanComponent * oceanComponent, OceanData * oceanData)
29 : oceanComponent(oceanComponent), oceanData(oceanData)
35 const glm::vec2& normPosition,
41 std::vector<RayPicking::RayPickHit>& hits)
43 const CameraData& cameraData = context->cameraSystem->getData(&camera);
46 assert(renderComponent);
52 Geometry::BoundingBox terrainBounds = Geometry::makeEmptyBoundingBox<BoundingBox>();
53 oceanData->terrainData->getBounds->getBounds(context, terrainBounds, dummy);
55 if (isEmpty(terrainBounds)) {
61 glm::vec4 aH = M * glm::vec4(normPosition, -1, 1.f);
62 glm::vec4 bH = M * glm::vec4(normPosition, 1, 1.f);
63 glm::vec3 a = (1.f / aH.w)*glm::vec3(aH);
64 glm::vec3 b = (1.f / bH.w)*glm::vec3(bH);
67 glm::vec4 eq = glm::vec4(0, 0, 1, 0);
69 float den = glm::dot(d, glm::vec3(eq));
70 if (glm::abs(den) < std::numeric_limits<float>::min()) {
73 float t = -glm::dot(glm::vec4(a, 1.f), eq) / den;
74 if ((t < 0.f) || (1.f < t)) {
78 glm::vec3 coordinates = glm::mix(a, b, t);
80 if ((coordinates.x < terrainBounds.min.x) ||
81 (coordinates.y < terrainBounds.min.y) ||
82 (terrainBounds.max.x < coordinates.x) ||
83 (terrainBounds.max.y < coordinates.y))
88 glm::vec4 clipPos = cameraData.rawViewProjection * glm::vec4(coordinates, 1.f);
89 if ((-clipPos.w > clipPos.z) || (clipPos.z > clipPos.w)) {
93 glm::vec4 viewPos = cameraData.viewMatrix * glm::vec4(glm::vec3(coordinates), 1.f);
94 float viewDist = -viewPos.z;
97 if (viewDist < hits[0].distance) {
114 oceanFormat = Cogs::VertexFormats::createVertexFormat(format);
119 for (
auto & ocean : pool) {
120 auto & oceanData = getData(&ocean);
122 if (!oceanData.initialized && ocean.terrain) {
130 context->materialManager->processLoading();
132 oceanData.streamsLayout.numStreams = 1;
133 oceanData.streamsLayout.vertexFormats[0] = oceanFormat;
134 oceanData.streamsLayout.updateHash();
135 oceanData.material = context->materialInstanceManager->createMaterialInstance(oceanData.oceanMaterial);
137 oceanData.terrainData = &terrainSystem->getData(terrainComponent);
138 oceanData.terrainData->oceanData = &oceanData;
140 oceanData.reflectionTexture = context->textureManager->create();
141 oceanData.reflectionTexture->setName(
"Ocean.Reflection");
143 auto planarKey = oceanData.oceanMaterial->getTextureKey(
"PlanarReflection");
144 oceanData.oceanMaterial->setTextureProperty(planarKey, oceanData.reflectionTexture);
146 const auto textureResolution =
static_cast<uint32_t
>(context->
variables->get(
"ocean.reflectionTextureResolution", 1024));
147 auto reflectionTex = context->textureManager->get(oceanData.reflectionTexture);
149 if (reflectionTex->description.width != textureResolution) {
150 reflectionTex->description.width = textureResolution;
151 reflectionTex->description.height = textureResolution;
152 reflectionTex->description.format = TextureFormat::R8G8B8A8_UNORM;
154 reflectionTex->setChanged();
157 context->textureManager->processLoading();
159 auto camera = context->cameraSystem->getMainCamera();
160 oceanData.reflectionCamera = context->
store->
createChildEntity(
"ReflectionCamera", camera->getContainer());
162 auto reflectionComponent = oceanData.reflectionCamera->getComponent<
ReflectionComponent>();
163 reflectionComponent->texture = oceanData.reflectionTexture;
165 auto cameraComponent = oceanData.reflectionCamera->getComponent<
CameraComponent>();
166 cameraComponent->
viewportSize = glm::vec2(reflectionTex->description.width, reflectionTex->description.height);
168 if (!oceanData.rayPick) {
169 oceanData.rayPick = std::make_unique<OceanPicker>(&ocean, &oceanData);
170 context->
rayPicking->addPickable(oceanData.rayPick.get());
173 oceanData.bounds = std::make_unique<OceanBounds>(&ocean, &oceanData);
174 context->
bounds->addBoundsExtension(oceanData.bounds.get());
176 oceanData.initialized =
true;
179 if (!oceanData.initialized)
continue;
181 oceanData.oceanComponent = &ocean;
183 if (oceanData.initialized && oceanData.terrainData->initialized) {
184 auto terrainData = oceanData.terrainData;
186 terrainData->renderContext.oceanEnabled =
true;
189 terrainGetEffectParameters(terrainData->context, &p);
191 if (p.changed || oceanData.first) {
192 oceanData.material->setVariant(
"NumTextures", p.numTextures);
193 oceanData.material->setVariant(
"NumActiveTextures", p.numActiveImagery);
195 if (terrainData->customComputeColor.size()) {
196 oceanData.material->setVariant(
"CustomComputeColor", terrainData->customComputeColor);
199 if (p.precomputeNormals) {
200 oceanData.material->setVariant(
"PrecomputeNormals", p.precomputeNormals);
203 oceanData.first =
false;
213 if (oceanData.rayPick) context->rayPicking->removePickable(oceanData.rayPick.get());
214 if (oceanData.bounds) context->bounds->removeBoundsExtension(oceanData.bounds.get());
221 if (!oceanData->initialized || !oceanData->terrainData || !oceanData->terrainData->initialized)
return;
224 Geometry::BoundingBox terrainBounds = Geometry::makeEmptyBoundingBox<BoundingBox>();
225 oceanData->terrainData->getBounds->getBounds(context, terrainBounds, dummy);
227 if (isEmpty(terrainBounds)) {
231 auto oceanBounds = terrainBounds;
232 oceanBounds.min.z = -oceanComponent->significantWaveHeight;
233 oceanBounds.max.z = oceanComponent->significantWaveHeight;
235 bounds += oceanBounds;
240 if (!oceanData->initialized || !oceanData->terrainData || !oceanData->terrainData->initialized)
return;
242 getBounds(context, bounds);
ComponentType * getComponent() const
glm::vec2 viewportSize
Size of the viewport covered by this instance, given in pixels.
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.
std::unique_ptr< class Bounds > bounds
Bounds service instance.
class EntityStore * store
Entity store.
std::unique_ptr< class RayPicking > rayPicking
RayPicking service instance.
std::unique_ptr< class Variables > variables
Variables service instance.
EntityPtr createChildEntity(const StringView &type, ComponentModel::Entity *parent, const StringView &name=StringView())
Create a new Entity, parenting it to the given parent.
Contains data to describe fog.
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.
void initialize(Context *context) override
Initialize the system.
void destroyComponent(ComponentHandle component) override
Base component for all rendering content.
constexpr bool isVisibleInLayer(RenderLayers layerMask) const
Check if the entity should be visible in the given layer mask.
constexpr bool isPickable() const
Check if the entity is pickable or not.
PicksReturned
* Options for returning picking hits.
@ Closest
Return just the closest hit.
@ CastShadows
Casts shadows.
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.
@ Position
Position semantic.
Handle to a Component instance.
ComponentType * resolveComponent() const
Contains data describing a Camera instance and its derived data structured such as matrix data and vi...
glm::mat4 rawProjectionMatrix
Projection matrix that has not been adjusted by the renderer, and is thus appropriate for direct scre...
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.
@ Clamp
Texture coordinates are clamped to the [0, 1] range.
@ RenderTarget
The texture can be used as a render target and drawn into.
Vertex element structure used to describe a single data element in a vertex for the input assembler.