Show visual-oriented 3D node gizmos only when selected

Affected nodes:

- DirectionalLight3D, OmniLight3D, SpotLight3D
- ReflectionProbe
- LightmapGI
- VoxelGI
- GPUParticles3D (but not collision/attractor nodes)
- AudioStreamPlayer3D

This reduces visual clutter in the editor with 3D scenes.
This commit is contained in:
Hugo Locurcio 2023-09-15 01:41:28 +02:00
parent b467afe65d
commit 1024ba0c0d
No known key found for this signature in database
GPG Key ID: 39E8F8BE30B0A49C
6 changed files with 367 additions and 352 deletions

View File

@ -121,136 +121,137 @@ void AudioStreamPlayer3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gi
}
void AudioStreamPlayer3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
const AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_node_3d());
p_gizmo->clear();
if (p_gizmo->is_selected()) {
const AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_node_3d());
if (player->get_attenuation_model() != AudioStreamPlayer3D::ATTENUATION_DISABLED || player->get_max_distance() > CMP_EPSILON) {
// Draw a circle to represent sound volume attenuation.
// Use only a billboard circle to represent radius.
// This helps distinguish AudioStreamPlayer3D gizmos from OmniLight3D gizmos.
const Ref<Material> lines_billboard_material = get_material("stream_player_3d_material_billboard", p_gizmo);
// Soft distance cap varies depending on attenuation model, as some will fade out more aggressively than others.
// Multipliers were empirically determined through testing.
float soft_multiplier;
switch (player->get_attenuation_model()) {
case AudioStreamPlayer3D::ATTENUATION_INVERSE_DISTANCE:
soft_multiplier = 12.0;
break;
case AudioStreamPlayer3D::ATTENUATION_INVERSE_SQUARE_DISTANCE:
soft_multiplier = 4.0;
break;
case AudioStreamPlayer3D::ATTENUATION_LOGARITHMIC:
soft_multiplier = 3.25;
break;
default:
// Ensures Max Distance's radius visualization is not capped by Unit Size
// (when the attenuation mode is Disabled).
soft_multiplier = 10000.0;
break;
}
// Draw the distance at which the sound can be reasonably heard.
// This can be either a hard distance cap with the Max Distance property (if set above 0.0),
// or a soft distance cap with the Unit Size property (sound never reaches true zero).
// When Max Distance is 0.0, `r` represents the distance above which the
// sound can't be heard in *most* (but not all) scenarios.
float r;
if (player->get_max_distance() > CMP_EPSILON) {
r = MIN(player->get_unit_size() * soft_multiplier, player->get_max_distance());
} else {
r = player->get_unit_size() * soft_multiplier;
}
Vector<Vector3> points_billboard;
for (int i = 0; i < 120; i++) {
// Create a circle.
const float ra = Math::deg_to_rad((float)(i * 3));
const float rb = Math::deg_to_rad((float)((i + 1) * 3));
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
// Draw a billboarded circle.
points_billboard.push_back(Vector3(a.x, a.y, 0));
points_billboard.push_back(Vector3(b.x, b.y, 0));
}
Color color;
switch (player->get_attenuation_model()) {
// Pick cold colors for all attenuation models (except Disabled),
// so that soft caps can be easily distinguished from hard caps
// (which use warm colors).
case AudioStreamPlayer3D::ATTENUATION_INVERSE_DISTANCE:
color = Color(0.4, 0.8, 1);
break;
case AudioStreamPlayer3D::ATTENUATION_INVERSE_SQUARE_DISTANCE:
color = Color(0.4, 0.5, 1);
break;
case AudioStreamPlayer3D::ATTENUATION_LOGARITHMIC:
color = Color(0.4, 0.2, 1);
break;
default:
// Disabled attenuation mode.
// This is never reached when Max Distance is 0, but the
// hue-inverted form of this color will be used if Max Distance is greater than 0.
color = Color(1, 1, 1);
break;
}
if (player->get_max_distance() > CMP_EPSILON) {
// Sound is hard-capped by max distance. The attenuation model still matters,
// so invert the hue of the color that was chosen above.
color.set_h(color.get_h() + 0.5);
}
p_gizmo->add_lines(points_billboard, lines_billboard_material, true, color);
}
if (player->is_emission_angle_enabled()) {
const float pc = player->get_emission_angle();
const float ofs = -Math::cos(Math::deg_to_rad(pc));
const float radius = Math::sin(Math::deg_to_rad(pc));
Vector<Vector3> points_primary;
points_primary.resize(200);
real_t step = Math_TAU / 100.0;
for (int i = 0; i < 100; i++) {
const float a = i * step;
const float an = (i + 1) * step;
const Vector3 from(Math::sin(a) * radius, Math::cos(a) * radius, ofs);
const Vector3 to(Math::sin(an) * radius, Math::cos(an) * radius, ofs);
points_primary.write[i * 2 + 0] = from;
points_primary.write[i * 2 + 1] = to;
}
const Ref<Material> material_primary = get_material("stream_player_3d_material_primary", p_gizmo);
p_gizmo->add_lines(points_primary, material_primary);
Vector<Vector3> points_secondary;
points_secondary.resize(16);
for (int i = 0; i < 8; i++) {
const float a = i * (Math_TAU / 8.0);
const Vector3 from(Math::sin(a) * radius, Math::cos(a) * radius, ofs);
points_secondary.write[i * 2 + 0] = from;
points_secondary.write[i * 2 + 1] = Vector3();
}
const Ref<Material> material_secondary = get_material("stream_player_3d_material_secondary", p_gizmo);
p_gizmo->add_lines(points_secondary, material_secondary);
Vector<Vector3> handles;
const float ha = Math::deg_to_rad(player->get_emission_angle());
handles.push_back(Vector3(Math::sin(ha), 0, -Math::cos(ha)));
p_gizmo->add_handles(handles, get_material("handles"));
}
}
const Ref<Material> icon = get_material("stream_player_3d_icon", p_gizmo);
if (player->get_attenuation_model() != AudioStreamPlayer3D::ATTENUATION_DISABLED || player->get_max_distance() > CMP_EPSILON) {
// Draw a circle to represent sound volume attenuation.
// Use only a billboard circle to represent radius.
// This helps distinguish AudioStreamPlayer3D gizmos from OmniLight3D gizmos.
const Ref<Material> lines_billboard_material = get_material("stream_player_3d_material_billboard", p_gizmo);
// Soft distance cap varies depending on attenuation model, as some will fade out more aggressively than others.
// Multipliers were empirically determined through testing.
float soft_multiplier;
switch (player->get_attenuation_model()) {
case AudioStreamPlayer3D::ATTENUATION_INVERSE_DISTANCE:
soft_multiplier = 12.0;
break;
case AudioStreamPlayer3D::ATTENUATION_INVERSE_SQUARE_DISTANCE:
soft_multiplier = 4.0;
break;
case AudioStreamPlayer3D::ATTENUATION_LOGARITHMIC:
soft_multiplier = 3.25;
break;
default:
// Ensures Max Distance's radius visualization is not capped by Unit Size
// (when the attenuation mode is Disabled).
soft_multiplier = 10000.0;
break;
}
// Draw the distance at which the sound can be reasonably heard.
// This can be either a hard distance cap with the Max Distance property (if set above 0.0),
// or a soft distance cap with the Unit Size property (sound never reaches true zero).
// When Max Distance is 0.0, `r` represents the distance above which the
// sound can't be heard in *most* (but not all) scenarios.
float r;
if (player->get_max_distance() > CMP_EPSILON) {
r = MIN(player->get_unit_size() * soft_multiplier, player->get_max_distance());
} else {
r = player->get_unit_size() * soft_multiplier;
}
Vector<Vector3> points_billboard;
for (int i = 0; i < 120; i++) {
// Create a circle.
const float ra = Math::deg_to_rad((float)(i * 3));
const float rb = Math::deg_to_rad((float)((i + 1) * 3));
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
// Draw a billboarded circle.
points_billboard.push_back(Vector3(a.x, a.y, 0));
points_billboard.push_back(Vector3(b.x, b.y, 0));
}
Color color;
switch (player->get_attenuation_model()) {
// Pick cold colors for all attenuation models (except Disabled),
// so that soft caps can be easily distinguished from hard caps
// (which use warm colors).
case AudioStreamPlayer3D::ATTENUATION_INVERSE_DISTANCE:
color = Color(0.4, 0.8, 1);
break;
case AudioStreamPlayer3D::ATTENUATION_INVERSE_SQUARE_DISTANCE:
color = Color(0.4, 0.5, 1);
break;
case AudioStreamPlayer3D::ATTENUATION_LOGARITHMIC:
color = Color(0.4, 0.2, 1);
break;
default:
// Disabled attenuation mode.
// This is never reached when Max Distance is 0, but the
// hue-inverted form of this color will be used if Max Distance is greater than 0.
color = Color(1, 1, 1);
break;
}
if (player->get_max_distance() > CMP_EPSILON) {
// Sound is hard-capped by max distance. The attenuation model still matters,
// so invert the hue of the color that was chosen above.
color.set_h(color.get_h() + 0.5);
}
p_gizmo->add_lines(points_billboard, lines_billboard_material, true, color);
}
if (player->is_emission_angle_enabled()) {
const float pc = player->get_emission_angle();
const float ofs = -Math::cos(Math::deg_to_rad(pc));
const float radius = Math::sin(Math::deg_to_rad(pc));
Vector<Vector3> points_primary;
points_primary.resize(200);
real_t step = Math_TAU / 100.0;
for (int i = 0; i < 100; i++) {
const float a = i * step;
const float an = (i + 1) * step;
const Vector3 from(Math::sin(a) * radius, Math::cos(a) * radius, ofs);
const Vector3 to(Math::sin(an) * radius, Math::cos(an) * radius, ofs);
points_primary.write[i * 2 + 0] = from;
points_primary.write[i * 2 + 1] = to;
}
const Ref<Material> material_primary = get_material("stream_player_3d_material_primary", p_gizmo);
p_gizmo->add_lines(points_primary, material_primary);
Vector<Vector3> points_secondary;
points_secondary.resize(16);
for (int i = 0; i < 8; i++) {
const float a = i * (Math_TAU / 8.0);
const Vector3 from(Math::sin(a) * radius, Math::cos(a) * radius, ofs);
points_secondary.write[i * 2 + 0] = from;
points_secondary.write[i * 2 + 1] = Vector3();
}
const Ref<Material> material_secondary = get_material("stream_player_3d_material_secondary", p_gizmo);
p_gizmo->add_lines(points_secondary, material_secondary);
Vector<Vector3> handles;
const float ha = Math::deg_to_rad(player->get_emission_angle());
handles.push_back(Vector3(Math::sin(ha), 0, -Math::cos(ha)));
p_gizmo->add_handles(handles, get_material("handles"));
}
p_gizmo->add_unscaled_billboard(icon, 0.05);
}

