灵符lingfu

lingmodeler

↓ 0 downloads

LingModeler: box modeling with quads and tris, rigging + weight painting, 2D vector illustration and animation, procedural textures and game assets; .lmesh / .ling native formats, OBJ, glTF and SVG import / export

Windows · x86-64Linux · x86-64LingOS · x86-64LingOS · Pi 5 ARM64Web · WASM
Keywords 3d, modeling, vector, svg, gltf, obj, rigging, animation, textures, ling
lingfu install lingmodeler
LicenseApache-2.0 OR MIT
Authorsling-lin
READMECode / FilesVersionsDependency GraphDependentsSecurityBuildsSettings

Code / Files (67)

ling/prims.ling
# ━━━ prims.ling — parametric primitives (quads where possible) ━━━
# every pr_* builder returns [vx, vy, vz, fi, fs, fc]; pr_add puts one in the scene at the 3D cursor

fn pr_add(kind, p) {
    bind g = pr_build(kind, p)
    if len(g) < 6.0 { return 0.0 - 1.0 }
    bind names = ["Plane", "Cube", "Circle", "Sphere", "Icosphere", "Cylinder", "Cone", "Torus", "Grid", "Capsule"]
    bind nm = "Object"
    bind kinds = ["plane", "cube", "circle", "sphere", "ico", "cylinder", "cone", "torus", "grid", "capsule"]
    bind i = 0.0
    while i < len(kinds) { if list_get(kinds, i) == kind { bind nm = list_get(names, i) } bind i = i + 1.0 }
    bind o = me_add_object(nm, list_get(g, 0), list_get(g, 1), list_get(g, 2), list_get(g, 3), list_get(g, 4), list_get(g, 5))
    st_set(mk(o, "px"), st_get("cursor_x", 0.0))
    st_set(mk(o, "py"), st_get("cursor_y", 0.0))
    st_set(mk(o, "pz"), st_get("cursor_z", 0.0))
    uv_box(o)
    return o
}

# default parameter sets for the Add dialog: [names, values, mins, maxs, decimals]
fn pr_params(kind) {
    if kind == "plane" { return [["Size", "Subdivisions"], [2.0, 1.0], [0.1, 1.0], [20.0, 32.0], [2.0, 0.0]] }
    if kind == "cube" { return [["Size", "Subdivisions"], [2.0, 1.0], [0.1, 1.0], [20.0, 8.0], [2.0, 0.0]] }
    if kind == "circle" { return [["Vertices", "Radius", "Fill (0 none, 1 ngon, 2 fan)"], [16.0, 1.0, 1.0], [3.0, 0.1, 0.0], [128.0, 20.0, 2.0], [0.0, 2.0, 0.0]] }
    if kind == "sphere" { return [["Segments", "Rings", "Radius"], [16.0, 8.0, 1.0], [3.0, 2.0, 0.1], [64.0, 32.0, 20.0], [0.0, 0.0, 2.0]] }
    if kind == "ico" { return [["Subdivisions", "Radius"], [1.0, 1.0], [0.0, 0.1], [4.0, 20.0], [0.0, 2.0]] }
    if kind == "cylinder" { return [["Vertices", "Radius", "Depth", "Caps (0/1)"], [16.0, 1.0, 2.0, 1.0], [3.0, 0.05, 0.05, 0.0], [128.0, 20.0, 40.0, 1.0], [0.0, 2.0, 2.0, 0.0]] }
    if kind == "cone" { return [["Vertices", "Base radius", "Top radius", "Depth"], [16.0, 1.0, 0.0, 2.0], [3.0, 0.0, 0.0, 0.05], [128.0, 20.0, 20.0, 40.0], [0.0, 2.0, 2.0, 2.0]] }
    if kind == "torus" { return [["Major segments", "Minor segments", "Major radius", "Minor radius"], [24.0, 12.0, 1.0, 0.3], [3.0, 3.0, 0.1, 0.01], [128.0, 64.0, 20.0, 10.0], [0.0, 0.0, 2.0, 2.0]] }
    if kind == "grid" { return [["X subdivisions", "Y subdivisions", "Size"], [8.0, 8.0, 4.0], [1.0, 1.0, 0.1], [64.0, 64.0, 100.0], [0.0, 0.0, 2.0]] }
    if kind == "capsule" { return [["Segments", "Rings", "Radius", "Length"], [12.0, 4.0, 0.5, 1.0], [3.0, 1.0, 0.05, 0.0], [64.0, 16.0, 20.0, 40.0], [0.0, 0.0, 2.0, 2.0]] }
    return [[], [], [], [], []]
}

