Cogs.Core
TeleportNavigationComponent.cpp
1#include "TeleportNavigationComponent.h"
2
3#include "Types.h"
4#include "ViewContext.h"
5#include "Input/InputManager.h"
6
7#include "Components/Core/CameraComponent.h"
8#include "Components/Core/TransformComponent.h"
9#include "Components/Core/SceneComponent.h"
10#include "Components/Geometry/MeshGeneratorComponent.h"
11#include "Components/Appearance/MaterialComponent.h"
12
13#include "Scene/RayPick.h"
14#include "EntityStore.h"
15
16#include "Systems/Core/CameraSystem.h"
17#include "Systems/Core/TransformSystem.h"
18#include "Systems/Core/SceneSystem.h"
19
20#include "Foundation/Logging/Logger.h"
21#include "Foundation/Reflection/Method.h"
22
23
24#include <glm/gtx/quaternion.hpp>
25
26#include <algorithm>
27
28namespace
29{
30 Cogs::Logging::Log logger = Cogs::Logging::getLogger("TeleportNavigationComponent");
31 glm::vec4 navEmissive(0.2f, 0.2f, 0.8f, 1);
32 glm::vec4 navDiffuse(0, 0, 0, 0.7f);
33}
34
35
36using namespace Cogs::Core;
37using namespace Cogs::Reflection;
38
39//static
40void Cogs::Core::TeleportNavigationComponent::registerType()
41{
42 Field fields[] = {
43 Field(Name("actionTeleport"), &TeleportNavigationComponent::actionTeleport),
44 Field(Name("aimEntity"), &TeleportNavigationComponent::aimEntity),
45 Field(Name("beamOffset"), &TeleportNavigationComponent::beamOffset),
46 Field(Name("beamRotation"), &TeleportNavigationComponent::beamRotation),
47 Field(Name("useCoordinate"), &TeleportNavigationComponent::useCoordinate),
48 Field(Name("teleportOffset"), &TeleportNavigationComponent::teleportOffset),
49 };
50 Method methods[] = {
51 Method(Name("initialize"), &TeleportNavigationComponent::initialize),
52 Method(Name("postUpdate"), &TeleportNavigationComponent::postUpdate),
53 Method(Name("update"), &TeleportNavigationComponent::update),
54 };
55
56 DynamicComponent::registerDerivedType<TeleportNavigationComponent>().setMethods(methods).setFields(fields);
57}
58
59void Cogs::Core::TeleportNavigationComponent::initialize(Cogs::Core::Context * context)
60{
61 this->context = context;
62 this->beam = context->store->findEntity("aimBeam", aimEntity.get());
63 if (!this->beam) {
64 this->beam = context->store->createChildEntity("Group", aimEntity.get(), "aimBeam");
65 }
66 EntityPtr beamGeometry = context->store->findEntity("aimCylinder", this->beam.get());
67 if (!beamGeometry) {
68 beamGeometry = context->store->createChildEntity("Cylinder", this->beam.get(), "aimCylinder");
69 }
70
71 MaterialComponent *beamMaterial = beamGeometry->getComponent<MaterialComponent>();
72 beamMaterial->emissiveColor = navEmissive;
73 beamMaterial->diffuseColor = navDiffuse;
74 beamMaterial->setChanged();
75
77 beamShape->size = glm::vec3(0.002f, 0, 2500); // radius, halfheight
78 beamShape->setChanged();
79
80 TransformComponent *beamGeometryTransform = beamGeometry->getComponent<TransformComponent>();
81 beamGeometryTransform->position = glm::vec3(0, 0, -2500);
82 beamGeometryTransform->setChanged();
83
84 TransformComponent *beamTransform = this->beam->getComponent<TransformComponent>();
85 beamTransform->position = beamOffset;
86 beamTransform->rotation = beamRotation;
87 beamTransform->setChanged();
88
89 SceneComponent *beamVisibility = beamGeometry->getComponent<SceneComponent>();
90 beamVisibility->visible = false;
91 beamVisibility->pickable = false;
92 beamVisibility->setChanged();
93 this->beamVisibility = beamVisibility->getComponentHandle<SceneComponent>();
94
95 CameraComponent *beamCam = beam.get()->getComponent<CameraComponent>();
96 if (!beamCam) {
97 beamCam = context->store->addComponent<CameraComponent>(beam.get());
98 }
99 //beamCam->projectionMode = CameraComponent::Orthographic;
100 //beamCam->orthoHeight = 0.1f;
101
103 beamCam->fieldOfView = 0.01f;
104
105 beamCam->flags = CameraFlags::EnablePicking;
106 beamCam->viewportSize = glm::vec2(3, 3);
107 beamCam->nearPlaneLimit = 0.1f;
108 beamCam->enableClippingPlaneAdjustment = true;
109 //beamCam->nearDistance = 0.1f;
110 //beamCam->farDistance = 5000;
111
112 beamCam->setChanged();
113
114 destinationMarker = context->store->findEntity("destinationMarker", aimEntity.get());
115 if (!destinationMarker) {
116 destinationMarker = context->store->createChildEntity("Group", aimEntity.get(), "destinationMarker");
117 }
118 EntityPtr destGeometry = context->store->findEntity("destinationSphere", destinationMarker.get());
119 if (!destGeometry) {
120 destGeometry = context->store->createChildEntity("Sphere", destinationMarker.get(), "destinationSphere");
121 }
122
123 MaterialComponent *destMaterial = destGeometry->getComponent<MaterialComponent>();
124 destMaterial->emissiveColor = navEmissive;
125 destMaterial->diffuseColor = navDiffuse;
126 destMaterial->setChanged();
127
128 TransformComponent *destTransform = destGeometry->getComponent<TransformComponent>();
129 destTransform->scale = glm::vec3(0.25f);
130 destTransform->setChanged();
131
132 destinationVisibility = destinationMarker->getComponentHandle<SceneComponent>();
133 SceneComponent *destVis = destinationVisibility.resolveComponent<SceneComponent>();
134 destVis->pickable = false;
135 destVis->visible = false;
136 destVis->setChanged();
137}
138
139void logVector(const Cogs::Logging::Log& logger_, const char * name, glm::dvec3 vector)
140{
141 LOG_DEBUG(logger_, "%s: (%f,%f,%f)", name, vector.x, vector.y, vector.z);
142}
143
144void Cogs::Core::TeleportNavigationComponent::postUpdate()
145{
146}
147
148void Cogs::Core::TeleportNavigationComponent::update()
149{
150 ViewContext* view = context->getDefaultView();
151 auto& input = view->inputManager;
152
153 if (!navigationTransform) {
154 navigationTransform = getComponent<TransformComponent>()->getComponentHandle<TransformComponent>();
155 }
156
157 auto destVis = destinationVisibility.resolveComponent<SceneComponent>();
158 auto destinationTransform = destinationMarker->getComponent<TransformComponent>();
159
160 bool pressed = input->getActionState(actionTeleport);
161
162 if (pressed)
163 {
164 //FIXME: Force camera system to update:
165 context->transformSystem->update(context);
166 context->cameraSystem->update(context);
167
168 //Keep raypicking while button down:
169 std::vector<RayPicking::RayPickHit> hits;
170 //We use a dummy camera to do the ray pick
171 auto beamCam = beam->getComponent<CameraComponent>();
172 auto size = beamCam->viewportSize;
173 context->rayPicking->pickCamera(context, *beamCam, 0.5f*size, std::numeric_limits<float>::max(), defaultPickingRadius, PickingFlags::None, PicksReturned::Closest, {}, hits);
174 if (!hits.empty()) {
175 destinationTransform->position = hits.front().position;
176 destinationTransform->coordinates = context->transformSystem->getOrigin();
177 destinationTransform->setChanged();
178 context->transformSystem->updateTransformData(*destinationTransform);
179
180 if (!destVis->visible) {
181 destVis->visible = true;
182 destVis->setChanged();
183 context->sceneSystem->updateState(*destVis);
184 }
185 }
186 else {
187 //Nothing was hit:
188 if (destVis->visible) {
189 destVis->visible = false;
190 destVis->setChanged();
191 context->sceneSystem->updateState(*destVis);
192 }
193 }
194
195 }
196 if (pressed != wasPressed) {
197 auto beamVis = beamVisibility.resolveComponent<SceneComponent>();
198 beamVis->visible = pressed;
199 beamVis->setChanged();
200 if (!pressed) {
201 //User released the teleport button, check if we should teleport:
202 if (destVis->visible) {
203 //we have a valid position:
204 destVis->visible = false;
205 destVis->setChanged();
206
207 auto pickedCoord = destinationTransform->position;
208
209 auto navTransform = navigationTransform.resolveComponent<TransformComponent>();
210 if (!useCoordinate) {
211 navTransform->position = pickedCoord;
212 }
213 else {
214 auto origin = context->transformSystem->getOrigin();
215 auto globalPickedPos = origin + glm::dvec3(pickedCoord);
216
217 glm::dvec3 newOrigin(globalPickedPos.x, globalPickedPos.y, 0);
218 glm::dvec3 newPosition = globalPickedPos - newOrigin;
219
220 logVector(logger, "origin", origin);
221 logVector(logger, "pickedCoord", pickedCoord);
222 logVector(logger, "globalPickedPos", globalPickedPos);
223 logVector(logger, "newOrigin", newOrigin);
224 logVector(logger, "newPosition", newPosition);
225
226 context->transformSystem->setOrigin(newOrigin);
227 navTransform->coordinates = newOrigin;
228 navTransform->position = glm::vec3(newPosition) + teleportOffset;
229 }
230 navTransform->setChanged();
231 context->transformSystem->updateTransformData(*navTransform);
232 }
233 }
234 }
235 wasPressed = pressed;
236}
void setChanged()
Sets the component to the ComponentFlags::Changed state with carry.
Definition: Component.h:202
ComponentType * getComponent() const
Definition: Component.h:159
ComponentHandle getComponentHandle() const
Definition: Component.h:177
glm::vec2 viewportSize
Size of the viewport covered by this instance, given in pixels.
ProjectionMode projectionMode
The projection mode to use for the camera.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
class EntityStore * store
Entity store.
Definition: Context.h:231
std::unique_ptr< class RayPicking > rayPicking
RayPicking service instance.
Definition: Context.h:213
ComponentModel::Component * addComponent(ComponentModel::Entity *entity, Reflection::TypeId typeId)
Add a component of the given type to the entity.
EntityPtr createChildEntity(const StringView &type, ComponentModel::Entity *parent, const StringView &name=StringView())
Create a new Entity, parenting it to the given parent.
EntityPtr findEntity(const StringView &name, const ComponentModel::Entity *root=nullptr, EntityFind findOptions=EntityFind::Default) const
Finds an entity with the given name.
Contains information on how the entity behaves in the scene.
bool visible
If the entity this component is a member of should be visible.
bool pickable
If the entity this component is a member of should be pickable.
Defines a 4x4 transformation matrix for the entity and a global offset for root entities.
glm::vec3 scale
Scale factor to apply to each of the axes.
glm::quat rotation
Rotation given as a quaternion.
glm::vec3 position
Local position relative to the global coordinates, or the parent coordinate system if the parent fiel...
void setOrigin(const glm::dvec3 &newOrigin)
Sets the Origin offset of the scene.
glm::dvec3 getOrigin() const
Gets the Origin offset of the scene.
void update(class Context *context) override
Updates the transform system.
void updateTransformData(const TransformComponent &component)
Force an update of the transform data associated with the given component.
std::unique_ptr< class InputManager > inputManager
Definition: ViewContext.h:78
Log implementation class.
Definition: LogManager.h:140
Field definition describing a single data member of a data structure.
Definition: Field.h:70
Simple method definition.
Definition: Method.h:72
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
std::shared_ptr< ComponentModel::Entity > EntityPtr
Smart pointer for Entity access.
Definition: EntityPtr.h:12
@ Closest
Return just the closest hit.
@ EnablePicking
Supports picking.
@ None
No flags specified,.
@ Perspective
Perspective projection.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:181
Contains reflection support.
Definition: Component.h:11
Exposes material properties for legacy entities and code.
Generates mesh data and assigns the generated mesh to a MeshComponent on the same entity.
Represents an unique name.
Definition: Name.h:70