Unravel Engine C++ Reference
Loading...
Searching...
No Matches
gizmo_entity.cpp
Go to the documentation of this file.
1#include "gizmo_entity.h"
2#include "gizmos.h"
3
5
11
15#include <hpp/type_name.hpp>
16#include <hpp/utility.hpp>
17
18namespace unravel
19{
20namespace
21{
22auto to_bx(const math::vec3& data) -> bx::Vec3
23{
24 return {data.x, data.y, data.z};
25}
26
27auto from_bx(const bx::Vec3& data) -> math::vec3
28{
29 return {data.x, data.y, data.z};
30}
31
32} // namespace
33
34void gizmo_entity::draw(rtti::context& ctx, entt::meta_any& var, const camera& cam, gfx::dd_raii& dd1)
35{
36 auto e = var.cast<entt::handle>();
37
38 if(!e || !e.all_of<transform_component>())
39 return;
40
41 auto& transform_comp = e.get<transform_component>();
42 const auto& world_transform = transform_comp.get_transform_global();
43
44 gfx::dd_raii dd(dd1.view);
45 if(e.all_of<camera_component>())
46 {
47 auto& selected_camera_comp = e.get<camera_component>();
48 auto& selected_camera = selected_camera_comp.get_camera();
49 const auto view_proj = selected_camera.get_view_projection();
50 const auto bounds = selected_camera.get_local_bounding_box();
52 dd.encoder.setColor(0xffffffff);
53 dd.encoder.setWireframe(true);
55 {
56 dd.encoder.drawFrustum(&view_proj);
57 }
58 else
59 {
60 bx::Aabb aabb;
61 aabb.min = to_bx(bounds.min);
62 aabb.max = to_bx(bounds.max);
63 dd.encoder.pushTransform((const float*)world_transform);
64 dd.encoder.draw(aabb);
66 }
67 }
68
69 if(e.all_of<light_component>())
70 {
71 const auto& light_comp = e.get<light_component>();
72 const auto& light = light_comp.get_light();
73
75 {
76 auto adjacent = light.spot_data.get_range();
77 {
78 auto tan_angle = math::tan(math::radians(light.spot_data.get_outer_angle() * 0.5f));
79 // oposite = tan * adjacent
80 auto oposite = tan_angle * adjacent;
82 dd.encoder.setColor(0xff00ff00);
83 dd.encoder.setWireframe(true);
84 dd.encoder.setLod(3);
85 math::vec3 from = transform_comp.get_position_global();
86 math::vec3 to = from + transform_comp.get_z_axis_local() * adjacent;
87 dd.encoder.drawCone(to_bx(to), to_bx(from), oposite);
88 }
89 {
90 auto tan_angle = math::tan(math::radians(light.spot_data.get_inner_angle() * 0.5f));
91 // oposite = tan * adjacent
92 auto oposite = tan_angle * adjacent;
94 dd.encoder.setColor(0xff00ffff);
95 dd.encoder.setWireframe(true);
96 dd.encoder.setLod(3);
97 math::vec3 from = transform_comp.get_position_global();
98 math::vec3 to = from + transform_comp.get_z_axis_local() * adjacent;
99 dd.encoder.drawCone(to_bx(to), to_bx(from), oposite);
100 }
101 }
102 else if(light.type == light_type::point)
103 {
104 auto radius = light.point_data.range;
106 dd.encoder.setColor(0xff00ff00);
107 dd.encoder.setWireframe(true);
108 math::vec3 center = transform_comp.get_position_global();
109 dd.encoder.drawCircle(Axis::X, center.x, center.y, center.z, radius);
110 dd.encoder.drawCircle(Axis::Y, center.x, center.y, center.z, radius);
111 dd.encoder.drawCircle(Axis::Z, center.x, center.y, center.z, radius);
112 }
114 {
116 dd.encoder.setLod(255);
117 dd.encoder.setColor(0xff00ff00);
118 dd.encoder.setWireframe(true);
119 math::vec3 from1 = transform_comp.get_position_global();
120 math::vec3 to1 = from1 + transform_comp.get_z_axis_local() * 1.0f;
121
122 bx::Cylinder cylinder = {to_bx(from1), to_bx(to1), 0.1f};
123
124 dd.encoder.draw(cylinder);
125 math::vec3 from2 = to1;
126 math::vec3 to2 = from2 + transform_comp.get_z_axis_local() * 0.5f;
127
128 bx::Cone cone = {to_bx(from2), to_bx(to2), 0.25f};
129 dd.encoder.draw(cone);
130 }
131 }
132
133 if(e.all_of<reflection_probe_component>())
134 {
135 const auto& probe_comp = e.get<reflection_probe_component>();
136 const auto& probe = probe_comp.get_probe();
137 if(probe.type == probe_type::box)
138 {
140 dd.encoder.setColor(0xff00ff00);
141 dd.encoder.setWireframe(true);
142 dd.encoder.pushTransform((const float*)world_transform);
143 bx::Aabb aabb;
144 aabb.min = to_bx(-probe.box_data.extents);
145 aabb.max = to_bx(probe.box_data.extents);
146
147 dd.encoder.draw(aabb);
149 }
150 else
151 {
152 auto radius = probe.get_face_extents(0, world_transform);
153 auto transform = world_transform;
154 transform.reset_scale();
155
157 dd.encoder.setColor(0xff00ff00);
158 dd.encoder.setWireframe(true);
159 dd.encoder.pushTransform((const float*)transform);
160 math::vec3 center{};
161 dd.encoder.drawCircle(Axis::X, center.x, center.y, center.z, radius);
162 dd.encoder.drawCircle(Axis::Y, center.x, center.y, center.z, radius);
163 dd.encoder.drawCircle(Axis::Z, center.x, center.y, center.z, radius);
164 }
165 }
166
167 // if(e.all_of<model_component>())
168 // {
169 // const auto& frustum = cam.get_frustum();
170 // const auto& model_comp = e.get<model_component>();
171
172 // // world bounds
173 // {
174 // auto world_bounds = model_comp.get_world_bounds();
175
176 // if(frustum.test_aabb(world_bounds))
177 // {
178 // DebugDrawEncoderScopePush scope(dd.encoder);
179 // dd.encoder.setColor(0xff00ffff);
180 // dd.encoder.setWireframe(true);
181 // bx::Aabb aabb;
182 // aabb.min = to_bx(world_bounds.min);
183 // aabb.max = to_bx(world_bounds.max);
184 // dd.encoder.draw(aabb);
185 // }
186 // }
187
188 // // local bounds
189 // {
190 // const auto& model = model_comp.get_model();
191 // if(!model.is_valid())
192 // {
193 // return;
194 // }
195
196 // const auto lod = model.get_lod(0);
197 // if(!lod)
198 // {
199 // return;
200 // }
201 // const auto& mesh = lod.get();
202 // const auto& bounds = mesh->get_bounds();
203 // // Test the bounding box of the mesh
204 // if(frustum.test_obb(bounds, world_transform))
205 // {
206 // DebugDrawEncoderScopePush scope(dd.encoder);
207 // dd.encoder.setColor(0xffffffff);
208 // dd.encoder.setWireframe(true);
209 // dd.encoder.pushTransform((const float*)world_transform);
210 // bx::Aabb aabb;
211 // aabb.min = to_bx(bounds.min);
212 // aabb.max = to_bx(bounds.max);
213 // dd.encoder.draw(aabb);
214 // dd.encoder.popTransform();
215 // }
216
217 // const auto& submeshes = model_comp.get_armature_entities();
218 // for(const auto& submesh : submeshes)
219 // {
220 // const auto& submesh_comp = submesh.try_get<submesh_component>();
221 // if(!submesh_comp)
222 // {
223 // continue;
224 // }
225 // const auto& submesh_transform_comp = submesh.get<transform_component>();
226 // const auto& submesh_transform = submesh_transform_comp.get_transform_global();
227 // DebugDrawEncoderScopePush scope(dd.encoder);
228 // dd.encoder.setColor(0xffaaaaaa);
229 // dd.encoder.setWireframe(true);
230 // for(const auto submesh_id : submesh_comp->submeshes)
231 // {
232 // const auto& submesh = mesh->get_submesh(submesh_id);
233
234 // if(frustum.test_obb(submesh.bbox, submesh_transform))
235 // {
236 // dd.encoder.pushTransform((const float*)submesh_transform);
237 // bx::Aabb aabb;
238 // aabb.min = to_bx(submesh.bbox.min);
239 // aabb.max = to_bx(submesh.bbox.max);
240 // dd.encoder.draw(aabb);
241 // dd.encoder.popTransform();
242 // }
243 // }
244 // }
245 // }
246 // }
247
248 if(e.all_of<text_component>())
249 {
250 const auto& frustum = cam.get_frustum();
251 const auto& text_comp = e.get<text_component>();
252
253 // world bounds
254 {
255 auto bbox = text_comp.get_bounds();
256
257 if(frustum.test_obb(bbox, world_transform))
258 {
260 dd.encoder.setColor(0xff00ffff);
261 dd.encoder.setWireframe(true);
262 dd.encoder.pushTransform((const float*)world_transform);
263 bx::Aabb aabb;
264 aabb.min = to_bx(bbox.min);
265 aabb.max = to_bx(bbox.max);
266 dd.encoder.draw(aabb);
268 }
269 }
270 }
271
272 hpp::for_each_tuple_type<all_inspectable_components>(
273 [&](auto index)
274 {
275 using ctype = std::tuple_element_t<decltype(index)::value, all_inspectable_components>;
276 auto component = e.try_get<ctype>();
277
278 if(!component)
279 {
280 return;
281 }
282
283 auto var_comp = entt::forward_as_meta(*component);
284 ::unravel::draw_gizmo_var(ctx, var_comp, cam, dd);
285 });
286}
287
288
289
290void gizmo_entity::draw_billboard(rtti::context& ctx, entt::meta_any& var, const camera& cam, gfx::dd_raii& dd)
291{
292 auto e = var.cast<entt::handle>();
293
294 if(!e || !e.all_of<transform_component>())
295 return;
296
297
298 auto& tm = ctx.get_cached<thumbnail_manager>();
299
300 auto& em = ctx.get_cached<editing_manager>();
301
302 auto& transform_comp = e.get<transform_component>();
303 const auto& world_transform = transform_comp.get_transform_global();
304
305 constexpr float MIN_VISIBLE_DISTANCE = 1.0f;
306 constexpr float MIN_FADE_RANGE = 0.5f;
307
308 constexpr float MAX_VISIBLE_DISTANCE = 50.0f;
309 constexpr float MAX_FADE_RANGE = 25.0f;
310
311 auto dist = math::distance(world_transform.get_position(), cam.get_position());
312
313 // Calculate distance-based alpha: full visibility in range (MIN_VISIBLE_DISTANCE - MAX_VISIBLE_DISTANCE), fade outside
314 float distance_alpha = 1.0f;
315 if(dist < MIN_VISIBLE_DISTANCE)
316 {
317 // Fade from 0 to 1 as distance goes from (MIN_VISIBLE_DISTANCE - MIN_FADE_RANGE) to MIN_VISIBLE_DISTANCE
318 float fade_start = MIN_VISIBLE_DISTANCE - MIN_FADE_RANGE;
319 distance_alpha = math::clamp((dist - fade_start) / MIN_FADE_RANGE, 0.0f, 1.0f);
320 }
321 else if(dist > MAX_VISIBLE_DISTANCE)
322 {
323 // Fade from 1 to 0 as distance goes from MAX_VISIBLE_DISTANCE to (MAX_VISIBLE_DISTANCE + MAX_FADE_RANGE)
324 distance_alpha = math::clamp(1.0f - (dist - MAX_VISIBLE_DISTANCE) / MAX_FADE_RANGE, 0.0f, 1.0f);
325 }
326 // else: dist is in range [MIN_VISIBLE_DISTANCE, MAX_VISIBLE_DISTANCE], keep distance_alpha = 1.0f
327
328 auto alpha = em.billboard_data.opacity * distance_alpha;
329
330 // Early return if completely transparent
331 if(alpha <= 0.0f)
332 return;
333
334 auto col = math::color::white();
335
336 float tint = 1.0f;
337 if(!transform_comp.is_active_global())
338 {
339 tint *= 0.5f;
340 }
341
342 auto icon = tm.get_gizmo_icon(e);
343
344 if(e.all_of<light_component>())
345 {
346 const auto& light_comp = e.get<light_component>();
347 const auto& light = light_comp.get_light();
348 col = light.color;
349 }
350
351 if(!cam.test_billboard(em.billboard_data.size, world_transform))
352 return; // completely outside → skip draw
353
354 if(icon)
355 {
356 dd.encoder.setState(em.billboard_data.depth_aware, false, false);
357
358 col.value.a = alpha;
359 col.value *= tint;
360 dd.encoder.setColor(col);
361
363 icon->native_handle(),
364 to_bx(world_transform.get_position()),
365 to_bx(cam.get_position()),
366 to_bx(cam.z_unit_axis()),
367 em.billboard_data.size);
368 dd.encoder.setColor(0xffffffff);
369
370 dd.encoder.setState(true, true, false);
371 }
372}
373} // namespace unravel
Class that contains core camera data, used for rendering and other purposes.
auto get_projection_mode() const -> projection_mode
Gets the projection mode.
auto get_camera() -> camera &
Gets the camera object.
Class representing a camera. Contains functionality for manipulating and updating a camera....
Definition camera.h:35
auto test_billboard(float size, const math::transform &t) const -> bool
Definition camera.cpp:453
auto z_unit_axis() const -> math::vec3
Retrieves the z-axis unit vector of the camera's local coordinate system.
Definition camera.cpp:360
auto get_position() const -> const math::vec3 &
Retrieves the current position of the camera.
Definition camera.cpp:346
auto get_frustum() const -> const math::frustum &
Retrieves the current camera object frustum.
Definition camera.cpp:365
Class that contains core light data, used for rendering and other purposes.
Class that contains core reflection probe data, used for rendering and other purposes.
auto get_probe() const -> const reflection_probe &
Gets the reflection probe object.
Component that handles transformations (position, rotation, scale, etc.) in the ACE framework.
auto get_transform_global() const noexcept -> const math::transform &
Gets the global transform.
const char * icon
void draw_billboard(DebugDrawEncoder &dd, bgfx::TextureHandle icon_texture, const bx::Vec3 &icon_center, const bx::Vec3 &camera_pos, const bx::Vec3 &camera_look_dir, float half_size)
Definition debugdraw.cpp:25
@ box
Box type reflection probe.
std::tuple< tag_component, layer_component, prefab_component, prefab_id_component, transform_component, test_component, model_component, animation_component, bone_component, submesh_component, camera_component, assao_component, tonemapping_component, fxaa_component, ssr_component, light_component, skylight_component, reflection_probe_component, physics_component, audio_source_component, audio_listener_component, text_component, ui_document_component > all_inspectable_components
void draw_gizmo_var(rtti::context &ctx, entt::meta_any &var, const camera &cam, gfx::dd_raii &dd)
Definition gizmos.cpp:39
auto to_bx(const glm::vec3 &data) -> bx::Vec3
Definition gizmos.cpp:7
@ X
Definition debugdraw.h:17
@ Y
Definition debugdraw.h:18
@ Z
Definition debugdraw.h:19
void draw(const bx::Aabb &_aabb)
void drawCone(const bx::Vec3 &_from, const bx::Vec3 &_to, float _radius)
void setColor(uint32_t _abgr)
void setWireframe(bool _wireframe)
void setState(bool _depthTest, bool _depthWrite, bool _clockwise, bool _alphaWrite=false, bool _alphaBlend=true)
void pushTransform(const void *_mtx)
void drawFrustum(const void *_viewProj)
void drawCircle(const bx::Vec3 &_normal, const bx::Vec3 &_center, float _radius, float _weight=0.0f)
void setLod(uint8_t _lod)
DebugDrawEncoder encoder
Definition debugdraw.h:15
view_id view
Definition debugdraw.h:16
static color white()
Definition math.h:287
auto get_cached() -> T &
Definition context.hpp:49
void draw_billboard(rtti::context &ctx, entt::meta_any &var, const camera &cam, gfx::dd_raii &dd) override
void draw(rtti::context &ctx, entt::meta_any &var, const camera &cam, gfx::dd_raii &dd) override
float range
The range of the point light.
Definition light.h:162
float get_range() const
Gets the range of the spot light.
Definition light.h:106
float get_outer_angle() const
Gets the outer angle of the spot light.
Definition light.h:121
float get_inner_angle() const
Gets the inner angle of the spot light.
Definition light.h:136
Struct representing a light.
Definition light.h:87
light_type type
The type of the light.
Definition light.h:89
math::color color
The color of the light.
Definition light.h:207
point point_data
Data specific to point lights.
Definition light.h:203
spot spot_data
Data specific to spot lights.
Definition light.h:201