Placing blueprinted meshes

This commit is contained in:
2025-11-20 22:38:31 +01:00
parent 24ce1edb38
commit 94e33c0cba

View File

@ -1,16 +1,20 @@
class_name ProceduralPiece extends StructuralPiece
# For a strut: Start Point, End Point
# For a plate: 3 or 4 vertices
@export var vertices: Array[Vector3] = []:
set(value):
vertices = value
_generate_geometry()
@export var vertices: Array[Vector3] = []
@export var thickness: float = 0.02
@export var thickness: float = 0.1
# This is inherited from StructuralPiece, but we use the setter to update visuals
# var is_preview: bool (Inherited)
func _ready():
# If data has vertices (from the Resource), use them.
if structure_data and structure_data.vertices.size() > 0:
vertices = structure_data.vertices
# Or if configured procedurally
# elif structure_data and structure_data.procedural_params:
# _configure_from_data()
func on_structure_data_update():
vertices = structure_data.vertices
if not vertices.is_empty():
_generate_geometry()
@ -60,12 +64,6 @@ func configure_plate(points: Array[Vector3]):
_generate_geometry()
func _generate_geometry():
if vertices.is_empty(): return
print("Generating geometry for ProceduralPiece with vertices:")
print(vertices)
# Clear existing meshes
for c in get_children():
if c is MeshInstance3D or c is CollisionShape3D:
c.queue_free()
@ -103,38 +101,109 @@ func _build_strut_mesh():
add_child(col)
func _build_plate_mesh():
# Use SurfaceTool to build a polygon
var st = SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_TRIANGLES)
# Assume points are coplanar and ordered
var normal = (vertices[1] - vertices[0]).cross(vertices[2] - vertices[0]).normalized()
# We assume the vertices are on the XY plane (Z=0) for simplicity of extrusion logic.
# If your vertices have varying Z, you'd need to calculate the face normal first.
# For plates defined in the resource, Z is 0.
# Simple Fan Triangulation (works for convex shapes)
for i in range(1, vertices.size() - 1):
st.set_normal(normal)
st.add_vertex(vertices[0])
st.set_normal(normal)
st.add_vertex(vertices[i])
st.set_normal(normal)
st.add_vertex(vertices[i + 1])
var half_thick = thickness / 2.0
var top_verts = []
var bottom_verts = []
# Generate offset vertices
# Assuming "Forward" / Thickness direction is -Z (Standard Godot Back)
# Actually, let's align thickness along Local Z axis.
for v in vertices:
top_verts.append(Vector3(v.x, v.y, half_thick)) # Front Face (+Z)
bottom_verts.append(Vector3(v.x, v.y, -half_thick)) # Back Face (-Z)
# --- 1. Top Face (Front) ---
var normal_top = Vector3.BACK # +Z in Godot is Back, but usually front face points to +Z
# Wait, Godot coordinate system: -Z is Forward.
# Let's say +Z is "Top" of the plate relative to its local space.
# Fan Triangulation for Convex Shape
for i in range(1, top_verts.size() - 1):
st.set_normal(Vector3.BACK) # +Z
st.add_vertex(top_verts[0])
st.add_vertex(top_verts[i])
st.add_vertex(top_verts[i+1])
# Backface
st.set_normal(-normal)
st.add_vertex(vertices[i + 1])
st.set_normal(-normal)
st.add_vertex(vertices[i])
st.set_normal(-normal)
st.add_vertex(vertices[0])
# --- 2. Bottom Face (Back) ---
for i in range(1, bottom_verts.size() - 1):
st.set_normal(Vector3.FORWARD) # -Z
# Winding order reversed for back face
st.add_vertex(bottom_verts[0])
st.add_vertex(bottom_verts[i+1])
st.add_vertex(bottom_verts[i])
# --- 3. Side Faces ---
# Connect Top[i] to Bottom[i] around the perimeter
for i in range(vertices.size()):
var next_i = (i + 1) % vertices.size()
var v1 = top_verts[i]
var v2 = top_verts[next_i]
var v3 = bottom_verts[next_i]
var v4 = bottom_verts[i]
# Calculate side normal
var side_vec = (v2 - v1).normalized()
var up_vec = Vector3.BACK # +Z
var normal = side_vec.cross(up_vec).normalized() # Points outward
st.set_normal(normal)
# Quad = 2 Triangles
# Tri 1: v1, v2, v4
st.add_vertex(v1)
st.add_vertex(v2)
st.add_vertex(v4)
# Tri 2: v2, v3, v4
st.add_vertex(v2)
st.add_vertex(v3)
st.add_vertex(v4)
var mesh_inst = MeshInstance3D.new()
mesh_inst.mesh = st.commit()
# Apply Blueprint Material if Preview
_apply_material(mesh_inst)
add_child(mesh_inst)
# Collision (Convex)
# For collision, we just feed ALL the points (top and bottom) to the convex hull generator.
var col = CollisionShape3D.new()
var shape = ConvexPolygonShape3D.new()
shape.points = vertices
# Extrude slightly for thickness? Or just use flat collision for plates.
var all_points = top_verts.duplicate()
all_points.append_array(bottom_verts)
shape.points = all_points
col.shape = shape
add_child(col)
func _apply_material(mesh_inst: MeshInstance3D):
var mat = StandardMaterial3D.new()
if is_preview:
mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
mat.albedo_color = Color(0.2, 0.6, 1.0, 0.4) # Semi-transparent Blue
mat.emission_enabled = true
mat.emission = Color(0.2, 0.6, 1.0)
mat.emission_energy_multiplier = 1.0
mat.cull_mode = BaseMaterial3D.CULL_DISABLED # See inside
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED # Glowy
else:
mat.albedo_color = Color(0.5, 0.5, 0.5) # Concrete/Metal Grey
mat.metallic = 0.5
mat.roughness = 0.5
mesh_inst.material_override = mat
# Override the parent's update function to use our specific material logic
func _update_preview_visuals():
for child in get_children():
if child is MeshInstance3D:
_apply_material(child)