threeJS 根据户型图绘制 3D模型 1

户型图

在这里插入图片描述

效果图

在这里插入图片描述
在这里插入图片描述

核心代码

<script>
    var vm = new Vue({
        el: "#app",
        data: {
            test: "改变相机位置",
            scene: '',
            renderer: "",
            camera: "",
            controls: "",  // 鼠标控件
            fh: 2, // 地面高度
            wallHeight: 12,
            wallWeight: 1,
            angle: 0,
            roam: false,  // 漫游  开启漫游状态时应该禁用一切

        },
        methods: {
            // 初始化场景
            initScene() {
                this.scene = new THREE.Scene()
            },
            // 初始化相机
            initCamera(w = 500, h = 500) {
                var camera = new THREE.PerspectiveCamera(45, w / h, 0.1, 10000);
                camera.position.set(100, 100, 100);
                camera.lookAt(100,-200,800);
                this.camera = camera
            },
            initRenderer(w = 500, h = 500) {
                renderer = new THREE.WebGLRenderer({
                    antialias: true
                });
                renderer.setSize(w, h);
                renderer.setClearColor(0x4682B4, 1.0);

                document.getElementById("3dAPP").appendChild(renderer.domElement);
                this.renderer = renderer
            },
            // 初始化灯光
            initLight() {
                var directionalLight = new THREE.DirectionalLight(0xffffff, 1); // 模拟远处类似太阳的光源
                directionalLight.color.setHSL(0.1, 1, 0.95);
                directionalLight.position.set(0, 200, 0).normalize();
                this.scene.add(directionalLight);
                var ambient = new THREE.AmbientLight(0xffffff, 1); // AmbientLight 影响整个场景的光源
                ambient.position.set(0, 0, 0);
                this.scene.add(ambient);
            },
            // 初始化轨迹球控件  鼠标控件
            initControls() {
                var controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
                controls.enableDamping = true;
                controls.dampingFactor = 0.5;
                // 视角最小距离
                controls.minDistance = 0;
                // 视角最远距离
                controls.maxDistance = 5000;
                controls.enableKeys = true;
                // 最大角度
                // controls.maxPolarAngle = Math.PI / 2;
                controls.target = new THREE.Vector3(10, 10, 10);
                this.controls = controls
                console.log(controls)
            },

            // 地面
            createFloor() {
                var loader = new THREE.TextureLoader();
                var floor, floor1;
                loader.load("./img/cz.jpg", (texture) => {
                    texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                    texture.repeat.set(30, 30);
                    var floorGeometry = new THREE.BoxGeometry(100, 100, this.fh);
                    var floorMaterial = new THREE.MeshBasicMaterial({
                        map: texture,
                    });
                    floor = new THREE.Mesh(floorGeometry, floorMaterial);
                    floor.rotation.x = -Math.PI / 2;
                    floor.position.set(0, 0, 0)
                    floor.name = "地面";
                    this.scene.add(floor);
                });
            },
            /**
             * @param i  某一块墙  
             * @param wallHeight 墙高  
             * 
             */
            createwall(i,width=100, wallHeight = this.wallHeight, wallWeight = this.wallWeight) {
                var Geometry = new THREE.BoxGeometry(width, wallHeight, wallWeight);
                var mtl = []
                for (let i = 0; i < Geometry.faces.length; i++) {
                    mtl.push(
                        new THREE.MeshBasicMaterial({
                            color: new THREE.Color(Math.random() * 0xffffff)
                        })
                    )
                }
                var mesh = new THREE.Mesh(Geometry, mtl)

                /*
                    刚好在地面
                    模型自身高度 h0
                    地面高度 h1
                    (地面高度 + 模型高度) / 2  即 (h0+h1)/2
                */
                mesh.name = `wall${i}`
                switch (i) {
                    case 1:
                        mesh.position.set(0, (this.fh + wallHeight) / 2, 24.5)
                        break;
                    case 2:
                        mesh.position.set(0, (this.fh + wallHeight) / 2, -24.5)
                        break;
                    case 3:
                        mesh.rotation.y = Math.PI/2
                        mesh.position.set(41.5, (this.fh + wallHeight) / 2, 0)
                        break;
                    case 4:
                        mesh.rotation.y = Math.PI/2
                        mesh.position.set(-41.5, (this.fh + wallHeight) / 2, 0)
                        break;
                    case 5:
                        mesh.rotation.y = Math.PI/2
                        mesh.position.set(-24, (this.fh + wallHeight) / 2, 0)
                        break;
                    case 6:
                        mesh.position.set(-33, (this.fh + wallHeight) / 2, -2)
                        break;
                    case 7:
                        mesh.rotation.y = Math.PI/2
                        mesh.position.set(-11, (this.fh + wallHeight) / 2, -13)
                        break;
                    case 8:
                        mesh.position.set(-17.5, (this.fh + wallHeight) / 2, -12)
                        break;
                    case 9:
                        mesh.position.set(15, (this.fh + wallHeight) / 2, -2)
                        break;
                    case 10:
                        mesh.rotation.y = Math.PI/2
                        mesh.position.set(3, (this.fh + wallHeight) / 2, -13)
                        break;
                    case 11:
                        mesh.position.set(9, (this.fh + wallHeight) / 2, -12)
                        break;
                    case 12:
                        mesh.rotation.y = Math.PI/2
                        mesh.position.set(15, (this.fh + wallHeight) / 2, -18)
                        break;
                    case 13:
                        mesh.rotation.y = Math.PI/2
                        mesh.position.set(-11, (this.fh + wallHeight) / 2, 21)
                        break;

                }
                this.scene.add(mesh)
                // console.log(Geometry)
            },
            // 模型
            initContent() {
                this.createFloor();
                this.createwall(1, 84)
                this.createwall(2, 84)
                this.createwall(3, 50)
                this.createwall(4, 50)
                this.createwall(5, 50)
                this.createwall(6, 18)
                this.createwall(7, 23)
                this.createwall(8, 13)
                this.createwall(9, 53)
                this.createwall(10,23)
                this.createwall(11,13)
                this.createwall(12,13)
                this.createwall(13,8)
            },
            animate() {
                requestAnimationFrame(this.animate);
                this.renderer.render(this.scene, this.camera);
                this.update();
                if(this.roam){
                    this.angle+=0.005
                    // 重新设置相机位置,相机在XOY平面绕着坐标原点旋转运动
                    this.camera.position.x=200*Math.sin(this.angle)
                    this.camera.position.z=200*Math.cos(this.angle)
                    this.camera.lookAt(0,0,0);
                }
            },

            // 更新控件
            update() {
                // stats.update();
                this.controls.update();
                TWEEN.update();
            },

            init() {
                this.initScene();
                this.initCamera();
                // 初始化渲染器
                this.initRenderer(700, 700);
                // 初始化模型
                this.initContent();
                // 初始化灯光
                this.initLight();
                this.initControls();
            },

            // changePOS() {
            //     this.camera.position.set(0, 300, 10)
            //     this.animate()
            // }
        },
        mounted() {
            this.init();
            this.animate();
        }
    })
</script>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值