OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / maps / shapes / param / param_hull.gd

55 lines · gd ref:
extends "res://scenes/maps/shapes/param/param_shape.gd"
## HULL — ANY BRUSH AS A PARAMETRIC SHAPE (#120 F2, docs/node-tree-and-stacks.md §3.1:
## "you should always be able to turn any brush into a parametric object").
##
## The identity generator: it emits the brush it was made from. Its planes are stored in
## the shape's UNIT box (0..1 on each axis of the shape's frame), so the shape's size
## stretches it like any other generator, and Make Real gives the brush back. Each plane
## keeps its own texture (face_tex, parallel to planes), so nothing the brush carried is
## lost. Both params are HIDDEN: data, not knobs (ParamShapes.rows skips them), and the
## create tool never offers this type (ParamShapes.ids).
##
## ⛔ VERSIONING as every generator: a change to the output is a new GV (ParamShape.GV,
## 1 here).


func id() -> String:
	return "hull"


func label() -> String:
	return "Hull"


func params() -> Array:
	return [
		{"id": "planes", "type": "planes", "default": [], "hidden": true,
			"tip": "n.x n.y n.z d per plane, n·u <= d, in the shape's unit box"},
		{"id": "face_tex", "type": "list", "default": [], "hidden": true,
			"tip": "one texture intent per plane (DCFaceTex shape), or empty"},
	]


## Unit-box planes -> the size box 0..size: u = x / size, so n·u <= d becomes
## (n / size)·x <= d, renormalised.
func local_pieces(size: Vector3, p: Dictionary) -> Array:
	var src: Array = p.get("planes", [])
	if src.size() < 16:                       # fewer than 4 planes encloses nothing
		return []
	var s := Vector3(maxf(size.x, 1.0e-6), maxf(size.y, 1.0e-6), maxf(size.z, 1.0e-6))
	var out := PackedFloat32Array()
	for i in range(0, src.size() - 3, 4):
		var n := Vector3(float(src[i]) / s.x, float(src[i + 1]) / s.y, float(src[i + 2]) / s.z)
		var l := n.length()
		if l < 1.0e-12:
			l = 1.0
		out.append(n.x / l)
		out.append(n.y / l)
		out.append(n.z / l)
		out.append(float(src[i + 3]) / l)
	var piece := {"planes": out, "edges": PackedVector3Array()}
	var ft: Array = p.get("face_tex", [])
	if ft.size() == out.size() / 4:
		piece["face_tex"] = ft.duplicate(true)
	return [piece]