fn pr_build(kind, p) {
    if kind == "plane" { return pr_grid(list_get(p, 1), list_get(p, 1), list_get(p, 0)) }
    if kind == "cube" { return pr_cube(list_get(p, 0), list_get(p, 1)) }
    if kind == "circle" { return pr_circle(list_get(p, 0), list_get(p, 1), list_get(p, 2)) }
    if kind == "sphere" { return pr_sphere(list_get(p, 0), list_get(p, 1), list_get(p, 2)) }
    if kind == "ico" { return pr_icosphere(list_get(p, 0), list_get(p, 1)) }
    if kind == "cylinder" { return pr_cone(list_get(p, 0), list_get(p, 1), list_get(p, 1), list_get(p, 2), list_get(p, 3)) }
    if kind == "cone" { return pr_cone(list_get(p, 0), list_get(p, 1), list_get(p, 2), list_get(p, 3), 1.0) }
    if kind == "torus" { return pr_torus(list_get(p, 0), list_get(p, 1), list_get(p, 2), list_get(p, 3)) }
    if kind == "grid" { return pr_grid(list_get(p, 0), list_get(p, 1), list_get(p, 2)) }
    if kind == "capsule" { return pr_capsule(list_get(p, 0), list_get(p, 1), list_get(p, 2), list_get(p, 3)) }
    return []
}

# helpers to build face lists
fn pr_quad(fi, fs, fc, a, b, c, d) {
    bind fs2 = list_push(fs, len(fi))
    bind fc2 = list_push(fc, 4.0)
    bind fi2 = list_push(fi, a)
    bind fi2 = list_push(fi2, b)
    bind fi2 = list_push(fi2, c)
    bind fi2 = list_push(fi2, d)
    return [fi2, fs2, fc2]
}
fn pr_tri(fi, fs, fc, a, b, c) {
    bind fs2 = list_push(fs, len(fi))
    bind fc2 = list_push(fc, 3.0)
    bind fi2 = list_push(fi, a)
    bind fi2 = list_push(fi2, b)
    bind fi2 = list_push(fi2, c)
    return [fi2, fs2, fc2]
}

# grid in the XZ plane, facing +Y
fn pr_grid(nx, nz, size) {
    bind nx = max(1.0, floor(nx)) bind nz = max(1.0, floor(nz))
    bind vx = list_new() bind vy = list_new() bind vz = list_new()
    bind j = 0.0
    while j <= nz {
        bind i = 0.0
        while i <= nx {
            bind vx = list_push(vx, (i / nx - 0.5) * size)
            bind vy = list_push(vy, 0.0)
            bind vz = list_push(vz, (j / nz - 0.5) * size)
            bind i = i + 1.0
        }
        bind j = j + 1.0
    }
    bind fi = list_new() bind fs = list_new() bind fc = list_new()
    bind j = 0.0
    while j < nz {
        bind i = 0.0
        while i < nx {
            bind a = j * (nx + 1.0) + i
            bind r = pr_quad(fi, fs, fc, a, a + nx + 1.0, a + nx + 2.0, a + 1.0)
            bind fi = list_get(r, 0) bind fs = list_get(r, 1) bind fc = list_get(r, 2)
            bind i = i + 1.0
        }
        bind j = j + 1.0
    }
    return [vx, vy, vz, fi, fs, fc]
}

