Skip to content

Commit

Permalink
Added chamfered cube and bent plane to 3D preview
Browse files Browse the repository at this point in the history
  • Loading branch information
RodZill4 committed Oct 17, 2024
1 parent f4be794 commit 855b270
Show file tree
Hide file tree
Showing 8 changed files with 370 additions and 132 deletions.
13 changes: 12 additions & 1 deletion material_maker/panels/preview_3d/mesh_config_popup.gd
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,18 @@ func configure_mesh(m : MeshInstance3D) -> void:
if mesh.can_tesselate:
$VBoxContainer/Tesselated.button_pressed = mesh.tesselated
else:
$VBoxContainer/Tesselated.disabled = true
$VBoxContainer/Tesselated.visible = false
for p in mesh.parameters:
var label : Label = Label.new()
label.text = (p.label if p.has("label") else p.name)+":"
%Parameters.add_child(label)
var float_edit = preload("res://material_maker/widgets/float_edit/float_edit.tscn").instantiate()
float_edit.float_only = true
float_edit.min_value = p.min_value
float_edit.max_value = p.max_value
float_edit.value = mesh.parameter_values[p.name]
%Parameters.add_child(float_edit)
float_edit.value_changed.connect(mesh.set_parameter.bind(p.name))
popup(Rect2(get_mouse_position(), $VBoxContainer.get_minimum_size()))

func _on_MeshConfiguration_popup_hide():
Expand Down
57 changes: 17 additions & 40 deletions material_maker/panels/preview_3d/mesh_config_popup.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,32 @@
[ext_resource type="Script" path="res://material_maker/panels/preview_3d/mesh_config_popup.gd" id="2"]

[node name="MeshConfiguration" type="PopupPanel"]
offset_right = 284.0
offset_bottom = 127.0
size = Vector2i(217, 101)
visible = true
script = ExtResource("2")
__meta__ = {
"_edit_use_anchors_": false
}