View File

@ -151,49 +151,50 @@ void GPUParticles3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo,
}
void GPUParticles3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_gizmo->get_node_3d());
p_gizmo->clear();
Vector<Vector3> lines;
AABB aabb = particles->get_visibility_aabb();
for (int i = 0; i < 12; i++) {
Vector3 a, b;
aabb.get_edge(i, a, b);
lines.push_back(a);
lines.push_back(b);
}
Vector<Vector3> handles;
for (int i = 0; i < 3; i++) {
Vector3 ax;
ax[i] = aabb.position[i] + aabb.size[i];
ax[(i + 1) % 3] = aabb.position[(i + 1) % 3] + aabb.size[(i + 1) % 3] * 0.5;
ax[(i + 2) % 3] = aabb.position[(i + 2) % 3] + aabb.size[(i + 2) % 3] * 0.5;
handles.push_back(ax);
}
Vector3 center = aabb.get_center();
for (int i = 0; i < 3; i++) {
Vector3 ax;
ax[i] = 1.0;
handles.push_back(center + ax);
lines.push_back(center);
lines.push_back(center + ax);
}
Ref<Material> material = get_material("particles_material", p_gizmo);
Ref<Material> icon = get_material("particles_icon", p_gizmo);
p_gizmo->add_lines(lines, material);
if (p_gizmo->is_selected()) {
GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_gizmo->get_node_3d());
Vector<Vector3> lines;
AABB aabb = particles->get_visibility_aabb();
for (int i = 0; i < 12; i++) {
Vector3 a, b;
aabb.get_edge(i, a, b);
lines.push_back(a);
lines.push_back(b);
}
Vector<Vector3> handles;
for (int i = 0; i < 3; i++) {
Vector3 ax;
ax[i] = aabb.position[i] + aabb.size[i];
ax[(i + 1) % 3] = aabb.position[(i + 1) % 3] + aabb.size[(i + 1) % 3] * 0.5;
ax[(i + 2) % 3] = aabb.position[(i + 2) % 3] + aabb.size[(i + 2) % 3] * 0.5;
handles.push_back(ax);
}
Vector3 center = aabb.get_center();
for (int i = 0; i < 3; i++) {
Vector3 ax;
ax[i] = 1.0;
handles.push_back(center + ax);
lines.push_back(center);
lines.push_back(center + ax);
}
Ref<Material> material = get_material("particles_material", p_gizmo);
p_gizmo->add_lines(lines, material);
Ref<Material> solid_material = get_material("particles_solid_material", p_gizmo);
p_gizmo->add_solid_box(solid_material, aabb.get_size(), aabb.get_center());
p_gizmo->add_handles(handles, get_material("handles"));
}
p_gizmo->add_handles(handles, get_material("handles"));
Ref<Material> icon = get_material("particles_icon", p_gizmo);
p_gizmo->add_unscaled_billboard(icon, 0.05);
}