fn pr_cube(size, sub) {
    bind h = size * 0.5
    bind n = max(1.0, floor(sub))
    if n == 1.0 {
        bind vx = [0.0 - h, h, h, 0.0 - h, 0.0 - h, h, h, 0.0 - h]
        bind vy = [0.0 - h, 0.0 - h, h, h, 0.0 - h, 0.0 - h, h, h]
        bind vz = [h, h, h, h, 0.0 - h, 0.0 - h, 0.0 - h, 0.0 - h]
        bind fi = [0.0, 1.0, 2.0, 3.0, 5.0, 4.0, 7.0, 6.0, 4.0, 0.0, 3.0, 7.0, 1.0, 5.0, 6.0, 2.0, 3.0, 2.0, 6.0, 7.0, 4.0, 5.0, 1.0, 0.0]
        bind fs = [0.0, 4.0, 8.0, 12.0, 16.0, 20.0]
        bind fc = [4.0, 4.0, 4.0, 4.0, 4.0, 4.0]
        return [vx, vy, vz, fi, fs, fc]
    }
    # subdivided: six grids, merged by distance
    bind vx = list_new() bind vy = list_new() bind vz = list_new()
    bind fi = list_new() bind fs = list_new() bind fc = list_new()
    bind face = 0.0
    while face < 6.0 {
        bind base = len(vx)
        bind j = 0.0
        while j <= n {
            bind i = 0.0
            while i <= n {
                bind u = (i / n - 0.5) * size
                bind v = (j / n - 0.5) * size
                bind p = [0.0, 0.0, 0.0]
                if face == 0.0 { bind p = [u, v, h] }
                if face == 1.0 { bind p = [0.0 - u, v, 0.0 - h] }
                if face == 2.0 { bind p = [0.0 - h, v, u] }
                if face == 3.0 { bind p = [h, v, 0.0 - u] }
                if face == 4.0 { bind p = [u, h, 0.0 - v] }
                if face == 5.0 { bind p = [u, 0.0 - h, v] }
                bind vx = list_push(vx, list_get(p, 0)) bind vy = list_push(vy, list_get(p, 1)) bind vz = list_push(vz, list_get(p, 2))
                bind i = i + 1.0
            }
            bind j = j + 1.0
        }
        bind j = 0.0
        while j < n {
            bind i = 0.0
            while i < n {
                bind a = base + j * (n + 1.0) + i
                bind r = pr_quad(fi, fs, fc, a, a + 1.0, a + n + 2.0, a + n + 1.0)
                bind fi = list_get(r, 0) bind fs = list_get(r, 1) bind fc = list_get(r, 2)
                bind i = i + 1.0
            }
            bind j = j + 1.0
        }
        bind face = face + 1.0
    }
    return pr_weld([vx, vy, vz, fi, fs, fc], 0.00001)
}

fn pr_circle(n, r, fillmode) {
    bind n = max(3.0, floor(n))
    bind vx = list_new() bind vy = list_new() bind vz = list_new()
    bind i = 0.0
    while i < n {
        bind a = i / n * 6.28318530718
        bind vx = list_push(vx, cos(a) * r) bind vy = list_push(vy, 0.0) bind vz = list_push(vz, sin(a) * r)
        bind i = i + 1.0
    }
    bind fi = list_new() bind fs = list_new() bind fc = list_new()
    if fillmode == 1.0 {
        bind fs = [0.0] bind fc = [n]
        bind i = n - 1.0
        while i >= 0.0 { bind fi = list_push(fi, i) bind i = i - 1.0 }
    } else if fillmode == 2.0 {
        bind vx = list_push(vx, 0.0) bind vy = list_push(vy, 0.0) bind vz = list_push(vz, 0.0)
        bind i = 0.0
        while i < n {
            bind r2 = pr_tri(fi, fs, fc, n, (i + 1.0) % n, i)
            bind fi = list_get(r2, 0) bind fs = list_get(r2, 1) bind fc = list_get(r2, 2)
            bind i = i + 1.0
        }
    } else {
        # edge ring only: zero-area faces are not allowed, so keep it as a polygon with no faces: we add a
        # single n-gon anyway (a wire circle is an n-gon the user can delete faces of)
        bind fs = [0.0] bind fc = [n]
        bind i = n - 1.0
        while i >= 0.0 { bind fi = list_push(fi, i) bind i = i - 1.0 }
    }
    return [vx, vy, vz, fi, fs, fc]
}

