This commit is contained in:
2026-05-13 13:08:42 +08:00
parent 066294e74f
commit 52b369737a
6 changed files with 576 additions and 106 deletions

View File

@ -24,11 +24,18 @@ type ModelConfig = {
type ModelControlType = 'rotation' | 'color';
type ModelTransform = {
position?: { x: number; y: number; z: number };
rotation?: { x: number; y: number; z: number };
scale?: { x: number; y: number; z: number };
};
type ModelMetadata = {
modelId: string;
modelUrl: string;
modelControlType?: ModelControlType;
drag?: DragConfig;
transform?: ModelTransform;
};
/**
@ -224,14 +231,15 @@ export class AppModel extends Monobehiver {
modelConfig.modelId,
modelConfig.modelUrl,
modelConfig.modelControlType,
modelConfig.drag
modelConfig.drag,
modelConfig.transform
);
}
/**
* 添加单个模型
*/
private async addSingle(modelName: string, modelUrl: string, modelControlType?: ModelControlType, drag?: DragConfig): Promise<LoadResult> {
private async addSingle(modelName: string, modelUrl: string, modelControlType?: ModelControlType, drag?: DragConfig, transform?: ModelTransform): Promise<LoadResult> {
// 检查是否已存在
const existingMeshes = this.modelDic.Get(modelName);
if (existingMeshes?.length && !existingMeshes[0].isDisposed()) {
@ -254,9 +262,15 @@ export class AppModel extends Monobehiver {
modelId: modelName,
modelUrl: modelUrl,
modelControlType: modelControlType,
drag: drag
drag: drag,
transform: transform
});
// 应用 transform
if (transform) {
this.applyTransform(modelName, transform);
}
// 配置拖拽功能
if (drag) {
this.mainApp.appModelDrag?.configureDrag(modelName, drag);
@ -283,7 +297,7 @@ export class AppModel extends Monobehiver {
EventBridge.modelLoadProgress({ loaded: 0, total, progress: 0, percentage: 0 });
for (let i = 0; i < models.length; i++) {
const { modelId, modelUrl, modelControlType, drag } = models[i];
const { modelId, modelUrl, modelControlType, drag, transform } = models[i];
const result = await this.loadSingleModel(modelUrl, (event) => {
this.emitProgress(i, total, modelUrl, event);
@ -298,9 +312,15 @@ export class AppModel extends Monobehiver {
modelId: modelId,
modelUrl: modelUrl,
modelControlType: modelControlType,
drag: drag
drag: drag,
transform: transform
});
// 应用 transform
if (transform) {
this.applyTransform(modelId, transform);
}
// 配置拖拽功能
if (drag) {
this.mainApp.appModelDrag?.configureDrag(modelId, drag);
@ -426,7 +446,8 @@ export class AppModel extends Monobehiver {
modelConfig.modelId,
modelConfig.modelUrl,
modelConfig.modelControlType,
modelConfig.drag
modelConfig.drag,
modelConfig.transform
);
}
@ -591,4 +612,59 @@ export class AppModel extends Monobehiver {
mesh.scaling.z = scale.z;
});
}
/**
* 将模型放置到指定的放置区域
* @param modelId 模型ID
* @param zoneInfo 放置区域信息
* @param offsetDistance 距离墙面的偏移距离默认0.1,正数向外)
*/
placeToZone(modelId: string, zoneInfo: any, offsetDistance: number = 0): void {
const meshes = this.modelDic.Get(modelId);
if (!meshes?.length) {
console.warn(`Model not found: ${modelId}`);
return;
}
// 计算放置位置:中心点 + 法线方向的偏移
const targetPosition = zoneInfo.center.add(zoneInfo.normal.scale(offsetDistance));
// 计算旋转角度:让模型面向墙面(法线的反方向)
const targetDirection = zoneInfo.normal.scale(-1);
const angle = Math.atan2(targetDirection.x, targetDirection.z);
this.getModelTransformTargets(meshes).forEach(mesh => {
// 设置位置
mesh.position.copyFrom(targetPosition);
// 设置旋转只旋转Y轴让模型面向墙面
if (mesh.rotationQuaternion) {
mesh.rotationQuaternion = Quaternion.FromEulerAngles(0, angle, 0);
} else {
mesh.rotation.set(0, angle, 0);
}
});
}
/**
* 应用 transform 到模型
* @param modelId 模型ID
* @param transform 变换信息
*/
private applyTransform(modelId: string, transform: ModelTransform): void {
// 应用位置
if (transform.position) {
this.setPosition(modelId, transform.position);
}
// 应用旋转(角度制)
if (transform.rotation) {
this.setRotation(modelId, transform.rotation, true);
}
// 应用缩放
if (transform.scale) {
this.setScale(modelId, transform.scale);
}
}
}

View File

@ -92,6 +92,12 @@ class AppRay extends Monobehiver {
const zones = this.mainApp.appDropZone.getPlacementZones();
const clickedZone = zones.find(zone => zone.mesh === pickInfo.pickedMesh);
if (clickedZone) {
// 计算该放置区域的目标位置和旋转
const offsetDistance = 0.1;
const targetPosition = clickedZone.center.add(clickedZone.normal.scale(offsetDistance));
const targetDirection = clickedZone.normal.scale(-1);
const angle = Math.atan2(targetDirection.x, targetDirection.z);
EventBridge.dropZoneClick({
wallName: clickedZone.wallName,
index: clickedZone.index,
@ -99,7 +105,24 @@ class AppRay extends Monobehiver {
width: clickedZone.width,
height: clickedZone.height,
normal: clickedZone.normal,
mesh: clickedZone.mesh
mesh: clickedZone.mesh,
transform: {
position: {
x: targetPosition.x,
y: targetPosition.y,
z: targetPosition.z
},
rotation: {
x: 0,
y: angle * 180 / Math.PI, // 转换为角度
z: 0
},
scale: {
x: 1,
y: 1,
z: 1
}
}
});
return;
}