View File

@ -158,124 +158,133 @@ void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
p_gizmo->clear();
if (Object::cast_to<DirectionalLight3D>(light)) {
Ref<Material> material = get_material("lines_primary", p_gizmo);
Ref<Material> icon = get_material("light_directional_icon", p_gizmo);
if (p_gizmo->is_selected()) {
Ref<Material> material = get_material("lines_primary", p_gizmo);
const int arrow_points = 7;
const float arrow_length = 1.5;
const int arrow_points = 7;
const float arrow_length = 1.5;
Vector3 arrow[arrow_points] = {
Vector3(0, 0, -1),
Vector3(0, 0.8, 0),
Vector3(0, 0.3, 0),
Vector3(0, 0.3, arrow_length),
Vector3(0, -0.3, arrow_length),
Vector3(0, -0.3, 0),
Vector3(0, -0.8, 0)
};
Vector3 arrow[arrow_points] = {
Vector3(0, 0, -1),
Vector3(0, 0.8, 0),
Vector3(0, 0.3, 0),
Vector3(0, 0.3, arrow_length),
Vector3(0, -0.3, arrow_length),
Vector3(0, -0.3, 0),
Vector3(0, -0.8, 0)
};
int arrow_sides = 2;
int arrow_sides = 2;
Vector<Vector3> lines;
Vector<Vector3> lines;
for (int i = 0; i < arrow_sides; i++) {
for (int j = 0; j < arrow_points; j++) {
Basis ma(Vector3(0, 0, 1), Math_PI * i / arrow_sides);
for (int i = 0; i < arrow_sides; i++) {
for (int j = 0; j < arrow_points; j++) {
Basis ma(Vector3(0, 0, 1), Math_PI * i / arrow_sides);
Vector3 v1 = arrow[j] - Vector3(0, 0, arrow_length);
Vector3 v2 = arrow[(j + 1) % arrow_points] - Vector3(0, 0, arrow_length);
Vector3 v1 = arrow[j] - Vector3(0, 0, arrow_length);
Vector3 v2 = arrow[(j + 1) % arrow_points] - Vector3(0, 0, arrow_length);
lines.push_back(ma.xform(v1));
lines.push_back(ma.xform(v2));
lines.push_back(ma.xform(v1));
lines.push_back(ma.xform(v2));
}
}
p_gizmo->add_lines(lines, material, false, color);
}
p_gizmo->add_lines(lines, material, false, color);
Ref<Material> icon = get_material("light_directional_icon", p_gizmo);
p_gizmo->add_unscaled_billboard(icon, 0.05, color);
}
if (Object::cast_to<OmniLight3D>(light)) {
// Use both a billboard circle and 3 non-billboard circles for a better sphere-like representation
const Ref<Material> lines_material = get_material("lines_secondary", p_gizmo);
const Ref<Material> lines_billboard_material = get_material("lines_billboard", p_gizmo);
const Ref<Material> icon = get_material("light_omni_icon", p_gizmo);
if (p_gizmo->is_selected()) {
// Use both a billboard circle and 3 non-billboard circles for a better sphere-like representation
const Ref<Material> lines_material = get_material("lines_secondary", p_gizmo);
const Ref<Material> lines_billboard_material = get_material("lines_billboard", p_gizmo);
OmniLight3D *on = Object::cast_to<OmniLight3D>(light);
const float r = on->get_param(Light3D::PARAM_RANGE);
Vector<Vector3> points;
Vector<Vector3> points_billboard;
OmniLight3D *on = Object::cast_to<OmniLight3D>(light);
const float r = on->get_param(Light3D::PARAM_RANGE);
Vector<Vector3> points;
Vector<Vector3> points_billboard;
for (int i = 0; i < 120; i++) {
// Create a circle
const float ra = Math::deg_to_rad((float)(i * 3));
const float rb = Math::deg_to_rad((float)((i + 1) * 3));
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
for (int i = 0; i < 120; i++) {
// Create a circle
const float ra = Math::deg_to_rad((float)(i * 3));
const float rb = Math::deg_to_rad((float)((i + 1) * 3));
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
// Draw axis-aligned circles
points.push_back(Vector3(a.x, 0, a.y));
points.push_back(Vector3(b.x, 0, b.y));
points.push_back(Vector3(0, a.x, a.y));
points.push_back(Vector3(0, b.x, b.y));
points.push_back(Vector3(a.x, a.y, 0));
points.push_back(Vector3(b.x, b.y, 0));
// Draw axis-aligned circles
points.push_back(Vector3(a.x, 0, a.y));
points.push_back(Vector3(b.x, 0, b.y));
points.push_back(Vector3(0, a.x, a.y));
points.push_back(Vector3(0, b.x, b.y));
points.push_back(Vector3(a.x, a.y, 0));
points.push_back(Vector3(b.x, b.y, 0));
// Draw a billboarded circle
points_billboard.push_back(Vector3(a.x, a.y, 0));
points_billboard.push_back(Vector3(b.x, b.y, 0));
// Draw a billboarded circle
points_billboard.push_back(Vector3(a.x, a.y, 0));
points_billboard.push_back(Vector3(b.x, b.y, 0));
}
p_gizmo->add_lines(points, lines_material, true, color);
p_gizmo->add_lines(points_billboard, lines_billboard_material, true, color);
Vector<Vector3> handles;
handles.push_back(Vector3(r, 0, 0));
p_gizmo->add_handles(handles, get_material("handles_billboard"), Vector<int>(), true);
}
p_gizmo->add_lines(points, lines_material, true, color);
p_gizmo->add_lines(points_billboard, lines_billboard_material, true, color);
const Ref<Material> icon = get_material("light_omni_icon", p_gizmo);
p_gizmo->add_unscaled_billboard(icon, 0.05, color);
Vector<Vector3> handles;
handles.push_back(Vector3(r, 0, 0));
p_gizmo->add_handles(handles, get_material("handles_billboard"), Vector<int>(), true);
}
if (Object::cast_to<SpotLight3D>(light)) {
const Ref<Material> material_primary = get_material("lines_primary", p_gizmo);
const Ref<Material> material_secondary = get_material("lines_secondary", p_gizmo);
const Ref<Material> icon = get_material("light_spot_icon", p_gizmo);
if (p_gizmo->is_selected()) {
const Ref<Material> material_primary = get_material("lines_primary", p_gizmo);
const Ref<Material> material_secondary = get_material("lines_secondary", p_gizmo);
Vector<Vector3> points_primary;
Vector<Vector3> points_secondary;
SpotLight3D *sl = Object::cast_to<SpotLight3D>(light);
Vector<Vector3> points_primary;
Vector<Vector3> points_secondary;
SpotLight3D *sl = Object::cast_to<SpotLight3D>(light);
float r = sl->get_param(Light3D::PARAM_RANGE);
float w = r * Math::sin(Math::deg_to_rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE)));
float d = r * Math::cos(Math::deg_to_rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE)));
float r = sl->get_param(Light3D::PARAM_RANGE);
float w = r * Math::sin(Math::deg_to_rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE)));
float d = r * Math::cos(Math::deg_to_rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE)));
for (int i = 0; i < 120; i++) {
// Draw a circle
const float ra = Math::deg_to_rad((float)(i * 3));
const float rb = Math::deg_to_rad((float)((i + 1) * 3));
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w;
for (int i = 0; i < 120; i++) {
// Draw a circle
const float ra = Math::deg_to_rad((float)(i * 3));
const float rb = Math::deg_to_rad((float)((i + 1) * 3));
const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w;
points_primary.push_back(Vector3(a.x, a.y, -d));
points_primary.push_back(Vector3(b.x, b.y, -d));
points_primary.push_back(Vector3(a.x, a.y, -d));
points_primary.push_back(Vector3(b.x, b.y, -d));
if (i % 15 == 0) {
// Draw 8 lines from the cone origin to the sides of the circle
points_secondary.push_back(Vector3(a.x, a.y, -d));
points_secondary.push_back(Vector3());
if (i % 15 == 0) {
// Draw 8 lines from the cone origin to the sides of the circle
points_secondary.push_back(Vector3(a.x, a.y, -d));
points_secondary.push_back(Vector3());
}
}
points_primary.push_back(Vector3(0, 0, -r));
points_primary.push_back(Vector3());
p_gizmo->add_lines(points_primary, material_primary, false, color);
p_gizmo->add_lines(points_secondary, material_secondary, false, color);
Vector<Vector3> handles = {
Vector3(0, 0, -r),
Vector3(w, 0, -d)
};
p_gizmo->add_handles(handles, get_material("handles"));
}
points_primary.push_back(Vector3(0, 0, -r));
points_primary.push_back(Vector3());
p_gizmo->add_lines(points_primary, material_primary, false, color);
p_gizmo->add_lines(points_secondary, material_secondary, false, color);
Vector<Vector3> handles = {
Vector3(0, 0, -r),
Vector3(w, 0, -d)
};
p_gizmo->add_handles(handles, get_material("handles"));
const Ref<Material> icon = get_material("light_spot_icon", p_gizmo);
p_gizmo->add_unscaled_billboard(icon, 0.05, color);
}
}