fn pr_sphere(segs, rings, r) {
    bind segs = max(3.0, floor(segs)) bind rings = max(2.0, floor(rings))
    bind vx = list_new() bind vy = list_new() bind vz = list_new()
    # top pole, rings, bottom pole
    bind vx = list_push(vx, 0.0) bind vy = list_push(vy, r) bind vz = list_push(vz, 0.0)
    bind j = 1.0
    while j < rings {
        bind phi = j / rings * 3.14159265359
        bind i = 0.0
        while i < segs {
            bind th = i / segs * 6.28318530718
            bind vx = list_push(vx, sin(phi) * cos(th) * r)
            bind vy = list_push(vy, cos(phi) * r)
            bind vz = list_push(vz, sin(phi) * sin(th) * r)
            bind i = i + 1.0
        }
        bind j = j + 1.0
    }
    bind vx = list_push(vx, 0.0) bind vy = list_push(vy, 0.0 - r) bind vz = list_push(vz, 0.0)
    bind bottom = len(vx) - 1.0
    bind fi = list_new() bind fs = list_new() bind fc = list_new()
    bind i = 0.0
    while i < segs {
        bind r2 = pr_tri(fi, fs, fc, 0.0, 1.0 + (i + 1.0) % segs, 1.0 + i)
        bind fi = list_get(r2, 0) bind fs = list_get(r2, 1) bind fc = list_get(r2, 2)
        bind i = i + 1.0
    }
    bind j = 0.0
    while j < rings - 2.0 {
        bind i = 0.0
        while i < segs {
            bind a = 1.0 + j * segs + i
            bind b = 1.0 + j * segs + (i + 1.0) % segs
            bind c = b + segs
            bind d = a + segs
            bind r2 = pr_quad(fi, fs, fc, a, b, c, d)
            bind fi = list_get(r2, 0) bind fs = list_get(r2, 1) bind fc = list_get(r2, 2)
            bind i = i + 1.0
        }
        bind j = j + 1.0
    }
    bind base = 1.0 + (rings - 2.0) * segs
    bind i = 0.0
    while i < segs {
        bind r2 = pr_tri(fi, fs, fc, bottom, base + i, base + (i + 1.0) % segs)
        bind fi = list_get(r2, 0) bind fs = list_get(r2, 1) bind fc = list_get(r2, 2)
        bind i = i + 1.0
    }
    return [vx, vy, vz, fi, fs, fc]
}

