nx_objload.nx source
↩ module page · 119 lines · 4959 B
1// nx_objload.nx -- ★sovereign Wavefront OBJ loader (the Stanford-corpus rung of the field-evidence foundation): parse
2// `v x y z` + `f a b c` ASCII into nx_trimesh, bbox-normalized to a target extent. Signed 6-decimal coords are read in
3// MICRO units (x1e6) so the bunny's 0.15-metre scale survives integer parsing. Two passes (bbox, emit). license_tier: ORIGINAL
4import "nx_syscalls.nx"
5import "nx_trimesh.nx"
6const K_MAGIC_1000000: i64 = 1000000
7const K_MAGIC_100000: i64 = 100000
8const K_MAGIC_2000000000: i64 = 2000000000
9const K_MAGIC_1024: i64 = 1024
10
11// parse a signed decimal at p (skips leading spaces) -> micro (x1e6). out[0]=value, returns new position.
12func obj_num(buf: *u8, end: i64, p0: i64, out: *i64) -> i64 {
13 var p: i64 = p0
14 var sk: i64 = 1
15 while sk == 1 { if p < end { if (buf[p] as i64) == 32 { p = p + 1 } else { sk = 0 } } else { sk = 0 } }
16 var neg: i64 = 0
17 if p < end { if (buf[p] as i64) == 45 { neg = 1; p = p + 1 } }
18 var ip: i64 = 0
19 var go: i64 = 1
20 while go == 1 {
21 if p < end {
22 let c: i64 = buf[p] as i64
23 var isd: i64 = 0
24 if c >= 48 { if c <= 57 { isd = 1 } }
25 if isd == 1 { ip = ip*10 + (c-48); p = p + 1 } else { go = 0 }
26 } else { go = 0 }
27 }
28 var micro: i64 = ip * K_MAGIC_1000000
29 if p < end { if (buf[p] as i64) == 46 {
30 p = p + 1
31 var fd: i64 = 0
32 var mul: i64 = K_MAGIC_100000
33 go = 1
34 while go == 1 {
35 if p < end {
36 let c: i64 = buf[p] as i64
37 var isd: i64 = 0
38 if c >= 48 { if c <= 57 { isd = 1 } }
39 if isd == 1 {
40 if fd < 6 { micro = micro + (c-48)*mul; mul = mul/10; fd = fd + 1 }
41 p = p + 1
42 } else { go = 0 }
43 } else { go = 0 }
44 }
45 } }
46 if neg == 1 { micro = 0 - micro }
47 out[0] = micro
48 return p
49}
50// is position p the start of a line whose first two bytes are ch,' '?
51func obj_linestart(buf: *u8, p: i64, ch: i64) -> i64 {
52 var atstart: i64 = 0
53 if p == 0 { atstart = 1 }
54 if p > 0 { if (buf[p-1] as i64) == 10 { atstart = 1 } }
55 if atstart == 0 { return 0 }
56 if (buf[p] as i64) != ch { return 0 }
57 if (buf[p+1] as i64) != 32 { return 0 }
58 return 1
59}
60// ★load an OBJ into trimesh, normalized to `target` extent about the origin. col = base vertex colour. 1 ok.
61func obj_load(path: *u8, target: i64, col: i64) -> i64 {
62 let szp: *i64 = sys_mmap(16) as *i64
63 let buf: *u8 = sys_read_file(path, szp)
64 let size: i64 = szp[0]
65 if (buf as i64) == 0 { return 0 }
66 if size < 32 { return 0 }
67 let num: *i64 = sys_mmap(8) as *i64
68 // ---- pass 1: bbox over v lines ----
69 var minx: i64 = K_MAGIC_2000000000; var miny: i64 = K_MAGIC_2000000000; var minz: i64 = K_MAGIC_2000000000
70 var maxx: i64 = 0-K_MAGIC_2000000000; var maxy: i64 = 0-K_MAGIC_2000000000; var maxz: i64 = 0-K_MAGIC_2000000000
71 var p: i64 = 0
72 while p < size {
73 if obj_linestart(buf, p, 118) == 1 { // 'v '
74 var q: i64 = p + 2
75 q = obj_num(buf, size, q, num); let x: i64 = num[0]
76 q = obj_num(buf, size, q, num); let y: i64 = num[0]
77 q = obj_num(buf, size, q, num); let z: i64 = num[0]
78 if x<minx {minx=x} if x>maxx {maxx=x}
79 if y<miny {miny=y} if y>maxy {maxy=y}
80 if z<minz {minz=z} if z>maxz {maxz=z}
81 p = q
82 } else { p = p + 1 }
83 }
84 var ext: i64 = maxx-minx
85 if maxy-miny > ext { ext = maxy-miny }
86 if maxz-minz > ext { ext = maxz-minz }
87 if ext < 1 { return 0 }
88 let s1024: i64 = target*K_MAGIC_1024/ext
89 if s1024 < 1 { return 0 }
90 let cx: i64 = (minx+maxx)/2; let cy: i64 = (miny+maxy)/2; let cz: i64 = (minz+maxz)/2
91 // ---- pass 2: emit ----
92 tm_reset()
93 p = 0
94 while p < size {
95 var handled: i64 = 0
96 if obj_linestart(buf, p, 118) == 1 { // 'v '
97 var q: i64 = p + 2
98 q = obj_num(buf, size, q, num); let x: i64 = (num[0]-cx)*s1024/K_MAGIC_1024
99 q = obj_num(buf, size, q, num); let y: i64 = (num[0]-cy)*s1024/K_MAGIC_1024
100 q = obj_num(buf, size, q, num); let z: i64 = (num[0]-cz)*s1024/K_MAGIC_1024
101 let idx: i64 = tm_vert(x, y, z)
102 tm_vcol(idx, col)
103 p = q
104 handled = 1
105 }
106 if handled == 0 { if obj_linestart(buf, p, 102) == 1 { // 'f '
107 var q: i64 = p + 2
108 q = obj_num(buf, size, q, num); let a: i64 = num[0]/K_MAGIC_1000000
109 q = obj_num(buf, size, q, num); let b: i64 = num[0]/K_MAGIC_1000000
110 q = obj_num(buf, size, q, num); let c: i64 = num[0]/K_MAGIC_1000000
111 tm_tri(a-1, b-1, c-1, col) // OBJ is 1-indexed
112 p = q
113 handled = 1
114 } }
115 if handled == 0 { p = p + 1 }
116 }
117 tm_compute_normals()
118 return 1
119}