# ════════════════════════════════════════════════════════════════════════════
# 3d-meta.ling — Hypercube-Möbius Mirror Room of Pyramids
#
# ┌── CORE ──────────────────────────────────────────────────────────────────┐
# │ Sierpiński stella octangula (two interlocked tetrahedra) — depth 3 │
# │ Framed inside a rotating 4-D tesseract (hypercube, 32 glowing edges) │
# └── RING ──────────────────────────────────────────────────────────────────┘
# │ 6 satellite stella-fractals (depth 1) orbiting on a Möbius path │
# └──────────────────────────────────────────────────────────────────────────┘
#
# Rendering pipeline (new):
# set_camera → stores cos/sin trig in GfxState
# วาดสามเหลี่ยม3มิติ → computes cel-shaded lighting, projects, depth-queues
# วาดเส้น3มิติ → projects + depth-queues line (used for tesseract)
# แสดงผล → sorts depth queue back→front, flushes, presents
#
# Fullscreen: ling run examples/3d-meta.ling
# Escape / close window to quit.
# ════════════════════════════════════════════════════════════════════════════
# ── Screen globals — seeded into every function automatically ─────────────────
bind CX = get_width() / 2
bind CY = get_height() / 2
bind FOCAL = get_height()
bind ZDIST = 5.0
bind D4 = 3.5
# ── 4-D serpentine colour ─────────────────────────────────────────────────────
fn สี4มิติ(ระดับ, หน้า, เฟรม) {
bind t = เฟรม * 0.025
bind p = ระดับ * 1.047 + หน้า * 0.785
bind w = sin(เฟรม * 0.071 + ระดับ * 2.094) * 0.35 + 0.65
bind r = (sin(t + p) * 127 + 128) * w
bind g = (sin(t + p + 2.094) * 127 + 128) * w
bind b = (sin(t + p + 4.189) * 127 + 128) * w
สีดินสอ(r, g, b)
}
# ── Sierpiński tetrahedron — paint large→small, uses depth+lighting pipeline ──
# No camera params needed — set_camera is called once per frame.
fn วาดเซียร์3มิติ(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, ระดับ, เฟรม) {
สี4มิติ(ระดับ, 0, เฟรม)
วาดสามเหลี่ยม3มิติ(ax, ay, az, bx, by, bz, cx, cy, cz)
สี4มิติ(ระดับ, 1, เฟรม)
วาดสามเหลี่ยม3มิติ(ax, ay, az, bx, by, bz, dx, dy, dz)
สี4มิติ(ระดับ, 2, เฟรม)
วาดสามเหลี่ยม3มิติ(ax, ay, az, cx, cy, cz, dx, dy, dz)
สี4มิติ(ระดับ, 3, เฟรม)
วาดสามเหลี่ยม3มิติ(bx, by, bz, cx, cy, cz, dx, dy, dz)
ถ้า ระดับ > 0 {
bind ด = ระดับ - 1
bind mabx = (ax+bx)/2 bind maby = (ay+by)/2 bind mabz = (az+bz)/2
bind macx = (ax+cx)/2 bind macy = (ay+cy)/2 bind macz = (az+cz)/2
bind madx = (ax+dx)/2 bind mady = (ay+dy)/2 bind madz = (az+dz)/2
bind mbcx = (bx+cx)/2 bind mbcy = (by+cy)/2 bind mbcz = (bz+cz)/2
bind mbdx = (bx+dx)/2 bind mbdy = (by+dy)/2 bind mbdz = (bz+dz)/2
bind mcdx = (cx+dx)/2 bind mcdy = (cy+dy)/2 bind mcdz = (cz+dz)/2
วาดเซียร์3มิติ(ax, ay, az, mabx, maby, mabz, macx, macy, macz, madx, mady, madz, ด, เฟรม)
วาดเซียร์3มิติ(mabx, maby, mabz, bx, by, bz, mbcx, mbcy, mbcz, mbdx, mbdy, mbdz, ด, เฟรม)
วาดเซียร์3มิติ(macx, macy, macz, mbcx, mbcy, mbcz, cx, cy, cz, mcdx, mcdy, mcdz, ด, เฟรม)
วาดเซียร์3มิติ(madx, mady, madz, mbdx, mbdy, mbdz, mcdx, mcdy, mcdz, dx, dy, dz, ด, เฟรม)
}
}
# ── 4-D tesseract edge — 4D rotate → 4D→3D stereo → วาดเส้น3มิติ ───────────
# ca/sa = XW rotation, cb/sb = YW rotation.
# After 4D→3D projection the 3D coords go straight into วาดเส้น3มิติ which
# applies the stored camera and queues the line for depth-sorted drawing.
fn tesseract_edge(ax, ay, az, aw, bx, by, bz, bw, ca, sa, cb, sb) {
# vertex A: 4D XW rotation
bind ax4 = ax * ca - aw * sa
bind aw4 = ax * sa + aw * ca
# vertex A: 4D YW rotation
bind ay4 = ay * cb - aw4 * sb
bind aw5 = ay * sb + aw4 * cb
# vertex A: 4D→3D stereographic
bind ad = aw5 + D4
bind ax3 = ax4 / ad
bind ay3 = ay4 / ad
bind az3 = az / ad
# vertex B: same pipeline
bind bx4 = bx * ca - bw * sa
bind bw4 = bx * sa + bw * ca
bind by4 = by * cb - bw4 * sb
bind bw5 = by * sb + bw4 * cb
bind bd = bw5 + D4
bind bx3 = bx4 / bd
bind by3 = by4 / bd
bind bz3 = bz / bd
# Depth-queued line — camera applied inside วาดเส้น3มิติ
วาดเส้น3มิติ(ax3, ay3, az3, bx3, by3, bz3)
}
# ── 12 edges of one cubic hyperface at w = cw ─────────────────────────────────
fn cube4d(s, cw, ca, sa, cb, sb) {
tesseract_edge(-s,-s,-s,cw, s,-s,-s,cw, ca,sa,cb,sb)
tesseract_edge( s,-s,-s,cw, s, s,-s,cw, ca,sa,cb,sb)
tesseract_edge( s, s,-s,cw, -s, s,-s,cw, ca,sa,cb,sb)
tesseract_edge(-s, s,-s,cw, -s,-s,-s,cw, ca,sa,cb,sb)
tesseract_edge(-s,-s, s,cw, s,-s, s,cw, ca,sa,cb,sb)
tesseract_edge( s,-s, s,cw, s, s, s,cw, ca,sa,cb,sb)
tesseract_edge( s, s, s,cw, -s, s, s,cw, ca,sa,cb,sb)
tesseract_edge(-s, s, s,cw, -s,-s, s,cw, ca,sa,cb,sb)
tesseract_edge(-s,-s,-s,cw, -s,-s, s,cw, ca,sa,cb,sb)
tesseract_edge( s,-s,-s,cw, s,-s, s,cw, ca,sa,cb,sb)
tesseract_edge( s, s,-s,cw, s, s, s,cw, ca,sa,cb,sb)
tesseract_edge(-s, s,-s,cw, -s, s, s,cw, ca,sa,cb,sb)
}
# ── Full tesseract: outer (w=+s) warm + inner (w=−s) cool + 8 connectors ──────
fn draw_tesseract(s, ca, sa, cb, sb, fr) {
bind tw = fr * 0.023
# outer cube — warm cycling hues
bind ro = sin(tw) * 100 + 155
bind go = sin(tw + 2.094) * 100 + 155
bind bo = sin(tw + 4.189) * 100 + 155
สีดินสอ(ro, go, bo)
cube4d(s, s, ca, sa, cb, sb)
# inner cube — complementary cool hues (π phase shift)
bind ri = sin(tw + pi) * 100 + 155
bind gi = sin(tw + pi + 2.094) * 100 + 155
bind bi = sin(tw + pi + 4.189) * 100 + 155
สีดินสอ(ri, gi, bi)
cube4d(s, -s, ca, sa, cb, sb)
# 8 connector edges — bright, faster oscillation
bind rc = sin(tw * 1.4) * 90 + 165
bind gc = sin(tw * 1.4 + 2.094) * 90 + 165
bind bc = sin(tw * 1.4 + 4.189) * 90 + 165
สีดินสอ(rc, gc, bc)
tesseract_edge(-s,-s,-s, s, -s,-s,-s,-s, ca,sa,cb,sb)
tesseract_edge( s,-s,-s, s, s,-s,-s,-s, ca,sa,cb,sb)
tesseract_edge( s, s,-s, s, s, s,-s,-s, ca,sa,cb,sb)
tesseract_edge(-s, s,-s, s, -s, s,-s,-s, ca,sa,cb,sb)
tesseract_edge(-s,-s, s, s, -s,-s, s,-s, ca,sa,cb,sb)
tesseract_edge( s,-s, s, s, s,-s, s,-s, ca,sa,cb,sb)
tesseract_edge( s, s, s, s, s, s, s,-s, ca,sa,cb,sb)
tesseract_edge(-s, s, s, s, -s, s, s,-s, ca,sa,cb,sb)
}
# ════════════════════════════════════════════════════════════════════════════
# MAIN
# ════════════════════════════════════════════════════════════════════════════
ผูก เริ่ม = ทำ {
เปิดหน้าต่างเต็มจอ("3-D Meta — Hypercube Mirror Room of Pyramids")
# Ambient light — dim purple fill so shadow sides stay visible
set_ambient(0.12)
# Regular tetrahedron (r = 1.8) + dual (stella octangula)
ผูก r = 1.8
ผูก v0x = 0.0 ผูก v0y = 0 - r ผูก v0z = 0.0
ผูก v1x = r * 0.9428 ผูก v1y = r * 0.3333 ผูก v1z = 0.0
ผูก v2x = 0 - r * 0.4714 ผูก v2y = r * 0.3333 ผูก v2z = r * 0.8165
ผูก v3x = 0 - r * 0.4714 ผูก v3y = r * 0.3333 ผูก v3z = 0 - r * 0.8165
ผูก n0x = 0.0 ผูก n0y = r ผูก n0z = 0.0
ผูก n1x = 0 - r * 0.9428 ผูก n1y = 0 - r * 0.3333 ผูก n1z = 0.0
ผูก n2x = r * 0.4714 ผูก n2y = 0 - r * 0.3333 ผูก n2z = 0 - r * 0.8165
ผูก n3x = r * 0.4714 ผูก n3y = 0 - r * 0.3333 ผูก n3z = r * 0.8165
ผูก เฟรม = 0
ขณะที่ หน้าต่างเปิดอยู่() {
เติม(2, 1, 6)
# ── camera ──────────────────────────────────────────────────────────
ผูก ry = เฟรม * 0.013
ผูก rx = sin(เฟรม * 0.009) * 0.55
ผูก cry = cos(ry) ผูก sry = sin(ry)
ผูก crx = cos(rx) ผูก srx = sin(rx)
# Store camera in GfxState — all 3D draw calls use it automatically
set_camera(cry, sry, crx, srx)
# ── 4D rotation angles ───────────────────────────────────────────────
ผูก ca = cos(เฟรม * 0.017) ผูก sa = sin(เฟรม * 0.017)
ผูก cb = cos(เฟรม * 0.011) ผูก sb = sin(เฟรม * 0.011)
# ── lights (updated each frame so they orbit with the scene) ─────────
# Key light — warm white, orbiting above-right
clear_lights()
add_light(
sin(เฟรม * 0.017) * 4.0,
0 - 3.5,
cos(เฟรม * 0.017) * 4.0,
1.0, 0.92, 0.80, # warm white
2.2, 9.0 # intensity, radius
)
# Fill light — cool blue, from the left
add_light(
0 - 3.0,
1.5,
2.0,
0.35, 0.55, 1.0, # cool blue
1.0, 7.0
)
# Accent — magenta rim from behind
add_light(
0 - sin(เฟรม * 0.011) * 3.5,
1.0,
0 - cos(เฟรม * 0.011) * 3.5,
1.0, 0.25, 0.8, # magenta
0.8, 5.5
)
# ══ Tesseract wireframe (32 depth-sorted glowing edges) ══════════════
draw_tesseract(2.2, ca, sa, cb, sb, เฟรม)
# ══ Central stella octangula (depth 3) ═══════════════════════════════
วาดเซียร์3มิติ(v0x, v0y, v0z, v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z,
3, เฟรม)
วาดเซียร์3มิติ(n0x, n0y, n0z, n1x, n1y, n1z, n2x, n2y, n2z, n3x, n3y, n3z,
3, เฟรม + 80)
# ══ Ring — 6 satellite stella fractals (depth 1) ═════════════════════
ผูก RR = 3.1
ผูก sc = 0.38
ผูก spin = เฟรม * 0.010
for k in 0..6 {
ผูก theta = k * 1.0472 + spin
ผูก tx = RR * cos(theta)
ผูก tz = RR * sin(theta)
ผูก p0x = v0x * sc + tx ผูก p0y = v0y * sc ผูก p0z = v0z * sc + tz
ผูก p1x = v1x * sc + tx ผูก p1y = v1y * sc ผูก p1z = v1z * sc + tz
ผูก p2x = v2x * sc + tx ผูก p2y = v2y * sc ผูก p2z = v2z * sc + tz
ผูก p3x = v3x * sc + tx ผูก p3y = v3y * sc ผูก p3z = v3z * sc + tz
ผูก q0x = n0x * sc + tx ผูก q0y = n0y * sc ผูก q0z = n0z * sc + tz
ผูก q1x = n1x * sc + tx ผูก q1y = n1y * sc ผูก q1z = n1z * sc + tz
ผูก q2x = n2x * sc + tx ผูก q2y = n2y * sc ผูก q2z = n2z * sc + tz
ผูก q3x = n3x * sc + tx ผูก q3y = n3y * sc ผูก q3z = n3z * sc + tz
วาดเซียร์3มิติ(p0x, p0y, p0z, p1x, p1y, p1z, p2x, p2y, p2z, p3x, p3y, p3z,
1, เฟรม + k * 20)
วาดเซียร์3มิติ(q0x, q0y, q0z, q1x, q1y, q1z, q2x, q2y, q2z, q3x, q3y, q3z,
1, เฟรม + k * 20 + 80)
}
# แสดงผล: depth-sorts all queued triangles+lines, then presents ─────
แสดงผล()
ผูก เฟรม = เฟรม + 1
}
}