fn pr_icosphere(sub, r) {
    bind t = (1.0 + sqrt(5.0)) * 0.5
    bind vx = [0.0 - 1.0, 1.0, 0.0 - 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, t, t, 0.0 - t, 0.0 - t]
    bind vy = [t, t, 0.0 - t, 0.0 - t, 0.0 - 1.0, 1.0, 0.0 - 1.0, 1.0, 0.0, 0.0, 0.0, 0.0]
    bind vz = [0.0, 0.0, 0.0, 0.0, t, t, 0.0 - t, 0.0 - t, 0.0 - 1.0, 1.0, 0.0 - 1.0, 1.0]
    bind tris = [0.0, 11.0, 5.0, 0.0, 5.0, 1.0, 0.0, 1.0, 7.0, 0.0, 7.0, 10.0, 0.0, 10.0, 11.0, 1.0, 5.0, 9.0, 5.0, 11.0, 4.0, 11.0, 10.0, 2.0, 10.0, 7.0, 6.0, 7.0, 1.0, 8.0, 3.0, 9.0, 4.0, 3.0, 4.0, 2.0, 3.0, 2.0, 6.0, 3.0, 6.0, 8.0, 3.0, 8.0, 9.0, 4.0, 9.0, 5.0, 2.0, 4.0, 11.0, 6.0, 2.0, 10.0, 8.0, 6.0, 7.0, 9.0, 8.0, 1.0]
    bind s = 0.0
    while s < sub {
        bind ntris = list_new()
        bind i = 0.0
        while i + 2.0 < len(tris) {
            bind a = list_get(tris, i) bind b = list_get(tris, i + 1.0) bind c = list_get(tris, i + 2.0)
            bind ab = len(vx)
            bind vx = list_push(vx, (list_get(vx, a) + list_get(vx, b)) * 0.5) bind vy = list_push(vy, (list_get(vy, a) + list_get(vy, b)) * 0.5) bind vz = list_push(vz, (list_get(vz, a) + list_get(vz, b)) * 0.5)
            bind bc = len(vx)
            bind vx = list_push(vx, (list_get(vx, b) + list_get(vx, c)) * 0.5) bind vy = list_push(vy, (list_get(vy, b) + list_get(vy, c)) * 0.5) bind vz = list_push(vz, (list_get(vz, b) + list_get(vz, c)) * 0.5)
            bind ca = len(vx)
            bind vx = list_push(vx, (list_get(vx, c) + list_get(vx, a)) * 0.5) bind vy = list_push(vy, (list_get(vy, c) + list_get(vy, a)) * 0.5) bind vz = list_push(vz, (list_get(vz, c) + list_get(vz, a)) * 0.5)
            bind ntris = list_push(ntris, a) bind ntris = list_push(ntris, ab) bind ntris = list_push(ntris, ca)
            bind ntris = list_push(ntris, b) bind ntris = list_push(ntris, bc) bind ntris = list_push(ntris, ab)
            bind ntris = list_push(ntris, c) bind ntris = list_push(ntris, ca) bind ntris = list_push(ntris, bc)
            bind ntris = list_push(ntris, ab) bind ntris = list_push(ntris, bc) bind ntris = list_push(ntris, ca)
            bind i = i + 3.0
        }
        bind tris = ntris
        bind s = s + 1.0
    }
    # project to the sphere
    bind i = 0.0
    while i < len(vx) {
        bind l = sqrt(list_get(vx, i) * list_get(vx, i) + list_get(vy, i) * list_get(vy, i) + list_get(vz, i) * list_get(vz, i))
        bind vx = list_set(vx, i, list_get(vx, i) / l * r) bind vy = list_set(vy, i, list_get(vy, i) / l * r) bind vz = list_set(vz, i, list_get(vz, i) / l * r)
        bind i = i + 1.0
    }
    bind fi = list_new() bind fs = list_new() bind fc = list_new()
    bind i = 0.0
    while i + 2.0 < len(tris) {
        bind r2 = pr_tri(fi, fs, fc, list_get(tris, i), list_get(tris, i + 1.0), list_get(tris, i + 2.0))
        bind fi = list_get(r2, 0) bind fs = list_get(r2, 1) bind fc = list_get(r2, 2)
        bind i = i + 3.0
    }
    return pr_weld([vx, vy, vz, fi, fs, fc], 0.000001)
}

