4 import iv
.glbinds
.utils
;
11 static import iv
.timer
;
16 // ////////////////////////////////////////////////////////////////////////// //
17 public __gshared
bool vox_optimize_hollow
= true;
20 //==========================================================================
24 //==========================================================================
25 private void loadKVX (ref VoxelData vox
, VFile fl
, uint fsize
) {
26 if (fsize
> int.max
/8) throw new Exception("voxel data too big (kvx)");
27 version(kvx_dump
) conwriteln("loading KVX...");
28 auto nextpos
= fl
.tell
+fsize
;
33 int xpivot
, ypivot
, zpivot
;
35 auto fx
= wrapStreamRO(fl
, fl
.tell
, fsize
);
36 xsiz
= fx
.readNum
!uint;
37 ysiz
= fx
.readNum
!uint;
38 zsiz
= fx
.readNum
!uint;
39 version(kvx_dump
) conwriteln("xsiz=", xsiz
, "; ysiz=", ysiz
, "; zsiz=", zsiz
);
40 if (xsiz
< 1 || ysiz
< 1 || zsiz
< 1 || xsiz
> 1024 || ysiz
> 1024 || zsiz
> 1024) throw new Exception("invalid voxel size");
41 xpivot
= fx
.readNum
!uint;
42 ypivot
= fx
.readNum
!uint;
43 zpivot
= fx
.readNum
!uint;
44 version(kvx_dump
) conwriteln("xpivot=", xpivot
>>8, "; ypivot=", ypivot
>>8, "; zpivot=", zpivot
>>8);
45 uint xstart
= (xsiz
+1)*4+xsiz
*(ysiz
+1)*2;
46 xofs
= new uint[](xsiz
+1);
47 foreach (ref o
; xofs
) o
= fx
.readNum
!uint-xstart
;
49 xyofs
= new ushort[][](xsiz
, ysiz
+1);
50 foreach (immutable x
; 0..xsiz
) {
51 foreach (immutable y
; 0..ysiz
+1) {
52 xyofs
[x
][y
] = fx
.readNum
!ushort;
55 assert(fx
.size
-fx
.tell
== fsize
-24-(xsiz
+1)*4-xsiz
*(ysiz
+1)*2);
56 data
= new ubyte[](cast(uint)(fx
.size
-fx
.tell
));
57 fx
.rawReadExact(data
);
61 while (fl
.size
-fl
.tell
> 768) {
62 fsize
= fl
.readNum
!uint; // size of this voxel (useful for mipmaps)
63 fl
.seek(fsize
, Seek
.Cur
);
64 version(kvx_dump
) conwriteln(" skiped ", fsize
, " bytes of mipmap");
67 if (fl
.size
-fl
.tell
== 768) {
68 version(kvx_dump
) conwriteln(" has palette!");
69 fl
.rawReadExact(pal
[]);
70 foreach (ref ubyte c
; pal
[]) {
71 if (c
> 63) throw new Exception("invalid palette value");
72 c
= clampToByte(255*c
/64);
75 foreach (immutable cidx
; 0..256) {
81 immutable float px
= 1.0f*xpivot
/256.0f;
82 immutable float py
= 1.0f*ypivot
/256.0f;
83 immutable float pz
= 1.0f*zpivot
/256.0f;
85 version(kvx_dump
) conwriteln("building voxel data...");
86 vox
.setSize(xsiz
, ysiz
, zsiz
);
87 foreach (immutable y
; 0..ysiz
) {
88 foreach (immutable x
; 0..xsiz
) {
89 uint sofs
= xofs
[x
]+xyofs
[x
][y
];
90 uint eofs
= xofs
[x
]+xyofs
[x
][y
+1];
92 int ztop
= data
[sofs
++];
93 uint zlen
= data
[sofs
++];
94 ubyte cull
= data
[sofs
++];
96 //conwritefln(" x=%s; y=%s; z=%s; len=%s; cull=0x%02x", x, y, ztop, zlen, cull);
98 foreach (immutable cidx
; 0..zlen
) {
99 ubyte palcol
= data
[sofs
++];
102 // no need to do this, voxel optimiser will take care of it
103 if (cidx
!= 0) cl
&= cast(ubyte)~0x10;
104 if (cidx
!= zlen
-1) cl
&= cast(ubyte)~0x20;
106 immutable ubyte r
= pal
[palcol
*3+0];
107 immutable ubyte g
= pal
[palcol
*3+1];
108 immutable ubyte b
= pal
[palcol
*3+2];
109 //addCube(cl, (xsiz-x-1)-px, y-py, (zsiz-ztop-1)-pz, b|(g<<8)|(r<<16));
110 //version(kvx_dump) conwriteln(" adding voxel at (", x, ",", y, ",", ztop, ")");
111 vox
.addVoxel(xsiz
-x
-1, y
, zsiz
-ztop
-1, b|
(g
<<8)|
(r
<<16), cl
);
112 //version(kvx_dump) conwriteln(" added.");
116 assert(sofs
== eofs
);
125 //==========================================================================
129 //==========================================================================
130 private void loadKV6 (ref VoxelData vox
, VFile fl
) {
131 version(kvx_dump
) conwriteln("loading KV6...");
132 int xsiz
, ysiz
, zsiz
;
133 float xpivot
, ypivot
, zpivot
;
134 xsiz
= fl
.readNum
!uint;
135 ysiz
= fl
.readNum
!uint;
136 zsiz
= fl
.readNum
!uint;
137 version(kvx_dump
) conwriteln("xsiz=", xsiz
, "; ysiz=", ysiz
, "; zsiz=", zsiz
);
138 if (xsiz
< 1 || ysiz
< 1 || zsiz
< 1 || xsiz
> 1024 || ysiz
> 1024 || zsiz
> 1024) {
139 throw new Exception("invalid voxel size (kv6)");
141 xpivot
= fl
.readNum
!float;
142 ypivot
= fl
.readNum
!float;
143 zpivot
= fl
.readNum
!float;
144 version(kvx_dump
) conwriteln("xpivot=", xpivot
, "; ypivot=", ypivot
, "; zpivot=", zpivot
);
145 uint voxcount
= fl
.readNum
!uint;
146 if (voxcount
== 0 || voxcount
> int.max
/8) throw new Exception("invalid number of voxels");
154 auto kvox
= new KVox
[](voxcount
);
155 foreach (immutable vidx
; 0..voxcount
) {
156 auto kv
= &kvox
[vidx
];
158 kv
.rgb |
= fl
.readNum
!ubyte;
159 kv
.rgb |
= fl
.readNum
!ubyte<<8;
160 kv
.rgb |
= fl
.readNum
!ubyte<<16;
161 kv
.rgb |
= 0xff_00_00_00U;
162 fl
.readNum
!ubyte; // always 128; ignore
163 kv
.zlo
= fl
.readNum
!ubyte;
164 kv
.zhi
= fl
.readNum
!ubyte;
165 if (kv
.zhi
) assert(0, "zhi is not zero!");
166 kv
.cull
= fl
.readNum
!ubyte;
167 kv
.normidx
= fl
.readNum
!ubyte;
169 auto xofs
= new uint[](xsiz
+1);
171 foreach (ref v
; xofs
[0..$-1]) {
173 auto count
= fl
.readNum
!uint;
177 auto xyofs
= new uint[][](xsiz
, ysiz
+1);
178 foreach (immutable xx
; 0..xsiz
) {
180 foreach (immutable yy
; 0..ysiz
) {
181 xyofs
[xx
][yy
] = curvidx
;
182 auto count
= fl
.readNum
!ushort;
185 xyofs
[xx
][$-1] = curvidx
;
188 vox
.setSize(xsiz
, ysiz
, zsiz
);
189 foreach (immutable y
; 0..ysiz
) {
190 foreach (immutable x
; 0..xsiz
) {
191 uint sofs
= xofs
[x
]+xyofs
[x
][y
];
192 uint eofs
= xofs
[x
]+xyofs
[x
][y
+1];
193 //if (sofs == eofs) continue;
194 //assert(sofs < data.length && eofs <= data.length);
195 while (sofs
< eofs
) {
196 auto kv
= &kvox
[sofs
++];
197 //debug(kvx_dump) conwritefln(" x=%s; y=%s; zlo=%s; zhi=%s; cull=0x%02x", x, y, kv.zlo, kv.zhi, kv.cull);
199 foreach (immutable cidx
; 0..kv
.zhi
+1) {
201 vox
.addVoxel(xsiz
-x
-1, y
, zsiz
-z
, kv
.rgb
, kv
.cull
);
206 //conwriteln(texpos);
213 //==========================================================================
217 //==========================================================================
218 private void loadVox (ref VoxelData vox
, VFile fl
, uint xsiz
) {
219 version(kvx_dump
) conwriteln("loading VOX...");
220 uint ysiz
= fl
.readNum
!uint;
221 uint zsiz
= fl
.readNum
!uint;
222 /*debug(kvx_dump)*/ conwriteln("xsiz=", xsiz
, "; ysiz=", ysiz
, "; zsiz=", zsiz
);
223 if (xsiz
< 1 || ysiz
< 1 || zsiz
< 1 || xsiz
> 1024 || ysiz
> 1024 || zsiz
> 1024) {
224 throw new Exception("invalid voxel size (vox)");
226 auto fpos
= fl
.tell();
227 fl
.seek(fpos
+xsiz
*ysiz
*zsiz
);
228 //auto data = new ubyte[](xsiz*ysiz*zsiz);
229 //fl.rawReadExact(data);
231 fl
.rawReadExact(pal
[]);
232 foreach (ref ubyte c
; pal
[]) {
233 if (c
> 63) throw new Exception("invalid palette value");
234 c
= clampToByte(255*c
/64);
236 immutable float px
= 1.0f*xsiz
/2.0f;
237 immutable float py
= 1.0f*ysiz
/2.0f;
238 immutable float pz
= 1.0f*zsiz
/2.0f;
241 vox
.setSize(xsiz
, ysiz
, zsiz
);
242 foreach (immutable x
; 0..xsiz
) {
243 foreach (immutable y
; 0..ysiz
) {
244 foreach (immutable z
; 0..zsiz
) {
245 ubyte palcol
= fl
.readNum
!ubyte;
247 uint rgb
= pal
[palcol
*3+2]|
(cast(uint)pal
[palcol
*3+1]<<8)|
(cast(uint)pal
[palcol
*3+0]<<16);
248 //addCube(0xff, (xsiz-x-1)-px, y-py, (zsiz-z-1)-pz, b|(g<<8)|(r<<16));
249 vox
.addVoxel(xsiz
-x
-1, y
, zsiz
-z
-1, rgb
, 0xff);
260 //==========================================================================
264 //==========================================================================
265 private void loadVxl (ref VoxelData vox
, VFile fl
) {
266 uint xsiz
= fl
.readNum
!uint;
267 uint ysiz
= fl
.readNum
!uint;
269 /*debug(kvx_dump)*/ conwriteln("xsiz=", xsiz
, "; ysiz=", ysiz
, "; zsiz=", zsiz
);
270 if (xsiz
< 1 || ysiz
< 1 || zsiz
< 1 || xsiz
> 1024 || ysiz
> 1024 || zsiz
> 1024) throw new Exception("invalid voxel size");
271 //immutable float px = 1.0f*xsiz/2.0f;
272 //immutable float py = 1.0f*ysiz/2.0f;
273 //immutable float pz = 1.0f*zsiz/2.0f;
276 px
= fl
.readNum
!double;
277 py
= fl
.readNum
!double;
278 pz
= fl
.readNum
!double;
293 vox
.setSize(xsiz
, ysiz
, zsiz
);
295 void vxlReset (int x
, int y
, int z
) {
296 vox
.removeVoxel(xsiz
-x
-1, y
, zsiz
-z
-1);
299 void vxlPaint (int x
, int y
, int z
, uint clr
) {
300 vox
.addVoxel(xsiz
-x
-1, y
, zsiz
-z
-1, clr
, 0x3f);
303 // now carve crap out of it
304 auto data
= new ubyte[](cast(uint)(fl
.size
-fl
.tell
));
305 fl
.rawReadExact(data
);
306 const(ubyte)* v
= data
.ptr
;
307 foreach (immutable y
; 0..ysiz
) {
308 foreach (immutable x
; 0..xsiz
) {
311 foreach (immutable i
; z
..v
[1]) vxlReset(x
, y
, i
);
312 for (z
= v
[1]; z
<= v
[2]; ++z
) {
313 const(uint)* cp
= cast(const(uint)*)(v
+(z
-v
[1]+1)*4);
314 vxlPaint(x
, y
, z
, *cp
);
317 z
= v
[2]-v
[1]-v
[0]+2;
319 for (z
+= v
[3]; z
< v
[3]; ++z
) {
320 const(uint)* cp
= cast(const(uint)*)(v
+(z
-v
[3])*4);
321 vxlPaint(x
, y
, z
, *cp
);
324 v
+= (v
[2]-v
[1]+2)*4;
333 //==========================================================================
337 //==========================================================================
338 public void loadVoxel (ref VoxelData vox
, string fname
, bool asvox
=false) {
339 auto fl
= VFile(fname
);
340 uint fsize
= fl
.readNum
!uint; // size of this voxel (useful for mipmaps)
341 auto tm
= iv
.timer
.Timer(true);
342 if (fsize
== 0x6c78764bU
) {
344 } else if (fsize
== 0x09072000U
) {
347 if (fname
.endsWithCI(".vox")) loadVox(vox
, fl
, fsize
);
348 else loadKVX(vox
, fl
, fsize
);
351 conwriteln("loaded in ", tm
.toString(), "; grid size: ", vox
.xsize
, "x", vox
.ysize
, "x", vox
.zsize
);
353 vox
.optimise(vox_optimize_hollow
);
355 conwriteln("optimised in ", tm
.toString());