VUE+THREEJS 创建完整会议室三维模型
最近学习threejs有些时间了,就想着着手做些东西。前端Vue里面引入thrssjs,先给大家看下效果。用到的知识点只要有三维几何体BoxGeometry、材质、纹理贴图、PlaneGeometry、CylinderGeometry,以及BSP的二元操作等。在使用Vue引入threejs中,我采用的方法是直接在index.html中引用。初次尝试,代码写的臃肿杂乱,不过比较适合刚入门的小伙伴,后
·
最近学习threejs有些时间了,就想着着手做些东西。前端Vue里面引入thrssjs,先给大家看下效果。
用到的知识点只要有三维几何体BoxGeometry、材质、纹理贴图、PlaneGeometry、CylinderGeometry,以及BSP的二元操作等。在使用Vue引入threejs中,我采用的方法是直接在index.html中引用。
初次尝试,代码写的臃肿杂乱,不过比较适合刚入门的小伙伴,后续我也会将样例发布到云服务器上,可供大家在线预览。有不足之处欢迎指出,下方评论留言。大神请略过。。。
<!-- 引入THREEJS 相关-->
<script src="lib/three/three.js"></script>
<script src="lib/three/controls/TrackballControls.js"></script>
<script src="lib/three/loaders/MTLLoader.js"></script>
<script src="lib/three/loaders/OBJLoader.js"></script>
<script src="lib/three/loaders/GLTFLoader.js"></script>
<script src="lib/three/controls/OrbitControls.js"></script>
<script src="lib/three/other/ThreeBSP.js"></script>
1 首先初始化场景
init(){
//创建三大件
//1.1 场景
this.scene = new THREE.Scene();
//1.2 相机
this.camera = new THREE.PerspectiveCamera(50, window.innerWidth/window.innerHeight, 0.1, 1000);
//1.3 渲染器
this.renderer = new THREE.WebGLRenderer({antialias: true});
//创建纹理加载器
this.textureLoader = new THREE.TextureLoader();
//设置相机
//设置摄像机位置,相机方向逆X轴方向,倾斜向下看
this.camera.position.set(360, 360 ,0);
//指向场景中心
this.camera.lookAt(this.scene.position);
//添加坐标轴,辅助判断位置
let axes = new THREE.AxesHelper(1000);
// this.scene.add(axes);
//设置环境
this.renderer.setClearColor(new THREE.Color(0xF7F2F1));
//设置场景大小
this.renderer.setSize(
document.getElementById("threeworld").clientWidth,
document.getElementById("threeworld").clientHeight);
//渲染器开启阴影效果
this.renderer.shadowMap.enabled = true;
//渲染div到canvas
document.getElementById("threeworld").appendChild(this.renderer.domElement);
//鼠标键盘控制
this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
//点光源
let point = new THREE.PointLight(0xffffff);
point.position.set(500, 300, 400); //点光源位置
this.scene.add(point); //点光源添加到场景中
// 环境光
let ambient = new THREE.AmbientLight(0x999999);
this.scene.add(ambient);
}
2 创建不同类型的几何体,组合成会议室
2.1 地板
地板基本单元是使用BoxBufferGeometry创建,使用纹理贴图。
addGeoBox(){
//创建材质并贴上纹理
let floorTexture = this.textureLoader.load('/static/textures/floor/floor.jpg');
let boxTextureMaterial = new THREE.MeshStandardMaterial({
map:floorTexture,
metalness: 0.2,
roughness: 0.07,
side: THREE.DoubleSide
});
//创建地板
for(let i=0; i<12; i++){
for(let j=0; j<16; j++){
let boxGeo = new THREE.BoxBufferGeometry(29.9,2, 29.9);
let boxMesh = new THREE.Mesh(boxGeo, boxTextureMaterial);
boxMesh.position.set(-150 + i*30, 0, -240 + j*30);
this.scene.add(boxMesh);
}
}
},
2.2 墙体
墙体使用BoxGeometry,使用两种不同图片的纹理贴图。墙上的门,窗户采用BSP的二元操作扣除。
createWall(){
//外墙
let wallMaterial = new THREE.MeshLambertMaterial({color: 0x00FFFF});
let wallGeo = new THREE.BoxGeometry(280, 120, 400);
let wallMesh = new THREE.Mesh(wallGeo, wallMaterial);
wallMesh.position.set(0, 60, -14.95);
//内墙
let wallInnerMaterial = new THREE.MeshLambertMaterial({color: 0x2D1BFF});
let wallInnerGeo = new THREE.BoxGeometry(270, 120, 390);
let wallInnerMesh = new THREE.Mesh(wallInnerGeo, wallInnerMaterial);
wallInnerMesh.position.set(0, 60, -14.95);
//门
let doorInnerMaterial = new THREE.MeshLambertMaterial({color: 0x2D1BFF});
let doorGeo = new THREE.BoxGeometry(18, 100, 70);
let doorMesh = new THREE.Mesh(doorGeo, doorInnerMaterial);
doorMesh.position.set(140.5, 50, 0);
// this.scene.add(doorMesh);
//转BSP
let wallBSP = new ThreeBSP(wallMesh);
let wallInnerBSP = new ThreeBSP(wallInnerMesh);
let doorBSP = new ThreeBSP(doorMesh);
let window1BSP = new ThreeBSP(this.createWindowRight());
let window2BSP = new ThreeBSP(this.createWindowLeft());
let wallResultBSP = wallBSP.subtract(wallInnerBSP);
wallResultBSP = wallResultBSP.subtract(doorBSP);
wallResultBSP = wallResultBSP.subtract(window1BSP);
wallResultBSP = wallResultBSP.subtract(window2BSP);
let wallResultMesh = wallResultBSP.toMesh();
//转换后的Mesh配置属性
let wallTexture = this.textureLoader.load('/static/textures/wall/wall.jpg');
let wallTextureMaterial = new THREE.MeshStandardMaterial({
map:wallTexture,
metalness: 0.2,
roughness: 0.07,
side: THREE.DoubleSide
});
let wallInnerTexture = this.textureLoader.load('/static/textures/wall/wallinner.jpg');
let wallInnerTextureMaterial = new THREE.MeshStandardMaterial({
map:wallInnerTexture,
metalness: 0.2,
roughness: 0.07,
side: THREE.DoubleSide
});
let wallResultMeshMaterial = [];
wallResultMeshMaterial.push(wallTextureMaterial);
wallResultMeshMaterial.push(wallInnerTextureMaterial);
wallResultMesh.material = wallResultMeshMaterial;
console.log(wallResultMesh.geometry.faces, 112233);
wallResultMesh.geometry.faces.forEach((item, i) => {
if(i<160){
item.materialIndex = 0;
} else {
item.materialIndex = 1;
}
})
wallResultMesh.geometry.computeFaceNormals();
wallResultMesh.geometry.computeVertexNormals();
//添加结果到场景中
this.scene.add(wallResultMesh);
}
2.3 窗户
同样的道理,生成窗户
createWindowRight(){
let shpMaterial1 = new THREE.MeshBasicMaterial({color:'#F7C777'});
let shpGeometry1 = new THREE.BoxGeometry(70, 90, 10);
let shpMesh1 = new THREE.Mesh(shpGeometry1, shpMaterial1);
shpMesh1.position.set(-40, 65, -213);
let wMaterial1 = new THREE.MeshBasicMaterial({color:0x2D1BFF});
let wGeometry1 = new THREE.BoxGeometry(70, 3, 10);
let wMesh1 = new THREE.Mesh(wGeometry1, wMaterial1);
wMesh1.position.set(-40, 85, -213);
let wMaterial2 = new THREE.MeshBasicMaterial({color:0x2B2B2B});
let wGeometry2 = new THREE.BoxGeometry(3, 90, 10);
let wMesh2 = new THREE.Mesh(wGeometry2, wMaterial2);
wMesh2.position.set(-40, 65, -213);
let shpMesh1BSP = new ThreeBSP(shpMesh1);
let wMesh1BSP = new ThreeBSP(wMesh1);
let wMesh2BSP = new ThreeBSP(wMesh2);
let shpMesh1BSPResult = shpMesh1BSP.subtract(wMesh1BSP);
shpMesh1BSPResult = shpMesh1BSPResult.subtract(wMesh2BSP);
let shpMesh1MeshResult = shpMesh1BSPResult.toMesh();
return shpMesh1MeshResult;
}
2.4 添加会议桌和桌上的花瓶
会议中使用BoxGeometry,BSP做二元操作,花瓶使用LatheGeometry生成。
createConferenceTable(){
let desktopTexture = this.textureLoader.load('/static/textures/desktop/desktop.jpg');
let desktopTextureMaterial = new THREE.MeshStandardMaterial({
map:desktopTexture,
metalness: 0.2,
roughness: 0.07,
side: THREE.DoubleSide
});
let desktopGeo = new THREE.BoxGeometry(100, 50, 280);
let desktopMesh = new THREE.Mesh(desktopGeo, desktopTextureMaterial);
desktopMesh.position.set(0, 25, -14.95);
let d1Material = new THREE.MeshBasicMaterial({color:0xC49235});
let d1Geo = new THREE.BoxGeometry(100, 44, 274);
let d1Mesh = new THREE.Mesh(d1Geo, d1Material);
d1Mesh.position.set(0, 22, -14.95);
let d2Material = new THREE.MeshBasicMaterial({color:0x0000FF});
let d2Geo = new THREE.BoxGeometry(94, 44, 320);
let d2Mesh = new THREE.Mesh(d2Geo, d2Material);
d2Mesh.position.set(0, 22, -14.95);
let desktopMeshBSP = new ThreeBSP(desktopMesh);
let d1BSP = new ThreeBSP(d1Mesh);
let d2BSP = new ThreeBSP(d2Mesh);
let desktopBSPResult = desktopMeshBSP.subtract(d1BSP);
desktopBSPResult = desktopBSPResult.subtract(d2BSP);
let desktopMeshResult = desktopBSPResult.toMesh();
desktopMeshResult.material = desktopTextureMaterial;
this.scene.add(desktopMeshResult);
// //会议桌上的花瓶
let points = [];
let height = 3;
let count = 30;
for(let i=0; i<count; i++){
let pointV3 = new THREE.Vector3(
(Math.sin(i*0.2) + Math.cos(i*0.3)) * height + 6,
(i-count) + count/2,
0
);
points.push(pointV3);
}
let latheGeometry = new THREE.LatheGeometry(
points,
20,
0,
2*Math.PI
);
let latheTexture = this.textureLoader.load('/static/textures/flowervase/flowervase.jpg');
let latheMaterial = new THREE.MeshStandardMaterial({
map:latheTexture,
metalness: 0.2,
roughness: 0.07,
side: THREE.DoubleSide
});
//花
var leafTexture = this.textureLoader.load('/static/textures/flowervase/flower.jpg');
var leafMaterial = new THREE.MeshBasicMaterial(
{
map:leafTexture,
side:THREE.DoubleSide,
transparent:true
});
let geom = new THREE.PlaneGeometry(4, 8);
//第一个花瓶
for(let i=0;i<40;i++){
let leaf = new THREE.Mesh(geom, leafMaterial );
leaf.position.x = Math.random()*2;
leaf.position.y = 70 + Math.random() * i/2;
leaf.position.z = Math.random() * 3 - 2;
leaf.rotation.x = -Math.PI/(i+1) + Math.random();
leaf.rotation.y = -Math.PI/(i+1) + Math.random();
leaf.rotation.z = -Math.PI/(i+1) + Math.random();
this.scene.add(leaf);
}
let latheMesh1 = new THREE.Mesh(latheGeometry, latheMaterial);
latheMesh1.position.set(0, 60, 0);
this.scene.add(latheMesh1);
//第二个花瓶
for(let i=0;i<40;i++){
let leaf = new THREE.Mesh(geom, leafMaterial );
leaf.position.x = Math.random()*2;
leaf.position.y = 70 + Math.random() * i/2;
leaf.position.z = Math.random() * 3 - 2 -100;
leaf.rotation.x = -Math.PI/(i+1) + Math.random();
leaf.rotation.y = -Math.PI/(i+1) + Math.random();
leaf.rotation.z = -Math.PI/(i+1) + Math.random();
this.scene.add(leaf);
}
let latheMesh = new THREE.Mesh(latheGeometry, latheMaterial);
latheMesh.position.set(0, 60, -100);
this.scene.add(latheMesh);
//第三个花瓶
for(let i=0;i<40;i++){
let leaf = new THREE.Mesh(geom, leafMaterial );
leaf.position.x = Math.random()*2;
leaf.position.y = 70 + Math.random() * i/2;
leaf.position.z = Math.random() * 3 - 2 +85.05;
leaf.rotation.x = -Math.PI/(i+1) + Math.random();
leaf.rotation.y = -Math.PI/(i+1) + Math.random();
leaf.rotation.z = -Math.PI/(i+1) + Math.random();
this.scene.add(leaf);
}
let latheMesh3 = new THREE.Mesh(latheGeometry, latheMaterial);
latheMesh3.position.set(0, 60, 85.05);
this.scene.add(latheMesh3);
}
2.5 椅子
createChair(){
let groupBox = new THREE.Group();
let boxMaterial = new THREE.MeshBasicMaterial({color:0x559762});
let boxTextures1 = this.textureLoader.load('/static/textures/chair/chair.jpg');
let boxMaterial1 = new THREE.MeshStandardMaterial({
map: boxTextures1,
metalness: 0.2,
roughness: 0.07,
side: THREE.DoubleSide
})
for(let i=0; i<6; i++){
//前面椅子
let boxGeo1 = new THREE.BoxGeometry(30, 40, 30);
let boxGeo2 = new THREE.BoxGeometry(24, 28, 32);
let boxGeo3 = new THREE.BoxGeometry(32, 28, 20);
let boxMesh1 = new THREE.Mesh(boxGeo1, boxMaterial1);
let boxMesh2 = new THREE.Mesh(boxGeo2, boxMaterial);
let boxMesh3 = new THREE.Mesh(boxGeo3, boxMaterial);
boxMesh1.position.set(0, 20, -i*45 + 10);
boxMesh2.position.set(0, 14, -i*45 + 10);
boxMesh3.position.set(0, 14, -i*45 + 10);
let boxMeshBSP1 = new ThreeBSP(boxMesh1);
let boxMeshBSP2 = new ThreeBSP(boxMesh2);
let boxMeshBSP3 = new ThreeBSP(boxMesh3);
let boxMeshBSPResult = boxMeshBSP1.subtract(boxMeshBSP2);
boxMeshBSPResult = boxMeshBSPResult.subtract(boxMeshBSP3);
let boxMeshResult = boxMeshBSPResult.toMesh();
boxMeshResult.material = boxMaterial1;
groupBox.add(boxMeshResult);
//靠背
let boxBackRestGeo = new THREE.BoxGeometry(3, 30, 30);
let boxBackRestMesh = new THREE.Mesh(boxBackRestGeo, boxMaterial1);
boxBackRestMesh.position.set(13, 55, -i*45+10);
groupBox.add(boxBackRestMesh);
//后面椅子
let boxGeob1 = new THREE.BoxGeometry(30, 40, 30);
let boxGeob2 = new THREE.BoxGeometry(24, 28, 32);
let boxGeob3 = new THREE.BoxGeometry(32, 28, 20);
let boxMeshb1 = new THREE.Mesh(boxGeob1, boxMaterial1);
let boxMeshb2 = new THREE.Mesh(boxGeob2, boxMaterial);
let boxMeshb3 = new THREE.Mesh(boxGeob3, boxMaterial);
boxMeshb1.position.set(-160, 20, -i*45 + 10);
boxMeshb2.position.set(-160, 14, -i*45 + 10);
boxMeshb3.position.set(-160, 14, -i*45 + 10);
let boxMeshBSPb1 = new ThreeBSP(boxMeshb1);
let boxMeshBSPb2 = new ThreeBSP(boxMeshb2);
let boxMeshBSPb3 = new ThreeBSP(boxMeshb3);
let boxMeshBSPResultb = boxMeshBSPb1.subtract(boxMeshBSPb2);
boxMeshBSPResultb = boxMeshBSPResultb.subtract(boxMeshBSPb3);
let boxMeshResultb = boxMeshBSPResultb.toMesh();
boxMeshResultb.material = boxMaterial1;
groupBox.add(boxMeshResultb);
//靠背
let boxBackRestGeob = new THREE.BoxGeometry(3, 30, 30);
let boxBackRestMeshb = new THREE.Mesh(boxBackRestGeob, boxMaterial1);
boxBackRestMeshb.position.set(-173.3, 55, -i*45+10);
groupBox.add(boxBackRestMeshb);
}
groupBox.position.set(80, 5, 100);
this.scene.add(groupBox);
}
2.6 盆栽
createPottedPlant(){
let group = new THREE.Group();
let cylinderMaterial = new THREE.MeshBasicMaterial({color:0x559762});
let cylinderTextures1 = this.textureLoader.load('/static/textures/cylinder/cylinder.jpg');
let cylinderMaterial1 = new THREE.MeshStandardMaterial({
map: cylinderTextures1,
metalness: 0.2,
roughness: 0.07,
side: THREE.DoubleSide
});
var leafTexture = this.textureLoader.load('/static/textures/leaf/leaf.jpg');
var leafMaterial = new THREE.MeshBasicMaterial(
{
map:leafTexture,
side:THREE.DoubleSide,
transparent:true
});
let geom = new THREE.PlaneGeometry(4, 8);
let cylinderGeo = new THREE.CylinderGeometry(12, 15, 40, 20, 10, false);
let cylinderMesh = new THREE.Mesh(cylinderGeo, cylinderMaterial1);
cylinderMesh.position.set(100, 20, -180);
group.add(cylinderMesh);
for(let i=0;i<40;i++){
let leaf = new THREE.Mesh(geom, leafMaterial);
leaf.position.x = 95 + Math.random() * 15;
leaf.position.y = 40 + Math.random() * i/1.2;
leaf.position.z = -185 + Math.random() * 10;
leaf.rotation.x = -Math.PI/(i+1) + Math.random();
leaf.rotation.y = -Math.PI/(i+1) + Math.random();
leaf.rotation.z = -Math.PI/(i+1) + Math.random();
group.add(leaf);
}
let cylinderGeo1 = new THREE.CylinderGeometry(12, 15, 40, 20, 10, false);
let cylinderMesh1 = new THREE.Mesh(cylinderGeo1, cylinderMaterial1);
cylinderMesh1.position.set(-100, 20, -180);
group.add(cylinderMesh1);
for(let i=0;i<60;i++){
let leaf = new THREE.Mesh(geom, leafMaterial);
leaf.position.x = -105 + Math.random() * 15;
leaf.position.y = 40 + Math.random() * i/1.2;
leaf.position.z = -185 + Math.random() * 10;
leaf.rotation.x = -Math.PI/(i+1) + Math.random();
leaf.rotation.y = -Math.PI/(i+1) + Math.random();
leaf.rotation.z = -Math.PI/(i+1) + Math.random();
group.add(leaf);
}
group.position.set(0, 0, 0);
this.scene.add(group);
console.log(Math.random(), 999999);
}
2.7 墙上大屏
createLargeScreen(){
let createLargeTextures1 = this.textureLoader.load('/static/textures/largeScreen/largeScreen.jpg');
let createLargeMaterial1 = new THREE.MeshStandardMaterial({
map: createLargeTextures1,
metalness: 0.2,
roughness: 0.07,
side: THREE.DoubleSide
});
let boxGeo1 = new THREE.BoxGeometry(140, 80, 0.1);
let boxGeo2 = new THREE.PlaneGeometry(140, 80);
let boxMesh1 = new THREE.Mesh(boxGeo1, createLargeMaterial1);
let boxMesh2 = new THREE.Mesh(boxGeo2, createLargeMaterial1);
boxMesh2.position.set(0, 70, 180);
this.scene.add(boxMesh2);
}
2.8 墙上文字
createText(){
this.fontload = new THREE.FontLoader();
this.fontload.load(
'../static/fonts/MI LANTING_Regular.json',
(response) => {
let options = {
size: 18,
height: 10,
font:response,
};
let textGeom = new THREE.TextGeometry("保密就是保安全,保发展", options);
let textMaterial = new THREE.MeshBasicMaterial({color:"red"});
let textMesh = new THREE.Mesh(textGeom, textMaterial);
textMesh.position.set(-140, 80, 100);
textMesh.rotation.y = 0.5 * Math.PI;
this.scene.add(textMesh);
}
);
}
至此,简单会议室创建完成
更多推荐
已为社区贡献3条内容
所有评论(0)