forked from michaljaz/webmc
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSectionComputer.js
More file actions
106 lines (98 loc) · 3.39 KB
/
SectionComputer.js
File metadata and controls
106 lines (98 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
const modulo = function (a, b) {
return ((+a % (b = +b)) + b) % b;
};
class BitArray {
constructor(options) {
if (options === null) {
return;
}
if (!options.bitsPerValue > 0) {
console.error("bits per value must at least 1");
}
if (!(options.bitsPerValue <= 32)) {
console.error("bits per value exceeds 32");
}
let valuesPerLong = Math.floor(64 / options.bitsPerValue);
let length = Math.ceil(options.capacity / valuesPerLong);
if (!options.data) {
options.data = Array(length * 2).fill(0);
}
let valueMask = (1 << options.bitsPerValue) - 1;
this.data = options.data;
this.capacity = options.capacity;
this.bitsPerValue = options.bitsPerValue;
this.valuesPerLong = valuesPerLong;
this.valueMask = valueMask;
}
get(index) {
if (!(index >= 0 && index < this.capacity)) {
console.error("index is out of bounds");
}
const startLongIndex = Math.floor(index / this.valuesPerLong);
const indexInLong =
(index - startLongIndex * this.valuesPerLong) * this.bitsPerValue;
if (indexInLong >= 32) {
let indexInStartLong = indexInLong - 32;
let startLong = this.data[startLongIndex * 2 + 1];
return (startLong >>> indexInStartLong) & this.valueMask;
}
let startLong = this.data[startLongIndex * 2];
let indexInStartLong = indexInLong;
let result = startLong >>> indexInStartLong;
const endBitOffset = indexInStartLong + this.bitsPerValue;
if (endBitOffset > 32) {
const endLong = this.data[startLongIndex * 2 + 1];
result |= endLong << (32 - indexInStartLong);
}
return result & this.valueMask;
}
}
const ChunkDecoder = class ChunkDecoder {
getBlockIndex(pos) {
return (pos.y << 8) | (pos.z << 4) | pos.x;
}
cvo(voxelX, voxelY, voxelZ) {
const x = modulo(voxelX, 16) | 0;
const y = modulo(voxelY, 16) | 0;
const z = modulo(voxelZ, 16) | 0;
return y * 16 * 16 + z * 16 + x;
}
computeSections(packet) {
const sections = packet.sections;
let num = 0;
const result = [];
for (let j = 0; j < sections.length; j++) {
const i = sections[j];
num += 1;
if (i !== null) {
const palette = i.palette;
const data = new BitArray(i.data);
const cell = new Uint32Array(16 * 16 * 16);
for (let x = 0; x < 16; x++) {
for (let y = 0; y < 16; y++) {
for (let z = 0; z < 16; z++) {
cell[this.cvo(x, y, z)] =
palette[
data.get(this.getBlockIndex({ x, y, z }))
];
}
}
}
result.push({
x: packet.x,
y: num,
z: packet.z,
cell,
});
} else {
result.push(null);
}
}
return result;
}
};
const cd = new ChunkDecoder();
const SectionComputer = function (data) {
return cd.computeSections(data);
};
export { SectionComputer };