update
This commit is contained in:
@@ -1,10 +1,76 @@
|
||||
extends RefCounted
|
||||
## Formen aus Regeln: jedes Ding hat eine Grundform aus Godot-Primitiven, und
|
||||
## Regeln setzen Teile darauf - Rand, Bänder, Reifen, Kappe. Kanten sind
|
||||
## schmale Ringe statt Fasen. Kein Mesh kommt aus einer Datei.
|
||||
## Formen aus Regeln. Der Kern des Low-Poly-Looks sind runde Kanten: jede
|
||||
## Form wird als Profil (Radius, Höhe) beschrieben und um die Achse gedreht.
|
||||
## Fasen sind Viertelkreise im Profil. Kein Mesh kommt aus einer Datei.
|
||||
## Kein class_name: den Klassencache baut nur der Editor, headless fehlt er.
|
||||
|
||||
const Stoffe = preload("res://scripts/stoffe.gd")
|
||||
const FASE_SEG := 4 ## Punkte je Viertelkreis - vier reichen bei glatten Normalen
|
||||
|
||||
|
||||
## Ein Profil um die Y-Achse drehen. `profil` läuft von unten (Achse) nach
|
||||
## oben (Achse), Punkte sind (radius, höhe). Glatte Normalen, damit die
|
||||
## Fasen weich wirken und nicht wie Absätze.
|
||||
static func drehen(profil: PackedVector2Array, segmente := 40) -> ArrayMesh:
|
||||
var st := SurfaceTool.new()
|
||||
st.begin(Mesh.PRIMITIVE_TRIANGLES)
|
||||
st.set_smooth_group(0)
|
||||
for i in range(profil.size() - 1):
|
||||
var a := profil[i]
|
||||
var b := profil[i + 1]
|
||||
for k in segmente:
|
||||
var t0 := TAU * float(k) / segmente
|
||||
var t1 := TAU * float(k + 1) / segmente
|
||||
var p00 := Vector3(cos(t0) * a.x, a.y, sin(t0) * a.x)
|
||||
var p10 := Vector3(cos(t1) * a.x, a.y, sin(t1) * a.x)
|
||||
var p01 := Vector3(cos(t0) * b.x, b.y, sin(t0) * b.x)
|
||||
var p11 := Vector3(cos(t1) * b.x, b.y, sin(t1) * b.x)
|
||||
if a.x > 0.0001:
|
||||
st.add_vertex(p00)
|
||||
st.add_vertex(p10)
|
||||
st.add_vertex(p01)
|
||||
if b.x > 0.0001:
|
||||
st.add_vertex(p10)
|
||||
st.add_vertex(p11)
|
||||
st.add_vertex(p01)
|
||||
st.index()
|
||||
st.generate_normals()
|
||||
return st.commit()
|
||||
|
||||
|
||||
## Viertelkreis von `von` nach `bis` um die Ecke `mitte` (Profilkoordinaten).
|
||||
static func _bogen(mitte: Vector2, r: float, a0: float, a1: float) -> PackedVector2Array:
|
||||
var out := PackedVector2Array()
|
||||
for k in range(1, FASE_SEG + 1):
|
||||
var t := lerpf(a0, a1, float(k) / FASE_SEG)
|
||||
out.append(mitte + Vector2(cos(t), sin(t)) * r)
|
||||
return out
|
||||
|
||||
|
||||
## Zylinder oder Kegelstumpf mit runden Kanten oben und unten.
|
||||
static func rund_zylinder(r_unten: float, r_oben: float, hoehe: float, fase: float) -> ArrayMesh:
|
||||
fase = minf(fase, minf(hoehe * 0.5, minf(r_unten, r_oben) * 0.9))
|
||||
var p := PackedVector2Array()
|
||||
p.append(Vector2(0.0, 0.0))
|
||||
p.append(Vector2(r_unten - fase, 0.0))
|
||||
p.append_array(_bogen(Vector2(r_unten - fase, fase), fase, -PI * 0.5, 0.0))
|
||||
p.append_array(_bogen(Vector2(r_oben - fase, hoehe - fase), fase, 0.0, PI * 0.5))
|
||||
p.append(Vector2(0.0, hoehe))
|
||||
return drehen(p)
|
||||
|
||||
|
||||
static func scheibe(radius: float, hoehe: float, fase: float) -> ArrayMesh:
|
||||
return rund_zylinder(radius, radius, hoehe, fase)
|
||||
|
||||
|
||||
## Ring mit rundem Querschnitt - für Ränder und Bänder.
|
||||
static func ring(radius: float, dicke: float) -> TorusMesh:
|
||||
var t := TorusMesh.new()
|
||||
t.inner_radius = radius - dicke
|
||||
t.outer_radius = radius + dicke
|
||||
t.rings = 40
|
||||
t.ring_segments = 10
|
||||
return t
|
||||
|
||||
|
||||
static func _teil(mesh: Mesh, stoff: Material, pos: Vector3, eltern: Node3D) -> MeshInstance3D:
|
||||
@@ -16,65 +82,31 @@ static func _teil(mesh: Mesh, stoff: Material, pos: Vector3, eltern: Node3D) ->
|
||||
return mi
|
||||
|
||||
|
||||
static func _zylinder(oben: float, unten: float, hoehe: float, segmente := 28) -> CylinderMesh:
|
||||
var c := CylinderMesh.new()
|
||||
c.top_radius = oben
|
||||
c.bottom_radius = unten
|
||||
c.height = hoehe
|
||||
c.radial_segments = segmente
|
||||
return c
|
||||
|
||||
|
||||
static func _ring(radius: float, dicke: float) -> TorusMesh:
|
||||
var t := TorusMesh.new()
|
||||
t.inner_radius = radius - dicke
|
||||
t.outer_radius = radius + dicke
|
||||
t.rings = 32
|
||||
t.ring_segments = 8
|
||||
return t
|
||||
|
||||
|
||||
## Würfelbecher: Kegelstumpf aus dunklem Holz, oben ein Messingrand, zwei
|
||||
## Messingbänder um den Bauch. Der Deckel oben ist geschlossen - die Kamera
|
||||
## schaut von oben, ein offener Becher zeigte nur ein schwarzes Loch.
|
||||
## Würfelbecher: Kegelstumpf mit runden Kanten, oben ein Messingrand, ein
|
||||
## Band um den Bauch. Geschlossen - die Kamera schaut von oben.
|
||||
static func becher(hoehe := 0.44, oben := 0.33, unten := 0.42) -> Node3D:
|
||||
var n := Node3D.new()
|
||||
_teil(_zylinder(oben, unten, hoehe), Stoffe.holz_dunkel(), Vector3(0, hoehe * 0.5, 0), n)
|
||||
_teil(_ring(oben, 0.012), Stoffe.messing(), Vector3(0, hoehe - 0.004, 0), n)
|
||||
for k in [0.22, 0.62]:
|
||||
var r: float = lerpf(unten, oben, k)
|
||||
_teil(_ring(r, 0.008), Stoffe.messing(), Vector3(0, hoehe * k, 0), n)
|
||||
_teil(rund_zylinder(unten, oben, hoehe, 0.05), Stoffe.holz_dunkel(), Vector3.ZERO, n)
|
||||
_teil(ring(oben - 0.01, 0.018), Stoffe.messing(), Vector3(0, hoehe - 0.02, 0), n)
|
||||
_teil(ring(lerpf(unten, oben, 0.35) + 0.004, 0.012), Stoffe.messing(), Vector3(0, hoehe * 0.35, 0), n)
|
||||
return n
|
||||
|
||||
|
||||
## Fass: bauchiger Zylinder, drei Reifen, Boden und Deckel etwas kleiner.
|
||||
static func fass(hoehe := 0.6, radius := 0.24) -> Node3D:
|
||||
var n := Node3D.new()
|
||||
_teil(_zylinder(radius * 0.86, radius * 0.86, hoehe), Stoffe.holz(), Vector3(0, hoehe * 0.5, 0), n)
|
||||
_teil(_zylinder(radius, radius, hoehe * 0.5), Stoffe.holz(), Vector3(0, hoehe * 0.5, 0), n)
|
||||
for k in [0.12, 0.5, 0.88]:
|
||||
var r: float = radius if absf(k - 0.5) < 0.2 else radius * 0.88
|
||||
_teil(_ring(r, 0.012), Stoffe.messing(), Vector3(0, hoehe * k, 0), n)
|
||||
return n
|
||||
|
||||
|
||||
## Laterne: Sockel, Glaskörper (leuchtend), Kappe mit Ring.
|
||||
## Laterne: Sockel, leuchtendes Glas, Kappe, Bügel.
|
||||
static func laterne(hoehe := 0.5) -> Node3D:
|
||||
var n := Node3D.new()
|
||||
_teil(_zylinder(0.09, 0.11, 0.05), Stoffe.messing(), Vector3(0, 0.025, 0), n)
|
||||
var glas := StandardMaterial3D.new()
|
||||
glas.albedo_color = Color(1.0, 0.85, 0.5, 0.75)
|
||||
glas.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
|
||||
_teil(rund_zylinder(0.11, 0.09, 0.05, 0.015), Stoffe.messing(), Vector3.ZERO, n)
|
||||
var glas := Stoffe.eigene("glas")
|
||||
glas.emission_enabled = true
|
||||
glas.emission = Color(1.0, 0.75, 0.35)
|
||||
glas.emission_energy_multiplier = 2.5
|
||||
_teil(_zylinder(0.07, 0.08, hoehe * 0.6), glas, Vector3(0, 0.05 + hoehe * 0.3, 0), n)
|
||||
_teil(_zylinder(0.03, 0.10, 0.08), Stoffe.messing(), Vector3(0, 0.05 + hoehe * 0.6 + 0.04, 0), n)
|
||||
_teil(_ring(0.035, 0.006), Stoffe.messing(), Vector3(0, 0.05 + hoehe * 0.6 + 0.10, 0), n)
|
||||
glas.emission = Color(1.0, 0.80, 0.40)
|
||||
glas.emission_energy_multiplier = 1.6
|
||||
_teil(rund_zylinder(0.08, 0.07, hoehe * 0.6, 0.02), glas, Vector3(0, 0.05, 0), n)
|
||||
_teil(rund_zylinder(0.10, 0.03, 0.08, 0.015), Stoffe.messing(), Vector3(0, 0.05 + hoehe * 0.6, 0), n)
|
||||
_teil(ring(0.035, 0.007), Stoffe.messing(), Vector3(0, 0.05 + hoehe * 0.6 + 0.10, 0), n)
|
||||
var licht := OmniLight3D.new()
|
||||
licht.light_color = Color(1.0, 0.8, 0.45)
|
||||
licht.light_energy = 1.2
|
||||
licht.omni_range = 1.8
|
||||
licht.light_color = Color(1.0, 0.85, 0.55)
|
||||
licht.light_energy = 0.8
|
||||
licht.omni_range = 1.6
|
||||
licht.position = Vector3(0, 0.05 + hoehe * 0.3, 0)
|
||||
n.add_child(licht)
|
||||
return n
|
||||
|
||||
Reference in New Issue
Block a user