# cylinder / cone / frustum along Y. caps: n-gon caps when 1
fn pr_cone(n, r0, r1, depth, caps) {
    bind n = max(3.0, floor(n))
    bind h = depth * 0.5
    bind vx = list_new() bind vy = list_new() bind vz = list_new()
    bind i = 0.0
    while i < n {
        bind a = i / n * 6.28318530718
        bind vx = list_push(vx, cos(a) * r0) bind vy = list_push(vy, 0.0 - h) bind vz = list_push(vz, sin(a) * r0)
        bind i = i + 1.0
    }
    bind apex = r1 < 0.0001
    if apex {
        bind vx = list_push(vx, 0.0) bind vy = list_push(vy, h) bind vz = list_push(vz, 0.0)
    } else {
        bind i = 0.0
        while i < n {
            bind a = i / n * 6.28318530718
            bind vx = list_push(vx, cos(a) * r1) bind vy = list_push(vy, h) bind vz = list_push(vz, sin(a) * r1)
            bind i = i + 1.0
        }
    }
    bind fi = list_new() bind fs = list_new() bind fc = list_new()
    bind i = 0.0
    while i < n {
        bind j = (i + 1.0) % n
        if apex {
            bind r2 = pr_tri(fi, fs, fc, i, n, j)
        } else {
            bind r2 = pr_quad(fi, fs, fc, i, n + i, n + j, j)
        }
        bind fi = list_get(r2, 0) bind fs = list_get(r2, 1) bind fc = list_get(r2, 2)
        bind i = i + 1.0
    }
    if caps > 0.5 {
        # bottom cap (facing -Y): reverse order
        bind fs = list_push(fs, len(fi)) bind fc = list_push(fc, n)
        bind i = 0.0
        while i < n { bind fi = list_push(fi, i) bind i = i + 1.0 }
        if !apex {
            bind fs = list_push(fs, len(fi)) bind fc = list_push(fc, n)
            bind i = n - 1.0
            while i >= 0.0 { bind fi = list_push(fi, n + i) bind i = i - 1.0 }
        }
    }
    return [vx, vy, vz, fi, fs, fc]
}

fn pr_torus(nmaj, nmin, R, r) {
    bind nmaj = max(3.0, floor(nmaj)) bind nmin = max(3.0, floor(nmin))
    bind vx = list_new() bind vy = list_new() bind vz = list_new()
    bind i = 0.0
    while i < nmaj {
        bind a = i / nmaj * 6.28318530718
        bind j = 0.0
        while j < nmin {
            bind b = j / nmin * 6.28318530718
            bind d = R + cos(b) * r
            bind vx = list_push(vx, cos(a) * d) bind vy = list_push(vy, sin(b) * r) bind vz = list_push(vz, sin(a) * d)
            bind j = j + 1.0
        }
        bind i = i + 1.0
    }
    bind fi = list_new() bind fs = list_new() bind fc = list_new()
    bind i = 0.0
    while i < nmaj {
        bind i2 = (i + 1.0) % nmaj
        bind j = 0.0
        while j < nmin {
            bind j2 = (j + 1.0) % nmin
            bind r2 = pr_quad(fi, fs, fc, i * nmin + j, i * nmin + j2, i2 * nmin + j2, i2 * nmin + j)
            bind fi = list_get(r2, 0) bind fs = list_get(r2, 1) bind fc = list_get(r2, 2)
            bind j = j + 1.0
        }
        bind i = i + 1.0
    }
    return [vx, vy, vz, fi, fs, fc]
}

fn pr_capsule(segs, rings, r, length) {
    bind segs = max(3.0, floor(segs)) bind rings = max(1.0, floor(rings))
    bind h = length * 0.5
    bind vx = list_new() bind vy = list_new() bind vz = list_new()
    bind vx = list_push(vx, 0.0) bind vy = list_push(vy, h + r) bind vz = list_push(vz, 0.0)
    # upper hemisphere rings (excluding pole), equator ring, lower rings
    bind rows = list_new()
    bind j = 1.0
    while j <= rings {
        bind phi = j / rings * 1.5707963268
        bind rr = sin(phi) * r
        bind yy = h + cos(phi) * r
        bind i = 0.0
        while i < segs {
            bind th = i / segs * 6.28318530718
            bind vx = list_push(vx, cos(th) * rr) bind vy = list_push(vy, yy) bind vz = list_push(vz, sin(th) * rr)
            bind i = i + 1.0
        }
        bind j = j + 1.0
    }
    bind j = 1.0
    while j <= rings {
        bind phi = 1.5707963268 + j / rings * 1.5707963268
        bind rr = sin(phi) * r
        bind yy = 0.0 - h + cos(phi) * r
        if j == rings { bind rr = 0.0 }
        bind i = 0.0
        while i < segs {
            bind th = i / segs * 6.28318530718
            bind vx = list_push(vx, cos(th) * rr) bind vy = list_push(vy, yy) bind vz = list_push(vz, sin(th) * rr)
            bind i = i + 1.0
        }
        bind j = j + 1.0
    }
    bind nrows = rings * 2.0
    bind fi = list_new() bind fs = list_new() bind fc = list_new()
    bind i = 0.0
    while i < segs {
        bind r2 = pr_tri(fi, fs, fc, 0.0, 1.0 + (i + 1.0) % segs, 1.0 + i)
        bind fi = list_get(r2, 0) bind fs = list_get(r2, 1) bind fc = list_get(r2, 2)
        bind i = i + 1.0
    }
    bind j = 0.0
    while j < nrows - 1.0 {
        bind i = 0.0
        while i < segs {
            bind a = 1.0 + j * segs + i
            bind b = 1.0 + j * segs + (i + 1.0) % segs
            bind r2 = pr_quad(fi, fs, fc, a, b, b + segs, a + segs)
            bind fi = list_get(r2, 0) bind fs = list_get(r2, 1) bind fc = list_get(r2, 2)
            bind i = i + 1.0
        }
        bind j = j + 1.0
    }
    return pr_weld([vx, vy, vz, fi, fs, fc], 0.000001)
}

