107 lines
3.3 KiB
GDScript
107 lines
3.3 KiB
GDScript
extends RefCounted
|
|
## Low-Poly Bausteine aus Godot-Primitiven.
|
|
|
|
const Mat = preload("res://scripts/mat.gd")
|
|
|
|
const TRUNK := Color("6b4a2f")
|
|
const PINE := [Color("2f7a45"), Color("35894e"), Color("276b3c")]
|
|
const LEAF := [Color("58a844"), Color("e0932f"), Color("d8c33c"), Color("7cb85a")]
|
|
const ROCK := Color("8c8b86")
|
|
|
|
static func _mi(mesh: Mesh, color: Color, pos: Vector3) -> MeshInstance3D:
|
|
var m := MeshInstance3D.new()
|
|
m.mesh = mesh
|
|
m.material_override = Mat.flat(color)
|
|
m.position = pos
|
|
return m
|
|
|
|
static func cone(bottom_r: float, height: float, sides: int = 7) -> CylinderMesh:
|
|
var c := CylinderMesh.new()
|
|
c.top_radius = 0.0
|
|
c.bottom_radius = bottom_r
|
|
c.height = height
|
|
c.radial_segments = sides
|
|
c.rings = 1
|
|
return c
|
|
|
|
static func cyl(r: float, height: float, sides: int = 7) -> CylinderMesh:
|
|
var c := CylinderMesh.new()
|
|
c.top_radius = r
|
|
c.bottom_radius = r
|
|
c.height = height
|
|
c.radial_segments = sides
|
|
c.rings = 1
|
|
return c
|
|
|
|
static func box(size: Vector3) -> BoxMesh:
|
|
var b := BoxMesh.new()
|
|
b.size = size
|
|
return b
|
|
|
|
static func blob(r: float) -> SphereMesh:
|
|
var s := SphereMesh.new()
|
|
s.radius = r
|
|
s.height = r * 1.9
|
|
s.radial_segments = 7
|
|
s.rings = 4
|
|
return s
|
|
|
|
## Nadelbaum: Stamm + zwei bis drei Kegel-Etagen.
|
|
static func pine_tree(rng: RandomNumberGenerator) -> Node3D:
|
|
var n := Node3D.new()
|
|
var h := rng.randf_range(3.4, 6.2)
|
|
var col: Color = PINE[rng.randi() % PINE.size()]
|
|
n.add_child(_mi(cyl(0.18, h * 0.3, 6), TRUNK, Vector3(0, h * 0.15, 0)))
|
|
var tiers := 3 if h > 4.6 else 2
|
|
for i in tiers:
|
|
var f := float(i) / float(tiers)
|
|
var r := lerpf(h * 0.28, h * 0.13, f)
|
|
var th := h * 0.42
|
|
var y := h * 0.26 + f * h * 0.32 + th * 0.5
|
|
n.add_child(_mi(cone(r, th, 7), col, Vector3(0, y, 0)))
|
|
n.rotate_y(rng.randf() * TAU)
|
|
return n
|
|
|
|
## Laubbaum: Stamm + facettierte Krone.
|
|
static func round_tree(rng: RandomNumberGenerator) -> Node3D:
|
|
var n := Node3D.new()
|
|
var h := rng.randf_range(2.6, 4.4)
|
|
var col: Color = LEAF[rng.randi() % LEAF.size()]
|
|
n.add_child(_mi(cyl(0.16, h * 0.55, 6), TRUNK, Vector3(0, h * 0.275, 0)))
|
|
var r := h * 0.42
|
|
n.add_child(_mi(blob(r), col, Vector3(0, h * 0.55 + r * 0.55, 0)))
|
|
n.rotate_y(rng.randf() * TAU)
|
|
return n
|
|
|
|
static func rock(rng: RandomNumberGenerator) -> Node3D:
|
|
var n := Node3D.new()
|
|
var r := rng.randf_range(0.4, 1.1)
|
|
var m := _mi(blob(r), ROCK, Vector3(0, r * 0.35, 0))
|
|
m.scale = Vector3(1.0, rng.randf_range(0.4, 0.7), rng.randf_range(0.8, 1.2))
|
|
n.add_child(m)
|
|
n.rotate_y(rng.randf() * TAU)
|
|
return n
|
|
|
|
## Haus: Quader + Giebeldach (+ optionaler Schornstein).
|
|
static func house(wall: Color, roof: Color, w: float, d: float, h: float, chimney := false) -> Node3D:
|
|
var n := Node3D.new()
|
|
n.add_child(_mi(box(Vector3(w, h, d)), wall, Vector3(0, h * 0.5, 0)))
|
|
var p := PrismMesh.new()
|
|
p.size = Vector3(w * 1.14, h * 0.6, d * 1.06)
|
|
n.add_child(_mi(p, roof, Vector3(0, h + h * 0.3, 0)))
|
|
if chimney:
|
|
n.add_child(_mi(box(Vector3(w * 0.16, h * 0.7, w * 0.16)), roof.darkened(0.3),
|
|
Vector3(w * 0.25, h + h * 0.45, 0)))
|
|
# Kollision nur fuer die Aussenkamera, damit sie nicht durch Waende schaut
|
|
var body := StaticBody3D.new()
|
|
body.collision_layer = 2
|
|
body.collision_mask = 0
|
|
var shape := CollisionShape3D.new()
|
|
var bs := BoxShape3D.new()
|
|
bs.size = Vector3(w * 1.14, h * 1.6, d * 1.06)
|
|
shape.shape = bs
|
|
shape.position = Vector3(0, h * 0.8, 0)
|
|
body.add_child(shape)
|
|
n.add_child(body)
|
|
return n
|