This commit is contained in:
syuilo
2026-03-03 21:22:56 +09:00
parent 46791a3bf2
commit 208c300460
4 changed files with 107 additions and 270 deletions

View File

@@ -5,7 +5,7 @@
import * as BABYLON from '@babylonjs/core';
import { defineObject } from '../engine.js';
import { getPlaneUvIndexes } from '../utility.js';
import { createPlaneUvMapper, getPlaneUvIndexes } from '../utility.js';
export const pictureFrame = defineObject({
id: 'pictureFrame',
@@ -84,21 +84,10 @@ export const pictureFrame = defineObject({
coverMesh.rotationQuaternion = null;
const pictureMesh = findMesh('__X_PICTURE__');
pictureMesh.rotationQuaternion = null;
pictureMesh.markVerticesDataAsUpdatable(BABYLON.VertexBuffer.UVKind, true);
const pictureMaterial = findMaterial('__X_PICTURE__');
const uvs = pictureMesh.getVerticesData(BABYLON.VertexBuffer.UVKind)!;
const uvIndexes = getPlaneUvIndexes(pictureMesh);
const ax = uvs[uvIndexes[0]];
const ay = uvs[uvIndexes[0] + 1];
const bx = uvs[uvIndexes[1]];
const by = uvs[uvIndexes[1] + 1];
const cx = uvs[uvIndexes[2]];
const cy = uvs[uvIndexes[2] + 1];
const dx = uvs[uvIndexes[3]];
const dy = uvs[uvIndexes[3] + 1];
const updateUv = createPlaneUvMapper(pictureMesh);
const applyFit = () => {
const tex = pictureMaterial.albedoTexture;
@@ -111,83 +100,7 @@ export const pictureFrame = defineObject({
const targetHeight = options.height * (1 - (options.matVThickness * MAT_THICKNESS_FACTOR));
const targetAspect = targetWidth / targetHeight;
let newAx = ax;
let newAy = ay;
let newBx = bx;
let newBy = by;
let newCx = cx;
let newCy = cy;
let newDx = dx;
let newDy = dy;
if (options.fit === 'cover') {
const ratio = targetAspect / srcAspect;
let uRange: number;
let vRange: number;
if (ratio < 1) {
uRange = ratio; // < 1
vRange = 1;
} else {
uRange = 1;
vRange = 1 / ratio; // < 1
}
const uMin = (1 - uRange) / 2;
const uMax = uMin + uRange;
const vMin = (1 - vRange) / 2;
const vMax = vMin + vRange;
newAx = uMin;
newBx = uMax;
newCx = uMin;
newDx = uMax;
newAy = 1 - vMax;
newBy = 1 - vMax;
newCy = 1 - vMin;
newDy = 1 - vMin;
} else if (options.fit === 'contain') {
const ratio = targetAspect / srcAspect;
let uRange: number;
let vRange: number;
if (ratio > 1) {
uRange = ratio; // > 1
vRange = 1;
} else {
uRange = 1;
vRange = 1 / ratio; // > 1
}
const uMin = (1 - uRange) / 2;
const uMax = uMin + uRange;
const vMin = (1 - vRange) / 2;
const vMax = vMin + vRange;
newAx = uMin;
newBx = uMax;
newCx = uMin;
newDx = uMax;
newAy = 1 - vMax;
newBy = 1 - vMax;
newCy = 1 - vMin;
newDy = 1 - vMin;
}
uvs[uvIndexes[0]] = newAx;
uvs[uvIndexes[0] + 1] = newAy;
uvs[uvIndexes[1]] = newBx;
uvs[uvIndexes[1] + 1] = newBy;
uvs[uvIndexes[2]] = newCx;
uvs[uvIndexes[2] + 1] = newCy;
uvs[uvIndexes[3]] = newDx;
uvs[uvIndexes[3] + 1] = newDy;
pictureMesh.updateVerticesData(BABYLON.VertexBuffer.UVKind, uvs);
updateUv(srcAspect, targetAspect, options.fit);
};
applyFit();

View File

@@ -5,7 +5,7 @@
import * as BABYLON from '@babylonjs/core';
import { defineObject } from '../engine.js';
import { getPlaneUvIndexes } from '../utility.js';
import { createPlaneUvMapper, getPlaneUvIndexes } from '../utility.js';
export const poster = defineObject({
id: 'poster',
@@ -47,23 +47,12 @@ export const poster = defineObject({
createInstance: ({ room, root, options, findMaterial, findMesh, findMeshes, meshUpdated }) => {
const pictureMesh = findMesh('__X_PICTURE__');
pictureMesh.rotationQuaternion = null;
pictureMesh.markVerticesDataAsUpdatable(BABYLON.VertexBuffer.UVKind, true);
const pictureMaterial = findMaterial('__X_PICTURE__');
const pinMeshes = findMeshes('__X_PIN__');
const uvs = pictureMesh.getVerticesData(BABYLON.VertexBuffer.UVKind)!;
const uvIndexes = getPlaneUvIndexes(pictureMesh);
const ax = uvs[uvIndexes[0]];
const ay = uvs[uvIndexes[0] + 1];
const bx = uvs[uvIndexes[1]];
const by = uvs[uvIndexes[1] + 1];
const cx = uvs[uvIndexes[2]];
const cy = uvs[uvIndexes[2] + 1];
const dx = uvs[uvIndexes[3]];
const dy = uvs[uvIndexes[3] + 1];
const updateUv = createPlaneUvMapper(pictureMesh);
const applyFit = () => {
const tex = pictureMaterial.albedoTexture;
@@ -76,83 +65,7 @@ export const poster = defineObject({
const targetHeight = options.height;
const targetAspect = targetWidth / targetHeight;
let newAx = ax;
let newAy = ay;
let newBx = bx;
let newBy = by;
let newCx = cx;
let newCy = cy;
let newDx = dx;
let newDy = dy;
if (options.fit === 'cover') {
const ratio = targetAspect / srcAspect;
let uRange: number;
let vRange: number;
if (ratio < 1) {
uRange = ratio; // < 1
vRange = 1;
} else {
uRange = 1;
vRange = 1 / ratio; // < 1
}
const uMin = (1 - uRange) / 2;
const uMax = uMin + uRange;
const vMin = (1 - vRange) / 2;
const vMax = vMin + vRange;
newAx = uMin;
newBx = uMax;
newCx = uMin;
newDx = uMax;
newAy = 1 - vMax;
newBy = 1 - vMax;
newCy = 1 - vMin;
newDy = 1 - vMin;
} else if (options.fit === 'contain') {
const ratio = targetAspect / srcAspect;
let uRange: number;
let vRange: number;
if (ratio > 1) {
uRange = ratio; // > 1
vRange = 1;
} else {
uRange = 1;
vRange = 1 / ratio; // > 1
}
const uMin = (1 - uRange) / 2;
const uMax = uMin + uRange;
const vMin = (1 - vRange) / 2;
const vMax = vMin + vRange;
newAx = uMin;
newBx = uMax;
newCx = uMin;
newDx = uMax;
newAy = 1 - vMax;
newBy = 1 - vMax;
newCy = 1 - vMin;
newDy = 1 - vMin;
}
uvs[uvIndexes[0]] = newAx;
uvs[uvIndexes[0] + 1] = newAy;
uvs[uvIndexes[1]] = newBx;
uvs[uvIndexes[1] + 1] = newBy;
uvs[uvIndexes[2]] = newCx;
uvs[uvIndexes[2] + 1] = newCy;
uvs[uvIndexes[3]] = newDx;
uvs[uvIndexes[3] + 1] = newDy;
pictureMesh.updateVerticesData(BABYLON.VertexBuffer.UVKind, uvs);
updateUv(srcAspect, targetAspect, options.fit);
};
applyFit();

View File

@@ -5,7 +5,7 @@
import * as BABYLON from '@babylonjs/core';
import { defineObject } from '../engine.js';
import { getPlaneUvIndexes } from '../utility.js';
import { createPlaneUvMapper, getPlaneUvIndexes } from '../utility.js';
export const tapestry = defineObject({
id: 'tapestry',
@@ -47,7 +47,6 @@ export const tapestry = defineObject({
createInstance: ({ room, root, options, findMaterial, findMesh, findMeshes, meshUpdated }) => {
const pictureMesh = findMesh('__X_PICTURE__');
pictureMesh.rotationQuaternion = null;
pictureMesh.markVerticesDataAsUpdatable(BABYLON.VertexBuffer.UVKind, true);
const pipeTopMesh = findMesh('__X_PIPE_TOP__');
const pipeBottomMesh = findMesh('__X_PIPE_BOTTOM__');
@@ -55,17 +54,7 @@ export const tapestry = defineObject({
const pictureMaterial = findMaterial('__X_PICTURE__');
const uvs = pictureMesh.getVerticesData(BABYLON.VertexBuffer.UVKind)!;
const uvIndexes = getPlaneUvIndexes(pictureMesh);
const ax = uvs[uvIndexes[0]];
const ay = uvs[uvIndexes[0] + 1];
const bx = uvs[uvIndexes[1]];
const by = uvs[uvIndexes[1] + 1];
const cx = uvs[uvIndexes[2]];
const cy = uvs[uvIndexes[2] + 1];
const dx = uvs[uvIndexes[3]];
const dy = uvs[uvIndexes[3] + 1];
const updateUv = createPlaneUvMapper(pictureMesh);
const applyFit = () => {
const tex = pictureMaterial.albedoTexture;
@@ -78,83 +67,7 @@ export const tapestry = defineObject({
const targetHeight = options.height;
const targetAspect = targetWidth / targetHeight;
let newAx = ax;
let newAy = ay;
let newBx = bx;
let newBy = by;
let newCx = cx;
let newCy = cy;
let newDx = dx;
let newDy = dy;
if (options.fit === 'cover') {
const ratio = targetAspect / srcAspect;
let uRange: number;
let vRange: number;
if (ratio < 1) {
uRange = ratio; // < 1
vRange = 1;
} else {
uRange = 1;
vRange = 1 / ratio; // < 1
}
const uMin = (1 - uRange) / 2;
const uMax = uMin + uRange;
const vMin = (1 - vRange) / 2;
const vMax = vMin + vRange;
newAx = uMin;
newBx = uMax;
newCx = uMin;
newDx = uMax;
newAy = 1 - vMax;
newBy = 1 - vMax;
newCy = 1 - vMin;
newDy = 1 - vMin;
} else if (options.fit === 'contain') {
const ratio = targetAspect / srcAspect;
let uRange: number;
let vRange: number;
if (ratio > 1) {
uRange = ratio; // > 1
vRange = 1;
} else {
uRange = 1;
vRange = 1 / ratio; // > 1
}
const uMin = (1 - uRange) / 2;
const uMax = uMin + uRange;
const vMin = (1 - vRange) / 2;
const vMax = vMin + vRange;
newAx = uMin;
newBx = uMax;
newCx = uMin;
newDx = uMax;
newAy = 1 - vMax;
newBy = 1 - vMax;
newCy = 1 - vMin;
newDy = 1 - vMin;
}
uvs[uvIndexes[0]] = newAx;
uvs[uvIndexes[0] + 1] = newAy;
uvs[uvIndexes[1]] = newBx;
uvs[uvIndexes[1] + 1] = newBy;
uvs[uvIndexes[2]] = newCx;
uvs[uvIndexes[2] + 1] = newCy;
uvs[uvIndexes[3]] = newDx;
uvs[uvIndexes[3] + 1] = newDy;
pictureMesh.updateVerticesData(BABYLON.VertexBuffer.UVKind, uvs);
updateUv(srcAspect, targetAspect, options.fit);
};
applyFit();

View File

@@ -369,3 +369,101 @@ export function getPlaneUvIndexes(mesh: BABYLON.Mesh) {
return [aIndex, bIndex, cIndex, dIndex];
}
export function createPlaneUvMapper(mesh: BABYLON.Mesh) {
mesh.markVerticesDataAsUpdatable(BABYLON.VertexBuffer.UVKind, true);
const uvs = mesh.getVerticesData(BABYLON.VertexBuffer.UVKind)!;
const uvIndexes = getPlaneUvIndexes(mesh);
const ax = uvs[uvIndexes[0]];
const ay = uvs[uvIndexes[0] + 1];
const bx = uvs[uvIndexes[1]];
const by = uvs[uvIndexes[1] + 1];
const cx = uvs[uvIndexes[2]];
const cy = uvs[uvIndexes[2] + 1];
const dx = uvs[uvIndexes[3]];
const dy = uvs[uvIndexes[3] + 1];
return (srcAspect: number, targetAspect: number, method: 'cover' | 'contain' | 'stretch') => {
let newAx = ax;
let newAy = ay;
let newBx = bx;
let newBy = by;
let newCx = cx;
let newCy = cy;
let newDx = dx;
let newDy = dy;
if (method === 'cover') {
const ratio = targetAspect / srcAspect;
let uRange: number;
let vRange: number;
if (ratio < 1) {
uRange = ratio; // < 1
vRange = 1;
} else {
uRange = 1;
vRange = 1 / ratio; // < 1
}
const uMin = (1 - uRange) / 2;
const uMax = uMin + uRange;
const vMin = (1 - vRange) / 2;
const vMax = vMin + vRange;
newAx = uMin;
newBx = uMax;
newCx = uMin;
newDx = uMax;
newAy = 1 - vMax;
newBy = 1 - vMax;
newCy = 1 - vMin;
newDy = 1 - vMin;
} else if (method === 'contain') {
const ratio = targetAspect / srcAspect;
let uRange: number;
let vRange: number;
if (ratio > 1) {
uRange = ratio; // > 1
vRange = 1;
} else {
uRange = 1;
vRange = 1 / ratio; // > 1
}
const uMin = (1 - uRange) / 2;
const uMax = uMin + uRange;
const vMin = (1 - vRange) / 2;
const vMax = vMin + vRange;
newAx = uMin;
newBx = uMax;
newCx = uMin;
newDx = uMax;
newAy = 1 - vMax;
newBy = 1 - vMax;
newCy = 1 - vMin;
newDy = 1 - vMin;
} else if (method === 'stretch') {
// nop
}
uvs[uvIndexes[0]] = newAx;
uvs[uvIndexes[0] + 1] = newAy;
uvs[uvIndexes[1]] = newBx;
uvs[uvIndexes[1] + 1] = newBy;
uvs[uvIndexes[2]] = newCx;
uvs[uvIndexes[2] + 1] = newCy;
uvs[uvIndexes[3]] = newDx;
uvs[uvIndexes[3] + 1] = newDy;
mesh.updateVerticesData(BABYLON.VertexBuffer.UVKind, uvs);
};
}