Placing blueprinted meshes
This commit is contained in:
@ -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)
|
||||
Reference in New Issue
Block a user