@worldmesh/runtime 0.1.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/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/abilities/abilities.d.ts +9 -0
- package/dist/abilities/abilities.d.ts.map +1 -0
- package/dist/abilities/abilities.js +25 -0
- package/dist/abilities/abilities.js.map +1 -0
- package/dist/camera/cameraRig.d.ts +39 -0
- package/dist/camera/cameraRig.d.ts.map +1 -0
- package/dist/camera/cameraRig.js +88 -0
- package/dist/camera/cameraRig.js.map +1 -0
- package/dist/controls/input.d.ts +64 -0
- package/dist/controls/input.d.ts.map +1 -0
- package/dist/controls/input.js +236 -0
- package/dist/controls/input.js.map +1 -0
- package/dist/controls/keymap.d.ts +8 -0
- package/dist/controls/keymap.d.ts.map +1 -0
- package/dist/controls/keymap.js +21 -0
- package/dist/controls/keymap.js.map +1 -0
- package/dist/controls/touch.d.ts +43 -0
- package/dist/controls/touch.d.ts.map +1 -0
- package/dist/controls/touch.js +329 -0
- package/dist/controls/touch.js.map +1 -0
- package/dist/core/events.d.ts +9 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +27 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/worldmesh.d.ts +10 -0
- package/dist/core/worldmesh.d.ts.map +1 -0
- package/dist/core/worldmesh.js +283 -0
- package/dist/core/worldmesh.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/movement/collision.d.ts +39 -0
- package/dist/movement/collision.d.ts.map +1 -0
- package/dist/movement/collision.js +93 -0
- package/dist/movement/collision.js.map +1 -0
- package/dist/movement/controller.d.ts +53 -0
- package/dist/movement/controller.d.ts.map +1 -0
- package/dist/movement/controller.js +200 -0
- package/dist/movement/controller.js.map +1 -0
- package/dist/net/adapter.d.ts +22 -0
- package/dist/net/adapter.d.ts.map +1 -0
- package/dist/net/adapter.js +8 -0
- package/dist/net/adapter.js.map +1 -0
- package/dist/player/avatar.d.ts +29 -0
- package/dist/player/avatar.d.ts.map +1 -0
- package/dist/player/avatar.js +420 -0
- package/dist/player/avatar.js.map +1 -0
- package/dist/player/player.d.ts +30 -0
- package/dist/player/player.d.ts.map +1 -0
- package/dist/player/player.js +76 -0
- package/dist/player/player.js.map +1 -0
- package/dist/portals/portals.d.ts +34 -0
- package/dist/portals/portals.d.ts.map +1 -0
- package/dist/portals/portals.js +132 -0
- package/dist/portals/portals.js.map +1 -0
- package/dist/types.d.ts +228 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/overlay.d.ts +19 -0
- package/dist/ui/overlay.d.ts.map +1 -0
- package/dist/ui/overlay.js +370 -0
- package/dist/ui/overlay.js.map +1 -0
- package/package.json +63 -0
- package/src/abilities/abilities.ts +30 -0
- package/src/camera/cameraRig.ts +106 -0
- package/src/controls/input.ts +252 -0
- package/src/controls/keymap.ts +23 -0
- package/src/controls/touch.ts +378 -0
- package/src/core/events.ts +31 -0
- package/src/core/worldmesh.ts +313 -0
- package/src/index.ts +46 -0
- package/src/movement/collision.ts +109 -0
- package/src/movement/controller.ts +248 -0
- package/src/net/adapter.ts +28 -0
- package/src/player/avatar.ts +495 -0
- package/src/player/player.ts +91 -0
- package/src/portals/portals.ts +173 -0
- package/src/types.ts +230 -0
- package/src/ui/overlay.ts +398 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
import { BufferAttribute, CanvasTexture, Group, LatheGeometry, MathUtils, Mesh, MeshBasicMaterial, MeshStandardMaterial, RingGeometry, SphereGeometry, SplineCurve, SRGBColorSpace, Vector2, } from 'three';
|
|
2
|
+
/**
|
|
3
|
+
* The default WorldMesh body: a small white figure with a big round head,
|
|
4
|
+
* a drawn-on face, a pear-shaped body and stubby limbs. Every world gets the
|
|
5
|
+
* same one until visitors bring their own, so it is deliberately plain.
|
|
6
|
+
*
|
|
7
|
+
* Built for a 1.8 m standing height with feet at y = 0, facing -Z (the
|
|
8
|
+
* direction the camera looks at yaw 0). Scale the result for other heights.
|
|
9
|
+
*/
|
|
10
|
+
const RIG_KEY = 'worldmeshAvatarRig';
|
|
11
|
+
/** Faces the default figure can pull, in number-key order (1–9, then 0). */
|
|
12
|
+
export const AVATAR_EXPRESSIONS = [
|
|
13
|
+
'smile',
|
|
14
|
+
'grin',
|
|
15
|
+
'laugh',
|
|
16
|
+
'wink',
|
|
17
|
+
'love',
|
|
18
|
+
'surprised',
|
|
19
|
+
'sad',
|
|
20
|
+
'angry',
|
|
21
|
+
'sleepy',
|
|
22
|
+
'neutral',
|
|
23
|
+
];
|
|
24
|
+
/** The expression bound to a number key: 1 is the first, 0 the tenth. */
|
|
25
|
+
export function expressionForDigit(digit) {
|
|
26
|
+
if (!Number.isInteger(digit) || digit < 0 || digit > 9)
|
|
27
|
+
return null;
|
|
28
|
+
return AVATAR_EXPRESSIONS[(digit + 9) % 10];
|
|
29
|
+
}
|
|
30
|
+
export function isAvatarExpression(value) {
|
|
31
|
+
return typeof value === 'string' && AVATAR_EXPRESSIONS.includes(value);
|
|
32
|
+
}
|
|
33
|
+
const HEAD_RADIUS = 0.47;
|
|
34
|
+
const HEAD_Y = 1.33;
|
|
35
|
+
/** How far the arms hang away from the body at rest, in radians. */
|
|
36
|
+
const ARM_REST = 0.4;
|
|
37
|
+
export function createDefaultAvatar(height = 1.8) {
|
|
38
|
+
const root = new Group();
|
|
39
|
+
root.name = 'worldmesh:avatar';
|
|
40
|
+
// Soft glossy white; a little self-light keeps the shaded side from going grey.
|
|
41
|
+
const skin = new MeshStandardMaterial({ color: 0xf7f7f7, emissive: 0x1e1e1e, roughness: 0.42, metalness: 0 });
|
|
42
|
+
const shaded = (geometry) => {
|
|
43
|
+
const mesh = new Mesh(geometry, skin);
|
|
44
|
+
mesh.castShadow = true;
|
|
45
|
+
return mesh;
|
|
46
|
+
};
|
|
47
|
+
// Everything above the legs bobs together while walking.
|
|
48
|
+
const torso = new Group();
|
|
49
|
+
root.add(torso);
|
|
50
|
+
// One soft bean: shoulders tucked right under the head, rounding off, a
|
|
51
|
+
// belly that is widest low down, and a rounded seat the legs grow out of.
|
|
52
|
+
const body = shaded(lathe([
|
|
53
|
+
[0, 1.1],
|
|
54
|
+
[0.12, 1.08],
|
|
55
|
+
[0.19, 1.02],
|
|
56
|
+
[0.217, 0.93],
|
|
57
|
+
[0.227, 0.8],
|
|
58
|
+
[0.232, 0.56],
|
|
59
|
+
[0.243, 0.44],
|
|
60
|
+
[0.232, 0.36],
|
|
61
|
+
[0.205, 0.29],
|
|
62
|
+
[0.155, 0.24],
|
|
63
|
+
[0.08, 0.214],
|
|
64
|
+
[0, 0.208],
|
|
65
|
+
]));
|
|
66
|
+
body.scale.z = 0.84;
|
|
67
|
+
torso.add(body);
|
|
68
|
+
const head = new Group();
|
|
69
|
+
head.position.y = HEAD_Y;
|
|
70
|
+
torso.add(head);
|
|
71
|
+
head.add(shaded(new SphereGeometry(HEAD_RADIUS, 64, 48)));
|
|
72
|
+
const faceMaterial = new MeshBasicMaterial({
|
|
73
|
+
map: faceTexture('smile', false),
|
|
74
|
+
transparent: true,
|
|
75
|
+
depthWrite: false,
|
|
76
|
+
polygonOffset: true,
|
|
77
|
+
polygonOffsetFactor: -1,
|
|
78
|
+
});
|
|
79
|
+
const face = new Mesh(faceGeometry(), faceMaterial);
|
|
80
|
+
face.name = 'worldmesh:avatar-face';
|
|
81
|
+
// Built facing +Z; turn it to the front of the figure.
|
|
82
|
+
face.rotation.y = Math.PI;
|
|
83
|
+
head.add(face);
|
|
84
|
+
// Limbs hang from pivots at the shoulders and hips so they can swing.
|
|
85
|
+
const limb = (x, y, length, top, bottom, target) => {
|
|
86
|
+
const pivot = new Group();
|
|
87
|
+
pivot.position.set(x, y, 0);
|
|
88
|
+
pivot.add(shaded(taperedCapsule(length, top, bottom)));
|
|
89
|
+
target.add(pivot);
|
|
90
|
+
return pivot;
|
|
91
|
+
};
|
|
92
|
+
// Thick, soft arms whose round tops sink into the shoulders, so there is
|
|
93
|
+
// no seam; hands swell slightly at the tips.
|
|
94
|
+
const armL = limb(-0.182, 0.92, 0.52, 0.074, 0.08, torso);
|
|
95
|
+
const armR = limb(0.182, 0.92, 0.52, 0.074, 0.08, torso);
|
|
96
|
+
armL.rotation.z = -ARM_REST;
|
|
97
|
+
armR.rotation.z = ARM_REST;
|
|
98
|
+
// Stubby legs, wide where they leave the body and rounded at the feet.
|
|
99
|
+
const legL = limb(-0.1, 0.34, 0.34, 0.088, 0.08, root);
|
|
100
|
+
const legR = limb(0.1, 0.34, 0.34, 0.088, 0.08, root);
|
|
101
|
+
const rig = {
|
|
102
|
+
torso,
|
|
103
|
+
head,
|
|
104
|
+
face: faceMaterial,
|
|
105
|
+
armL,
|
|
106
|
+
armR,
|
|
107
|
+
legL,
|
|
108
|
+
legR,
|
|
109
|
+
phase: 0,
|
|
110
|
+
stride: 0,
|
|
111
|
+
air: 0,
|
|
112
|
+
expression: 'smile',
|
|
113
|
+
blinking: false,
|
|
114
|
+
blinkTimer: nextBlink(),
|
|
115
|
+
};
|
|
116
|
+
root.userData[RIG_KEY] = rig;
|
|
117
|
+
if (height !== 1.8)
|
|
118
|
+
root.scale.setScalar(height / 1.8);
|
|
119
|
+
return root;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Change the face of an avatar made by `createDefaultAvatar`. Unknown names
|
|
123
|
+
* and custom avatars are ignored.
|
|
124
|
+
*/
|
|
125
|
+
export function setAvatarExpression(avatar, expression) {
|
|
126
|
+
const rig = avatar.userData[RIG_KEY];
|
|
127
|
+
if (!rig || !isAvatarExpression(expression) || rig.expression === expression)
|
|
128
|
+
return;
|
|
129
|
+
rig.expression = expression;
|
|
130
|
+
rig.face.map = faceTexture(expression, rig.blinking);
|
|
131
|
+
}
|
|
132
|
+
export function getAvatarExpression(avatar) {
|
|
133
|
+
const rig = avatar.userData[RIG_KEY];
|
|
134
|
+
return rig ? rig.expression : null;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Swing the limbs of an avatar made by `createDefaultAvatar`. Call once per
|
|
138
|
+
* frame with how fast it is moving; anything else is ignored, so it is safe
|
|
139
|
+
* to call on custom avatars too.
|
|
140
|
+
*/
|
|
141
|
+
export function animateDefaultAvatar(avatar, motion) {
|
|
142
|
+
const rig = avatar.userData[RIG_KEY];
|
|
143
|
+
if (!rig || motion.dt <= 0)
|
|
144
|
+
return;
|
|
145
|
+
const blend = 1 - Math.exp(-motion.dt * 10);
|
|
146
|
+
const walking = motion.grounded ? MathUtils.clamp(motion.speed / 4.5, 0, 1) : 0;
|
|
147
|
+
rig.stride += (walking - rig.stride) * blend;
|
|
148
|
+
rig.air += ((motion.grounded ? 0 : 1) - rig.air) * blend;
|
|
149
|
+
// Steps get longer, not just faster, as speed rises.
|
|
150
|
+
rig.phase += motion.dt * (4 + motion.speed * 1.2) * (rig.stride > 0.01 ? 1 : 0);
|
|
151
|
+
const swing = Math.sin(rig.phase) * 0.75 * rig.stride;
|
|
152
|
+
rig.legL.rotation.x = swing + rig.air * 0.35;
|
|
153
|
+
rig.legR.rotation.x = -swing - rig.air * 0.15;
|
|
154
|
+
rig.armL.rotation.x = -swing * 0.8;
|
|
155
|
+
rig.armR.rotation.x = swing * 0.8;
|
|
156
|
+
rig.armL.rotation.z = -ARM_REST - rig.air * 0.6;
|
|
157
|
+
rig.armR.rotation.z = ARM_REST + rig.air * 0.6;
|
|
158
|
+
rig.torso.position.y = Math.abs(Math.cos(rig.phase)) * 0.045 * rig.stride;
|
|
159
|
+
rig.head.rotation.z = Math.sin(rig.phase) * 0.04 * rig.stride;
|
|
160
|
+
rig.blinkTimer -= motion.dt;
|
|
161
|
+
if (rig.blinkTimer <= 0) {
|
|
162
|
+
rig.blinking = !rig.blinking;
|
|
163
|
+
rig.blinkTimer = rig.blinking ? 0.12 : nextBlink();
|
|
164
|
+
rig.face.map = faceTexture(rig.expression, rig.blinking);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function nextBlink() {
|
|
168
|
+
return 2.5 + Math.random() * 3.5;
|
|
169
|
+
}
|
|
170
|
+
// --- Geometry ---------------------------------------------------------------
|
|
171
|
+
/** A smooth solid of revolution through (radius, y) points, top to bottom. */
|
|
172
|
+
function lathe(profile) {
|
|
173
|
+
const curve = new SplineCurve(profile.map(([r, y]) => new Vector2(r, y)));
|
|
174
|
+
// Lathe wants the profile bottom to top so the faces point outward.
|
|
175
|
+
const points = curve.getSpacedPoints(96).reverse();
|
|
176
|
+
points[0].x = 0;
|
|
177
|
+
points[points.length - 1].x = 0;
|
|
178
|
+
return new LatheGeometry(points, 64);
|
|
179
|
+
}
|
|
180
|
+
/** A capsule hanging down from its top, `top` wide at the pivot and `bottom` wide at the tip. */
|
|
181
|
+
function taperedCapsule(length, top, bottom) {
|
|
182
|
+
const points = [];
|
|
183
|
+
const steps = 16;
|
|
184
|
+
// Bottom cap, then the straight taper, then the top cap.
|
|
185
|
+
for (let i = 0; i <= steps; i++) {
|
|
186
|
+
const a = -Math.PI / 2 + (i / steps) * (Math.PI / 2);
|
|
187
|
+
points.push(new Vector2(Math.cos(a) * bottom, -length + bottom + Math.sin(a) * bottom));
|
|
188
|
+
}
|
|
189
|
+
for (let i = 0; i <= steps; i++) {
|
|
190
|
+
const a = (i / steps) * (Math.PI / 2);
|
|
191
|
+
points.push(new Vector2(Math.cos(a) * top, -top + Math.sin(a) * top));
|
|
192
|
+
}
|
|
193
|
+
points[0].x = 0;
|
|
194
|
+
points[points.length - 1].x = 0;
|
|
195
|
+
return new LatheGeometry(points, 40);
|
|
196
|
+
}
|
|
197
|
+
/** Half the width of the square the face is drawn in, in metres on the head. */
|
|
198
|
+
const FACE_EXTENT = 0.4;
|
|
199
|
+
/**
|
|
200
|
+
* A disc wrapped onto the front of the head. Its UVs are a straight front-on
|
|
201
|
+
* projection, so whatever is drawn on the face canvas looks exactly like that
|
|
202
|
+
* when the figure faces the camera.
|
|
203
|
+
*/
|
|
204
|
+
function faceGeometry() {
|
|
205
|
+
const geometry = new RingGeometry(0.001, FACE_EXTENT - 0.02, 64, 24);
|
|
206
|
+
const position = geometry.getAttribute('position');
|
|
207
|
+
const normals = new Float32Array(position.count * 3);
|
|
208
|
+
const radius = HEAD_RADIUS * 1.004;
|
|
209
|
+
for (let i = 0; i < position.count; i++) {
|
|
210
|
+
const x = position.getX(i);
|
|
211
|
+
const y = position.getY(i);
|
|
212
|
+
const z = Math.sqrt(Math.max(0, radius * radius - x * x - y * y));
|
|
213
|
+
position.setZ(i, z);
|
|
214
|
+
normals.set([x / radius, y / radius, z / radius], i * 3);
|
|
215
|
+
}
|
|
216
|
+
geometry.setAttribute('normal', new BufferAttribute(normals, 3));
|
|
217
|
+
const uv = geometry.getAttribute('uv');
|
|
218
|
+
for (let i = 0; i < uv.count; i++) {
|
|
219
|
+
uv.setXY(i, (position.getX(i) + FACE_EXTENT) / (2 * FACE_EXTENT), (position.getY(i) + FACE_EXTENT) / (2 * FACE_EXTENT));
|
|
220
|
+
}
|
|
221
|
+
return geometry;
|
|
222
|
+
}
|
|
223
|
+
// --- Faces ------------------------------------------------------------------
|
|
224
|
+
const FACE_SIZE = 512;
|
|
225
|
+
const INK = '#111114';
|
|
226
|
+
const EYE_X = 0.22;
|
|
227
|
+
const EYE_Y = -0.055;
|
|
228
|
+
const EYE_R = 0.05;
|
|
229
|
+
const LINE = 0.014;
|
|
230
|
+
/** How big the features are drawn, relative to the layout below. */
|
|
231
|
+
const FACE_SCALE = 0.78;
|
|
232
|
+
/** The point between the eyes and the mouth the features shrink toward. */
|
|
233
|
+
const FACE_CENTER_Y = -0.13;
|
|
234
|
+
/** Every avatar shares one texture per face, so a crowd costs no more than one visitor. */
|
|
235
|
+
const faceCache = new Map();
|
|
236
|
+
function faceTexture(expression, blinking) {
|
|
237
|
+
const key = `${expression}${blinking ? ':blink' : ''}`;
|
|
238
|
+
let texture = faceCache.get(key);
|
|
239
|
+
if (texture)
|
|
240
|
+
return texture;
|
|
241
|
+
const canvas = document.createElement('canvas');
|
|
242
|
+
canvas.width = canvas.height = FACE_SIZE;
|
|
243
|
+
const ctx = canvas.getContext('2d');
|
|
244
|
+
// Draw in metres on the head, y up, origin at the head centre.
|
|
245
|
+
const scale = FACE_SIZE / (2 * FACE_EXTENT);
|
|
246
|
+
ctx.setTransform(scale, 0, 0, -scale, FACE_SIZE / 2, FACE_SIZE / 2);
|
|
247
|
+
// Shrink the features around the middle of the face, not the head centre,
|
|
248
|
+
// so the face gets smaller without sliding up the head.
|
|
249
|
+
ctx.translate(0, FACE_CENTER_Y);
|
|
250
|
+
ctx.scale(FACE_SCALE, FACE_SCALE);
|
|
251
|
+
ctx.translate(0, -FACE_CENTER_Y);
|
|
252
|
+
ctx.lineCap = 'round';
|
|
253
|
+
ctx.lineJoin = 'round';
|
|
254
|
+
drawFace(ctx, expression, blinking);
|
|
255
|
+
texture = new CanvasTexture(canvas);
|
|
256
|
+
texture.colorSpace = SRGBColorSpace;
|
|
257
|
+
texture.anisotropy = 4;
|
|
258
|
+
faceCache.set(key, texture);
|
|
259
|
+
return texture;
|
|
260
|
+
}
|
|
261
|
+
function drawFace(ctx, expression, blinking) {
|
|
262
|
+
const eyes = (radius = EYE_R) => {
|
|
263
|
+
for (const side of [-1, 1]) {
|
|
264
|
+
if (blinking)
|
|
265
|
+
closedEye(ctx, side * EYE_X, EYE_Y, 'flat');
|
|
266
|
+
else
|
|
267
|
+
dotEye(ctx, side * EYE_X, EYE_Y, radius);
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
switch (expression) {
|
|
271
|
+
case 'smile':
|
|
272
|
+
eyes();
|
|
273
|
+
smile(ctx, 0.084, -0.127, -0.235);
|
|
274
|
+
break;
|
|
275
|
+
case 'grin':
|
|
276
|
+
eyes();
|
|
277
|
+
openMouth(ctx, 0.11, -0.115, -0.285);
|
|
278
|
+
break;
|
|
279
|
+
case 'laugh':
|
|
280
|
+
for (const side of [-1, 1])
|
|
281
|
+
closedEye(ctx, side * EYE_X, EYE_Y, 'happy');
|
|
282
|
+
openMouth(ctx, 0.125, -0.105, -0.31);
|
|
283
|
+
break;
|
|
284
|
+
case 'wink':
|
|
285
|
+
// The figure's right eye (the viewer's left) stays open.
|
|
286
|
+
if (blinking)
|
|
287
|
+
closedEye(ctx, -EYE_X, EYE_Y, 'flat');
|
|
288
|
+
else
|
|
289
|
+
dotEye(ctx, -EYE_X, EYE_Y, EYE_R);
|
|
290
|
+
closedEye(ctx, EYE_X, EYE_Y, 'happy');
|
|
291
|
+
smile(ctx, 0.084, -0.127, -0.235);
|
|
292
|
+
break;
|
|
293
|
+
case 'love':
|
|
294
|
+
for (const side of [-1, 1])
|
|
295
|
+
heart(ctx, side * EYE_X, EYE_Y, 0.092);
|
|
296
|
+
smile(ctx, 0.084, -0.127, -0.235);
|
|
297
|
+
break;
|
|
298
|
+
case 'surprised':
|
|
299
|
+
eyes(EYE_R * 1.2);
|
|
300
|
+
for (const side of [-1, 1])
|
|
301
|
+
brow(ctx, side, 0.05, 0.05, 0.035);
|
|
302
|
+
ctx.fillStyle = INK;
|
|
303
|
+
ctx.beginPath();
|
|
304
|
+
ctx.ellipse(0, -0.175, 0.04, 0.052, 0, 0, Math.PI * 2);
|
|
305
|
+
ctx.fill();
|
|
306
|
+
break;
|
|
307
|
+
case 'sad':
|
|
308
|
+
eyes();
|
|
309
|
+
for (const side of [-1, 1])
|
|
310
|
+
brow(ctx, side, 0.06, -0.035);
|
|
311
|
+
smile(ctx, 0.07, -0.19, -0.1);
|
|
312
|
+
tear(ctx, EYE_X + 0.01, EYE_Y - 0.085);
|
|
313
|
+
break;
|
|
314
|
+
case 'angry':
|
|
315
|
+
eyes();
|
|
316
|
+
for (const side of [-1, 1])
|
|
317
|
+
brow(ctx, side, -0.015, 0.05);
|
|
318
|
+
smile(ctx, 0.075, -0.18, -0.115);
|
|
319
|
+
break;
|
|
320
|
+
case 'sleepy':
|
|
321
|
+
for (const side of [-1, 1])
|
|
322
|
+
closedEye(ctx, side * EYE_X, EYE_Y, 'sleep');
|
|
323
|
+
ctx.fillStyle = INK;
|
|
324
|
+
ctx.beginPath();
|
|
325
|
+
ctx.ellipse(0, -0.17, 0.022, 0.028, 0, 0, Math.PI * 2);
|
|
326
|
+
ctx.fill();
|
|
327
|
+
break;
|
|
328
|
+
case 'neutral':
|
|
329
|
+
eyes();
|
|
330
|
+
line(ctx, [[-0.065, -0.155], [0.065, -0.155]]);
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function dotEye(ctx, x, y, radius) {
|
|
335
|
+
ctx.fillStyle = INK;
|
|
336
|
+
ctx.beginPath();
|
|
337
|
+
ctx.arc(x, y, radius, 0, Math.PI * 2);
|
|
338
|
+
ctx.fill();
|
|
339
|
+
ctx.fillStyle = '#ffffff';
|
|
340
|
+
ctx.beginPath();
|
|
341
|
+
ctx.arc(x - radius * 0.5, y + radius * 0.46, radius * 0.26, 0, Math.PI * 2);
|
|
342
|
+
ctx.fill();
|
|
343
|
+
}
|
|
344
|
+
/** `happy` is an upturned ^, `sleep` a relaxed downturned curve, `flat` a blink. */
|
|
345
|
+
function closedEye(ctx, x, y, shape) {
|
|
346
|
+
const w = EYE_R * 1.15;
|
|
347
|
+
const bend = shape === 'happy' ? 0.07 : shape === 'sleep' ? -0.04 : 0;
|
|
348
|
+
ctx.strokeStyle = INK;
|
|
349
|
+
ctx.lineWidth = LINE * 1.15;
|
|
350
|
+
ctx.beginPath();
|
|
351
|
+
ctx.moveTo(x - w, y);
|
|
352
|
+
ctx.quadraticCurveTo(x, y + bend, x + w, y);
|
|
353
|
+
ctx.stroke();
|
|
354
|
+
}
|
|
355
|
+
/** A curve from (±halfWidth, endY) through a control point at controlY: below the ends smiles, above frowns. */
|
|
356
|
+
function smile(ctx, halfWidth, endY, controlY) {
|
|
357
|
+
ctx.strokeStyle = INK;
|
|
358
|
+
ctx.lineWidth = LINE;
|
|
359
|
+
// A soft U rather than a V: both handles pulled in from the corners and
|
|
360
|
+
// only half as deep, so the bottom is round and flat-ish and the corners
|
|
361
|
+
// rise gently.
|
|
362
|
+
const handleY = endY + (controlY - endY) * 0.52;
|
|
363
|
+
ctx.beginPath();
|
|
364
|
+
ctx.moveTo(-halfWidth, endY);
|
|
365
|
+
ctx.bezierCurveTo(-halfWidth * 0.5, handleY, halfWidth * 0.5, handleY, halfWidth, endY);
|
|
366
|
+
ctx.stroke();
|
|
367
|
+
}
|
|
368
|
+
/** A D-shaped open mouth with a tongue. */
|
|
369
|
+
function openMouth(ctx, halfWidth, topY, controlY) {
|
|
370
|
+
ctx.save();
|
|
371
|
+
ctx.beginPath();
|
|
372
|
+
ctx.moveTo(-halfWidth, topY);
|
|
373
|
+
ctx.quadraticCurveTo(0, controlY, halfWidth, topY);
|
|
374
|
+
ctx.closePath();
|
|
375
|
+
ctx.fillStyle = INK;
|
|
376
|
+
ctx.fill();
|
|
377
|
+
ctx.clip();
|
|
378
|
+
const bottom = (topY + controlY) / 2;
|
|
379
|
+
ctx.fillStyle = '#ff7b8c';
|
|
380
|
+
ctx.beginPath();
|
|
381
|
+
ctx.ellipse(0, bottom - 0.005, halfWidth * 0.55, 0.045, 0, 0, Math.PI * 2);
|
|
382
|
+
ctx.fill();
|
|
383
|
+
ctx.restore();
|
|
384
|
+
}
|
|
385
|
+
/** A brow over one eye. `inner` and `outer` are heights above the eye top, so they set the slant; `arch` bows it upward. */
|
|
386
|
+
function brow(ctx, side, inner, outer, arch = 0) {
|
|
387
|
+
const x = side * EYE_X;
|
|
388
|
+
const base = EYE_Y + EYE_R + 0.03;
|
|
389
|
+
ctx.strokeStyle = INK;
|
|
390
|
+
ctx.lineWidth = LINE;
|
|
391
|
+
ctx.beginPath();
|
|
392
|
+
ctx.moveTo(x - side * 0.05, base + inner);
|
|
393
|
+
ctx.quadraticCurveTo(x, base + (inner + outer) / 2 + arch * 2, x + side * 0.05, base + outer);
|
|
394
|
+
ctx.stroke();
|
|
395
|
+
}
|
|
396
|
+
function heart(ctx, x, y, size) {
|
|
397
|
+
ctx.fillStyle = '#ff4d6d';
|
|
398
|
+
ctx.beginPath();
|
|
399
|
+
ctx.moveTo(x, y - size * 0.75);
|
|
400
|
+
ctx.bezierCurveTo(x - size * 1.1, y - size * 0.05, x - size * 0.7, y + size * 0.85, x, y + size * 0.35);
|
|
401
|
+
ctx.bezierCurveTo(x + size * 0.7, y + size * 0.85, x + size * 1.1, y - size * 0.05, x, y - size * 0.75);
|
|
402
|
+
ctx.fill();
|
|
403
|
+
}
|
|
404
|
+
function tear(ctx, x, y) {
|
|
405
|
+
ctx.fillStyle = '#6cc4ff';
|
|
406
|
+
ctx.beginPath();
|
|
407
|
+
ctx.moveTo(x, y + 0.04);
|
|
408
|
+
ctx.quadraticCurveTo(x + 0.028, y - 0.002, x + 0.02, y - 0.016);
|
|
409
|
+
ctx.arc(x, y - 0.016, 0.02, 0, Math.PI, true);
|
|
410
|
+
ctx.quadraticCurveTo(x - 0.028, y - 0.002, x, y + 0.04);
|
|
411
|
+
ctx.fill();
|
|
412
|
+
}
|
|
413
|
+
function line(ctx, points) {
|
|
414
|
+
ctx.strokeStyle = INK;
|
|
415
|
+
ctx.lineWidth = LINE;
|
|
416
|
+
ctx.beginPath();
|
|
417
|
+
points.forEach(([x, y], i) => (i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y)));
|
|
418
|
+
ctx.stroke();
|
|
419
|
+
}
|
|
420
|
+
//# sourceMappingURL=avatar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avatar.js","sourceRoot":"","sources":["../../src/player/avatar.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Group, type Vector3 } from 'three';
|
|
2
|
+
import type { PlayerOptions } from '../types.js';
|
|
3
|
+
import { type AvatarExpression, type AvatarMotion } from './avatar.js';
|
|
4
|
+
export interface PlayerAvatarOptions extends PlayerOptions {
|
|
5
|
+
height: number;
|
|
6
|
+
radius: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The visible body. It is a plain Object3D so a world can swap in its own
|
|
10
|
+
* model, and so a future multiplayer layer can instantiate the same avatar
|
|
11
|
+
* for remote peers without touching movement code.
|
|
12
|
+
*/
|
|
13
|
+
export declare class Player {
|
|
14
|
+
readonly root: Group | null;
|
|
15
|
+
readonly height: number;
|
|
16
|
+
readonly radius: number;
|
|
17
|
+
readonly eyeHeight: number;
|
|
18
|
+
/** Tracked even for custom avatars, so worlds and peers can react to it. */
|
|
19
|
+
expression: AvatarExpression;
|
|
20
|
+
/** Where the body faces. In third person it follows movement, not the camera. */
|
|
21
|
+
facing: number;
|
|
22
|
+
private isDefaultAvatar;
|
|
23
|
+
constructor(options: PlayerAvatarOptions);
|
|
24
|
+
/** Place the avatar at the player's feet, facing `yaw`, and animate it for `motion`. */
|
|
25
|
+
sync(feet: Vector3, yaw: number, currentHeight: number, motion?: AvatarMotion, freeLook?: boolean): void;
|
|
26
|
+
setExpression(expression: AvatarExpression): void;
|
|
27
|
+
setVisible(visible: boolean): void;
|
|
28
|
+
dispose(): void;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=player.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../../src/player/player.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAkB,KAAK,OAAO,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,qBAAa,MAAM;IACjB,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,4EAA4E;IAC5E,UAAU,EAAE,gBAAgB,CAAW;IACvC,iFAAiF;IACjF,MAAM,SAAK;IAEX,OAAO,CAAC,eAAe,CAAU;gBAErB,OAAO,EAAE,mBAAmB;IAmBxC,wFAAwF;IACxF,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,EAAE,QAAQ,UAAQ,GAAG,IAAI;IAiBtG,aAAa,CAAC,UAAU,EAAE,gBAAgB,GAAG,IAAI;IAKjD,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIlC,OAAO,IAAI,IAAI;CAWhB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Group, Mesh } from 'three';
|
|
2
|
+
import { animateDefaultAvatar, createDefaultAvatar, setAvatarExpression, } from './avatar.js';
|
|
3
|
+
/**
|
|
4
|
+
* The visible body. It is a plain Object3D so a world can swap in its own
|
|
5
|
+
* model, and so a future multiplayer layer can instantiate the same avatar
|
|
6
|
+
* for remote peers without touching movement code.
|
|
7
|
+
*/
|
|
8
|
+
export class Player {
|
|
9
|
+
root;
|
|
10
|
+
height;
|
|
11
|
+
radius;
|
|
12
|
+
eyeHeight;
|
|
13
|
+
/** Tracked even for custom avatars, so worlds and peers can react to it. */
|
|
14
|
+
expression = 'smile';
|
|
15
|
+
/** Where the body faces. In third person it follows movement, not the camera. */
|
|
16
|
+
facing = 0;
|
|
17
|
+
isDefaultAvatar;
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.height = options.height;
|
|
20
|
+
this.radius = options.radius;
|
|
21
|
+
this.eyeHeight = options.eyeHeight ?? options.height - 0.22;
|
|
22
|
+
if (options.avatar === false) {
|
|
23
|
+
this.root = null;
|
|
24
|
+
this.isDefaultAvatar = false;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
this.root = new Group();
|
|
28
|
+
this.root.name = 'worldmesh:player';
|
|
29
|
+
this.isDefaultAvatar = !options.avatar;
|
|
30
|
+
const body = options.avatar ?? createDefaultAvatar(options.height);
|
|
31
|
+
this.root.add(body);
|
|
32
|
+
}
|
|
33
|
+
/** Place the avatar at the player's feet, facing `yaw`, and animate it for `motion`. */
|
|
34
|
+
sync(feet, yaw, currentHeight, motion, freeLook = false) {
|
|
35
|
+
if (!freeLook)
|
|
36
|
+
this.facing = yaw;
|
|
37
|
+
else if (motion && motion.speed > 0.3 && motion.heading !== undefined) {
|
|
38
|
+
let delta = motion.heading - this.facing;
|
|
39
|
+
delta = Math.atan2(Math.sin(delta), Math.cos(delta));
|
|
40
|
+
this.facing += delta * (1 - Math.exp(-12 * motion.dt));
|
|
41
|
+
}
|
|
42
|
+
if (!this.root)
|
|
43
|
+
return;
|
|
44
|
+
this.root.position.copy(feet);
|
|
45
|
+
this.root.rotation.y = this.facing;
|
|
46
|
+
if (this.isDefaultAvatar) {
|
|
47
|
+
// Squash the default body while crouching instead of rebuilding it.
|
|
48
|
+
this.root.scale.y = currentHeight / this.height;
|
|
49
|
+
if (motion)
|
|
50
|
+
animateDefaultAvatar(this.root.children[0], motion);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
setExpression(expression) {
|
|
54
|
+
this.expression = expression;
|
|
55
|
+
if (this.root && this.isDefaultAvatar)
|
|
56
|
+
setAvatarExpression(this.root.children[0], expression);
|
|
57
|
+
}
|
|
58
|
+
setVisible(visible) {
|
|
59
|
+
if (this.root)
|
|
60
|
+
this.root.visible = visible;
|
|
61
|
+
}
|
|
62
|
+
dispose() {
|
|
63
|
+
this.root?.traverse((child) => {
|
|
64
|
+
if (child instanceof Mesh) {
|
|
65
|
+
child.geometry.dispose();
|
|
66
|
+
const material = child.material;
|
|
67
|
+
if (Array.isArray(material))
|
|
68
|
+
material.forEach((m) => m.dispose());
|
|
69
|
+
else
|
|
70
|
+
material.dispose();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
this.root?.removeFromParent();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=player.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player.js","sourceRoot":"","sources":["../../src/player/player.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Object3D, Scene, Vector3 } from 'three';
|
|
2
|
+
import type { PortalMode, PortalOptions } from '../types.js';
|
|
3
|
+
export interface ResolvedPortal extends PortalOptions {
|
|
4
|
+
label: string;
|
|
5
|
+
radius: number;
|
|
6
|
+
mode: PortalMode;
|
|
7
|
+
object: Object3D | null;
|
|
8
|
+
center: Vector3;
|
|
9
|
+
inside: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Portals are the link element of the spatial web. For the MVP "following a
|
|
13
|
+
* link" is literally a page navigation to the destination world's own URL —
|
|
14
|
+
* WorldMesh hosts nothing about the destination. A `from` parameter is added
|
|
15
|
+
* so the destination knows where the visitor came from; state handoff and
|
|
16
|
+
* transitions can be layered on later without changing the world-side API.
|
|
17
|
+
*/
|
|
18
|
+
export declare class PortalManager {
|
|
19
|
+
private portals;
|
|
20
|
+
private scene;
|
|
21
|
+
private group;
|
|
22
|
+
constructor(scene: Scene, portals?: PortalOptions[]);
|
|
23
|
+
get all(): readonly ResolvedPortal[];
|
|
24
|
+
add(options: PortalOptions): ResolvedPortal;
|
|
25
|
+
/** Nearest portal the player is standing in, if any. */
|
|
26
|
+
findActive(feet: Vector3): ResolvedPortal | null;
|
|
27
|
+
animate(elapsed: number): void;
|
|
28
|
+
dispose(): void;
|
|
29
|
+
}
|
|
30
|
+
/** Build the destination URL, carrying a back-reference to this world. */
|
|
31
|
+
export declare function buildTravelUrl(target: string): string;
|
|
32
|
+
/** Where the visitor came from, if they arrived through a portal. */
|
|
33
|
+
export declare function getReferringWorld(): string | null;
|
|
34
|
+
//# sourceMappingURL=portals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portals.d.ts","sourceRoot":"","sources":["../../src/portals/portals.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,QAAQ,EACR,KAAK,EAEL,OAAO,EACR,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7D,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;GAMG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,KAAK,CAAe;gBAEhB,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE,aAAa,EAAO;IAOvD,IAAI,GAAG,IAAI,SAAS,cAAc,EAAE,CAEnC;IAED,GAAG,CAAC,OAAO,EAAE,aAAa,GAAG,cAAc;IAsB3C,wDAAwD;IACxD,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI;IAiBhD,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ9B,OAAO,IAAI,IAAI;CAYhB;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAUrD;AAED,qEAAqE;AACrE,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAGjD"}
|