View File

@ -68,17 +68,17 @@ void LightmapGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
LightmapGI *baker = Object::cast_to<LightmapGI>(p_gizmo->get_node_3d());
Ref<LightmapGIData> data = baker->get_light_data();
p_gizmo->clear();
p_gizmo->add_unscaled_billboard(icon, 0.05);
if (data.is_null()) {
if (data.is_null() || !p_gizmo->is_selected()) {
return;
}
Ref<Material> material_lines = get_material("lightmap_lines", p_gizmo);
Ref<Material> material_probes = get_material("lightmap_probe_material", p_gizmo);
p_gizmo->clear();
Vector<Vector3> lines;
HashSet<Vector2i> lines_found;

View File

@ -151,55 +151,57 @@ void ReflectionProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo,
}
void ReflectionProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_node_3d());
p_gizmo->clear();
Vector<Vector3> lines;
Vector<Vector3> internal_lines;
Vector3 size = probe->get_size();
AABB aabb;
aabb.position = -size / 2;
aabb.size = size;
for (int i = 0; i < 12; i++) {
Vector3 a, b;
aabb.get_edge(i, a, b);
lines.push_back(a);
lines.push_back(b);
}
for (int i = 0; i < 8; i++) {
Vector3 ep = aabb.get_endpoint(i);
internal_lines.push_back(probe->get_origin_offset());
internal_lines.push_back(ep);
}
Vector<Vector3> handles = helper->box_get_handles(probe->get_size());
for (int i = 0; i < 3; i++) {
Vector3 orig_handle = probe->get_origin_offset();
orig_handle[i] -= 0.25;
lines.push_back(orig_handle);
handles.push_back(orig_handle);
orig_handle[i] += 0.5;
lines.push_back(orig_handle);
}
Ref<Material> material = get_material("reflection_probe_material", p_gizmo);
Ref<Material> material_internal = get_material("reflection_internal_material", p_gizmo);
Ref<Material> icon = get_material("reflection_probe_icon", p_gizmo);
p_gizmo->add_lines(lines, material);
p_gizmo->add_lines(internal_lines, material_internal);
if (p_gizmo->is_selected()) {
Ref<Material> solid_material = get_material("reflection_probe_solid_material", p_gizmo);
p_gizmo->add_solid_box(solid_material, probe->get_size());
ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_node_3d());
Vector<Vector3> lines;
Vector<Vector3> internal_lines;
Vector3 size = probe->get_size();
AABB aabb;
aabb.position = -size / 2;
aabb.size = size;
for (int i = 0; i < 12; i++) {
Vector3 a, b;
aabb.get_edge(i, a, b);
lines.push_back(a);
lines.push_back(b);
}
for (int i = 0; i < 8; i++) {
Vector3 ep = aabb.get_endpoint(i);
internal_lines.push_back(probe->get_origin_offset());
internal_lines.push_back(ep);
}
Vector<Vector3> handles = helper->box_get_handles(probe->get_size());
for (int i = 0; i < 3; i++) {
Vector3 orig_handle = probe->get_origin_offset();
orig_handle[i] -= 0.25;
lines.push_back(orig_handle);
handles.push_back(orig_handle);
orig_handle[i] += 0.5;
lines.push_back(orig_handle);
}
Ref<Material> material = get_material("reflection_probe_material", p_gizmo);
Ref<Material> material_internal = get_material("reflection_internal_material", p_gizmo);
p_gizmo->add_lines(lines, material);
p_gizmo->add_lines(internal_lines, material_internal);
if (p_gizmo->is_selected()) {
Ref<Material> solid_material = get_material("reflection_probe_solid_material", p_gizmo);
p_gizmo->add_solid_box(solid_material, probe->get_size());
}
p_gizmo->add_handles(handles, get_material("handles"));
}
Ref<Material> icon = get_material("reflection_probe_icon", p_gizmo);
p_gizmo->add_unscaled_billboard(icon, 0.05);
p_gizmo->add_handles(handles, get_material("handles"));
}

