Add item pile object.

This commit is contained in:
Nekojimi 2025-05-12 11:21:38 +01:00
parent 3fa58bc6df
commit b682981a26
3 changed files with 150 additions and 0 deletions

52
objects/ItemPile.tscn Normal file

File diff suppressed because one or more lines are too long

97
scripts/item_pile.gd Normal file
View File

@ -0,0 +1,97 @@
@tool
extends StaticBody3D
@export var item: Item:
set(val):
item = val
if !is_node_ready(): await ready
$Props.multimesh.mesh = item.model
$Cone.material_override = item.model.surface_get_material(0)
@export var count: int = 10:
set(val):
count = val
update()
@export var item_volume: float = 0.2:
set(val):
item_volume = val
item_radius = pow(item_volume,1.0/3.0)
update()
@export var item_radius: float = 0.0:
set(val):
item_radius = val
item_volume = pow(item_radius, 3.0)
update()
@export_range(0,60) var slope_angle: float = 45:
set(val):
slope_angle = val
slope_ratio = cos(deg_to_rad(slope_angle)) / sin(deg_to_rad(slope_angle))
print("slope ratio: %f" % slope_ratio)
update()
var slope_ratio: float = 1.0
@onready var cone: MeshInstance3D = $Cone
@onready var props: MultiMeshInstance3D = $Props
@onready var collision_shape: CollisionShape3D = $CollisionShape3D
func _ready() -> void:
props.multimesh = props.multimesh.duplicate()
func update() -> void:
var volume: float = count * item_volume
var three_v_over_pi: float = (3 * volume) / PI
var height: float = pow(three_v_over_pi, 1.0/3.0) / pow(slope_ratio, 2.0/3.0)
var radius: float = height * slope_ratio
var v: float = (1.0/3.0) * PI * pow(radius,2) * height
assert(is_equal_approx(v,volume))
cone.scale = Vector3(radius,height,radius)
cone.position.y = height/2.0
var slope_length: float = Vector2(radius,height).length()
var ring_count: int = ceili(slope_length / (item_radius*2))
var positions: PackedVector3Array = []
var angle: float = 0.0
for ring in range(ring_count):
#var perc: float = ring/float(ring_count-1)
var slope_l: float = ring * (item_radius * 2)
var ring_y: float = height-( sin(deg_to_rad(slope_angle)) * slope_l )
var ring_radius: float = cos(deg_to_rad(slope_angle)) * slope_l
var ring_circ: float = ring_radius * TAU
var ring_item_count: int = ceili(ring_circ / (item_radius*2))
if ring_item_count == 0:
ring_item_count = 1
var ring_angle_offset: float = TAU / ring_item_count
for i in range(ring_item_count):
angle += ring_angle_offset
#var angle: float = ring_angle_offset * i
var x: float = cos(angle) * ring_radius
var z: float = sin(angle) * ring_radius
var pos: Vector3 = Vector3(x,ring_y,z)
positions.append(pos)
props.multimesh.instance_count = positions.size()
for i in range(positions.size()):
#DebugDraw3D.draw_sphere(positions[i], item_radius, Color.RED, 0.1)
#var y_rot: float = randf() * TAU
var y_rot: float = 0
props.multimesh.set_instance_transform(i, Transform3D(Basis(Vector3.UP,y_rot),positions[i]))
props.multimesh.visible_instance_count = min(count, positions.size())
#print("Rings: %d, Items: %d" % [ring_count, positions.size()])
#var surface_item_count: int = ceil(pow(count, 2.0/3.0))
#props.multimesh.instance_count = ceil(surface_item_count)
#var theta: float = chord_offset / distance_offset
#for i in range(surface_item_count):
#var away: float = distance_offset * theta
#var around: float = theta + 0
#var x: float = cos(around) * away
#var z: float = sin(around) * away
#var y: float = height - (away * slope_ratio)
#var trans: Transform3D = Transform3D(Basis(), Vector3(x,y,z))
#props.multimesh.set_instance_transform(i,trans)
#theta += chord_offset / away

1
scripts/item_pile.gd.uid Normal file
View File

@ -0,0 +1 @@
uid://b742u7cr6efqm