上节实现了户型列表和户型切换:

这节我们来写一下家具列表和家具导入。
首先我们找一个餐桌的模型:
https://sketchfab.com/search?q=dining+table&type=models

用这个:
https://sketchfab.com/3d-models/modern-dining-table-3c4acb271fdd44c785d68c55351d6ffe#download

下载下来放到 public 目录下:

我们先加载下看下效果:

const gltfLoader = new GLTFLoader();
gltfLoader.load('./dining-table.glb', (gltf) => {
house.add(gltf.scene);
});

加载出来了,但位置不大对。

改下位置,旋转角度。
gltf.scene.position.x = 1500;
gltf.scene.position.z = 3000;
gltf.scene.rotateY(Math.PI / 2);

这样家具的位置就对了。
当然,我们现在是写死的,应该是存在 json 里动态渲染出来。

interface Furniture {
modelUrl: string,
position: {
x: number,
y: number,
z: number
},
rotation: {
x: number,
y: number,
z: number
}
}
export interface State {
data: {
walls: Array<Wall>,
floors: Array<Floor>,
ceilings: Array<Ceiling>,
furnitures: Array<Furniture>
}
}
先在类型加一下。
不需要 scale,因为家具模型大小是不能放缩的,模型多大就是多大。
可以调位置和旋转。
然后我们在户型数据里加一下这部分:

furnitures: [
{
modelUrl: './dining-table.glb',
position: {
x: 1500,
y: 0,
z: 3000
},
rotation: {
x: 0,
y: Math.PI / 2,
z: 0
}
}
]
渲染 3D 场景的时候渲染下家具:

去掉之前写死的代码,我们动态加载。
data.furnitures.forEach(furniture => {
const gltfLoader = new GLTFLoader();
gltfLoader.load(furniture.modelUrl, (gltf) => {
house.add(gltf.scene);
gltf.scene.position.set(
furniture.position.x,
furniture.position.y,
furniture.position.z
);
gltf.scene.rotation.x = furniture.rotation.x;
gltf.scene.rotation.y = furniture.rotation.y;
gltf.scene.rotation.z = furniture.rotation.z;
});
})

渲染没问题。
在另一个户型也加一下家具数据:

furnitures: [
{
modelUrl: './dining-table.glb',
position: {
x: 1500,
y: 0,
z: 3000
},
rotation: {
x: 0,
y: Math.PI / 2,
z: 0
}
}
]

也渲染出来了。
这样我们就实现了家具数据的保存和动态渲染。
有了家具之后,开启墙隐藏功能看起来更方便:


相机角度还是有点高,我们调低一点:

camera.position.set(6000, 4000, 6000);

这样就好多了。
案例代码上传了小册仓库
总结
这节我们实现了家具导入。
从 sketchfab.com 找的家具模型,然后在 json 里保存了家具数据,包括 url、position、rotation。
渲染的时候动态渲染家具并设置位置、旋转角度就好了。
家具导入之后,就可以做位置、角度的编辑了。