nx_creaturegen.nx source
↩ module page · 474 lines · 28441 B
1// nx_creaturegen.nx -- ★SOVEREIGN INFINIGEN: procedural ANIMALS. Reuses the SAME layered-anatomy method as the
2// human head (nx_anatstack: skeleton -> muscle -> skin envelope), generalized to a seed-parametric QUADRUPED body
3// plan -- skull+snout, neck, spine, ribcage, pelvis, tail, four (upper+lower+foot) legs, + shoulder/haunch/belly
4// muscles. The skin EMERGES as the smooth-union envelope + dermal offset (not eyeballed). Seeded proportions
5// (body/leg/neck length, head/tail size, build) -> different creatures (dog-ish, deer-ish, ...). Renders via the
6// shared anatstack ray-marcher. No ML, no assets. license_tier: ORIGINAL
7import "nx_anatstack.nx"
8const K_MAGIC_6364136223846793005: i64 = 6364136223846793005
9const K_MAGIC_1442695040888963407: i64 = 1442695040888963407
10const K_MAGIC_2147483647: i64 = 2147483647
11const K_MAGIC_4096: i64 = 4096
12const K_MAGIC_65536: i64 = 65536
13const K_MAGIC_2654435761: i64 = 2654435761
14const K_MAGIC_40503: i64 = 40503
15const K_MAGIC_90001: i64 = 90001
16const K_MAGIC_1013904223: i64 = 1013904223
17const CGB_ROWS: i64 = 2
18const CGB_KIND_SONGBIRD: i64 = 1
19const CG_PLAN_GULL: i64 = 3
20
21func cg_next(st: *i64) -> i64 { var h: i64=st[0]; h=h*K_MAGIC_6364136223846793005+K_MAGIC_1442695040888963407; st[0]=h; return (h>>33)&K_MAGIC_2147483647 }
22func cg_range(st: *i64, lo: i64, hi: i64) -> i64 { return lo + cg_next(st) % (hi-lo+1) }
23
24// ★R9 ARTICULATION: forward kinematics for a 2-bone leg in the sagittal (Y-Z) plane. thigh rotates the WHOLE
25// leg about the hip; shin bends the knee (the lower bone only). angles it4096; 0 = straight down. Fills
26// out[0..2]=knee, out[3..5]=foot. This is the FK the census demands: parent joint moves the subtree, child
27// joint moves only its descendants.
28func cg_fk_leg(hipx: i64, hipy: i64, hipz: i64, thigh: i64, shin: i64, L1: i64, L2: i64, out: *i64) -> i64 {
29 let ct1: i64 = it_cos4096(thigh)
30 let st1: i64 = it_sin4096(thigh)
31 let kneeY: i64 = hipy - L1*ct1/K_MAGIC_4096
32 let kneeZ: i64 = hipz + L1*st1/K_MAGIC_4096
33 let a2: i64 = thigh + shin
34 let ct2: i64 = it_cos4096(a2)
35 let st2: i64 = it_sin4096(a2)
36 out[0]=hipx; out[1]=kneeY; out[2]=kneeZ
37 out[3]=hipx; out[4]=kneeY - L2*ct2/K_MAGIC_4096; out[5]=kneeZ + L2*st2/K_MAGIC_4096
38 return 0
39}
40// place a POSED 2-bone leg (upper hip->knee + lower knee->foot + hoof) from FK.
41func cg_leg_posed(P: *i64, i: i64, hipx: i64, hipy: i64, hipz: i64, thigh: i64, shin: i64, L1: i64, L2: i64, r: i64) -> i64 {
42 let fk: *i64 = sys_mmap(8*8) as *i64
43 cg_fk_leg(hipx, hipy, hipz, thigh, shin, L1, L2, fk)
44 var n: i64 = i
45 n = as_caps(P, n, hipx, hipy, hipz, fk[0], fk[1], fk[2], r, AS_BONE)
46 n = as_fuzz_last(P, n)
47 n = as_caps(P, n, fk[0], fk[1], fk[2], fk[3], fk[4], fk[5], r*8/10, AS_BONE)
48 n = as_fuzz_last(P, n)
49 n = as_ellip(P, n, fk[3], fk[4], fk[5], r, r*7/10, r*13/10, AS_BONE)
50 n = as_color_last(P, n, 52 + 44*256 + 38*K_MAGIC_65536 + AS_GLOSS)
51 return n
52}
53
54// one leg = upper capsule (joint->knee) + lower capsule (knee->foot) + foot/hoof ellipsoid
55func cg_leg(P: *i64, i: i64, lx: i64, lz: i64, topY: i64, footY: i64, r: i64) -> i64 {
56 let kneeY: i64 = (topY + footY)/2
57 let kneeZ: i64 = lz + r/2
58 var n: i64 = i
59 n = as_caps(P, n, lx, topY, lz, lx, kneeY, kneeZ, r, AS_BONE)
60 n = as_caps(P, n, lx, kneeY, kneeZ, lx, footY, lz, r*8/10, AS_BONE)
61 n = as_ellip(P, n, lx, footY, lz, r, r*7/10, r*13/10, AS_BONE)
62 return n
63}
64
65// ★R1 DIVERSITY: BODY-PLAN LIBRARY (census critic: "ONE quadruped body plan; theirs: multi-class creatures").
66// Plans over the SAME layered-anatomy method: 0 QUADRUPED (below) · 1 BIRD · 2 FISH.
67func creaturegen_build_plan(P: *i64, seed: i64, plan: i64) -> i64 {
68 if plan == 1 { return cg_bird_row(P, seed, cg_bird_canon(), CGB_ROWS, CGB_KIND_SONGBIRD) }
69 if plan == 2 { return cg_build_fish(P, seed) }
70 if plan == CG_PLAN_GULL { return cg_shorebird(P, seed) }
71 return creaturegen_build(P, seed)
72}
73
74// BIRD: ovoid tilted body, 2 thin legs, folded WINGS (flattened fuzzy ellipsoids), tail fan, small head + BEAK.
75func cg_build_bird(P: *i64, seed: i64) -> i64 {
76 let st: *i64 = sys_mmap(16) as *i64
77 st[0] = seed*K_MAGIC_2654435761 + K_MAGIC_40503; cg_next(st); cg_next(st)
78 let bodyl: i64 = cg_range(st, 210, 290) // body half-length
79 let bodyr: i64 = cg_range(st, 130, 175) // body radius
80 let legl: i64 = cg_range(st, 150, 230)
81 let headr: i64 = cg_range(st, 62, 84)
82 let bodyY: i64 = 0 - 40
83 let footY: i64 = bodyY - bodyr - legl
84 let headY: i64 = bodyY + bodyr + headr*6/10
85 let headZ: i64 = 0 - bodyl*7/10
86 var i: i64 = 0
87 // body (fuzzy = feathers), tilted ovoid (front-down)
88 i = as_ellip(P, i, 0, bodyY, 0, bodyr, bodyr*9/10, bodyl, AS_BONE)
89 i = as_fuzz_last(P, i)
90 // breast
91 i = as_ellip(P, i, 0, bodyY - bodyr*3/10, 0-bodyl*4/10, bodyr*8/10, bodyr*8/10, bodyr*8/10, AS_MUSCLE)
92 i = as_fuzz_last(P, i)
93 // head + neck
94 i = as_caps(P, i, 0, bodyY + bodyr*6/10, headZ*8/10, 0, headY, headZ, headr*5/10, AS_BONE)
95 i = as_ellip(P, i, 0, headY, headZ, headr, headr, headr*11/10, AS_BONE)
96 i = as_fuzz_last(P, i)
97 // BEAK (crisp gloss cone-ish)
98 i = as_ellip(P, i, 0, headY - headr*15/100, headZ - headr*12/10, headr*32/100, headr*22/100, headr*7/10, AS_MUSCLE)
99 i = as_feature_last(P, i, 224 + 168*256 + 64*K_MAGIC_65536 + AS_GLOSS)
100 // eyes
101 i = as_ellip(P, i, 0-headr*62/100, headY + headr*15/100, headZ - headr*45/100, headr*16/100, headr*16/100, headr*16/100, AS_MUSCLE)
102 i = as_feature_last(P, i, 20 + 16*256 + 14*K_MAGIC_65536 + AS_GLOSS)
103 i = as_ellip(P, i, headr*62/100, headY + headr*15/100, headZ - headr*45/100, headr*16/100, headr*16/100, headr*16/100, AS_MUSCLE)
104 i = as_feature_last(P, i, 20 + 16*256 + 14*K_MAGIC_65536 + AS_GLOSS)
105 // WINGS: flattened fuzzy ellipsoids folded on the flanks
106 i = as_ellip(P, i, 0-bodyr*95/100, bodyY + bodyr*15/100, bodyl*5/100, bodyr*35/100, bodyr*7/10, bodyl*85/100, AS_MUSCLE)
107 i = as_fuzz_last(P, i)
108 i = as_ellip(P, i, bodyr*95/100, bodyY + bodyr*15/100, bodyl*5/100, bodyr*35/100, bodyr*7/10, bodyl*85/100, AS_MUSCLE)
109 i = as_fuzz_last(P, i)
110 // TAIL FAN: flattened wedge behind
111 i = as_ellip(P, i, 0, bodyY + bodyr*2/10, bodyl*115/100, bodyr*55/100, bodyr*25/100, bodyl*55/100, AS_MUSCLE)
112 i = as_fuzz_last(P, i)
113 // 2 thin legs + feet
114 i = as_caps(P, i, 0-bodyr*55/100, bodyY - bodyr*8/10, 0, 0-bodyr*55/100, footY, 0, 13, AS_BONE)
115 i = as_color_last(P, i, 224 + 168*256 + 64*K_MAGIC_65536)
116 i = as_ellip(P, i, 0-bodyr*55/100, footY, 0-20, 19, 8, 30, AS_BONE)
117 i = as_feature_last(P, i, 224 + 168*256 + 64*K_MAGIC_65536)
118 i = as_caps(P, i, bodyr*55/100, bodyY - bodyr*8/10, 0, bodyr*55/100, footY, 0, 13, AS_BONE)
119 i = as_color_last(P, i, 224 + 168*256 + 64*K_MAGIC_65536)
120 i = as_ellip(P, i, bodyr*55/100, footY, 0-20, 19, 8, 30, AS_BONE)
121 i = as_feature_last(P, i, 224 + 168*256 + 64*K_MAGIC_65536)
122 return i / AS_STRIDE
123}
124
125// ★PG37 BIRD CANON -- bird species are ROWS over the ONE bird body plan above, never a second builder. A species
126// with no row is not emitted: cg_bird_row returns 0 parts and writes nothing, so the table IS the species list
127// (the rung's done-rule: a canon without the gull row emits no gull). Row fields: the seeded ranges the incumbent
128// draws from, permil shape ratios of those draws, and per-part rgb where CGB_RGB_NONE (0) is the anatstack
129// 'inherit the base colour' word -- as_color_last(0) leaves the slot exactly as as_ellip wrote it, so the songbird
130// row reproduces the hand-written cg_build_bird BYTE FOR BYTE (nx_shorebird_gate holds it to that).
131const CGB_F: i64 = 24
132const CGB_KIND: i64 = 0
133const CGB_BODYL_LO: i64 = 1
134const CGB_BODYL_HI: i64 = 2
135const CGB_BODYR_LO: i64 = 3
136const CGB_BODYR_HI: i64 = 4
137const CGB_LEGL_LO: i64 = 5
138const CGB_LEGL_HI: i64 = 6
139const CGB_HEADR_LO: i64 = 7
140const CGB_HEADR_HI: i64 = 8
141const CGB_WING_LEN: i64 = 9 // permil of bodyl (half-length of the folded wing)
142const CGB_WING_THICK: i64 = 10 // permil of bodyr
143const CGB_WING_H: i64 = 11 // permil of bodyr
144const CGB_LEG_R: i64 = 12
145const CGB_BODY_RGB: i64 = 13
146const CGB_WING_RGB: i64 = 14
147const CGB_HEAD_RGB: i64 = 15
148const CGB_BEAK_RGB: i64 = 16
149const CGB_LEG_RGB: i64 = 17
150const CGB_SALT: i64 = 18
151const CGB_TIP_RGB: i64 = 19 // wingtip colour; CGB_RGB_NONE = no tip parts at all
152const CGB_FOOT_RX: i64 = 20
153const CGB_FOOT_RY: i64 = 21
154const CGB_FOOT_RZ: i64 = 22
155const CGB_TAIL_LEN: i64 = 23 // permil of bodyl
156const CGB_RGB_NONE: i64 = 0
157const CGB_KIND_GULL: i64 = 2
158const CGB_PERMIL: i64 = 1000
159const CGB_SONGBIRD_YELLOW: i64 = 4237536 // 224 + 168*256 + 64*65536, the incumbent's beak and leg yellow
160const CGB_EYE: i64 = 921620 // 20 + 16*256 + 14*65536, the incumbent's eye (gloss added at the call)
161const CGB_GULL_WHITE: i64 = 15920876 // 236 + 238*256 + 242*65536
162const CGB_GULL_GREY: i64 = 10919576 // 152 + 158*256 + 166*65536
163const CGB_GULL_BLACK: i64 = 2367518 // 30 + 32*256 + 36*65536
164const CGB_GULL_BILL: i64 = 3196136 // 232 + 196*256 + 48*65536
165const CGB_GULL_LEG: i64 = 9871574 // 214 + 160*256 + 150*65536
166const CGB_GULL_SALT: i64 = 77003
167const CGB_TIP_AT: i64 = 850 // permil of the wing half-length behind the wing centre
168const CGB_TIP_LEN: i64 = 220 // permil of the wing half-length
169const CGB_TIP_H: i64 = 450 // permil of the wing half-height
170const CGB_TIP_X: i64 = 900 // permil of bodyr (the wing itself sits at 950)
171const CGB_TIB: i64 = 550 // posed leg: tibiotarsus share of hip-to-ground, permil
172const CGB_SHIN_R: i64 = 800 // posed leg: lower capsule radius, permil of the upper
173const CGB_TOE_Z: i64 = 20 // the incumbent's foot-forward offset
174static CGB_TBL: i64
175
176func cgb_set(t: *i64, r: i64, f: i64, v: i64) -> i64 { t[r*CGB_F + f] = v; return 0 }
177func cgb_get(t: *i64, r: i64, f: i64) -> i64 { return t[r*CGB_F + f] }
178// row: the SONGBIRD, transcribed field for field from cg_build_bird above (the KAT twin the gate holds it to)
179func cgb_fill_songbird(t: *i64, r: i64) -> i64 {
180 cgb_set(t, r, CGB_KIND, CGB_KIND_SONGBIRD)
181 cgb_set(t, r, CGB_BODYL_LO, 210); cgb_set(t, r, CGB_BODYL_HI, 290)
182 cgb_set(t, r, CGB_BODYR_LO, 130); cgb_set(t, r, CGB_BODYR_HI, 175)
183 cgb_set(t, r, CGB_LEGL_LO, 150); cgb_set(t, r, CGB_LEGL_HI, 230)
184 cgb_set(t, r, CGB_HEADR_LO, 62); cgb_set(t, r, CGB_HEADR_HI, 84)
185 cgb_set(t, r, CGB_WING_LEN, 850); cgb_set(t, r, CGB_WING_THICK, 350); cgb_set(t, r, CGB_WING_H, 700)
186 cgb_set(t, r, CGB_LEG_R, 13)
187 cgb_set(t, r, CGB_BODY_RGB, CGB_RGB_NONE); cgb_set(t, r, CGB_WING_RGB, CGB_RGB_NONE); cgb_set(t, r, CGB_HEAD_RGB, CGB_RGB_NONE)
188 cgb_set(t, r, CGB_BEAK_RGB, CGB_SONGBIRD_YELLOW); cgb_set(t, r, CGB_LEG_RGB, CGB_SONGBIRD_YELLOW)
189 cgb_set(t, r, CGB_SALT, K_MAGIC_40503)
190 cgb_set(t, r, CGB_TIP_RGB, CGB_RGB_NONE)
191 cgb_set(t, r, CGB_FOOT_RX, 19); cgb_set(t, r, CGB_FOOT_RY, 8); cgb_set(t, r, CGB_FOOT_RZ, 30)
192 cgb_set(t, r, CGB_TAIL_LEN, 550)
193 return 0
194}
195// row: the GULL -- slimmer, longer body; folded wings past the tail with dark tips; stilt legs; webbed feet;
196// white body and head, grey mantle, yellow bill, pink legs. Standing on the ground like the songbird row.
197func cgb_fill_gull(t: *i64, r: i64) -> i64 {
198 cgb_set(t, r, CGB_KIND, CGB_KIND_GULL)
199 cgb_set(t, r, CGB_BODYL_LO, 300); cgb_set(t, r, CGB_BODYL_HI, 380)
200 cgb_set(t, r, CGB_BODYR_LO, 118); cgb_set(t, r, CGB_BODYR_HI, 150)
201 cgb_set(t, r, CGB_LEGL_LO, 210); cgb_set(t, r, CGB_LEGL_HI, 290)
202 cgb_set(t, r, CGB_HEADR_LO, 60); cgb_set(t, r, CGB_HEADR_HI, 78)
203 cgb_set(t, r, CGB_WING_LEN, 1150); cgb_set(t, r, CGB_WING_THICK, 280); cgb_set(t, r, CGB_WING_H, 640)
204 cgb_set(t, r, CGB_LEG_R, 9)
205 cgb_set(t, r, CGB_BODY_RGB, CGB_GULL_WHITE); cgb_set(t, r, CGB_WING_RGB, CGB_GULL_GREY); cgb_set(t, r, CGB_HEAD_RGB, CGB_GULL_WHITE)
206 cgb_set(t, r, CGB_BEAK_RGB, CGB_GULL_BILL); cgb_set(t, r, CGB_LEG_RGB, CGB_GULL_LEG)
207 cgb_set(t, r, CGB_SALT, CGB_GULL_SALT)
208 cgb_set(t, r, CGB_TIP_RGB, CGB_GULL_BLACK)
209 cgb_set(t, r, CGB_FOOT_RX, 26); cgb_set(t, r, CGB_FOOT_RY, 6); cgb_set(t, r, CGB_FOOT_RZ, 34)
210 cgb_set(t, r, CGB_TAIL_LEN, 450)
211 return 0
212}
213// the default canon: one table, filled once, the same on every door (no file read, so the wasm lane carries it too)
214func cg_bird_canon() -> *i64 {
215 if CGB_TBL == 0 {
216 let t: *i64 = sys_mmap(CGB_ROWS*CGB_F*8) as *i64
217 cgb_fill_songbird(t, 0)
218 cgb_fill_gull(t, 1)
219 CGB_TBL = t as i64
220 }
221 return CGB_TBL as *i64
222}
223func cg_bird_canon_rows() -> i64 { return CGB_ROWS }
224// first row of a kind, or -1: the caller decides what an absent species means (the builder emits nothing)
225func cg_bird_canon_find(t: *i64, nrows: i64, kind: i64) -> i64 {
226 var r: i64 = 0
227 while r < nrows { if cgb_get(t, r, CGB_KIND) == kind { return r } r = r + 1 }
228 return 0 - 1
229}
230// a posed bird leg through the SAME FK the quadruped uses (cg_fk_leg): upper capsule hip->joint, lower joint->foot,
231// webbed foot ellipsoid; every dimension and colour from the row
232func cgb_leg_fk(P: *i64, i: i64, hipx: i64, hipy: i64, thigh: i64, shin: i64, L1: i64, L2: i64, t: *i64, r: i64) -> i64 {
233 let fk: *i64 = sys_mmap(8*8) as *i64
234 cg_fk_leg(hipx, hipy, 0, thigh, shin, L1, L2, fk)
235 let legr: i64 = cgb_get(t, r, CGB_LEG_R)
236 let rgb: i64 = cgb_get(t, r, CGB_LEG_RGB)
237 var n: i64 = i
238 n = as_caps(P, n, hipx, hipy, 0, fk[0], fk[1], fk[2], legr, AS_BONE)
239 n = as_color_last(P, n, rgb)
240 n = as_caps(P, n, fk[0], fk[1], fk[2], fk[3], fk[4], fk[5], legr*CGB_SHIN_R/CGB_PERMIL, AS_BONE)
241 n = as_color_last(P, n, rgb)
242 n = as_ellip(P, n, fk[3], fk[4], fk[5] - CGB_TOE_Z, cgb_get(t, r, CGB_FOOT_RX), cgb_get(t, r, CGB_FOOT_RY), cgb_get(t, r, CGB_FOOT_RZ), AS_BONE)
243 n = as_feature_last(P, n, rgb)
244 return n
245}
246// ONE builder for every bird row. pose == 0: static capsule legs (byte-identical to the incumbent for the songbird
247// row). pose[0..3] = L thigh, L shin, R thigh, R shin (it4096, 0 = straight down): the legs become FK 2-bone legs,
248// so the bird stands and WALKS through the existing articulation. There is no wing pose on this plan: NOT FLYING.
249func cg_bird_row_posed(P: *i64, seed: i64, t: *i64, nrows: i64, kind: i64, pose: *i64) -> i64 {
250 let r: i64 = cg_bird_canon_find(t, nrows, kind)
251 if r < 0 { return 0 }
252 let st: *i64 = sys_mmap(16) as *i64
253 st[0] = seed*K_MAGIC_2654435761 + cgb_get(t, r, CGB_SALT); cg_next(st); cg_next(st)
254 let bodyl: i64 = cg_range(st, cgb_get(t, r, CGB_BODYL_LO), cgb_get(t, r, CGB_BODYL_HI))
255 let bodyr: i64 = cg_range(st, cgb_get(t, r, CGB_BODYR_LO), cgb_get(t, r, CGB_BODYR_HI))
256 let legl: i64 = cg_range(st, cgb_get(t, r, CGB_LEGL_LO), cgb_get(t, r, CGB_LEGL_HI))
257 let headr: i64 = cg_range(st, cgb_get(t, r, CGB_HEADR_LO), cgb_get(t, r, CGB_HEADR_HI))
258 let body_rgb: i64 = cgb_get(t, r, CGB_BODY_RGB)
259 let wing_rgb: i64 = cgb_get(t, r, CGB_WING_RGB)
260 let head_rgb: i64 = cgb_get(t, r, CGB_HEAD_RGB)
261 let beak_rgb: i64 = cgb_get(t, r, CGB_BEAK_RGB)
262 let leg_rgb: i64 = cgb_get(t, r, CGB_LEG_RGB)
263 let tip_rgb: i64 = cgb_get(t, r, CGB_TIP_RGB)
264 let wlen: i64 = bodyl*cgb_get(t, r, CGB_WING_LEN)/CGB_PERMIL
265 let wth: i64 = bodyr*cgb_get(t, r, CGB_WING_THICK)/CGB_PERMIL
266 let wh: i64 = bodyr*cgb_get(t, r, CGB_WING_H)/CGB_PERMIL
267 let tail: i64 = bodyl*cgb_get(t, r, CGB_TAIL_LEN)/CGB_PERMIL
268 let legr: i64 = cgb_get(t, r, CGB_LEG_R)
269 let frx: i64 = cgb_get(t, r, CGB_FOOT_RX)
270 let fry: i64 = cgb_get(t, r, CGB_FOOT_RY)
271 let frz: i64 = cgb_get(t, r, CGB_FOOT_RZ)
272 let bodyY: i64 = 0 - 40
273 let footY: i64 = bodyY - bodyr - legl
274 let headY: i64 = bodyY + bodyr + headr*6/10
275 let headZ: i64 = 0 - bodyl*7/10
276 let hipY: i64 = bodyY - bodyr*8/10
277 let legx: i64 = bodyr*55/100
278 var i: i64 = 0
279 i = as_ellip(P, i, 0, bodyY, 0, bodyr, bodyr*9/10, bodyl, AS_BONE)
280 i = as_color_last(P, i, body_rgb)
281 i = as_fuzz_last(P, i)
282 i = as_ellip(P, i, 0, bodyY - bodyr*3/10, 0-bodyl*4/10, bodyr*8/10, bodyr*8/10, bodyr*8/10, AS_MUSCLE)
283 i = as_color_last(P, i, body_rgb)
284 i = as_fuzz_last(P, i)
285 i = as_caps(P, i, 0, bodyY + bodyr*6/10, headZ*8/10, 0, headY, headZ, headr*5/10, AS_BONE)
286 i = as_color_last(P, i, head_rgb)
287 i = as_ellip(P, i, 0, headY, headZ, headr, headr, headr*11/10, AS_BONE)
288 i = as_color_last(P, i, head_rgb)
289 i = as_fuzz_last(P, i)
290 i = as_ellip(P, i, 0, headY - headr*15/100, headZ - headr*12/10, headr*32/100, headr*22/100, headr*7/10, AS_MUSCLE)
291 i = as_feature_last(P, i, beak_rgb + AS_GLOSS)
292 i = as_ellip(P, i, 0-headr*62/100, headY + headr*15/100, headZ - headr*45/100, headr*16/100, headr*16/100, headr*16/100, AS_MUSCLE)
293 i = as_feature_last(P, i, CGB_EYE + AS_GLOSS)
294 i = as_ellip(P, i, headr*62/100, headY + headr*15/100, headZ - headr*45/100, headr*16/100, headr*16/100, headr*16/100, AS_MUSCLE)
295 i = as_feature_last(P, i, CGB_EYE + AS_GLOSS)
296 i = as_ellip(P, i, 0-bodyr*95/100, bodyY + bodyr*15/100, bodyl*5/100, wth, wh, wlen, AS_MUSCLE)
297 i = as_color_last(P, i, wing_rgb)
298 i = as_fuzz_last(P, i)
299 i = as_ellip(P, i, bodyr*95/100, bodyY + bodyr*15/100, bodyl*5/100, wth, wh, wlen, AS_MUSCLE)
300 i = as_color_last(P, i, wing_rgb)
301 i = as_fuzz_last(P, i)
302 if tip_rgb != CGB_RGB_NONE {
303 let tipz: i64 = bodyl*5/100 + wlen*CGB_TIP_AT/CGB_PERMIL
304 let tipx: i64 = bodyr*CGB_TIP_X/CGB_PERMIL
305 i = as_ellip(P, i, 0-tipx, bodyY + bodyr*15/100, tipz, wth, wh*CGB_TIP_H/CGB_PERMIL, wlen*CGB_TIP_LEN/CGB_PERMIL, AS_MUSCLE)
306 i = as_feature_last(P, i, tip_rgb + AS_MATTE)
307 i = as_ellip(P, i, tipx, bodyY + bodyr*15/100, tipz, wth, wh*CGB_TIP_H/CGB_PERMIL, wlen*CGB_TIP_LEN/CGB_PERMIL, AS_MUSCLE)
308 i = as_feature_last(P, i, tip_rgb + AS_MATTE)
309 }
310 i = as_ellip(P, i, 0, bodyY + bodyr*2/10, bodyl*115/100, bodyr*55/100, bodyr*25/100, tail, AS_MUSCLE)
311 i = as_color_last(P, i, body_rgb)
312 i = as_fuzz_last(P, i)
313 if (pose as i64) == 0 {
314 i = as_caps(P, i, 0-legx, hipY, 0, 0-legx, footY, 0, legr, AS_BONE)
315 i = as_color_last(P, i, leg_rgb)
316 i = as_ellip(P, i, 0-legx, footY, 0-CGB_TOE_Z, frx, fry, frz, AS_BONE)
317 i = as_feature_last(P, i, leg_rgb)
318 i = as_caps(P, i, legx, hipY, 0, legx, footY, 0, legr, AS_BONE)
319 i = as_color_last(P, i, leg_rgb)
320 i = as_ellip(P, i, legx, footY, 0-CGB_TOE_Z, frx, fry, frz, AS_BONE)
321 i = as_feature_last(P, i, leg_rgb)
322 } else {
323 let total: i64 = hipY - footY
324 let L1: i64 = total*CGB_TIB/CGB_PERMIL
325 let L2: i64 = total - L1
326 i = cgb_leg_fk(P, i, 0-legx, hipY, pose[0], pose[1], L1, L2, t, r)
327 i = cgb_leg_fk(P, i, legx, hipY, pose[2], pose[3], L1, L2, t, r)
328 }
329 return i / AS_STRIDE
330}
331func cg_bird_row(P: *i64, seed: i64, t: *i64, nrows: i64, kind: i64) -> i64 { return cg_bird_row_posed(P, seed, t, nrows, kind, 0 as *i64) }
332// ★PG37 THE FIRST ANIMAL, HONESTLY A GULL: the gull ROW of the bird canon -- white-grey palette, longer folded wings
333// with dark tips, stilt legs, webbed feet, standing on the ground (cg_shorebird_posed walks it through the FK
334// legs). EXPLICITLY NOT FLYING: this plan carries no wing pose, and that is the named ceiling. A crab is refused
335// by name until a radial eight-leg plan exists.
336func cg_shorebird(P: *i64, seed: i64) -> i64 { return cg_bird_row(P, seed, cg_bird_canon(), CGB_ROWS, CGB_KIND_GULL) }
337func cg_shorebird_posed(P: *i64, seed: i64, pose: *i64) -> i64 { return cg_bird_row_posed(P, seed, cg_bird_canon(), CGB_ROWS, CGB_KIND_GULL, pose) }
338
339// FISH: fusiform body, tail fin, dorsal fin, pectoral fins, gloss eye. No legs; renders mid-frame (as if swimming).
340func cg_build_fish(P: *i64, seed: i64) -> i64 {
341 let st: *i64 = sys_mmap(16) as *i64
342 st[0] = seed*K_MAGIC_2654435761 + K_MAGIC_90001; cg_next(st); cg_next(st)
343 let bl: i64 = cg_range(st, 330, 430) // body half-length
344 let br: i64 = cg_range(st, 95, 140) // body radius
345 let finr: i64 = cg_range(st, 80, 130)
346 var i: i64 = 0
347 // fusiform body: main + tapered snout + tapered rear
348 i = as_ellip(P, i, 0, 0, 0, br, br*88/100, bl, AS_BONE)
349 i = as_ellip(P, i, 0, 0-br*6/100, 0-bl*78/100, br*55/100, br*48/100, bl*38/100, AS_BONE) // snout taper
350 i = as_ellip(P, i, 0, 0, bl*75/100, br*45/100, br*40/100, bl*40/100, AS_BONE) // rear taper
351 // TAIL FIN: thin vertical wedge (crisp so it stays a blade)
352 i = as_ellip(P, i, 0, 0, bl*128/100, br*8/100, finr*13/10, finr*9/10, AS_MUSCLE)
353 i = as_feature_last(P, i, 0)
354 // DORSAL FIN
355 i = as_ellip(P, i, 0, br*95/100, 0-bl*5/100, br*7/100, finr*75/100, bl*42/100, AS_MUSCLE)
356 i = as_feature_last(P, i, 0)
357 // PECTORAL fins
358 i = as_ellip(P, i, 0-br*92/100, 0-br*25/100, 0-bl*28/100, br*6/100, finr*38/100, finr*55/100, AS_MUSCLE)
359 i = as_feature_last(P, i, 0)
360 i = as_ellip(P, i, br*92/100, 0-br*25/100, 0-bl*28/100, br*6/100, finr*38/100, finr*55/100, AS_MUSCLE)
361 i = as_feature_last(P, i, 0)
362 // eyes (gloss)
363 i = as_ellip(P, i, 0-br*72/100, br*18/100, 0-bl*62/100, br*13/100, br*13/100, br*13/100, AS_MUSCLE)
364 i = as_feature_last(P, i, 22 + 20*256 + 18*K_MAGIC_65536 + AS_GLOSS)
365 i = as_ellip(P, i, br*72/100, br*18/100, 0-bl*62/100, br*13/100, br*13/100, br*13/100, AS_MUSCLE)
366 i = as_feature_last(P, i, 22 + 20*256 + 18*K_MAGIC_65536 + AS_GLOSS)
367 // belly
368 i = as_ellip(P, i, 0, 0-br*45/100, 0-bl*15/100, br*70/100, br*55/100, bl*55/100, AS_FAT)
369 return i / AS_STRIDE
370}
371
372// ★R9 POSED quadruped: the same seed's body with 4 FK-driven legs placed from a POSE (8 angles: FL/FR/BL/BR
373// x thigh/shin, it4096). Rest pose = all zeros = standing. A walk cycle = animate the angles. Returns part count.
374func creaturegen_build_posed(P: *i64, seed: i64, pose: *i64) -> i64 {
375 let st: *i64 = sys_mmap(16) as *i64
376 st[0] = seed*K_MAGIC_2654435761 + K_MAGIC_1013904223; cg_next(st); cg_next(st)
377 let bodylen: i64 = cg_range(st, 360, 500)
378 let build: i64 = cg_range(st, 90, 118)
379 let sZ: i64 = 0 - bodylen/2
380 let hZ: i64 = bodylen/2
381 let backY: i64 = 160
382 let L1: i64 = 132 // upper-leg length
383 let L2: i64 = 120 // lower-leg length
384 let hipY: i64 = backY - 40
385 let headZ: i64 = sZ - 150
386 let headY: i64 = backY + 130
387 var i: i64 = 0
388 // body barrel (fuzzy), chest, neck, head, snout, tail
389 i = as_ellip(P, i, 0, backY-70, 0, 150*build/100, 128, bodylen/2, AS_BONE); i = as_fuzz_last(P, i)
390 i = as_ellip(P, i, 0, backY-40, sZ+40, 150*build/100, 150, 175, AS_BONE); i = as_fuzz_last(P, i)
391 i = as_caps(P, i, 0, backY, sZ, 0, headY, headZ, 54*build/100, AS_BONE); i = as_fuzz_last(P, i)
392 i = as_ellip(P, i, 0, headY, headZ, 118, 106, 130, AS_BONE); i = as_fuzz_last(P, i)
393 i = as_ellip(P, i, 0, headY-48, headZ-108, 72, 60, 84, AS_BONE)
394 i = as_caps(P, i, 0, backY, hZ, 0, backY-100, hZ+300, 28, AS_BONE); i = as_fuzz_last(P, i)
395 // 4 FK legs from the pose
396 i = cg_leg_posed(P, i, 0-108, hipY, sZ+34, pose[0], pose[1], L1, L2, 40)
397 i = cg_leg_posed(P, i, 108, hipY, sZ+34, pose[2], pose[3], L1, L2, 40)
398 i = cg_leg_posed(P, i, 0-114, hipY, hZ-16, pose[4], pose[5], L1, L2, 44)
399 i = cg_leg_posed(P, i, 114, hipY, hZ-16, pose[6], pose[7], L1, L2, 44)
400 // eyes
401 i = as_ellip(P, i, 0-92, headY+20, headZ-108, 18, 18, 18, AS_MUSCLE); i = as_feature_last(P, i, 24 + 20*256 + 18*K_MAGIC_65536 + AS_GLOSS)
402 i = as_ellip(P, i, 92, headY+20, headZ-108, 18, 18, 18, AS_MUSCLE); i = as_feature_last(P, i, 24 + 20*256 + 18*K_MAGIC_65536 + AS_GLOSS)
403 return i / AS_STRIDE
404}
405
406// build a QUADRUPED from a seed (plan 0; the original). Returns the part count.
407func creaturegen_build(P: *i64, seed: i64) -> i64 {
408 let st: *i64 = sys_mmap(16) as *i64
409 st[0] = seed*K_MAGIC_2654435761 + K_MAGIC_1013904223; cg_next(st); cg_next(st)
410 let bodylen: i64 = cg_range(st, 360, 500)
411 let leglen: i64 = cg_range(st, 360, 560)
412 let necklen: i64 = cg_range(st, 170, 440)
413 let headsz: i64 = cg_range(st, 96, 148)
414 let taillen: i64 = cg_range(st, 130, 420)
415 let build: i64 = cg_range(st, 85, 122)
416 let sZ: i64 = 0 - bodylen/2 // shoulder z (front)
417 let hZ: i64 = bodylen/2 // hip z (back)
418 let backY: i64 = 160
419 let footY: i64 = backY - leglen // ground
420 let headY: i64 = backY + necklen*7/10
421 let headZ: i64 = sZ - necklen*7/10
422 var i: i64 = 0
423 // --- SKELETON (body masses are FUZZY = fur displacement in the geometry) ---
424 i = as_ellip(P, i, 0, backY-40, sZ+40, 150*build/100, 152*build/100, 185, AS_BONE) // ribcage
425 i = as_fuzz_last(P, i)
426 i = as_ellip(P, i, 0, backY-28, hZ-30, 140*build/100, 142, 150, AS_BONE) // pelvis
427 i = as_fuzz_last(P, i)
428 i = as_caps(P, i, 0, backY, sZ, 0, backY, hZ, 58, AS_BONE) // spine
429 i = as_fuzz_last(P, i)
430 i = as_caps(P, i, 0, backY, sZ, 0, headY, headZ, 54*build/100, AS_BONE) // neck
431 i = as_fuzz_last(P, i)
432 i = as_ellip(P, i, 0, headY, headZ, headsz, headsz*9/10, headsz*11/10, AS_BONE) // skull
433 i = as_fuzz_last(P, i)
434 i = as_ellip(P, i, 0, headY-headsz*4/10, headZ-headsz*9/10, headsz*6/10, headsz*5/10, headsz*7/10, AS_BONE) // snout
435 i = as_caps(P, i, 0, backY, hZ, 0, backY-taillen/3, hZ+taillen, 28, AS_BONE) // tail
436 i = as_fuzz_last(P, i)
437 let hoof: i64 = 52 + 44*256 + 38*K_MAGIC_65536 + AS_GLOSS
438 i = cg_leg(P, i, 0-108, sZ+34, backY-58, footY, 40) // front-left
439 i = as_color_last(P, i, hoof)
440 i = cg_leg(P, i, 108, sZ+34, backY-58, footY, 40) // front-right
441 i = as_color_last(P, i, hoof)
442 i = cg_leg(P, i, 0-114, hZ-16, backY-70, footY, 44) // back-left
443 i = as_color_last(P, i, hoof)
444 i = cg_leg(P, i, 114, hZ-16, backY-70, footY, 44) // back-right
445 i = as_color_last(P, i, hoof)
446 // --- MUSCLE (fuzzy too) ---
447 i = as_ellip(P, i, 0-100, backY-64, sZ+24, 100, 132, 122, AS_MUSCLE) // L shoulder
448 i = as_fuzz_last(P, i)
449 i = as_ellip(P, i, 100, backY-64, sZ+24, 100, 132, 122, AS_MUSCLE) // R shoulder
450 i = as_fuzz_last(P, i)
451 i = as_ellip(P, i, 0-104, backY-86, hZ-22, 116, 150, 132, AS_MUSCLE) // L haunch (thigh)
452 i = as_fuzz_last(P, i)
453 i = as_ellip(P, i, 104, backY-86, hZ-22, 116, 150, 132, AS_MUSCLE) // R haunch
454 i = as_fuzz_last(P, i)
455 i = as_ellip(P, i, 0, backY-120, 0, 150*build/100, 120, bodylen/2, AS_MUSCLE) // belly/barrel
456 i = as_fuzz_last(P, i)
457 i = as_caps(P, i, 0, backY+8, sZ, 0, headY-18, headZ+28, 60, AS_MUSCLE) // neck muscle
458 i = as_fuzz_last(P, i)
459 // --- FEATURES (Phase-1: ears, eyes, nose leather, tail tuft; crisp + low-inflate so they stay sharp) ---
460 let er: i64 = headsz*30/100
461 i = as_ellip(P, i, 0-headsz*52/100, headY+headsz*85/100, headZ+headsz*10/100, er, er*140/100, er*70/100, AS_MUSCLE)
462 i = as_feature_last(P, i, 0) // L ear (skin, crisp)
463 i = as_ellip(P, i, headsz*52/100, headY+headsz*85/100, headZ+headsz*10/100, er, er*140/100, er*70/100, AS_MUSCLE)
464 i = as_feature_last(P, i, 0) // R ear
465 i = as_ellip(P, i, 0-headsz*78/100, headY+headsz*18/100, headZ-headsz*95/100, headsz*16/100, headsz*16/100, headsz*16/100, AS_MUSCLE)
466 i = as_feature_last(P, i, 24 + 20*256 + 18*K_MAGIC_65536 + AS_GLOSS) // L eye (dark, glint)
467 i = as_ellip(P, i, headsz*78/100, headY+headsz*18/100, headZ-headsz*95/100, headsz*16/100, headsz*16/100, headsz*16/100, AS_MUSCLE)
468 i = as_feature_last(P, i, 24 + 20*256 + 18*K_MAGIC_65536 + AS_GLOSS) // R eye (glint)
469 i = as_ellip(P, i, 0, headY-headsz*45/100, headZ-headsz*180/100, headsz*20/100, headsz*16/100, headsz*18/100, AS_MUSCLE)
470 i = as_feature_last(P, i, 56 + 44*256 + 40*K_MAGIC_65536 + AS_GLOSS) // nose leather (moist gloss)
471 i = as_ellip(P, i, 0, backY-taillen/3, hZ+taillen, 40, 40, 52, AS_MUSCLE)
472 i = as_color_last(P, i, 88 + 66*256 + 48*K_MAGIC_65536 + AS_MATTE) // tail tuft (darker, matte)
473 return i / AS_STRIDE
474}