bucciafico-lib 1.0.7 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/core/SkinViewer.js +154 -9
- package/src/managers/EventManager.js +74 -0
- package/src/managers/PostProcessingManager.js +24 -0
- package/src/objects/SceneSetup.js +49 -8
- package/src/objects/SkinModel.js +205 -12
- package/src/plugins/EditorPlugin.js +45 -14
- package/src/plugins/EffectsPlugin.js +45 -20
- package/src/plugins/IOPlugin.js +46 -17
- package/src/plugins/ItemsPlugin.js +121 -2
- package/src/utils/SkinUtils.js +17 -17
- package/src/utils/ThreeUtils.js +27 -0
- package/src/utils/Voxelizer.js +139 -33
package/src/utils/Voxelizer.js
CHANGED
|
@@ -1,58 +1,164 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
let cachedCanvas = null;
|
|
4
|
+
let cachedCtx = null;
|
|
5
|
+
|
|
6
|
+
function getImageData(image) {
|
|
7
|
+
if (!cachedCanvas) {
|
|
8
|
+
cachedCanvas = document.createElement('canvas');
|
|
9
|
+
cachedCanvas.width = 64;
|
|
10
|
+
cachedCanvas.height = 64;
|
|
11
|
+
cachedCtx = cachedCanvas.getContext('2d', { willReadFrequently: true });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
cachedCtx.clearRect(0, 0, 64, 64);
|
|
15
|
+
cachedCtx.drawImage(image, 0, 0);
|
|
16
|
+
return cachedCtx.getImageData(0, 0, 64, 64).data;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const CUBE = {
|
|
20
|
+
vertices: [
|
|
21
|
+
// Right
|
|
22
|
+
0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5,
|
|
23
|
+
// Left
|
|
24
|
+
-0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5,
|
|
25
|
+
// Top
|
|
26
|
+
-0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5,
|
|
27
|
+
// Bottom
|
|
28
|
+
-0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5,
|
|
29
|
+
// Front
|
|
30
|
+
-0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5,
|
|
31
|
+
// Back
|
|
32
|
+
-0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5
|
|
33
|
+
],
|
|
34
|
+
normals: [
|
|
35
|
+
// Right
|
|
36
|
+
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
|
|
37
|
+
// Left
|
|
38
|
+
-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,
|
|
39
|
+
// Top
|
|
40
|
+
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
|
|
41
|
+
// Bottom
|
|
42
|
+
0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,
|
|
43
|
+
// Front
|
|
44
|
+
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,
|
|
45
|
+
// Back
|
|
46
|
+
0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1
|
|
47
|
+
],
|
|
48
|
+
indices: [
|
|
49
|
+
0, 1, 2, 0, 2, 3, // Right
|
|
50
|
+
4, 5, 6, 4, 6, 7, // Left
|
|
51
|
+
8, 9, 10, 8, 10, 11, // Top
|
|
52
|
+
12, 13, 14, 12, 14, 15, // Bottom
|
|
53
|
+
16, 17, 18, 16, 18, 19, // Front
|
|
54
|
+
20, 21, 22, 20, 22, 23 // Back
|
|
55
|
+
]
|
|
56
|
+
};
|
|
3
57
|
|
|
4
58
|
/**
|
|
5
59
|
* Converts the 2nd layer of a skin (Hat, Jacket) into 3D Voxels.
|
|
6
|
-
*
|
|
60
|
+
* Optimized version: Direct buffer manipulation instead of object merging.
|
|
61
|
+
*
|
|
7
62
|
* @param {THREE.Texture} texture
|
|
8
63
|
* @param {Object} layerDef - Definition of UVs and dimensions.
|
|
9
64
|
* @returns {THREE.BufferGeometry|null} Merged geometry of all voxels.
|
|
10
65
|
*/
|
|
11
66
|
export function createVoxelLayer(texture, layerDef) {
|
|
12
|
-
const
|
|
13
|
-
canvas.width = 64; canvas.height = 64;
|
|
14
|
-
const ctx = canvas.getContext('2d');
|
|
15
|
-
ctx.drawImage(texture.image, 0, 0);
|
|
16
|
-
const imgData = ctx.getImageData(0, 0, 64, 64).data;
|
|
17
|
-
|
|
18
|
-
const geometries = [];
|
|
67
|
+
const imgData = getImageData(texture.image);
|
|
19
68
|
const { outer } = layerDef.uv;
|
|
20
69
|
const { w, h, d } = layerDef.size;
|
|
21
70
|
|
|
22
|
-
|
|
71
|
+
const positions = [];
|
|
72
|
+
const normals = [];
|
|
73
|
+
const uvs = [];
|
|
74
|
+
const indices = [];
|
|
75
|
+
|
|
76
|
+
let vertexOffset = 0;
|
|
77
|
+
|
|
78
|
+
const addVoxel = (cx, cy, cz, sx, sy, sz, u, v) => {
|
|
79
|
+
const uCoord = (u + 0.5) / 64;
|
|
80
|
+
const vCoord = 1.0 - (v + 0.5) / 64;
|
|
81
|
+
|
|
82
|
+
for (let i = 0; i < 24; i++) {
|
|
83
|
+
const vx = CUBE.vertices[i * 3] * sx + cx;
|
|
84
|
+
const vy = CUBE.vertices[i * 3 + 1] * sy + cy;
|
|
85
|
+
const vz = CUBE.vertices[i * 3 + 2] * sz + cz;
|
|
86
|
+
|
|
87
|
+
positions.push(vx, vy, vz);
|
|
88
|
+
normals.push(CUBE.normals[i * 3], CUBE.normals[i * 3 + 1], CUBE.normals[i * 3 + 2]);
|
|
89
|
+
uvs.push(uCoord, vCoord);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (let i = 0; i < CUBE.indices.length; i++) {
|
|
93
|
+
indices.push(CUBE.indices[i] + vertexOffset);
|
|
94
|
+
}
|
|
95
|
+
vertexOffset += 24;
|
|
96
|
+
};
|
|
97
|
+
|
|
23
98
|
const faces = [
|
|
24
|
-
|
|
25
|
-
{
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
99
|
+
// Face 0: Front (Z+)
|
|
100
|
+
{
|
|
101
|
+
u: outer.x + d, v: outer.y + d, width: w, height: h,
|
|
102
|
+
pos: (i, j) => ({ x: i - w/2 + 0.5, y: j - h/2 + 0.5, z: d/2 + 0.25 }),
|
|
103
|
+
scale: { z: 0.5 }
|
|
104
|
+
},
|
|
105
|
+
// Face 1: Back (Z-)
|
|
106
|
+
{
|
|
107
|
+
u: outer.x + d + w + d, v: outer.y + d, width: w, height: h,
|
|
108
|
+
pos: (i, j) => ({ x: -(i - w/2 + 0.5), y: j - h/2 + 0.5, z: -d/2 - 0.25 }),
|
|
109
|
+
scale: { z: 0.5 }
|
|
110
|
+
},
|
|
111
|
+
// Face 2: Right UV / Left 3D (X-)
|
|
112
|
+
{
|
|
113
|
+
u: outer.x, v: outer.y + d, width: d, height: h,
|
|
114
|
+
pos: (i, j) => ({ x: -w/2 - 0.25, y: j - h/2 + 0.5, z: i - d/2 + 0.5 }),
|
|
115
|
+
scale: { x: 0.5 }
|
|
116
|
+
},
|
|
117
|
+
// Face 3: Left UV / Right 3D (X+)
|
|
118
|
+
{
|
|
119
|
+
u: outer.x + d + w, v: outer.y + d, width: d, height: h,
|
|
120
|
+
pos: (i, j) => ({ x: w/2 + 0.25, y: j - h/2 + 0.5, z: -(i - d/2 + 0.5) }),
|
|
121
|
+
scale: { x: 0.5 }
|
|
122
|
+
},
|
|
123
|
+
// Face 4: Top (Y+)
|
|
124
|
+
{
|
|
125
|
+
u: outer.x + d, v: outer.y, width: w, height: d,
|
|
126
|
+
pos: (i, j) => ({ x: i - w/2 + 0.5, y: h/2 + 0.25, z: -(j - d/2 + 0.5) }),
|
|
127
|
+
scale: { y: 0.5 }
|
|
128
|
+
},
|
|
129
|
+
// Face 5: Bottom (Y-)
|
|
130
|
+
{
|
|
131
|
+
u: outer.x + d + w, v: outer.y, width: w, height: d,
|
|
132
|
+
pos: (i, j) => ({ x: i - w/2 + 0.5, y: -h/2 - 0.25, z: (d - 1 - j) - d/2 + 0.5 }),
|
|
133
|
+
scale: { y: 0.5 }
|
|
134
|
+
}
|
|
30
135
|
];
|
|
31
136
|
|
|
32
|
-
const baseGeo = new THREE.BoxGeometry(1, 1, 1);
|
|
33
|
-
|
|
34
137
|
faces.forEach(f => {
|
|
35
|
-
for(let i=0; i<f.
|
|
36
|
-
for(let j=0; j<f.
|
|
138
|
+
for (let i = 0; i < f.width; i++) {
|
|
139
|
+
for (let j = 0; j < f.height; j++) {
|
|
37
140
|
const u = f.u + i;
|
|
38
141
|
const v = f.v + j;
|
|
39
142
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const scale = new THREE.Vector3(f.sx||1, f.sy||1, f.sz||1);
|
|
48
|
-
if(f === faces[0] || f === faces[1]) scale.z = 0.5;
|
|
49
|
-
m.compose(f.pos(i, (f.h-1)-j), new THREE.Quaternion(), scale);
|
|
50
|
-
geo.applyMatrix4(m);
|
|
51
|
-
geometries.push(geo);
|
|
143
|
+
const alphaIndex = (v * 64 + u) * 4 + 3;
|
|
144
|
+
if (imgData[alphaIndex] > 0) {
|
|
145
|
+
const pos = f.pos(i, (f.height - 1) - j);
|
|
146
|
+
const sx = f.scale?.x ?? 1;
|
|
147
|
+
const sy = f.scale?.y ?? 1;
|
|
148
|
+
const sz = f.scale?.z ?? 1;
|
|
149
|
+
addVoxel(pos.x, pos.y, pos.z, sx, sy, sz, u, v);
|
|
52
150
|
}
|
|
53
151
|
}
|
|
54
152
|
}
|
|
55
153
|
});
|
|
56
154
|
|
|
57
|
-
|
|
155
|
+
if (positions.length === 0) return null;
|
|
156
|
+
|
|
157
|
+
const geometry = new THREE.BufferGeometry();
|
|
158
|
+
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
|
|
159
|
+
geometry.setAttribute('normal', new THREE.Float32BufferAttribute(normals, 3));
|
|
160
|
+
geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2));
|
|
161
|
+
geometry.setIndex(indices);
|
|
162
|
+
|
|
163
|
+
return geometry;
|
|
58
164
|
}
|