mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-20 19:55:28 +02:00
wip
This commit is contained in:
@@ -161,13 +161,6 @@ function vecToLocal(vector: BABYLON.Vector3, mesh: BABYLON.Mesh): BABYLON.Vector
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isIntersectXZ(a: BABYLON.BoundingBox, b: BABYLON.BoundingBox): boolean {
|
|
||||||
return (a.minimumWorld.x <= b.maximumWorld.x &&
|
|
||||||
a.maximumWorld.x >= b.minimumWorld.x) &&
|
|
||||||
(a.minimumWorld.z <= b.maximumWorld.z &&
|
|
||||||
a.maximumWorld.z >= b.minimumWorld.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
const _assumedFramesPerSecond = 60;
|
const _assumedFramesPerSecond = 60;
|
||||||
|
|
||||||
class HorizontalCameraKeyboardMoveInput extends BABYLON.BaseCameraPointersInput {
|
class HorizontalCameraKeyboardMoveInput extends BABYLON.BaseCameraPointersInput {
|
||||||
@@ -293,11 +286,13 @@ export class RoomEngine {
|
|||||||
private timeoutIds: number[] = [];
|
private timeoutIds: number[] = [];
|
||||||
private objectMeshs: Map<string, BABYLON.AbstractMesh> = new Map();
|
private objectMeshs: Map<string, BABYLON.AbstractMesh> = new Map();
|
||||||
private grabbing: {
|
private grabbing: {
|
||||||
|
objectId: string;
|
||||||
mesh: BABYLON.AbstractMesh;
|
mesh: BABYLON.AbstractMesh;
|
||||||
startOffset: BABYLON.Vector3;
|
startOffset: BABYLON.Vector3;
|
||||||
startRotationY: number;
|
startRotationY: number;
|
||||||
startDistance: number;
|
startDistance: number;
|
||||||
ghost: BABYLON.AbstractMesh;
|
ghost: BABYLON.AbstractMesh;
|
||||||
|
descendantStickyObjectIds: string[];
|
||||||
} | null = null;
|
} | null = null;
|
||||||
private highlightedObjectId: string | null = null;
|
private highlightedObjectId: string | null = null;
|
||||||
private time: 0 | 1 | 2 = 2; // 0: 昼, 1: 夕, 2: 夜
|
private time: 0 | 1 | 2 = 2; // 0: 昼, 1: 夕, 2: 夜
|
||||||
@@ -589,96 +584,58 @@ export class RoomEngine {
|
|||||||
|
|
||||||
private handleGrabbing() {
|
private handleGrabbing() {
|
||||||
if (this.grabbing == null) return;
|
if (this.grabbing == null) return;
|
||||||
|
const grabbing = this.grabbing;
|
||||||
|
|
||||||
const dir = this.camera.getDirection(BABYLON.Axis.Z);
|
const dir = this.camera.getDirection(BABYLON.Axis.Z);
|
||||||
this.grabbing.ghost.position = this.camera.position.add(dir.scale(this.grabbing.startDistance)).add(this.grabbing.startOffset);
|
grabbing.ghost.position = this.camera.position.add(dir.scale(grabbing.startDistance)).add(grabbing.startOffset);
|
||||||
this.grabbing.ghost.rotation = new BABYLON.Vector3(0, this.camera.rotation.y + this.grabbing.startRotationY, 0);
|
grabbing.ghost.rotation = new BABYLON.Vector3(0, this.camera.rotation.y + grabbing.startRotationY, 0);
|
||||||
|
|
||||||
if (this.enableGridSnapping) {
|
if (this.enableGridSnapping) {
|
||||||
const scale = 10/*cm*/;
|
const scale = 10/*cm*/;
|
||||||
this.grabbing.ghost.position.x = Math.round(this.grabbing.ghost.position.x / scale) * scale;
|
grabbing.ghost.position.x = Math.round(grabbing.ghost.position.x / scale) * scale;
|
||||||
this.grabbing.ghost.position.y = Math.round(this.grabbing.ghost.position.y / scale) * scale;
|
grabbing.ghost.position.y = Math.round(grabbing.ghost.position.y / scale) * scale;
|
||||||
this.grabbing.ghost.position.z = Math.round(this.grabbing.ghost.position.z / scale) * scale;
|
grabbing.ghost.position.z = Math.round(grabbing.ghost.position.z / scale) * scale;
|
||||||
this.grabbing.ghost.rotation.y = Math.round(this.grabbing.ghost.rotation.y / (Math.PI / 4)) * (Math.PI / 4);
|
grabbing.ghost.rotation.y = Math.round(grabbing.ghost.rotation.y / (Math.PI / 4)) * (Math.PI / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
const stickyObjectIds = Array.from(this.def.objects.filter(o => o.sticky === this.grabbing.mesh.metadata.objectId)).map(o => o.id);
|
|
||||||
|
|
||||||
let y = 0;
|
let y = 0;
|
||||||
let sticky = null;
|
let sticky: string | null = null;
|
||||||
|
|
||||||
for (const rcmb of this.roomCollisionMeshes.filter(m => m.name.startsWith('_COLLISION_FLOOR_'))) {
|
// 下に向かってレイを飛ばす
|
||||||
const rcb = rcmb.getBoundingInfo().boundingBox;
|
const ray = new BABYLON.Ray(grabbing.ghost.position, new BABYLON.Vector3(0, -1, 0), 1000/*cm*/);
|
||||||
for (const tm of this.grabbing.mesh.getChildMeshes()) {
|
const hit = this.scene.pickWithRay(ray, (m) =>
|
||||||
const tmb = tm.getBoundingInfo().boundingBox;
|
m.metadata?.objectId !== grabbing.objectId &&
|
||||||
if (isIntersectXZ(tmb, rcb)) {
|
!m.metadata?.isGhost &&
|
||||||
const topY = rcb.maximumWorld.y;
|
!grabbing.descendantStickyObjectIds.includes(m.metadata?.objectId) &&
|
||||||
if (y === 0 || topY > y) {
|
(m.name.startsWith('_COLLISION_FLOOR_') || m.name.startsWith('_COLLISION_TOP_')));
|
||||||
y = topY;
|
if (hit != null && hit.pickedPoint != null && hit.pickedMesh != null) {
|
||||||
}
|
y = hit.pickedPoint.y;
|
||||||
}
|
sticky = hit.pickedMesh.metadata?.objectId ?? null;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const isStickyChild = (parent: BABYLON.AbstractMesh, target: BABYLON.AbstractMesh): boolean => {
|
|
||||||
const stickyObjectIds = Array.from(this.def.objects.filter(o => o.sticky === parent.metadata.objectId)).map(o => o.id);
|
|
||||||
for (const soid of stickyObjectIds) {
|
|
||||||
if (soid === target.metadata.objectId) return true;
|
|
||||||
const soMesh = this.objectMeshs.get(soid)!;
|
|
||||||
if (isStickyChild(soMesh, target)) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkObjectEntries = this.objectMeshs.entries()
|
|
||||||
.filter(([_id, o]) => {
|
|
||||||
if (o === this.grabbing.mesh) return false;
|
|
||||||
if (stickyObjectIds.includes(_id)) return false;
|
|
||||||
if (isStickyChild(this.grabbing.mesh, o)) return false;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const [id, o] of checkObjectEntries) {
|
|
||||||
for (const om of o.getChildMeshes()) {
|
|
||||||
if (!om.name.startsWith('_COLLISION_TOP_')) continue;
|
|
||||||
const omb = om.getBoundingInfo().boundingBox;
|
|
||||||
for (const tm of this.grabbing.mesh.getChildMeshes()) {
|
|
||||||
const tmb = tm.getBoundingInfo().boundingBox;
|
|
||||||
if (isIntersectXZ(tmb, omb)) {
|
|
||||||
const topY = omb.maximumWorld.y;
|
|
||||||
if (topY > this.grabbing.ghost.position.y) continue;
|
|
||||||
if (y === 0 || topY > y) {
|
|
||||||
y = topY;
|
|
||||||
sticky = id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sticky != null) {
|
if (sticky != null) {
|
||||||
this.def.objects.find(o => o.id === this.grabbing.mesh.metadata.objectId)!.sticky = sticky;
|
this.def.objects.find(o => o.id === grabbing.objectId)!.sticky = sticky;
|
||||||
} else {
|
} else {
|
||||||
this.def.objects.find(o => o.id === this.grabbing.mesh.metadata.objectId)!.sticky = null;
|
this.def.objects.find(o => o.id === grabbing.objectId)!.sticky = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.grabbing.mesh.position = this.grabbing.ghost.position.clone();
|
grabbing.mesh.position = grabbing.ghost.position.clone();
|
||||||
//this.grabbing.mesh.position.x = Math.min(Math.max(this.grabbing.position.x, -(this.ROOM_SIZE / 2)), (this.ROOM_SIZE / 2));
|
//grabbing.mesh.position.x = Math.min(Math.max(grabbing.position.x, -(this.ROOM_SIZE / 2)), (this.ROOM_SIZE / 2));
|
||||||
//this.grabbing.mesh.position.z = Math.min(Math.max(this.grabbing.position.z, -(this.ROOM_SIZE / 2)), (this.ROOM_SIZE / 2));
|
//grabbing.mesh.position.z = Math.min(Math.max(grabbing.position.z, -(this.ROOM_SIZE / 2)), (this.ROOM_SIZE / 2));
|
||||||
this.grabbing.mesh.position.y = y;
|
grabbing.mesh.position.y = y;
|
||||||
|
|
||||||
this.grabbing.mesh.rotation = this.grabbing.ghost.rotation.clone();
|
grabbing.mesh.rotation = grabbing.ghost.rotation.clone();
|
||||||
|
|
||||||
const ray = new BABYLON.Ray(this.camera.position, this.camera.getDirection(BABYLON.Axis.Z), 1000/*cm*/);
|
//const ray = new BABYLON.Ray(this.camera.position, this.camera.getDirection(BABYLON.Axis.Z), 1000/*cm*/);
|
||||||
const hit = this.scene.pickWithRay(ray, (m) => m.name.startsWith('_COLLISION_WALL_'))!;
|
//const hit = this.scene.pickWithRay(ray, (m) => m.name.startsWith('_COLLISION_WALL_'))!;
|
||||||
if (hit.pickedMesh != null) {
|
//if (hit.pickedMesh != null) {
|
||||||
const grabbingBox = this.grabbing.mesh.getBoundingInfo().boundingBox;
|
// const grabbingBox = this.grabbing.mesh.getBoundingInfo().boundingBox;
|
||||||
const grabDistanceVector = this.grabbing.mesh.position.subtract(this.camera.position);
|
// const grabDistanceVector = this.grabbing.mesh.position.subtract(this.camera.position);
|
||||||
if (grabDistanceVector.length() > hit.distance) {
|
// if (grabDistanceVector.length() > hit.distance) {
|
||||||
this.grabbing.mesh.position = this.camera.position.add(dir.scale(hit.distance));
|
// this.grabbing.mesh.position = this.camera.position.add(dir.scale(hit.distance));
|
||||||
this.grabbing.mesh.position.y = y;
|
// this.grabbing.mesh.position.y = y;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
//const displacementVector = new BABYLON.Vector3(
|
//const displacementVector = new BABYLON.Vector3(
|
||||||
// this.grabbing.ghost.position.x - this.grabbing.mesh.position.x,
|
// this.grabbing.ghost.position.x - this.grabbing.mesh.position.x,
|
||||||
@@ -688,11 +645,11 @@ export class RoomEngine {
|
|||||||
//this.grabbing.mesh.moveWithCollisions(displacementVector);
|
//this.grabbing.mesh.moveWithCollisions(displacementVector);
|
||||||
//this.grabbing.mesh.position.y = y;
|
//this.grabbing.mesh.position.y = y;
|
||||||
|
|
||||||
for (const soid of stickyObjectIds) {
|
//for (const soid of stickyObjectIds) {
|
||||||
//const soMesh = this.objectMeshs.get(soid)!;
|
// //const soMesh = this.objectMeshs.get(soid)!;
|
||||||
//const offset = this.grabbing.mesh!.position.subtract(soMeshStartPosition);
|
// //const offset = this.grabbing.mesh!.position.subtract(soMeshStartPosition);
|
||||||
//soMesh.position = this.grabbing.mesh!.position.subtract(offset);
|
// //soMesh.position = this.grabbing.mesh!.position.subtract(offset);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async loadEnvModel() {
|
private async loadEnvModel() {
|
||||||
@@ -807,8 +764,9 @@ export class RoomEngine {
|
|||||||
}
|
}
|
||||||
const startDistance = BABYLON.Vector3.Distance(this.camera.position, highlightedObject.position);
|
const startDistance = BABYLON.Vector3.Distance(this.camera.position, highlightedObject.position);
|
||||||
const ghost = highlightedObject.clone('ghost', null, false)!;
|
const ghost = highlightedObject.clone('ghost', null, false)!;
|
||||||
|
ghost.metadata = { isGhost: true };
|
||||||
for (const m of ghost.getChildMeshes()) {
|
for (const m of ghost.getChildMeshes()) {
|
||||||
m.metadata = {};
|
m.metadata = { isGhost: true };
|
||||||
if (m.material) {
|
if (m.material) {
|
||||||
const mat = m.material.clone(`${m.material.name}_ghost`);
|
const mat = m.material.clone(`${m.material.name}_ghost`);
|
||||||
mat.alpha = 0.3;
|
mat.alpha = 0.3;
|
||||||
@@ -830,12 +788,24 @@ export class RoomEngine {
|
|||||||
};
|
};
|
||||||
setStickyParentRecursively(highlightedObject);
|
setStickyParentRecursively(highlightedObject);
|
||||||
|
|
||||||
|
const descendantStickyObjectIds: string[] = [];
|
||||||
|
const collectDescendantStickyObjectIds = (parentId: string) => {
|
||||||
|
const childIds = Array.from(this.def.objects.filter(o => o.sticky === parentId)).map(o => o.id);
|
||||||
|
for (const cid of childIds) {
|
||||||
|
descendantStickyObjectIds.push(cid);
|
||||||
|
collectDescendantStickyObjectIds(cid);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
collectDescendantStickyObjectIds(highlightedObject.metadata.objectId);
|
||||||
|
|
||||||
this.grabbing = {
|
this.grabbing = {
|
||||||
|
objectId: highlightedObject.metadata.objectId,
|
||||||
mesh: highlightedObject,
|
mesh: highlightedObject,
|
||||||
startOffset: highlightedObject.position.subtract(this.camera.position.add(this.camera.getDirection(BABYLON.Axis.Z).scale(startDistance))),
|
startOffset: highlightedObject.position.subtract(this.camera.position.add(this.camera.getDirection(BABYLON.Axis.Z).scale(startDistance))),
|
||||||
startRotationY: highlightedObject.rotation.subtract(this.camera.rotation).y,
|
startRotationY: highlightedObject.rotation.subtract(this.camera.rotation).y,
|
||||||
startDistance: startDistance,
|
startDistance: startDistance,
|
||||||
ghost: ghost,
|
ghost: ghost,
|
||||||
|
descendantStickyObjectIds,
|
||||||
};
|
};
|
||||||
|
|
||||||
sound.playUrl('/client-assets/room/sfx/grab.mp3', {
|
sound.playUrl('/client-assets/room/sfx/grab.mp3', {
|
||||||
|
|||||||
Reference in New Issue
Block a user