1
This commit is contained in:
@ -43,7 +43,7 @@
|
||||
|
||||
const config = {
|
||||
container: document.querySelector('#renderDom'),
|
||||
modelUrlList: ['https://sdk.zguiy.com/resurces/model/model_new.glb'],
|
||||
modelUrlList: ['https://sdk.zguiy.com/resurces/model/model.glb'],
|
||||
env: { envPath: 'https://sdk.zguiy.com/resurces/hdr/hdr.env', intensity: 1.2, rotationY: 0.3, background: false },
|
||||
};
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
console.log('模型点击事件', data);
|
||||
|
||||
// 切换卷帘门开关
|
||||
kernel.door.toggle({ speed: 1.2 });
|
||||
kernel.door.toggle({ upY: 28, downY: 0, speed: 12 });
|
||||
|
||||
// Y轴剖切,只作用于卷帘门网格,保留下方,剖掉上方
|
||||
const clipHeight = 28; // 调整这个值找到合适的剖切高度
|
||||
|
||||
@ -24,6 +24,7 @@ export class GameManager extends Monobehiver {
|
||||
private meshDic: Dictionary<any>;
|
||||
private oldTextureDic: Dictionary<any>;
|
||||
private rollerDoorMeshes: AbstractMesh[];
|
||||
private rollerDoorGroup: AbstractMesh | null;
|
||||
private rollerDoorInitialY: Map<string, number>;
|
||||
private rollerDoorObserver: Nullable<Observer<Scene>>;
|
||||
private rollerDoorIsOpen: boolean;
|
||||
@ -32,7 +33,7 @@ export class GameManager extends Monobehiver {
|
||||
private yClipTargets: string[] | null;
|
||||
private clipPlaneVisualization: Mesh | null;
|
||||
|
||||
// 记录加载失败的贴图
|
||||
// 记录加载失败的贴图
|
||||
private failedTextures: Array<{
|
||||
path: string;
|
||||
materialName?: string;
|
||||
@ -47,6 +48,7 @@ export class GameManager extends Monobehiver {
|
||||
this.meshDic = new Dictionary<any>();
|
||||
this.oldTextureDic = new Dictionary<any>();
|
||||
this.rollerDoorMeshes = [];
|
||||
this.rollerDoorGroup = null;
|
||||
this.rollerDoorInitialY = new Map();
|
||||
this.rollerDoorObserver = null;
|
||||
this.rollerDoorIsOpen = false;
|
||||
@ -82,12 +84,16 @@ export class GameManager extends Monobehiver {
|
||||
// 初始化网格字典
|
||||
for (const mesh of scene.meshes) {
|
||||
if (mesh instanceof Mesh) {
|
||||
|
||||
|
||||
this.meshDic.Set(mesh.name, mesh);
|
||||
}
|
||||
}
|
||||
this.cacheRollerDoorMeshes();
|
||||
console.log('材质字典:', this.materialDic);
|
||||
console.log('材质字典:', this.materialDic);
|
||||
this.setRollerDoorScale("Box006.001", new Vector3(0.12,0.02,0.118));
|
||||
|
||||
// 单独设置 Box005.001 的缩放为 (1, 2, 1)
|
||||
this.setRollerDoorScale("Box005.001", new Vector3(0.13,0.02,0.12));
|
||||
}
|
||||
|
||||
/** 初始化设置材质 */
|
||||
@ -278,14 +284,14 @@ export class GameManager extends Monobehiver {
|
||||
apply: (value: number) => {
|
||||
mat.metallic = value;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "alpha",
|
||||
value: component.alpha,
|
||||
apply: (value: number) => {
|
||||
mat.alpha = value;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "environmentIntensity",
|
||||
value: component.environmentIntensity,
|
||||
@ -381,76 +387,63 @@ export class GameManager extends Monobehiver {
|
||||
|
||||
this.cacheRollerDoorMeshes(options?.meshNames);
|
||||
|
||||
if (!this.rollerDoorMeshes.length) {
|
||||
console.warn('Roller door meshes not found');
|
||||
if (!this.rollerDoorGroup || !this.rollerDoorMeshes.length) {
|
||||
console.warn('Roller door group or meshes not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const speed = Math.max(options?.speed ?? 1, 0.01);
|
||||
|
||||
const targets = this.rollerDoorMeshes.map(mesh => {
|
||||
const baseY = this.rollerDoorInitialY.get(mesh.name) ?? mesh.position.y;
|
||||
let targetY: number;
|
||||
|
||||
if (open) {
|
||||
// 上升时:如果指定了绝对高度就用绝对高度,否则用相对高度
|
||||
if (options?.upY !== undefined) {
|
||||
targetY = options.upY;
|
||||
} else {
|
||||
// 找到所有门中最高的初始位置,让所有门都升到这个高度+3
|
||||
const maxBaseY = Math.max(...this.rollerDoorMeshes.map(m =>
|
||||
this.rollerDoorInitialY.get(m.name) ?? m.position.y
|
||||
));
|
||||
targetY = maxBaseY + 3;
|
||||
}
|
||||
// 计算目标高度
|
||||
let targetY: number;
|
||||
if (open) {
|
||||
// 上升时:如果指定了绝对高度就用绝对高度,否则用相对高度
|
||||
if (options?.upY !== undefined) {
|
||||
targetY = options.upY;
|
||||
} else {
|
||||
// 下降时:回到各自的初始位置
|
||||
targetY = options?.downY ?? baseY;
|
||||
// 找到所有门中最高的初始位置,让所有门都升到这个高度+3
|
||||
const maxBaseY = Math.max(...this.rollerDoorMeshes.map(m =>
|
||||
this.rollerDoorInitialY.get(m.name) ?? m.position.y
|
||||
));
|
||||
targetY = maxBaseY + 3;
|
||||
}
|
||||
} else {
|
||||
// 下降时:回到初始位置
|
||||
targetY = 0;
|
||||
}
|
||||
|
||||
const direction = targetY >= mesh.position.y ? 1 : -1;
|
||||
const distance = Math.abs(targetY - mesh.position.y);
|
||||
console.log(`[door] ${mesh.name}: current=${mesh.position.y.toFixed(2)}, target=${targetY.toFixed(2)}, distance=${distance.toFixed(2)}`);
|
||||
return { mesh, targetY, direction, distance };
|
||||
});
|
||||
|
||||
const alreadyAtTarget = targets.every(({ mesh, targetY }) => Math.abs(mesh.position.y - targetY) < 0.001);
|
||||
if (alreadyAtTarget) {
|
||||
// 检查是否已经在目标位置
|
||||
if (Math.abs(this.rollerDoorGroup.position.y - targetY) < 0.001) {
|
||||
this.rollerDoorIsOpen = open;
|
||||
return;
|
||||
}
|
||||
|
||||
// 找到最大移动距离,用于计算统一的移动时间
|
||||
const maxDistance = Math.max(...targets.map(t => t.distance), 0.001);
|
||||
|
||||
this.rollerDoorIsOpen = open;
|
||||
this.stopRollerDoorAnimation();
|
||||
|
||||
this.rollerDoorObserver = scene.onBeforeRenderObservable.add(() => {
|
||||
const dt = scene.getEngine().getDeltaTime() / 1000;
|
||||
let finished = true;
|
||||
const current = this.rollerDoorGroup!.position.y;
|
||||
const direction = targetY >= current ? 1 : -1;
|
||||
|
||||
for (const item of targets) {
|
||||
const current = item.mesh.position.y;
|
||||
const dir = item.direction;
|
||||
// 使用固定速度变量
|
||||
const step = speed * dt;
|
||||
let next = current + direction * step;
|
||||
|
||||
// 根据每个门的移动距离占比调整速度,确保同时到达
|
||||
const speedMultiplier = item.distance / maxDistance;
|
||||
const step = speed * dt * speedMultiplier;
|
||||
let next = current + dir * step;
|
||||
|
||||
if ((dir > 0 && next >= item.targetY) || (dir < 0 && next <= item.targetY)) {
|
||||
next = item.targetY;
|
||||
} else {
|
||||
finished = false;
|
||||
}
|
||||
|
||||
item.mesh.position.y = next;
|
||||
}
|
||||
|
||||
if (finished) {
|
||||
if ((direction > 0 && next >= targetY) || (direction < 0 && next <= targetY)) {
|
||||
next = targetY;
|
||||
this.stopRollerDoorAnimation();
|
||||
this.rollerDoorIsOpen = open;
|
||||
console.log('Roller door animation finished');
|
||||
}
|
||||
|
||||
// 移动透明盒子
|
||||
this.rollerDoorGroup!.position.y = next;
|
||||
|
||||
// 打印每个卷帘门的当前位置
|
||||
console.log('Roller door positions:');
|
||||
for (const mesh of this.rollerDoorMeshes) {
|
||||
console.log(`${mesh.name}: ${mesh.position.y.toFixed(2)}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -460,6 +453,40 @@ export class GameManager extends Monobehiver {
|
||||
return this.rollerDoorIsOpen;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置卷帘门的缩放
|
||||
* @param meshName - 卷帘门网格名称
|
||||
* @param scale - 缩放值(可以是单个数字或 Vector3)
|
||||
*/
|
||||
setRollerDoorScale(meshName: string, scale: number | Vector3): void {
|
||||
const mesh = this.meshDic.Get(meshName);
|
||||
if (mesh) {
|
||||
if (typeof scale === 'number') {
|
||||
mesh.scaling.set(scale, scale, scale);
|
||||
} else {
|
||||
mesh.scaling.copyFrom(scale);
|
||||
}
|
||||
console.log(`Set scale for ${meshName}:`, mesh.scaling.asArray());
|
||||
} else {
|
||||
console.warn(`Roller door mesh not found: ${meshName}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置所有卷帘门的缩放
|
||||
* @param scale - 缩放值(可以是单个数字或 Vector3)
|
||||
*/
|
||||
setAllRollerDoorsScale(scale: number | Vector3): void {
|
||||
this.rollerDoorMeshes.forEach(mesh => {
|
||||
if (typeof scale === 'number') {
|
||||
mesh.scaling.set(scale, scale, scale);
|
||||
} else {
|
||||
mesh.scaling.copyFrom(scale);
|
||||
}
|
||||
console.log(`Set scale for ${mesh.name}:`, mesh.scaling.asArray());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置基于 Y 轴的剖切平面,keepAbove=true 时保留平面以上部分
|
||||
* onlyMeshNames 指定只作用于哪些网格,其他网格不受影响
|
||||
@ -508,15 +535,41 @@ export class GameManager extends Monobehiver {
|
||||
}
|
||||
|
||||
private cacheRollerDoorMeshes(customNames?: string[]): void {
|
||||
const scene = this.mainApp.appScene?.object;
|
||||
if (!scene) return;
|
||||
|
||||
const names = customNames?.length ? customNames : this.rollerDoorNames;
|
||||
this.rollerDoorMeshes = [];
|
||||
|
||||
// 创建或获取 group 作为父级
|
||||
if (!this.rollerDoorGroup) {
|
||||
// 创建一个 AbstractMesh 作为组
|
||||
this.rollerDoorGroup = new AbstractMesh('rollerDoorGroup', scene);
|
||||
// 确保 group 的缩放为 1
|
||||
// 确保 group 的初始位置为 (0, 0, 0)
|
||||
this.rollerDoorGroup.position.set(0, 0, 0);
|
||||
}
|
||||
|
||||
for (const name of names) {
|
||||
const mesh = this.meshDic.Get(name);
|
||||
if (mesh) {
|
||||
this.rollerDoorMeshes.push(mesh);
|
||||
|
||||
// 保存网格的当前位置作为初始位置
|
||||
if (!this.rollerDoorInitialY.has(name)) {
|
||||
this.rollerDoorInitialY.set(name, mesh.position.y);
|
||||
}
|
||||
|
||||
// 保存网格的世界位置和缩放
|
||||
const worldPosition = mesh.getAbsolutePosition();
|
||||
const worldScaling = new Vector3(mesh.scaling.x, mesh.scaling.y, mesh.scaling.z);
|
||||
|
||||
// 将网格添加到 group 中
|
||||
mesh.parent = this.rollerDoorGroup;
|
||||
|
||||
// 调整网格的局部位置和缩放,保持世界位置和大小不变
|
||||
mesh.setAbsolutePosition(worldPosition);
|
||||
mesh.scaling.copyFrom(worldScaling);
|
||||
} else {
|
||||
console.warn(`Roller door mesh not found: ${name}`);
|
||||
}
|
||||
@ -579,6 +632,12 @@ export class GameManager extends Monobehiver {
|
||||
this.rollerDoorInitialY.clear();
|
||||
this.rollerDoorIsOpen = false;
|
||||
|
||||
// 清理 rollerDoorGroup
|
||||
if (this.rollerDoorGroup && this.rollerDoorGroup.dispose) {
|
||||
this.rollerDoorGroup.dispose();
|
||||
this.rollerDoorGroup = null;
|
||||
}
|
||||
|
||||
// 清理所有材质资源
|
||||
this.materialDic.Values().forEach((material) => {
|
||||
if (material && material.dispose) {
|
||||
@ -679,26 +738,26 @@ export class GameManager extends Monobehiver {
|
||||
applyMaterial(target: string, attribute: string, value: number | string): void {
|
||||
// 这里需要根据实际的材质管理逻辑实现
|
||||
console.log(`Applying attribute ${attribute} to ${value}`);
|
||||
|
||||
|
||||
// 示例实现:根据目标和材质路径应用材质
|
||||
// 1. 查找目标网格
|
||||
const targetMaterials: PBRMaterial[] = [];
|
||||
this.materialDic.Values().forEach(material => {
|
||||
if (material.name.includes(target)) {
|
||||
console.log(`${this.materialDic.Get(material.name)}`,material);
|
||||
console.log(`${this.materialDic.Get(material.name)}`, material);
|
||||
targetMaterials.push(material);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (targetMaterials.length === 0) {
|
||||
console.warn(`Target not found: ${target}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 2. 处理材质路径
|
||||
// 这里可以根据材质路径加载对应的材质配置
|
||||
// 例如:paint/blue 可以映射到特定的材质配置
|
||||
|
||||
|
||||
// 3. 应用材质到目标网格
|
||||
targetMaterials.forEach(material => {
|
||||
if (material[attribute]) {
|
||||
|
||||
Reference in New Issue
Block a user