1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-13 14:05:35 +02:00
This commit is contained in:
syuilo
2026-04-11 13:03:11 +09:00
parent eeae06014a
commit 69ac19d018
3 changed files with 76 additions and 39 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 KiB

After

Width:  |  Height:  |  Size: 774 KiB

View File

@@ -320,6 +320,7 @@ type ObjectDef<OpSc extends OptionsSchema = OptionsSchema> = {
root: BABYLON.Mesh;
options: Readonly<GetOptionsSchemaValues<OpSc>>;
model: ModelManager;
id: string;
}) => RoomObjectInstance<GetOptionsSchemaValues<OpSc>> | Promise<RoomObjectInstance<GetOptionsSchemaValues<OpSc>>>; // TODO: createInstanceをasyncにするのではなく、別にreadyみたいなものを返させる
};
@@ -1245,6 +1246,7 @@ export class RoomEngine {
root,
options: args.options,
model,
id: args.id,
});
objectInstance.onInited?.();
@@ -1852,9 +1854,12 @@ export class RoomObjectPreviewEngine {
const options = deepClone(def.options.default);
const id = genId();
await this.loadObject({
type,
options,
id,
});
// なぜかちょっと待たないとbounding boxのサイズが正しくない
@@ -1877,6 +1882,7 @@ export class RoomObjectPreviewEngine {
private async loadObject(args: {
type: string;
options: any;
id: string;
}) {
const def = getObjectDef(args.type);
@@ -1931,6 +1937,7 @@ export class RoomObjectPreviewEngine {
root,
options: args.options,
model,
id: args.id,
});
objectInstance.onInited?.();

View File

@@ -2,7 +2,9 @@
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import * as BABYLON from '@babylonjs/core';
import seedrandom from 'seedrandom';
import { defineObject, WORLD_SCALE } from '../engine.js';
const randomRange = (min: number, max: number) => Math.random() * (max - min) + min;
@@ -20,13 +22,21 @@ export const randomBooks = defineObject({
type: 'boolean',
label: 'Plain cover',
},
seed: {
type: 'range',
label: 'Seed',
min: 0,
max: 1000,
step: 1,
},
},
default: {
plainCover: false,
seed: 0,
},
},
placement: 'top',
createInstance: ({ options, model, scene }) => {
createInstance: ({ options, model, scene, id }) => {
const bodyMesh = model.findMesh('__X_BODY__');
const tex = new BABYLON.Texture('/client-assets/room/objects/random-books/texture.png', scene, {
invertY: false,
@@ -36,54 +46,74 @@ export const randomBooks = defineObject({
const TEXTURE_DIVISION = 8;
const count = 10;
let bookMeshes: BABYLON.Mesh[] = [];
let accumulatedPos = 0;
const meshes: BABYLON.Mesh[] = [];
for (let i = 0; i < count; i++) {
const mesh = bodyMesh.clone();
mesh.makeGeometryUnique();
mesh.morphTargetManager = bodyMesh.morphTargetManager.clone();
mesh.markVerticesDataAsUpdatable(BABYLON.VertexBuffer.UVKind, true);
const index = Math.floor(Math.random() * 27);
const x = index % TEXTURE_DIVISION;
const y = Math.floor(index / TEXTURE_DIVISION);
const uvs = mesh.getVerticesData(BABYLON.VertexBuffer.UVKind)!;
for (let uvi = 0; uvi < uvs.length; uvi += 2) {
const u = uvs[uvi];
const v = uvs[uvi + 1];
uvs[uvi] = (u / TEXTURE_DIVISION) + (x / TEXTURE_DIVISION);
uvs[uvi + 1] = (v / TEXTURE_DIVISION) + (y / TEXTURE_DIVISION);
const gen = () => {
for (const m of bookMeshes) {
m.dispose();
}
mesh.updateVerticesData(BABYLON.VertexBuffer.UVKind, uvs);
bookMeshes = [];
const width = randomRange(0.1, 0.2);
const height = randomRange(0.3, 0.4);
const thickness = randomRange(0, 0.03);
mesh.morphTargetManager!.getTargetByName('Width')!.influence = width;
mesh.morphTargetManager!.getTargetByName('Height')!.influence = height;
mesh.morphTargetManager!.getTargetByName('Thickness')!.influence = thickness;
const thicknessCm = 2 + remap(thickness, 0, 1, 0, 100);
const gap = 0.25;
mesh.position.x = (accumulatedPos + (thicknessCm / 2)) / WORLD_SCALE;
accumulatedPos += thicknessCm + gap;
meshes.push(mesh);
}
const rng = seedrandom(options.seed === 0 ? id : options.seed.toString());
// centering
for (let i = 0; i < count; i++) {
meshes[i].position.x -= accumulatedPos / 2 / WORLD_SCALE;
}
let accumulatedPos = 0;
bodyMesh.isVisible = false;
for (let i = 0; i < count; i++) {
const mesh = bodyMesh.clone();
mesh.isVisible = true;
mesh.setEnabled(true);
mesh.makeGeometryUnique();
mesh.morphTargetManager = bodyMesh.morphTargetManager.clone();
mesh.markVerticesDataAsUpdatable(BABYLON.VertexBuffer.UVKind, true);
model.updated();
const index = Math.floor(rng() * 44);
const x = index % TEXTURE_DIVISION;
const y = Math.floor(index / TEXTURE_DIVISION);
const uvs = mesh.getVerticesData(BABYLON.VertexBuffer.UVKind)!;
for (let uvi = 0; uvi < uvs.length; uvi += 2) {
const u = uvs[uvi];
const v = uvs[uvi + 1];
uvs[uvi] = (u / TEXTURE_DIVISION) + (x / TEXTURE_DIVISION);
uvs[uvi + 1] = (v / TEXTURE_DIVISION) + (y / TEXTURE_DIVISION);
}
mesh.updateVerticesData(BABYLON.VertexBuffer.UVKind, uvs);
const width = randomRange(0.125, 0.175);
const height = randomRange(0.3, 0.4);
const thickness = randomRange(0, 0.03);
mesh.morphTargetManager!.getTargetByName('Width')!.influence = width;
mesh.morphTargetManager!.getTargetByName('Height')!.influence = height;
mesh.morphTargetManager!.getTargetByName('Thickness')!.influence = thickness;
const thicknessCm = 2 + remap(thickness, 0, 1, 0, 100);
const widthCm = 2 + remap(width, 0, 1, 0, 100);
const gap = 0.25;
mesh.position.x = (accumulatedPos + (thicknessCm / 2)) / WORLD_SCALE;
mesh.position.z = widthCm / 2 / WORLD_SCALE;
accumulatedPos += thicknessCm + gap;
bookMeshes.push(mesh);
}
// centering
for (let i = 0; i < count; i++) {
bookMeshes[i].position.x -= accumulatedPos / 2 / WORLD_SCALE;
}
bodyMesh.isVisible = false;
model.updated();
};
gen();
return {
onInited: () => {
},
onOptionsUpdated: ([k, v]) => {
switch (k) {
case 'seed': gen(); break;
}
},
interactions: {},
};