mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-13 17:35:40 +02:00
wip
This commit is contained in:
@@ -220,6 +220,10 @@ const resolution = computed<number>(() => resolutionRaw.value ?? resolutionAutoV
|
||||
|
||||
const useVirtualJoystick = isTouchUsing && (deviceKind === 'smartphone' || deviceKind === 'tablet');
|
||||
|
||||
const wasdVec = { x: 0, y: 0 };
|
||||
const pointerVec = { x: 0, y: 0 };
|
||||
let isDashing = false;
|
||||
|
||||
const joyStickRadiusPx = 100;
|
||||
const joyStickLeftEl = useTemplateRef('joyStickLeftEl');
|
||||
const joyStickRightEl = useTemplateRef('joyStickRightEl');
|
||||
@@ -270,7 +274,7 @@ const roomControllerOptions = computed<RoomControllerOptions>(() => ({
|
||||
fps: fps.value,
|
||||
resolution: resolution.value,
|
||||
useVirtualJoystick,
|
||||
workerMode: false,
|
||||
workerMode: true,
|
||||
}));
|
||||
|
||||
const controller = new RoomController(data, roomControllerOptions.value);
|
||||
@@ -343,6 +347,104 @@ onMounted(async () => {
|
||||
});
|
||||
}
|
||||
|
||||
canvas.value!.addEventListener('keydown', (ev) => {
|
||||
if (ev.repeat) return;
|
||||
|
||||
switch (ev.code) {
|
||||
case 'KeyW':
|
||||
wasdVec.y = -1;
|
||||
controller.setCameraMoveVector(wasdVec, isDashing);
|
||||
break;
|
||||
case 'KeyS':
|
||||
wasdVec.y = 1;
|
||||
controller.setCameraMoveVector(wasdVec, isDashing);
|
||||
break;
|
||||
case 'KeyA':
|
||||
wasdVec.x = -1;
|
||||
controller.setCameraMoveVector(wasdVec, isDashing);
|
||||
break;
|
||||
case 'KeyD':
|
||||
wasdVec.x = 1;
|
||||
controller.setCameraMoveVector(wasdVec, isDashing);
|
||||
break;
|
||||
case 'ShiftLeft':
|
||||
case 'ShiftRight':
|
||||
isDashing = true;
|
||||
controller.setCameraMoveVector(wasdVec, isDashing);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
canvas.value!.addEventListener('keyup', (ev) => {
|
||||
switch (ev.code) {
|
||||
case 'KeyW':
|
||||
wasdVec.y = 0;
|
||||
controller.setCameraMoveVector(wasdVec, isDashing);
|
||||
break;
|
||||
case 'KeyS':
|
||||
wasdVec.y = 0;
|
||||
controller.setCameraMoveVector(wasdVec, isDashing);
|
||||
break;
|
||||
case 'KeyA':
|
||||
wasdVec.x = 0;
|
||||
controller.setCameraMoveVector(wasdVec, isDashing);
|
||||
break;
|
||||
case 'KeyD':
|
||||
wasdVec.x = 0;
|
||||
controller.setCameraMoveVector(wasdVec, isDashing);
|
||||
break;
|
||||
case 'ShiftLeft':
|
||||
case 'ShiftRight':
|
||||
isDashing = false;
|
||||
controller.setCameraMoveVector(wasdVec, isDashing);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
canvas.value!.addEventListener('pointerdown', (ev) => {
|
||||
pointerVec.x = ev.clientX;
|
||||
pointerVec.y = ev.clientY;
|
||||
|
||||
let timeoutId: number | null = null;
|
||||
|
||||
const onMove = (ev: PointerEvent) => {
|
||||
if (timeoutId != null) {
|
||||
window.clearTimeout(timeoutId);
|
||||
timeoutId = null;
|
||||
}
|
||||
|
||||
const before = pointerVec;
|
||||
const after = { x: ev.clientX, y: ev.clientY };
|
||||
|
||||
controller.setCameraRotateVector({
|
||||
x: after.x - before.x,
|
||||
y: after.y - before.y,
|
||||
});
|
||||
|
||||
pointerVec.x = after.x;
|
||||
pointerVec.y = after.y;
|
||||
|
||||
timeoutId = window.setTimeout(() => {
|
||||
timeoutId = null;
|
||||
pointerVec.x = 0;
|
||||
pointerVec.y = 0;
|
||||
|
||||
controller.setCameraRotateVector(pointerVec);
|
||||
}, 10);
|
||||
};
|
||||
|
||||
canvas.value!.addEventListener('pointermove', onMove);
|
||||
|
||||
canvas.value!.addEventListener('pointerup', (ev) => {
|
||||
canvas.value!.removeEventListener('pointermove', onMove);
|
||||
|
||||
pointerVec.x = 0;
|
||||
pointerVec.y = 0;
|
||||
|
||||
controller.setCameraRotateVector(pointerVec);
|
||||
});
|
||||
});
|
||||
|
||||
watch([graphicsQuality, fps, resolution], () => {
|
||||
refresh();
|
||||
});
|
||||
|
||||
@@ -245,6 +245,22 @@ export class RoomController {
|
||||
}
|
||||
}
|
||||
|
||||
public setCameraMoveVector(vec: { x: number; y: number }, dash: boolean) {
|
||||
if (this.worker != null) {
|
||||
this.worker.postMessage({ type: 'call', fn: 'cameraMove', args: [vec, dash] });
|
||||
} else if (this.engine != null) {
|
||||
this.engine.cameraMove(vec, dash);
|
||||
}
|
||||
}
|
||||
|
||||
public setCameraRotateVector(vec: { x: number; y: number }) {
|
||||
if (this.worker != null) {
|
||||
this.worker.postMessage({ type: 'call', fn: 'cameraRotate', args: [vec] });
|
||||
} else if (this.engine != null) {
|
||||
this.engine.cameraRotate(vec);
|
||||
}
|
||||
}
|
||||
|
||||
public setCameraJoystickMoveVector(vec: { x: number; y: number }) {
|
||||
if (this.worker != null) {
|
||||
this.worker.postMessage({ type: 'call', fn: 'cameraJoystickMove', args: [vec] });
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import * as BABYLON from '@babylonjs/core';
|
||||
import { registerBuiltInLoaders } from '@babylonjs/loaders/dynamic';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import { TIME_MAP, scaleMorph, camelToKebab, cm, WORLD_SCALE, getMeshesBoundingBox, Timer, getYRotationDirection, FreeCameraTouchVirtualJoystickInput } from '../utility.js';
|
||||
import { TIME_MAP, scaleMorph, camelToKebab, cm, WORLD_SCALE, getMeshesBoundingBox, Timer, getYRotationDirection, FreeCameraVirtualJoystickInput, FreeCameraManualInput } from '../utility.js';
|
||||
import { getObjectDef } from './object-defs.js';
|
||||
import { findMaterial, ModelManager, SYSTEM_HEYA_MESH_NAMES, SYSTEM_MESH_NAMES } from './utility.js';
|
||||
import { SimpleHeyaManager } from './heya.js';
|
||||
@@ -26,7 +26,7 @@ import { deepClone } from '@/utility/clone.js';
|
||||
|
||||
const BAKE_TRANSFORM = false; // 実験的
|
||||
const SNAPSHOT_RENDERING = true; // 実験的
|
||||
const IGNORE_OBJECTS: string[] = []; // for debug
|
||||
const IGNORE_OBJECTS: string[] = ['aquarium']; // for debug
|
||||
const RENDER_OUTDOOR_ENV = false;
|
||||
const IN_WEB_WORKER = typeof window === 'undefined';
|
||||
|
||||
@@ -290,7 +290,7 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
|
||||
|
||||
this.scene.collisionsEnabled = true;
|
||||
|
||||
this.camera = options.useVirtualJoystick ? new BABYLON.FreeCamera('camera', new BABYLON.Vector3(0, cm(130), cm(0)), this.scene) : new BABYLON.UniversalCamera('camera', new BABYLON.Vector3(0, cm(130), cm(0)), this.scene);
|
||||
this.camera = new BABYLON.FreeCamera('camera', new BABYLON.Vector3(0, cm(130), cm(0)), this.scene);
|
||||
this.camera.minZ = cm(1);
|
||||
this.camera.maxZ = RENDER_OUTDOOR_ENV ? cm(10000) : cm(1000);
|
||||
this.camera.fov = 1;
|
||||
@@ -298,36 +298,19 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
|
||||
this.camera.checkCollisions = true;
|
||||
this.camera.applyGravity = true;
|
||||
this.camera.needMoveForGravity = true;
|
||||
this.camera.inputs.clear();
|
||||
|
||||
if (options.useVirtualJoystick) {
|
||||
this.camera.inputs.clear();
|
||||
this.camera.inputs.add(new FreeCameraTouchVirtualJoystickInput({
|
||||
this.camera.inputs.add(new FreeCameraVirtualJoystickInput({
|
||||
moveSensitivity: 0.015 * WORLD_SCALE,
|
||||
rotationSensitivity: 0.1,
|
||||
rotationSensitivity: 0.01,
|
||||
}));
|
||||
this.camera.inertia = 0.75;
|
||||
} else {
|
||||
const normalSpeed = 0.02 * WORLD_SCALE;
|
||||
this.camera.speed = normalSpeed;
|
||||
|
||||
this.camera.keysUp.push(87); // W
|
||||
this.camera.keysDown.push(83); // S
|
||||
this.camera.keysLeft.push(65); // A
|
||||
this.camera.keysRight.push(68); // D
|
||||
this.scene.onKeyboardObservable.add((kbInfo) => {
|
||||
switch (kbInfo.type) {
|
||||
case BABYLON.KeyboardEventTypes.KEYDOWN:
|
||||
if (kbInfo.event.key === 'Shift') {
|
||||
this.camera.speed = normalSpeed * 4;
|
||||
}
|
||||
break;
|
||||
case BABYLON.KeyboardEventTypes.KEYUP:
|
||||
if (kbInfo.event.key === 'Shift') {
|
||||
this.camera.speed = normalSpeed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
this.camera.inputs.add(new FreeCameraManualInput({
|
||||
moveSensitivity: 0.001 * WORLD_SCALE,
|
||||
rotationSensitivity: 0.01,
|
||||
}));
|
||||
}
|
||||
|
||||
this.camera.attachControl(this.canvas);
|
||||
@@ -622,12 +605,20 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
|
||||
this.startRenderLoop();
|
||||
}
|
||||
|
||||
public cameraMove(vector: { x: number; y: number; }, dash: boolean) {
|
||||
(this.camera.inputs.attached.manual as FreeCameraManualInput).setMoveVector(dash ? { x: vector.x * 4, y: vector.y * 4 } : vector);
|
||||
}
|
||||
|
||||
public cameraRotate(vector: { x: number; y: number; }) {
|
||||
(this.camera.inputs.attached.manual as FreeCameraManualInput).setRotationVector(vector);
|
||||
}
|
||||
|
||||
public cameraJoystickMove(vector: { x: number; y: number; }) {
|
||||
(this.camera.inputs.attached.joystick as FreeCameraTouchVirtualJoystickInput).setJoystickMoveVector(vector);
|
||||
(this.camera.inputs.attached.joystick as FreeCameraVirtualJoystickInput).setJoystickMoveVector(vector);
|
||||
}
|
||||
|
||||
public cameraJoystickRotate(vector: { x: number; y: number; }) {
|
||||
(this.camera.inputs.attached.joystick as FreeCameraTouchVirtualJoystickInput).setJoystickRotationVector(vector);
|
||||
(this.camera.inputs.attached.joystick as FreeCameraVirtualJoystickInput).setJoystickRotationVector(vector);
|
||||
}
|
||||
|
||||
public selectObject(objectId: string | null) {
|
||||
|
||||
@@ -618,20 +618,20 @@ export function getRgb(hex: string | number): [number, number, number] | null {
|
||||
return m.map(x => parseInt(x, 16) / 255) as [number, number, number];
|
||||
}
|
||||
|
||||
export class FreeCameraTouchVirtualJoystickInput implements BABYLON.ICameraInput<BABYLON.FreeCamera> {
|
||||
export class FreeCameraVirtualJoystickInput implements BABYLON.ICameraInput<BABYLON.FreeCamera> {
|
||||
public camera: BABYLON.FreeCamera;
|
||||
private joystickMoveSensitivity: number;
|
||||
private joystickRotationSensitivity: number;
|
||||
private joystickMoveVector = BABYLON.Vector3.Zero();
|
||||
private joystickRotationVecX = 0;
|
||||
private joystickRotationVecY = 0;
|
||||
private moveSensitivity: number;
|
||||
private rotationSensitivity: number;
|
||||
private moveVector = BABYLON.Vector3.Zero();
|
||||
private rotationVecX = 0;
|
||||
private rotationVecY = 0;
|
||||
|
||||
constructor(options: {
|
||||
moveSensitivity?: number;
|
||||
rotationSensitivity?: number;
|
||||
}) {
|
||||
this.joystickMoveSensitivity = options.moveSensitivity ?? 0.01;
|
||||
this.joystickRotationSensitivity = options.rotationSensitivity ?? 0.01;
|
||||
this.moveSensitivity = options.moveSensitivity ?? 0.01;
|
||||
this.rotationSensitivity = options.rotationSensitivity ?? 0.01;
|
||||
}
|
||||
|
||||
getClassName = () => this.constructor.name;
|
||||
@@ -645,7 +645,7 @@ export class FreeCameraTouchVirtualJoystickInput implements BABYLON.ICameraInput
|
||||
}
|
||||
|
||||
public setJoystickMoveVector(vec: { x: number; y: number }) {
|
||||
this.joystickMoveVector = new BABYLON.Vector3(vec.x, 0, -vec.y).scale(this.joystickMoveSensitivity);
|
||||
this.moveVector = new BABYLON.Vector3(vec.x, 0, -vec.y).scale(this.moveSensitivity);
|
||||
}
|
||||
|
||||
public setJoystickRotationVector(vec: { x: number; y: number }) {
|
||||
@@ -653,16 +653,65 @@ export class FreeCameraTouchVirtualJoystickInput implements BABYLON.ICameraInput
|
||||
if (this.camera.getScene().useRightHandedSystem) directionAdjust *= -1;
|
||||
if (this.camera.parent && this.camera.parent._getWorldMatrixDeterminant() < 0) directionAdjust *= -1;
|
||||
|
||||
this.joystickRotationVecX = vec.y * this.joystickRotationSensitivity * this.joystickRotationSensitivity;
|
||||
this.joystickRotationVecY = vec.x * this.joystickRotationSensitivity * directionAdjust * this.joystickRotationSensitivity;
|
||||
this.rotationVecX = vec.y * this.rotationSensitivity;
|
||||
this.rotationVecY = vec.x * this.rotationSensitivity * directionAdjust;
|
||||
}
|
||||
|
||||
checkInputs() {
|
||||
this.camera.cameraRotation.y += this.joystickRotationVecY;
|
||||
this.camera.cameraRotation.x += this.joystickRotationVecX;
|
||||
this.camera.cameraRotation.y += this.rotationVecY;
|
||||
this.camera.cameraRotation.x += this.rotationVecX;
|
||||
|
||||
this.camera.cameraDirection.addInPlace(
|
||||
BABYLON.Vector3.TransformCoordinates(this.joystickMoveVector, BABYLON.Matrix.RotationY(this.camera.rotation.y)),
|
||||
BABYLON.Vector3.TransformCoordinates(this.moveVector, BABYLON.Matrix.RotationY(this.camera.rotation.y)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class FreeCameraManualInput implements BABYLON.ICameraInput<BABYLON.FreeCamera> {
|
||||
public camera: BABYLON.FreeCamera;
|
||||
private moveSensitivity: number;
|
||||
private rotationSensitivity: number;
|
||||
private moveVector = BABYLON.Vector3.Zero();
|
||||
private rotationVecX = 0;
|
||||
private rotationVecY = 0;
|
||||
|
||||
constructor(options: {
|
||||
moveSensitivity?: number;
|
||||
rotationSensitivity?: number;
|
||||
}) {
|
||||
this.moveSensitivity = options.moveSensitivity ?? 0.01;
|
||||
this.rotationSensitivity = options.rotationSensitivity ?? 0.01;
|
||||
}
|
||||
|
||||
getClassName = () => this.constructor.name;
|
||||
|
||||
getSimpleName = () => 'manual';
|
||||
|
||||
attachControl(noPreventDefault) {
|
||||
}
|
||||
|
||||
detachControl() {
|
||||
}
|
||||
|
||||
public setMoveVector(vec: { x: number; y: number }) {
|
||||
this.moveVector = new BABYLON.Vector3(vec.x, 0, -vec.y).scale(this.moveSensitivity);
|
||||
}
|
||||
|
||||
public setRotationVector(vec: { x: number; y: number }) {
|
||||
let directionAdjust = 1;
|
||||
if (this.camera.getScene().useRightHandedSystem) directionAdjust *= -1;
|
||||
if (this.camera.parent && this.camera.parent._getWorldMatrixDeterminant() < 0) directionAdjust *= -1;
|
||||
|
||||
this.rotationVecX = vec.y * this.rotationSensitivity;
|
||||
this.rotationVecY = vec.x * this.rotationSensitivity * directionAdjust;
|
||||
}
|
||||
|
||||
checkInputs() {
|
||||
this.camera.cameraRotation.y += this.rotationVecY;
|
||||
this.camera.cameraRotation.x += this.rotationVecX;
|
||||
|
||||
this.camera.cameraDirection.addInPlace(
|
||||
BABYLON.Vector3.TransformCoordinates(this.moveVector, BABYLON.Matrix.RotationY(this.camera.rotation.y)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user