mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-20 21:05:28 +02:00
wip
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 435 KiB After Width: | Height: | Size: 774 KiB |
@@ -320,6 +320,7 @@ type ObjectDef<OpSc extends OptionsSchema = OptionsSchema> = {
|
|||||||
root: BABYLON.Mesh;
|
root: BABYLON.Mesh;
|
||||||
options: Readonly<GetOptionsSchemaValues<OpSc>>;
|
options: Readonly<GetOptionsSchemaValues<OpSc>>;
|
||||||
model: ModelManager;
|
model: ModelManager;
|
||||||
|
id: string;
|
||||||
}) => RoomObjectInstance<GetOptionsSchemaValues<OpSc>> | Promise<RoomObjectInstance<GetOptionsSchemaValues<OpSc>>>; // TODO: createInstanceをasyncにするのではなく、別にreadyみたいなものを返させる
|
}) => RoomObjectInstance<GetOptionsSchemaValues<OpSc>> | Promise<RoomObjectInstance<GetOptionsSchemaValues<OpSc>>>; // TODO: createInstanceをasyncにするのではなく、別にreadyみたいなものを返させる
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1245,6 +1246,7 @@ export class RoomEngine {
|
|||||||
root,
|
root,
|
||||||
options: args.options,
|
options: args.options,
|
||||||
model,
|
model,
|
||||||
|
id: args.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
objectInstance.onInited?.();
|
objectInstance.onInited?.();
|
||||||
@@ -1852,9 +1854,12 @@ export class RoomObjectPreviewEngine {
|
|||||||
|
|
||||||
const options = deepClone(def.options.default);
|
const options = deepClone(def.options.default);
|
||||||
|
|
||||||
|
const id = genId();
|
||||||
|
|
||||||
await this.loadObject({
|
await this.loadObject({
|
||||||
type,
|
type,
|
||||||
options,
|
options,
|
||||||
|
id,
|
||||||
});
|
});
|
||||||
|
|
||||||
// なぜかちょっと待たないとbounding boxのサイズが正しくない
|
// なぜかちょっと待たないとbounding boxのサイズが正しくない
|
||||||
@@ -1877,6 +1882,7 @@ export class RoomObjectPreviewEngine {
|
|||||||
private async loadObject(args: {
|
private async loadObject(args: {
|
||||||
type: string;
|
type: string;
|
||||||
options: any;
|
options: any;
|
||||||
|
id: string;
|
||||||
}) {
|
}) {
|
||||||
const def = getObjectDef(args.type);
|
const def = getObjectDef(args.type);
|
||||||
|
|
||||||
@@ -1931,6 +1937,7 @@ export class RoomObjectPreviewEngine {
|
|||||||
root,
|
root,
|
||||||
options: args.options,
|
options: args.options,
|
||||||
model,
|
model,
|
||||||
|
id: args.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
objectInstance.onInited?.();
|
objectInstance.onInited?.();
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as BABYLON from '@babylonjs/core';
|
import * as BABYLON from '@babylonjs/core';
|
||||||
|
import seedrandom from 'seedrandom';
|
||||||
import { defineObject, WORLD_SCALE } from '../engine.js';
|
import { defineObject, WORLD_SCALE } from '../engine.js';
|
||||||
|
|
||||||
const randomRange = (min: number, max: number) => Math.random() * (max - min) + min;
|
const randomRange = (min: number, max: number) => Math.random() * (max - min) + min;
|
||||||
@@ -20,13 +22,21 @@ export const randomBooks = defineObject({
|
|||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
label: 'Plain cover',
|
label: 'Plain cover',
|
||||||
},
|
},
|
||||||
|
seed: {
|
||||||
|
type: 'range',
|
||||||
|
label: 'Seed',
|
||||||
|
min: 0,
|
||||||
|
max: 1000,
|
||||||
|
step: 1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
default: {
|
default: {
|
||||||
plainCover: false,
|
plainCover: false,
|
||||||
|
seed: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
placement: 'top',
|
placement: 'top',
|
||||||
createInstance: ({ options, model, scene }) => {
|
createInstance: ({ options, model, scene, id }) => {
|
||||||
const bodyMesh = model.findMesh('__X_BODY__');
|
const bodyMesh = model.findMesh('__X_BODY__');
|
||||||
const tex = new BABYLON.Texture('/client-assets/room/objects/random-books/texture.png', scene, {
|
const tex = new BABYLON.Texture('/client-assets/room/objects/random-books/texture.png', scene, {
|
||||||
invertY: false,
|
invertY: false,
|
||||||
@@ -36,54 +46,74 @@ export const randomBooks = defineObject({
|
|||||||
|
|
||||||
const TEXTURE_DIVISION = 8;
|
const TEXTURE_DIVISION = 8;
|
||||||
const count = 10;
|
const count = 10;
|
||||||
|
let bookMeshes: BABYLON.Mesh[] = [];
|
||||||
|
|
||||||
let accumulatedPos = 0;
|
const gen = () => {
|
||||||
const meshes: BABYLON.Mesh[] = [];
|
for (const m of bookMeshes) {
|
||||||
|
m.dispose();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
mesh.updateVerticesData(BABYLON.VertexBuffer.UVKind, uvs);
|
bookMeshes = [];
|
||||||
|
|
||||||
const width = randomRange(0.1, 0.2);
|
const rng = seedrandom(options.seed === 0 ? id : options.seed.toString());
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// centering
|
let accumulatedPos = 0;
|
||||||
for (let i = 0; i < count; i++) {
|
|
||||||
meshes[i].position.x -= accumulatedPos / 2 / WORLD_SCALE;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
return {
|
||||||
onInited: () => {
|
onInited: () => {
|
||||||
|
|
||||||
|
},
|
||||||
|
onOptionsUpdated: ([k, v]) => {
|
||||||
|
switch (k) {
|
||||||
|
case 'seed': gen(); break;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
interactions: {},
|
interactions: {},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user