View File

@ -100,74 +100,76 @@ void VoxelGIGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_i
}
void VoxelGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_node_3d());
Ref<Material> material = get_material("voxel_gi_material", p_gizmo);
Ref<Material> icon = get_material("voxel_gi_icon", p_gizmo);
Ref<Material> material_internal = get_material("voxel_gi_internal_material", p_gizmo);
p_gizmo->clear();
Vector<Vector3> lines;
Vector3 size = probe->get_size();
if (p_gizmo->is_selected()) {
VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_node_3d());
Ref<Material> material = get_material("voxel_gi_material", p_gizmo);
Ref<Material> material_internal = get_material("voxel_gi_internal_material", p_gizmo);
static const int subdivs[VoxelGI::SUBDIV_MAX] = { 64, 128, 256, 512 };
Vector<Vector3> lines;
Vector3 size = probe->get_size();
AABB aabb = AABB(-size / 2, size);
int subdiv = subdivs[probe->get_subdiv()];
float cell_size = aabb.get_longest_axis_size() / subdiv;
static const int subdivs[VoxelGI::SUBDIV_MAX] = { 64, 128, 256, 512 };
for (int i = 0; i < 12; i++) {
Vector3 a, b;
aabb.get_edge(i, a, b);
lines.push_back(a);
lines.push_back(b);
}
AABB aabb = AABB(-size / 2, size);
int subdiv = subdivs[probe->get_subdiv()];
float cell_size = aabb.get_longest_axis_size() / subdiv;
p_gizmo->add_lines(lines, material);
for (int i = 0; i < 12; i++) {
Vector3 a, b;
aabb.get_edge(i, a, b);
lines.push_back(a);
lines.push_back(b);
}
lines.clear();
p_gizmo->add_lines(lines, material);
for (int i = 1; i < subdiv; i++) {
for (int j = 0; j < 3; j++) {
if (cell_size * i > aabb.size[j]) {
continue;
}
lines.clear();
int j_n1 = (j + 1) % 3;
int j_n2 = (j + 2) % 3;
for (int k = 0; k < 4; k++) {
Vector3 from = aabb.position, to = aabb.position;
from[j] += cell_size * i;
to[j] += cell_size * i;
if (k & 1) {
to[j_n1] += aabb.size[j_n1];
} else {
to[j_n2] += aabb.size[j_n2];
for (int i = 1; i < subdiv; i++) {
for (int j = 0; j < 3; j++) {
if (cell_size * i > aabb.size[j]) {
continue;
}
if (k & 2) {
from[j_n1] += aabb.size[j_n1];
from[j_n2] += aabb.size[j_n2];
}
int j_n1 = (j + 1) % 3;
int j_n2 = (j + 2) % 3;
lines.push_back(from);
lines.push_back(to);
for (int k = 0; k < 4; k++) {
Vector3 from = aabb.position, to = aabb.position;
from[j] += cell_size * i;
to[j] += cell_size * i;
if (k & 1) {
to[j_n1] += aabb.size[j_n1];
} else {
to[j_n2] += aabb.size[j_n2];
}
if (k & 2) {
from[j_n1] += aabb.size[j_n1];
from[j_n2] += aabb.size[j_n2];
}
lines.push_back(from);
lines.push_back(to);
}
}
}
p_gizmo->add_lines(lines, material_internal);
Vector<Vector3> handles = helper->box_get_handles(probe->get_size());
if (p_gizmo->is_selected()) {
Ref<Material> solid_material = get_material("voxel_gi_solid_material", p_gizmo);
p_gizmo->add_solid_box(solid_material, aabb.get_size());
}
p_gizmo->add_handles(handles, get_material("handles"));
}
p_gizmo->add_lines(lines, material_internal);
Vector<Vector3> handles = helper->box_get_handles(probe->get_size());
if (p_gizmo->is_selected()) {
Ref<Material> solid_material = get_material("voxel_gi_solid_material", p_gizmo);
p_gizmo->add_solid_box(solid_material, aabb.get_size());
}
Ref<Material> icon = get_material("voxel_gi_icon", p_gizmo);
p_gizmo->add_unscaled_billboard(icon, 0.05);
p_gizmo->add_handles(handles, get_material("handles"));
}