let-them-talk 3.5.0 → 3.6.0
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/CHANGELOG.md +57 -0
- package/README.md +62 -21
- package/cli.js +16 -9
- package/conversation-templates/code-review.json +11 -0
- package/conversation-templates/debug-squad.json +11 -0
- package/conversation-templates/feature-build.json +11 -0
- package/conversation-templates/managed-team.json +12 -0
- package/conversation-templates/research-write.json +11 -0
- package/dashboard.html +7389 -5720
- package/dashboard.js +2017 -1766
- package/mods/built-in-accessories.json +122 -0
- package/mods/registry.json +4 -0
- package/office/accessories.js +265 -0
- package/office/agents.js +376 -0
- package/office/animation.js +337 -0
- package/office/appearance.js +56 -0
- package/office/character.js +208 -0
- package/office/constants.js +62 -0
- package/office/environment.js +805 -0
- package/office/face.js +258 -0
- package/office/hair.js +183 -0
- package/office/index.js +337 -0
- package/office/mod-loader.js +257 -0
- package/office/monitors.js +113 -0
- package/office/outfits.js +212 -0
- package/office/scene.js +75 -0
- package/office/spectator-camera.js +177 -0
- package/office/state.js +25 -0
- package/package.json +58 -56
- package/server.js +2704 -2196
- package/templates/managed.json +26 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "builtin-glasses-round",
|
|
4
|
+
"name": "Round Glasses",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"author": "built-in",
|
|
7
|
+
"type": "accessory",
|
|
8
|
+
"category": "glasses",
|
|
9
|
+
"tags": ["classic", "glasses"],
|
|
10
|
+
"colorable": true,
|
|
11
|
+
"default_color": "#555555",
|
|
12
|
+
"asset": { "format": "procedural", "procedural_id": "round" }
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "builtin-glasses-square",
|
|
16
|
+
"name": "Square Glasses",
|
|
17
|
+
"version": "1.0.0",
|
|
18
|
+
"author": "built-in",
|
|
19
|
+
"type": "accessory",
|
|
20
|
+
"category": "glasses",
|
|
21
|
+
"tags": ["modern", "glasses"],
|
|
22
|
+
"colorable": true,
|
|
23
|
+
"default_color": "#555555",
|
|
24
|
+
"asset": { "format": "procedural", "procedural_id": "square" }
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "builtin-glasses-sunglasses",
|
|
28
|
+
"name": "Sunglasses",
|
|
29
|
+
"version": "1.0.0",
|
|
30
|
+
"author": "built-in",
|
|
31
|
+
"type": "accessory",
|
|
32
|
+
"category": "glasses",
|
|
33
|
+
"tags": ["cool", "sunglasses"],
|
|
34
|
+
"colorable": true,
|
|
35
|
+
"default_color": "#111111",
|
|
36
|
+
"asset": { "format": "procedural", "procedural_id": "sunglasses" }
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "builtin-headwear-beanie",
|
|
40
|
+
"name": "Beanie",
|
|
41
|
+
"version": "1.0.0",
|
|
42
|
+
"author": "built-in",
|
|
43
|
+
"type": "accessory",
|
|
44
|
+
"category": "headwear",
|
|
45
|
+
"tags": ["casual", "hat"],
|
|
46
|
+
"colorable": true,
|
|
47
|
+
"default_color": "#333333",
|
|
48
|
+
"asset": { "format": "procedural", "procedural_id": "beanie" }
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"id": "builtin-headwear-cap",
|
|
52
|
+
"name": "Baseball Cap",
|
|
53
|
+
"version": "1.0.0",
|
|
54
|
+
"author": "built-in",
|
|
55
|
+
"type": "accessory",
|
|
56
|
+
"category": "headwear",
|
|
57
|
+
"tags": ["casual", "cap"],
|
|
58
|
+
"colorable": true,
|
|
59
|
+
"default_color": "#333333",
|
|
60
|
+
"asset": { "format": "procedural", "procedural_id": "cap" }
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"id": "builtin-headwear-headphones",
|
|
64
|
+
"name": "Headphones",
|
|
65
|
+
"version": "1.0.0",
|
|
66
|
+
"author": "built-in",
|
|
67
|
+
"type": "accessory",
|
|
68
|
+
"category": "headwear",
|
|
69
|
+
"tags": ["tech", "audio"],
|
|
70
|
+
"colorable": false,
|
|
71
|
+
"default_color": "#2a2a2a",
|
|
72
|
+
"asset": { "format": "procedural", "procedural_id": "headphones" }
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"id": "builtin-headwear-headband",
|
|
76
|
+
"name": "Headband",
|
|
77
|
+
"version": "1.0.0",
|
|
78
|
+
"author": "built-in",
|
|
79
|
+
"type": "accessory",
|
|
80
|
+
"category": "headwear",
|
|
81
|
+
"tags": ["sporty"],
|
|
82
|
+
"colorable": true,
|
|
83
|
+
"default_color": "#333333",
|
|
84
|
+
"asset": { "format": "procedural", "procedural_id": "headband" }
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"id": "builtin-neckwear-tie",
|
|
88
|
+
"name": "Tie",
|
|
89
|
+
"version": "1.0.0",
|
|
90
|
+
"author": "built-in",
|
|
91
|
+
"type": "accessory",
|
|
92
|
+
"category": "neckwear",
|
|
93
|
+
"tags": ["formal"],
|
|
94
|
+
"colorable": true,
|
|
95
|
+
"default_color": "#c0392b",
|
|
96
|
+
"asset": { "format": "procedural", "procedural_id": "tie" }
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"id": "builtin-neckwear-bowtie",
|
|
100
|
+
"name": "Bow Tie",
|
|
101
|
+
"version": "1.0.0",
|
|
102
|
+
"author": "built-in",
|
|
103
|
+
"type": "accessory",
|
|
104
|
+
"category": "neckwear",
|
|
105
|
+
"tags": ["formal", "fancy"],
|
|
106
|
+
"colorable": true,
|
|
107
|
+
"default_color": "#c0392b",
|
|
108
|
+
"asset": { "format": "procedural", "procedural_id": "bowtie" }
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "builtin-neckwear-lanyard",
|
|
112
|
+
"name": "Lanyard & Badge",
|
|
113
|
+
"version": "1.0.0",
|
|
114
|
+
"author": "built-in",
|
|
115
|
+
"type": "accessory",
|
|
116
|
+
"category": "neckwear",
|
|
117
|
+
"tags": ["professional", "badge"],
|
|
118
|
+
"colorable": true,
|
|
119
|
+
"default_color": "#1a5276",
|
|
120
|
+
"asset": { "format": "procedural", "procedural_id": "lanyard" }
|
|
121
|
+
}
|
|
122
|
+
]
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { HEAD_R } from './constants.js';
|
|
3
|
+
|
|
4
|
+
function headSurfaceZ(x, y) {
|
|
5
|
+
return Math.sqrt(Math.max(0, HEAD_R * HEAD_R - x * x - y * y));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function buildGlasses(style, color, headMesh) {
|
|
9
|
+
var glassesGroup = new THREE.Group();
|
|
10
|
+
glassesGroup.userData.isAccessories = true;
|
|
11
|
+
var frameColor = new THREE.Color(color).getHex();
|
|
12
|
+
var frameMat = new THREE.MeshStandardMaterial({ color: frameColor, roughness: 0.3, metalness: 0.4 });
|
|
13
|
+
|
|
14
|
+
var eyeX = 0.042;
|
|
15
|
+
var eyeY = -0.018;
|
|
16
|
+
|
|
17
|
+
if (style === 'round') {
|
|
18
|
+
var lensRadius = 0.04;
|
|
19
|
+
var tubeRadius = 0.006;
|
|
20
|
+
var leftLens = new THREE.Mesh(new THREE.TorusGeometry(lensRadius, tubeRadius, 8, 24), frameMat);
|
|
21
|
+
var lz = headSurfaceZ(eyeX, eyeY) + 0.008;
|
|
22
|
+
leftLens.position.set(-eyeX, eyeY, lz);
|
|
23
|
+
glassesGroup.add(leftLens);
|
|
24
|
+
var rightLens = new THREE.Mesh(new THREE.TorusGeometry(lensRadius, tubeRadius, 8, 24), frameMat);
|
|
25
|
+
rightLens.position.set(eyeX, eyeY, lz);
|
|
26
|
+
glassesGroup.add(rightLens);
|
|
27
|
+
var lensTintMat = new THREE.MeshBasicMaterial({ color: 0x88ccff, transparent: true, opacity: 0.15, side: THREE.DoubleSide });
|
|
28
|
+
var lensTintGeo = new THREE.CircleGeometry(lensRadius - 0.002, 16);
|
|
29
|
+
var leftTint = new THREE.Mesh(lensTintGeo, lensTintMat);
|
|
30
|
+
leftTint.position.set(-eyeX, eyeY, lz - 0.001);
|
|
31
|
+
glassesGroup.add(leftTint);
|
|
32
|
+
var rightTint = new THREE.Mesh(lensTintGeo, lensTintMat);
|
|
33
|
+
rightTint.position.set(eyeX, eyeY, lz - 0.001);
|
|
34
|
+
glassesGroup.add(rightTint);
|
|
35
|
+
var bridgeGeo = new THREE.CylinderGeometry(tubeRadius, tubeRadius, eyeX * 2 - lensRadius * 2, 6);
|
|
36
|
+
var bridge = new THREE.Mesh(bridgeGeo, frameMat);
|
|
37
|
+
bridge.rotation.z = Math.PI / 2;
|
|
38
|
+
bridge.position.set(0, eyeY, lz + 0.003);
|
|
39
|
+
glassesGroup.add(bridge);
|
|
40
|
+
var armMat2 = new THREE.MeshStandardMaterial({ color: frameColor, roughness: 0.4 });
|
|
41
|
+
[-1, 1].forEach(function(side) {
|
|
42
|
+
var armGroup = new THREE.Group();
|
|
43
|
+
var segCount = 5;
|
|
44
|
+
for (var s = 0; s < segCount; s++) {
|
|
45
|
+
var t0 = s / segCount;
|
|
46
|
+
var t1 = (s + 1) / segCount;
|
|
47
|
+
var angle0 = Math.asin(Math.min(1, (eyeX + lensRadius) / HEAD_R)) + t0 * 0.6;
|
|
48
|
+
var angle1 = Math.asin(Math.min(1, (eyeX + lensRadius) / HEAD_R)) + t1 * 0.6;
|
|
49
|
+
var x0 = side * Math.sin(angle0) * (HEAD_R + 0.008);
|
|
50
|
+
var z0 = Math.cos(angle0) * (HEAD_R + 0.008);
|
|
51
|
+
var x1 = side * Math.sin(angle1) * (HEAD_R + 0.008);
|
|
52
|
+
var z1 = Math.cos(angle1) * (HEAD_R + 0.008);
|
|
53
|
+
var segLen = Math.sqrt((x1 - x0) * (x1 - x0) + (z1 - z0) * (z1 - z0));
|
|
54
|
+
var seg = new THREE.Mesh(new THREE.BoxGeometry(segLen, 0.008, 0.008), armMat2);
|
|
55
|
+
seg.position.set((x0 + x1) / 2, eyeY, (z0 + z1) / 2);
|
|
56
|
+
seg.rotation.y = -Math.atan2(z1 - z0, x1 - x0) + Math.PI / 2;
|
|
57
|
+
if (side < 0) seg.rotation.y = Math.atan2(z1 - z0, x1 - x0) - Math.PI / 2;
|
|
58
|
+
armGroup.add(seg);
|
|
59
|
+
}
|
|
60
|
+
glassesGroup.add(armGroup);
|
|
61
|
+
});
|
|
62
|
+
} else if (style === 'square') {
|
|
63
|
+
var lensW = 0.07, lensH = 0.05;
|
|
64
|
+
var lz2 = headSurfaceZ(eyeX, eyeY) + 0.008;
|
|
65
|
+
var t2 = 0.006;
|
|
66
|
+
[-eyeX, eyeX].forEach(function(ex) {
|
|
67
|
+
var top = new THREE.Mesh(new THREE.BoxGeometry(lensW, t2, t2), frameMat);
|
|
68
|
+
top.position.set(ex, eyeY + lensH / 2, lz2); glassesGroup.add(top);
|
|
69
|
+
var bot = new THREE.Mesh(new THREE.BoxGeometry(lensW, t2, t2), frameMat);
|
|
70
|
+
bot.position.set(ex, eyeY - lensH / 2, lz2); glassesGroup.add(bot);
|
|
71
|
+
var left = new THREE.Mesh(new THREE.BoxGeometry(t2, lensH, t2), frameMat);
|
|
72
|
+
left.position.set(ex - lensW / 2, eyeY, lz2); glassesGroup.add(left);
|
|
73
|
+
var right = new THREE.Mesh(new THREE.BoxGeometry(t2, lensH, t2), frameMat);
|
|
74
|
+
right.position.set(ex + lensW / 2, eyeY, lz2); glassesGroup.add(right);
|
|
75
|
+
var tintMat = new THREE.MeshBasicMaterial({ color: 0x88ccff, transparent: true, opacity: 0.12, side: THREE.DoubleSide });
|
|
76
|
+
var tint = new THREE.Mesh(new THREE.PlaneGeometry(lensW - t2, lensH - t2), tintMat);
|
|
77
|
+
tint.position.set(ex, eyeY, lz2 - 0.001); glassesGroup.add(tint);
|
|
78
|
+
});
|
|
79
|
+
var bridgeLen = eyeX * 2 - lensW;
|
|
80
|
+
var br2 = new THREE.Mesh(new THREE.BoxGeometry(bridgeLen, t2, t2), frameMat);
|
|
81
|
+
br2.position.set(0, eyeY + lensH / 2 - t2, lz2); glassesGroup.add(br2);
|
|
82
|
+
[-1, 1].forEach(function(side) {
|
|
83
|
+
var armLen = 0.15;
|
|
84
|
+
var arm = new THREE.Mesh(new THREE.BoxGeometry(0.008, 0.008, armLen), frameMat);
|
|
85
|
+
var sx = side * (eyeX + lensW / 2);
|
|
86
|
+
arm.position.set(sx, eyeY, lz2 - armLen / 2);
|
|
87
|
+
glassesGroup.add(arm);
|
|
88
|
+
});
|
|
89
|
+
} else if (style === 'sunglasses') {
|
|
90
|
+
var lz3 = headSurfaceZ(eyeX, eyeY) + 0.008;
|
|
91
|
+
var sgW = 0.055, sgH = 0.04;
|
|
92
|
+
var darkMat = new THREE.MeshStandardMaterial({ color: 0x111111, roughness: 0.2, metalness: 0.3 });
|
|
93
|
+
[-eyeX, eyeX].forEach(function(ex) {
|
|
94
|
+
var lens = new THREE.Mesh(new THREE.PlaneGeometry(sgW, sgH), darkMat);
|
|
95
|
+
lens.position.set(ex, eyeY, lz3); glassesGroup.add(lens);
|
|
96
|
+
var chromeMat = new THREE.MeshStandardMaterial({ color: 0xcccccc, roughness: 0.1, metalness: 0.8 });
|
|
97
|
+
var ft = 0.005;
|
|
98
|
+
var frameTop = new THREE.Mesh(new THREE.BoxGeometry(sgW + ft * 2, ft, ft), chromeMat);
|
|
99
|
+
frameTop.position.set(ex, eyeY + sgH / 2, lz3 + 0.002); glassesGroup.add(frameTop);
|
|
100
|
+
var frameBot = new THREE.Mesh(new THREE.BoxGeometry(sgW + ft * 2, ft, ft), chromeMat);
|
|
101
|
+
frameBot.position.set(ex, eyeY - sgH / 2, lz3 + 0.002); glassesGroup.add(frameBot);
|
|
102
|
+
});
|
|
103
|
+
var sgBridge = new THREE.Mesh(new THREE.BoxGeometry(eyeX * 2 - sgW, 0.005, 0.005), frameMat);
|
|
104
|
+
sgBridge.position.set(0, eyeY + sgH / 2, lz3 + 0.002); glassesGroup.add(sgBridge);
|
|
105
|
+
[-1, 1].forEach(function(side) {
|
|
106
|
+
var arm = new THREE.Mesh(new THREE.BoxGeometry(0.008, 0.008, 0.15), frameMat);
|
|
107
|
+
arm.position.set(side * (eyeX + sgW / 2), eyeY, lz3 - 0.07);
|
|
108
|
+
glassesGroup.add(arm);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
headMesh.add(glassesGroup);
|
|
113
|
+
return glassesGroup;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function buildHeadwear(style, color, headMesh) {
|
|
117
|
+
var hwGroup = new THREE.Group();
|
|
118
|
+
hwGroup.userData.isAccessories = true;
|
|
119
|
+
var hwColor = new THREE.Color(color).getHex();
|
|
120
|
+
var mat = new THREE.MeshStandardMaterial({ color: hwColor, roughness: 0.8 });
|
|
121
|
+
|
|
122
|
+
if (style === 'beanie') {
|
|
123
|
+
var beanieGeo = new THREE.SphereGeometry(0.26, 16, 12, 0, Math.PI * 2, 0, Math.PI * 0.45);
|
|
124
|
+
var beanie = new THREE.Mesh(beanieGeo, mat);
|
|
125
|
+
beanie.position.y = 0.04; beanie.castShadow = true;
|
|
126
|
+
hwGroup.add(beanie);
|
|
127
|
+
var rimGeo = new THREE.TorusGeometry(0.23, 0.02, 8, 24);
|
|
128
|
+
var rimMat = new THREE.MeshStandardMaterial({ color: hwColor, roughness: 0.9 });
|
|
129
|
+
var rim = new THREE.Mesh(rimGeo, rimMat);
|
|
130
|
+
rim.rotation.x = Math.PI / 2; rim.position.y = 0.04;
|
|
131
|
+
hwGroup.add(rim);
|
|
132
|
+
var pomGeo = new THREE.SphereGeometry(0.04, 8, 6);
|
|
133
|
+
var pom = new THREE.Mesh(pomGeo, mat);
|
|
134
|
+
pom.position.y = 0.28;
|
|
135
|
+
hwGroup.add(pom);
|
|
136
|
+
} else if (style === 'cap') {
|
|
137
|
+
var crownGeo = new THREE.SphereGeometry(0.26, 16, 12, 0, Math.PI * 2, 0, Math.PI * 0.4);
|
|
138
|
+
var crown = new THREE.Mesh(crownGeo, mat);
|
|
139
|
+
crown.position.y = 0.03; crown.castShadow = true;
|
|
140
|
+
hwGroup.add(crown);
|
|
141
|
+
var brimGeo = new THREE.CylinderGeometry(0.18, 0.2, 0.015, 16, 1, false, -Math.PI / 2, Math.PI);
|
|
142
|
+
var brimMat = new THREE.MeshStandardMaterial({ color: hwColor, roughness: 0.7 });
|
|
143
|
+
var brim = new THREE.Mesh(brimGeo, brimMat);
|
|
144
|
+
brim.rotation.x = Math.PI / 2; brim.rotation.z = Math.PI;
|
|
145
|
+
brim.position.set(0, 0.04, 0.16); brim.castShadow = true;
|
|
146
|
+
hwGroup.add(brim);
|
|
147
|
+
} else if (style === 'headphones') {
|
|
148
|
+
var hpMat = new THREE.MeshStandardMaterial({ color: 0x2a2a2a, roughness: 0.4, metalness: 0.3 });
|
|
149
|
+
var bandGeo = new THREE.TorusGeometry(0.24, 0.015, 8, 24, Math.PI);
|
|
150
|
+
var band = new THREE.Mesh(bandGeo, hpMat);
|
|
151
|
+
band.rotation.z = Math.PI / 2; band.rotation.y = Math.PI / 2;
|
|
152
|
+
band.position.y = 0.06;
|
|
153
|
+
hwGroup.add(band);
|
|
154
|
+
var padGeo = new THREE.TorusGeometry(0.24, 0.025, 6, 20, Math.PI * 0.6);
|
|
155
|
+
var padMat = new THREE.MeshStandardMaterial({ color: 0x444444, roughness: 0.8 });
|
|
156
|
+
var pad = new THREE.Mesh(padGeo, padMat);
|
|
157
|
+
pad.rotation.z = Math.PI / 2; pad.rotation.y = Math.PI / 2;
|
|
158
|
+
pad.position.y = 0.08;
|
|
159
|
+
hwGroup.add(pad);
|
|
160
|
+
[-1, 1].forEach(function(side) {
|
|
161
|
+
var cupOuter = new THREE.Mesh(new THREE.CylinderGeometry(0.06, 0.06, 0.03, 16), hpMat);
|
|
162
|
+
cupOuter.rotation.z = Math.PI / 2;
|
|
163
|
+
cupOuter.position.set(side * 0.26, 0, 0); cupOuter.castShadow = true;
|
|
164
|
+
hwGroup.add(cupOuter);
|
|
165
|
+
var cushionMat = new THREE.MeshStandardMaterial({ color: 0x555555, roughness: 0.9 });
|
|
166
|
+
var cushion = new THREE.Mesh(new THREE.CylinderGeometry(0.055, 0.055, 0.015, 16), cushionMat);
|
|
167
|
+
cushion.rotation.z = Math.PI / 2;
|
|
168
|
+
cushion.position.set(side * 0.25, 0, 0);
|
|
169
|
+
hwGroup.add(cushion);
|
|
170
|
+
});
|
|
171
|
+
} else if (style === 'headband') {
|
|
172
|
+
var hbMat = new THREE.MeshStandardMaterial({ color: hwColor, roughness: 0.7 });
|
|
173
|
+
var hbGeo = new THREE.TorusGeometry(0.252, 0.015, 6, 24, Math.PI);
|
|
174
|
+
var hb = new THREE.Mesh(hbGeo, hbMat);
|
|
175
|
+
hb.rotation.z = Math.PI / 2; hb.rotation.y = Math.PI / 2;
|
|
176
|
+
hb.position.y = 0.06;
|
|
177
|
+
hwGroup.add(hb);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
headMesh.add(hwGroup);
|
|
181
|
+
return hwGroup;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function buildNeckwear(style, color, charGroup) {
|
|
185
|
+
var nwGroup = new THREE.Group();
|
|
186
|
+
var nwColor = new THREE.Color(color).getHex();
|
|
187
|
+
var mat = new THREE.MeshStandardMaterial({ color: nwColor, roughness: 0.7 });
|
|
188
|
+
nwGroup.userData.isNeckwear = true;
|
|
189
|
+
|
|
190
|
+
if (style === 'tie') {
|
|
191
|
+
var knot = new THREE.Mesh(new THREE.BoxGeometry(0.04, 0.03, 0.02), mat);
|
|
192
|
+
knot.position.set(0, 0.76, 0.1);
|
|
193
|
+
nwGroup.add(knot);
|
|
194
|
+
var tieGeo = new THREE.BufferGeometry();
|
|
195
|
+
var verts = new Float32Array([
|
|
196
|
+
-0.025, 0, 0.01, 0.025, 0, 0.01, 0.018, -0.18, 0.01,
|
|
197
|
+
-0.025, 0, 0.01, 0.018, -0.18, 0.01, -0.018, -0.18, 0.01,
|
|
198
|
+
-0.018, -0.18, 0.01, 0.018, -0.18, 0.01, 0, -0.22, 0.01,
|
|
199
|
+
]);
|
|
200
|
+
tieGeo.setAttribute('position', new THREE.BufferAttribute(verts, 3));
|
|
201
|
+
tieGeo.computeVertexNormals();
|
|
202
|
+
var tieMesh = new THREE.Mesh(tieGeo, mat);
|
|
203
|
+
tieMesh.position.set(0, 0.73, 0);
|
|
204
|
+
nwGroup.add(tieMesh);
|
|
205
|
+
} else if (style === 'bowtie') {
|
|
206
|
+
var btMat = new THREE.MeshStandardMaterial({ color: nwColor, roughness: 0.6 });
|
|
207
|
+
var btKnot = new THREE.Mesh(new THREE.BoxGeometry(0.02, 0.025, 0.02), btMat);
|
|
208
|
+
btKnot.position.set(0, 0.76, 0.1);
|
|
209
|
+
nwGroup.add(btKnot);
|
|
210
|
+
var wingGeo = new THREE.BufferGeometry();
|
|
211
|
+
var wv = new Float32Array([
|
|
212
|
+
0, 0.012, 0.01, -0.05, 0.02, 0.005, -0.05, -0.02, 0.005,
|
|
213
|
+
0, 0.012, 0.01, -0.05, -0.02, 0.005, 0, -0.012, 0.01,
|
|
214
|
+
]);
|
|
215
|
+
wingGeo.setAttribute('position', new THREE.BufferAttribute(wv, 3));
|
|
216
|
+
wingGeo.computeVertexNormals();
|
|
217
|
+
var leftWing = new THREE.Mesh(wingGeo, btMat);
|
|
218
|
+
leftWing.position.set(-0.01, 0.76, 0.09);
|
|
219
|
+
nwGroup.add(leftWing);
|
|
220
|
+
var rwv = new Float32Array([
|
|
221
|
+
0, 0.012, 0.01, 0.05, 0.02, 0.005, 0.05, -0.02, 0.005,
|
|
222
|
+
0, 0.012, 0.01, 0.05, -0.02, 0.005, 0, -0.012, 0.01,
|
|
223
|
+
]);
|
|
224
|
+
var rwGeo = new THREE.BufferGeometry();
|
|
225
|
+
rwGeo.setAttribute('position', new THREE.BufferAttribute(rwv, 3));
|
|
226
|
+
rwGeo.computeVertexNormals();
|
|
227
|
+
var rightWing = new THREE.Mesh(rwGeo, btMat);
|
|
228
|
+
rightWing.position.set(0.01, 0.76, 0.09);
|
|
229
|
+
nwGroup.add(rightWing);
|
|
230
|
+
} else if (style === 'lanyard') {
|
|
231
|
+
var lanyardMat = new THREE.MeshStandardMaterial({ color: nwColor, roughness: 0.8 });
|
|
232
|
+
var cordGeo = new THREE.TorusGeometry(0.12, 0.005, 6, 16, Math.PI);
|
|
233
|
+
var cord = new THREE.Mesh(cordGeo, lanyardMat);
|
|
234
|
+
cord.rotation.x = Math.PI; cord.position.set(0, 0.72, 0.06);
|
|
235
|
+
nwGroup.add(cord);
|
|
236
|
+
var badge = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.08, 0.005), new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 0.3 }));
|
|
237
|
+
badge.position.set(0, 0.58, 0.08);
|
|
238
|
+
nwGroup.add(badge);
|
|
239
|
+
var stripe = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.015, 0.006), new THREE.MeshStandardMaterial({ color: nwColor, roughness: 0.5 }));
|
|
240
|
+
stripe.position.set(0, 0.6, 0.083);
|
|
241
|
+
nwGroup.add(stripe);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
charGroup.add(nwGroup);
|
|
245
|
+
return nwGroup;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function removeAccessories(headMesh, charGroup) {
|
|
249
|
+
var toRemoveHead = [];
|
|
250
|
+
headMesh.children.forEach(function(c) {
|
|
251
|
+
if (c.userData && c.userData.isAccessories) toRemoveHead.push(c);
|
|
252
|
+
});
|
|
253
|
+
toRemoveHead.forEach(function(c) {
|
|
254
|
+
headMesh.remove(c);
|
|
255
|
+
c.traverse(function(ch) { if (ch.geometry) ch.geometry.dispose(); if (ch.material) ch.material.dispose(); });
|
|
256
|
+
});
|
|
257
|
+
var toRemoveGroup = [];
|
|
258
|
+
charGroup.children.forEach(function(c) {
|
|
259
|
+
if (c.userData && c.userData.isNeckwear) toRemoveGroup.push(c);
|
|
260
|
+
});
|
|
261
|
+
toRemoveGroup.forEach(function(c) {
|
|
262
|
+
charGroup.remove(c);
|
|
263
|
+
c.traverse(function(ch) { if (ch.geometry) ch.geometry.dispose(); if (ch.material) ch.material.dispose(); });
|
|
264
|
+
});
|
|
265
|
+
}
|