[node name="VBoxContainer" type="VBoxContainer" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 4.0
offset_top = 4.0
offset_right = -4.0
offset_bottom = -4.0
__meta__ = {
"_edit_use_anchors_": false
}
offset_right = 213.0
offset_bottom = 97.0

[node name="Panel" type="PanelContainer" parent="VBoxContainer"]
offset_right = 276.0
offset_bottom = 28.0
layout_mode = 2

[node name="Label" type="Label" parent="VBoxContainer/Panel"]
offset_left = 77.0
offset_top = 7.0
offset_right = 199.0
offset_bottom = 21.0
layout_mode = 2
size_flags_horizontal = 4
text = "Mesh configuration"
__meta__ = {
"_edit_use_anchors_": false
}

[node name="UVScale" type="HBoxContainer" parent="VBoxContainer"]
offset_top = 32.0
offset_right = 276.0
offset_bottom = 56.0
layout_mode = 2

[node name="Label" type="Label" parent="VBoxContainer/UVScale"]
offset_top = 5.0
offset_right = 59.0
offset_bottom = 19.0
layout_mode = 2
tooltip_text = "The texture's display scale on the 3D preview.
Higher values will make the texture span a smaller area.
The texture will repeat automatically to cover the whole mesh.
Expand All @@ -54,36 +38,29 @@ mouse_filter = 1
text = "UV Scale:"

[node name="X" parent="VBoxContainer/UVScale" instance=ExtResource("1")]
anchor_left = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
offset_left = 63.0
offset_right = 121.0
offset_bottom = 24.0
layout_mode = 2
value = 1.0
max_value = 5.0
step = 0.01
float_only = true

[node name="Y" parent="VBoxContainer/UVScale" instance=ExtResource("1")]
anchor_left = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
offset_left = 125.0
offset_right = 183.0
offset_bottom = 24.0
layout_mode = 2
value = 1.0
max_value = 5.0
step = 0.01
float_only = true

[node name="Tesselated" type="CheckBox" parent="VBoxContainer"]
offset_top = 60.0
offset_right = 276.0
offset_bottom = 84.0
layout_mode = 2
tooltip_text = "If tesselation is enabled, the mesh will be subdivided, which is necessary for materials that use vertex displacement."
text = "Tesselated"

[node name="Parameters" type="GridContainer" parent="VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
columns = 2

[connection signal="popup_hide" from="." to="." method="_on_MeshConfiguration_popup_hide"]
[connection signal="value_changed" from="VBoxContainer/UVScale/X" to="." method="_on_UV_value_changed"]
[connection signal="value_changed" from="VBoxContainer/UVScale/Y" to="." method="_on_UV_value_changed"]
Expand Down
6 changes: 3 additions & 3 deletions material_maker/panels/preview_3d/preview_3d.gd
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,12 @@ func set_rotate_model_speed(speed: float) -> void:
object_rotate.play("rotate")

func get_materials() -> Array:
if current_object != null and current_object.get_surface_override_material(0) != null:
return [ current_object.get_surface_override_material(0) ]
if current_object != null and current_object.get_material() != null:
return [ current_object.get_material() ]
return []

func on_dep_update_value(_buffer_name, parameter_name, value) -> bool:
var preview_material = current_object.get_surface_override_material(0)
var preview_material = current_object.get_material()
preview_material.set_shader_parameter(parameter_name, value)
return false

Expand Down
12 changes: 1 addition & 11 deletions material_maker/panels/preview_3d/preview_3d_panel.tscn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[gd_scene load_steps=10 format=3 uid="uid://cj6b1r8b6jel3"]
[gd_scene load_steps=7 format=3 uid="uid://cj6b1r8b6jel3"]

[ext_resource type="PackedScene" uid="uid://dpaxvlnn2u1f6" path="res://material_maker/panels/preview_3d/preview_3d.tscn" id="1"]
[ext_resource type="PackedScene" uid="uid://brlp703awvxbn" path="res://material_maker/panels/preview_3d/preview_3d_ui.tscn" id="2"]
Expand Down Expand Up @@ -26,17 +26,7 @@ shader = SubResource("1")
shader_parameter/aabb_position = null
shader_parameter/aabb_size = null

[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_40ogr"]

[sub_resource type="Sky" id="Sky_wye7d"]
sky_material = SubResource("PanoramaSkyMaterial_40ogr")

[sub_resource type="Environment" id="Environment_qxxdb"]
background_mode = 2
sky = SubResource("Sky_wye7d")

[sub_resource type="World3D" id="World3D_3xlky"]
environment = SubResource("Environment_qxxdb")

[node name="Preview3D" instance=ExtResource("1")]
custom_minimum_size = Vector2(250, 200)
Expand Down
2 changes: 1 addition & 1 deletion material_maker/panels/preview_3d/preview_3d_scene.tscn
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[gd_scene load_steps=7 format=3 uid="uid://dpulty2lkvcht"]

[ext_resource type="PackedScene" path="res://material_maker/panels/preview_3d/preview_objects.tscn" id="2"]
[ext_resource type="PackedScene" uid="uid://cxcw0mi4sfl2x" path="res://material_maker/panels/preview_3d/preview_objects.tscn" id="2"]

[sub_resource type="Animation" id="3"]
tracks/0/type = "value"
Expand Down
89 changes: 49 additions & 40 deletions material_maker/panels/preview_3d/preview_mesh.gd
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,42 @@ extends MeshInstance3D
@export var uv_scale : Vector2 = Vector2(1, 1): set = set_uv_scale
@export var tesselated : bool = false: set = set_tesselated

@export var parameters : Array = []
var parameter_values : Dictionary = {}

var material : Material


func _ready():
var m : ShaderMaterial = ShaderMaterial.new()
m.shader = Shader.new()
set_surface_override_material(0, m)
m.set_shader_parameter("uv1_scale", Vector3(uv_scale.x, uv_scale.y, 1))
material = ShaderMaterial.new()
material.shader = Shader.new()
material.set_shader_parameter("uv1_scale", Vector3(uv_scale.x, uv_scale.y, 1))
for p in parameters:
if not parameter_values.has(p.name):
parameter_values[p.name] = p.default_value
update_mesh.call_deferred()

func get_material() -> Material:
update_mesh()
set_surface_override_material(0, material)
return material

func set_uv_scale(s : Vector2) -> void:
if s != uv_scale:
uv_scale = s
var material = get_surface_override_material(0)
print(material)
if material != null:
if material is StandardMaterial3D:
material.uv1_scale.x = uv_scale.x
material.uv1_scale.y = uv_scale.y
elif material is ShaderMaterial:
material.set_shader_parameter("uv1_scale", Vector3(uv_scale.x, uv_scale.y, 1))

func set_parameter(v : float, n : String) -> void:
if parameter_values[n] != v:
parameter_values[n] = v
update_mesh()

func set_tesselated(t : bool) -> void:
var new_tesselated = t && can_tesselate
if new_tesselated == tesselated:
Expand All @@ -39,40 +56,32 @@ func set_tesselated(t : bool) -> void:
func update_mesh() -> void:
if mesh == null:
return
var subdivide = 0
var radial_segments = 64
var cylinder_rings = 1
var sphere_rings = 32
if tesselated:
var tesselation_detail: int = mm_globals.main_window.preview_tesselation_detail
match mesh.get_class():
"BoxMesh", "PrismMesh":
mesh.subdivide_width = tesselation_detail
mesh.subdivide_height = tesselation_detail
mesh.subdivide_depth = tesselation_detail
"PlaneMesh":
mesh.subdivide_width = tesselation_detail
mesh.subdivide_depth = tesselation_detail
"CylinderMesh":
mesh.radial_segments = tesselation_detail
mesh.rings = tesselation_detail
"SphereMesh":
mesh.radial_segments = tesselation_detail
mesh.rings = round(tesselation_detail * 0.5)
_:
push_error("Unknown tesselated mesh type: %s" % mesh.get_class())
else:
match mesh.get_class():
"BoxMesh", "PrismMesh":
mesh.subdivide_width = 0
mesh.subdivide_height = 0
mesh.subdivide_depth = 0
"PlaneMesh":
mesh.subdivide_width = 0
mesh.subdivide_depth = 0
"CylinderMesh":
mesh.radial_segments = 64
mesh.rings = 1
"SphereMesh":
mesh.radial_segments = 64
mesh.rings = 32
"ArrayMesh":
pass
_:
push_error("Unknown non-tesselated mesh type: %s" % mesh.get_class())
subdivide = tesselation_detail
radial_segments = tesselation_detail
cylinder_rings = tesselation_detail
sphere_rings = round(tesselation_detail * 0.5)
match mesh.get_class():
"BoxMesh", "PrismMesh":
mesh.subdivide_width = subdivide
mesh.subdivide_height = subdivide
mesh.subdivide_depth = subdivide
"PlaneMesh":
mesh.subdivide_width = subdivide
mesh.subdivide_depth = subdivide
"CylinderMesh":
mesh.radial_segments = radial_segments
mesh.rings = cylinder_rings
"SphereMesh":
mesh.radial_segments = radial_segments
mesh.rings = sphere_rings
"ArrayMesh":
pass
_:
push_error("Unknown non-tesselated mesh type: %s" % mesh.get_class())
set_surface_override_material(0, material)
76 changes: 76 additions & 0 deletions material_maker/panels/preview_3d/preview_mesh_generated.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
extends "res://material_maker/panels/preview_3d/preview_mesh.gd"


@export_multiline var compute_shader : String
@export var vertex_count_expression : String
@export var index_count_expression : String


static var shader : MMComputeShader = MMComputeShader.new()
static var shader_string : String = ""
static var shader_size : int = 0


func _ready():
super._ready()
can_tesselate = false

func get_expression_value_from_string(expression_string : String, values: Dictionary) -> int:
var expression : Expression = Expression.new()
var input_names : PackedStringArray = PackedStringArray()
var input_values : Array = []
for k in values.keys():
input_names.append(k)
input_values.append(values[k])
expression.parse(expression_string, input_names)
var rv : int = expression.execute(input_values)
return rv

func do_update_mesh() -> void:
var size : int = mm_globals.main_window.preview_tesselation_detail
if size != shader_size or compute_shader != shader_string:
print("Updating mesh generation compute shader")
var vertex_count : int = get_expression_value_from_string(vertex_count_expression, { size=size} )
var index_count : int = get_expression_value_from_string(index_count_expression, { size=size} )
shader.local_size = size if size < 32 else 32
shader.clear()
shader.add_parameter_or_texture("size", "int", size)
for p in parameters:
shader.add_parameter_or_texture(p.name, "float", p.default_value)
shader.add_output_parameter("vertices", "float", 3*vertex_count)
shader.add_output_parameter("normals", "float", 3*vertex_count)
shader.add_output_parameter("tangents", "float", 4*vertex_count)
shader.add_output_parameter("tex_uvs", "float", 2*vertex_count)
shader.add_output_parameter("indexes", "int", index_count)
await shader.set_shader_ext(compute_shader)
shader_size = size
shader_string = compute_shader
print("Running mesh generation compute shader")
var opv : Dictionary = { vertices_format="vec3", normals_format="vec3", tex_uvs_format="vec2" }
shader.set_parameter("size", size)
for p in parameters:
shader.set_parameter(p.name, parameter_values[p.name])
await shader.render_ext([], Vector2i(size, size), opv)
mesh.clear_surfaces()
var flags : int = Mesh.ARRAY_FORMAT_VERTEX | Mesh.ARRAY_FORMAT_NORMAL | Mesh.ARRAY_FORMAT_TEX_UV | Mesh.ARRAY_FORMAT_INDEX
var vertices : PackedVector3Array = opv.vertices
var normals : PackedVector3Array = opv.normals
var tangents : PackedFloat32Array = opv.tangents
var tex_uvs : PackedVector2Array = opv.tex_uvs
var indexes : PackedInt32Array = opv.indexes
var arrays : Array = [vertices, normals, tangents, null, tex_uvs, null, null, null, null, null, null, null, indexes]
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLE_STRIP, arrays, [], {}, flags)
set_surface_override_material(0, material)

var need_update : bool = false
static var updating : bool = false

func update_mesh() -> void:
need_update = true
if updating:
return
while need_update:
need_update = false
updating = true
await do_update_mesh()
updating = false
Loading

0 comments on commit 855b270

Please sign in to comment.