finish heat map shader

This commit is contained in:
Nitwel 2024-04-07 14:17:52 +02:00
parent c0dccc8401
commit 586ea20d1a
5 changed files with 80 additions and 33 deletions

View File

@ -4,8 +4,10 @@
[sub_resource type="Gradient" id="Gradient_2jwis"]
interpolation_color_space = 2
offsets = PackedFloat32Array(0.00280112, 1)
colors = PackedColorArray(0, 0.558935, 0.886772, 1, 0.999396, 0, 0.058647, 1)
offsets = PackedFloat32Array(0.00840336, 0.1, 0.4375, 0.5625, 1)
colors = PackedColorArray(0.533333, 0, 1, 1, 0, 0.45, 1, 1, 0, 0.95, 1, 1, 0.983333, 1, 0, 1, 0.999396, 0, 0.058647, 1)
metadata/_snap_enabled = true
metadata/_snap_count = 16
[sub_resource type="GradientTexture1D" id="GradientTexture1D_rrsal"]
gradient = SubResource("Gradient_2jwis")
@ -15,5 +17,5 @@ render_priority = 0
shader = ExtResource("1_sbr3e")
shader_parameter/data = PackedFloat32Array()
shader_parameter/data_size = 0
shader_parameter/min_max_data = null
shader_parameter/alpha = 0.3
shader_parameter/color_gradient = SubResource("GradientTexture1D_rrsal")

View File

