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);
51 Geometry::BoundingBox terrainBounds = Geometry::makeEmptyBoundingBox<BoundingBox>();
52 oceanData->terrainData->getBounds->getBounds(context, terrainBounds, dummy);
54 if (isEmpty(terrainBounds)) {
60 glm::vec4 aH = M * glm::vec4(normPosition, -1, 1.f);
61 glm::vec4 bH = M * glm::vec4(normPosition, 1, 1.f);
62 glm::vec3 a = (1.f / aH.w)*glm::vec3(aH);
63 glm::vec3 b = (1.f / bH.w)*glm::vec3(bH);
66 glm::vec4 eq = glm::vec4(0, 0, 1, 0);
68 float den = glm::dot(d, glm::vec3(eq));
69 if (glm::abs(den) < std::numeric_limits<float>::min()) {
72 float t = -glm::dot(glm::vec4(a, 1.f), eq) / den;
73 if ((t < 0.f) || (1.f < t)) {
77 glm::vec3 coordinates = glm::mix(a, b, t);
79 if ((coordinates.x < terrainBounds.min.x) ||
80 (coordinates.y < terrainBounds.min.y) ||
81 (terrainBounds.max.x < coordinates.x) ||
82 (terrainBounds.max.y < coordinates.y))
87 glm::vec4 clipPos = cameraData.rawViewProjection * glm::vec4(coordinates, 1.f);
88 if ((-clipPos.w > clipPos.z) || (clipPos.z > clipPos.w)) {
92 glm::vec4 viewPos = cameraData.viewMatrix * glm::vec4(glm::vec3(coordinates), 1.f);
93 float viewDist = -viewPos.z;
98 if (hits[0].isBehind(ordinal, viewDist)) {
115 oceanFormat = Cogs::VertexFormats::createVertexFormat(format);
120 for (
auto & ocean : pool) {
121 auto & oceanData = getData(&ocean);
123 if (!oceanData.initialized && ocean.terrain) {
131 context->materialManager->processLoading();
133 oceanData.streamsLayout.numStreams = 1;
134 oceanData.streamsLayout.vertexFormats[0] = oceanFormat;
135 oceanData.streamsLayout.updateHash();
136 oceanData.material = context->materialInstanceManager->createMaterialInstance(oceanData.oceanMaterial);
138 oceanData.terrainData = &terrainSystem->getData(terrainComponent);
139 oceanData.terrainData->oceanData = &oceanData;
141 oceanData.reflectionTexture = context->textureManager->create();
142 oceanData.reflectionTexture->setName(
"Ocean.Reflection");
144 auto planarKey = oceanData.oceanMaterial->getTextureKey(
"PlanarReflection");
145 oceanData.oceanMaterial->setTextureProperty(planarKey, oceanData.reflectionTexture);
147 const auto textureResolution =
static_cast<uint32_t
>(context->
variables->get(
"ocean.reflectionTextureResolution", 1024));
148 auto reflectionTex = context->textureManager->get(oceanData.reflectionTexture);
150 if (reflectionTex->description.width != textureResolution) {
151 reflectionTex->description.width = textureResolution;
152 reflectionTex->description.height = textureResolution;
153 reflectionTex->description.format = TextureFormat::R8G8B8A8_UNORM;
155 reflectionTex->setChanged();
158 context->textureManager->processLoading();
160 auto camera = context->cameraSystem->getMainCamera();
161 oceanData.reflectionCamera = context->
store->
createChildEntity(
"ReflectionCamera", camera->getContainer());
163 auto reflectionComponent = oceanData.reflectionCamera->getComponent<
ReflectionComponent>();
164 reflectionComponent->texture = oceanData.reflectionTexture;
166 auto cameraComponent = oceanData.reflectionCamera->getComponent<
CameraComponent>();
167 cameraComponent->
viewportSize = glm::vec2(reflectionTex->description.width, reflectionTex->description.height);
169 if (!oceanData.rayPick) {
170 oceanData.rayPick = std::make_unique<OceanPicker>(&ocean, &oceanData);
171 context->
rayPicking->addPickable(oceanData.rayPick.get());
174 oceanData.bounds = std::make_unique<OceanBounds>(&ocean, &oceanData);
175 context->
bounds->addBoundsExtension(oceanData.bounds.get());
177 oceanData.initialized =
true;
180 if (!oceanData.initialized)
continue;
182 oceanData.oceanComponent = &ocean;
184 if (oceanData.initialized && oceanData.terrainData->initialized) {
185 auto terrainData = oceanData.terrainData;
187 terrainData->renderContext.oceanEnabled =
true;
190 terrainGetEffectParameters(terrainData->context, &p);
192 if (p.changed || oceanData.first) {
193 oceanData.material->setVariant(
"NumTextures", p.numTextures);
194 oceanData.material->setVariant(
"NumActiveTextures", p.numActiveImagery);
196 if (terrainData->customComputeColor.size()) {
197 oceanData.material->setVariant(
"CustomComputeColor", terrainData->customComputeColor);
200 if (p.precomputeNormals) {
201 oceanData.material->setVariant(
"PrecomputeNormals", p.precomputeNormals);
204 oceanData.first =
false;
214 if (oceanData.rayPick) context->rayPicking->removePickable(oceanData.rayPick.get());
215 if (oceanData.bounds) context->bounds->removeBoundsExtension(oceanData.bounds.get());
222 if (!oceanData->initialized || !oceanData->terrainData || !oceanData->terrainData->initialized)
return;
225 Geometry::BoundingBox terrainBounds = Geometry::makeEmptyBoundingBox<BoundingBox>();
226 oceanData->terrainData->getBounds->getBounds(context, terrainBounds, dummy);
228 if (isEmpty(terrainBounds)) {
232 auto oceanBounds = terrainBounds;
233 oceanBounds.min.z = -oceanComponent->significantWaveHeight;
234 oceanBounds.max.z = oceanComponent->significantWaveHeight;
236 bounds += oceanBounds;
241 if (!oceanData->initialized || !oceanData->terrainData || !oceanData->terrainData->initialized)
return;
243 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.