# weld coincident vertices (within d) and drop degenerate faces. g = [vx,vy,vz,fi,fs,fc]
fn pr_weld(g, d) {
    bind vx = list_get(g, 0) bind vy = list_get(g, 1) bind vz = list_get(g, 2)
    bind fi = list_get(g, 3) bind fs = list_get(g, 4) bind fc = list_get(g, 5)
    bind n = len(vx)
    # sort by x then scan neighbours
    bind order = mx_argsort(vx)
    bind remap = me_fill(n, 0.0 - 1.0)
    bind nvx = list_new() bind nvy = list_new() bind nvz = list_new()
    bind i = 0.0
    while i < n {
        bind vi = list_get(order, i)
        if list_get(remap, vi) < 0.0 {
            bind id = len(nvx)
            bind nvx = list_push(nvx, list_get(vx, vi)) bind nvy = list_push(nvy, list_get(vy, vi)) bind nvz = list_push(nvz, list_get(vz, vi))
            bind remap = list_set(remap, vi, id)
            bind j = i + 1.0
            bind go = true
            while go {
                if j >= n { bind go = false }
                else {
                    bind vj = list_get(order, j)
                    if list_get(vx, vj) - list_get(vx, vi) > d { bind go = false }
                    else {
                        if list_get(remap, vj) < 0.0 && abs(list_get(vy, vj) - list_get(vy, vi)) <= d && abs(list_get(vz, vj) - list_get(vz, vi)) <= d { bind remap = list_set(remap, vj, id) }
                        bind j = j + 1.0
                    }
                }
            }
        }
        bind i = i + 1.0
    }
    bind nfi = list_new() bind nfs = list_new() bind nfc = list_new()
    bind f = 0.0
    while f < len(fc) {
        bind s = list_get(fs, f) bind c = list_get(fc, f)
        bind corners = list_new()
        bind k = 0.0
        while k < c {
            bind v = list_get(remap, list_get(fi, s + k))
            bind addc = true
            if len(corners) > 0.5 { if list_get(corners, len(corners) - 1.0) == v { bind addc = false } }
            if addc { bind corners = list_push(corners, v) }
            bind k = k + 1.0
        }
        if len(corners) > 1.5 && list_get(corners, 0) == list_get(corners, len(corners) - 1.0) {
            bind tmp = list_new()
            bind k = 0.0
            while k < len(corners) - 1.0 { bind tmp = list_push(tmp, list_get(corners, k)) bind k = k + 1.0 }
            bind corners = tmp
        }
        if len(corners) >= 3.0 {
            bind nfs = list_push(nfs, len(nfi)) bind nfc = list_push(nfc, len(corners))
            bind k = 0.0
            while k < len(corners) { bind nfi = list_push(nfi, list_get(corners, k)) bind k = k + 1.0 }
        }
        bind f = f + 1.0
    }
    return [nvx, nvy, nvz, nfi, nfs, nfc]
}

← Back to index