@ -3,32 +3,55 @@ render_mode blend_mix, depth_draw_opaque, cull_disabled, diffuse_lambert, specul
uniform vec4 data[100];
uniform int data_size: hint_range(0, 100, 1);
uniform vec2 min_max_data;
uniform float alpha: hint_range(0.0, 1.0, 0.1) = 0.3;
uniform sampler2D color_gradient;
varying vec3 color;
float simple_weight(int index, vec3 world_pos, float p) {
return 1.0 / pow(distance(data[index].xyz, world_pos), p);
}
float sphere_weight(int index, vec3 world_pos, float r) {
float dist = distance(data[index].xyz, world_pos);
return pow(max(0, r - dist) / (r * dist), 2);
}
void vertex() {
// Calculate Global Coordinates
vec3 world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
color = vec3(1.0, 1.0, 1.0);
vec2 distances[100];
float distances[100];
float dist_sum = 0.0;
float data_sum = 0.0;
float closest_dist = -1.0;
int closest_index = 0;
if(data_size > 0) {
for(int i = 0; i < data_size; i++) {
float delta = 1.0 / distance(data[i].xyz, world_position);
closest_dist = distance(data[0].xyz, world_position);
distances[i] = vec2(delta, data[i].w);
dist_sum += delta;
// Inverse distance weighting using Shepard's method
for(int i = 0; i < data_size; i++) {
distances[i] = sphere_weight(i, world_position, 5.0);
dist_sum += distances[i];
data_sum += distances[i] * data[i].w;
float dist = distance(data[i].xyz, world_position);
if(dist < closest_dist) {
closest_dist = dist;
closest_index = i;
}
}
for(int i = 0; i < data_size; i++) {
float average = distances[i].x / dist_sum * distances[i].y;
color.xyz = texture(color_gradient, vec2(average, 0)).xyz;
float value = (1.0 / dist_sum) * data_sum;
if( value > 0.0 || value < 1.0) {
color.xyz = texture(color_gradient, vec2(value, 0)).xyz;
} else {
color.xyz = texture(color_gradient, vec2(data[closest_index].w, 0)).xyz;
}
}
}

View File

@ -3,11 +3,14 @@ extends Node3D
const ConstructRoomMesh = preload ("res://lib/utils/mesh/construct_room_mesh.gd")
const wall_material = preload ("./mini_wall.tres")
@onready var walls_mesh = $WallsMesh
@onready var floor_mesh = $FloorMesh
@onready var collision_shape = $CollisionShape3D
@onready var walls_mesh = $Body/Model/WallsMesh
@onready var floor_mesh = $Body/Model/FloorMesh
@onready var collision_shape = $Body/CollisionShape3D
@onready var toggle_heatmap = $HeatmapButton
# var temperature_scale := Vector2( - 20.0, 60.0)
var temperature_scale := Vector2(22.0, 25.0)
var enabled = true:
set(value):
enabled = value
@ -19,6 +22,9 @@ func _ready():
if Store.house.is_loaded() == false:
await Store.house.on_loaded
if Store.house.rooms.size() == 0:
return
var room = Store.house.rooms[0]
var corners = room.corners
@ -31,7 +37,7 @@ func _ready():
floor_mesh.material_override = wall_material
active = true
update_data(0.0)
EventSystem.on_slow_tick.connect(update_data)
toggle_heatmap.on_button_down.connect(func():
active=true
@ -56,7 +62,6 @@ var active: bool = false
func update_data(delta: float) -> void:
var data_list = []
var min_max_data
for room in House.body.get_rooms(0):
for entity in room.get_node("Entities").get_children():
@ -68,17 +73,14 @@ func update_data(delta: float) -> void:
var sensor_pos = sensor.global_position
if min_max_data == null:
min_max_data = Vector2(float(data), float(data))
else:
min_max_data.x = min(min_max_data.x, float(data))
min_max_data.y = max(min_max_data.y, float(data))
data_list.append(Vector4(sensor_pos.x, sensor_pos.y, sensor_pos.z, float(data)))
for data in data_list:
data.w = (data.w - min_max_data.x) / (min_max_data.y - min_max_data.x)
data_list = data_list.map(func(data: Vector4) -> Vector4:
data.w=(data.w - temperature_scale.x) / (temperature_scale.y - temperature_scale.x)
return data
)
print(data_list)
wall_material.set_shader_parameter("data", data_list)
wall_material.set_shader_parameter("min_max_data", min_max_data)
wall_material.set_shader_parameter("data_size", data_list.size())

View File

@ -6,19 +6,24 @@
[sub_resource type="BoxShape3D" id="BoxShape3D_bckw3"]
[node name="Miniature" type="StaticBody3D"]
[node name="Miniature" type="Node3D"]
script = ExtResource("1_b53yn")
[node name="WallsMesh" type="MeshInstance3D" parent="."]
[node name="HeatmapButton" parent="." instance=ExtResource("3_tgdcf")]
toggleable = true
[node name="FloorMesh" type="MeshInstance3D" parent="."]
[node name="Body" type="StaticBody3D" parent="."]
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
[node name="CollisionShape3D" type="CollisionShape3D" parent="Body"]
shape = SubResource("BoxShape3D_bckw3")
[node name="Movable" type="Node" parent="."]
[node name="Movable" type="Node" parent="Body"]
script = ExtResource("2_x7oed")
[node name="HeatmapButton" parent="." instance=ExtResource("3_tgdcf")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.25, 0.5, 0.48)
toggleable = true
[node name="Model" type="Node3D" parent="Body"]
[node name="WallsMesh" type="MeshInstance3D" parent="Body/Model"]
skeleton = NodePath("../../..")
[node name="FloorMesh" type="MeshInstance3D" parent="Body/Model"]
skeleton = NodePath("../../..")

View File

@ -127,6 +127,21 @@ static func generate_ceiling_mesh_grid(corners, grid: Vector2=Vector2(0.1, 0.1))
var size = max_val - min_val
# Subdivide edges to grid
for i in range(corners.size()):
var corner = corners[i]
var next_index = (i + 1) % corners.size()
var next_corner = corners[next_index]
var steps = ceil(Vector2((next_corner - corner).length() / grid.x, size.y / grid.y))
var forward_dir = (next_corner - corner).normalized() * grid.x
for x in range(1, steps.x):
var point = corner + forward_dir * x
points.append(Vector2(point.x, point.y))
## Fill points insde the polygon
for y in range(1, int(size.y / grid.y)):
var x_intersections: Array[float] = []