Vue+Three.js建造3D小房子

这篇具有很好参考价值的文章主要介绍了Vue+Three.js建造3D小房子。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文章目录

前言

一、Three.js简介

二、开发步骤

1.安装Three.js

2.创建容器

3.创建模型

总结


前言

3D模型给人一种更真实的感受,带来极致的视觉体验。本文介绍Vue结合Three.js开发3D小房子,接触过OpenGL的小伙伴看起来会更轻松一点。


一、Three.js简介

Three.js,一个WebGL引擎,基于JavaScript,可直接运行GPU驱动游戏与图形驱动应用于浏览器。其库提供大量特性与API以绘制3D场景于浏览器。官网地址

二、开发步骤

1.安装Three.js

这里是使用的npm安装

npm install three

2.创建容器

Three.js是使用Js将3D模型渲染在一个画布中,需要创建一个容器来存放。

<div class="three_page" id="threePage">
</div>

3.创建模型

Three.js有几个非常重要的概念,场景、相机、光源、坐标系,渲染器......首先需要创建一个场景对象,因为其他模型都需要放在场景中,最后将场景交由渲染器进行渲染。

initScene(){
    this.scene = new THREE.Scene();
}

为了方便确定模型的位置,所以我引入了坐标系。红色代表 X 轴.,绿色代表 Y 轴.,蓝色代表 Z 轴。

initAxes(){
    let axes = new THREE.AxesHelper(50);
    // 将坐标加入到场景
    this.scene.add(axes)
}

创建一个地面

initPlane(){
    let plane = new THREE.PlaneGeometry(this.planeWidth, this.planeHeight);
    let materialPlane = new THREE.MeshLambertMaterial({
        color: 0xcccccc
    });
    let planeMesh = new THREE.Mesh(plane, materialPlane);
    planeMesh.rotation.x = -0.5 * Math.PI;
    planeMesh.position.set(0, 0, 0);
    this.scene.add(planeMesh);
},

创建光源,光源是非常重要的,要是没有光源,将会什么都看不见。光源有好几种,本文中使用的是环境光和点光源。

initLight(){
    this.scene.add(new THREE.AmbientLight(0x444444));//环境光,可以看到所有物体
    // 光源1
    // DirectionalLight 方向光
    let pointLight = new THREE.PointLight(0xffffff);//点光源
    pointLight.position.set(20, 30, 20);
    this.scene.add(pointLight);
    // 光源2
    let pointLight2 = new THREE.PointLight(0xffffff);//点光源
    pointLight2.position.set(150, 100, 20);
    this.scene.add(pointLight2);
},

创建相机,相机就相当于人眼,你要在什么位置看,看多大的范围,都在相机里面配置。

initCamera(){
    this.camera = new THREE.PerspectiveCamera(45, 2, 0.1, 2000);
    this.camera.position.set(120, 100, 0);
    this.camera.lookAt(this.scene.position);
},

创建渲染器,这一步很重要,我们创建的模型都是放在Scene里面的,最后需要将Scene和Samera交由渲染器进行渲染。

initRenderer(){
    this.container = document.getElementById('threePage');
    this.renderer = new THREE.WebGLRenderer({
        antialias: true //消除锯齿
    });
    this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
    this.renderer.setClearColor(0xb9d3ff, 1);

    this.renderer.render(this.scene, this.camera);
    this.container.appendChild(this.renderer.domElement);
    this.container.addEventListener('click', this.onMouseClick);

    //增加鼠标拾取效果
    let controls = new OrbitControls(this.camera, this.renderer.domElement);
    controls.addEventListener('change', () => {
        this.renderer.render(this.scene, this.camera);
    });
},

到此,就已经完成了平面和坐标系的渲染。

Vue+Three.js建造3D小房子

接着往容器中加入模型,官网介绍了很多模型的创建方法,本文是导入的外部模型,感兴趣的小伙伴可以去一些网站下载模型,这里提供一个网站。模型也有很多种格式,本文导入的是glb的格式

async initModel() {
    let glb = await this.loadGlb('./model/house_type13.glb');
    // 设置模型位置 (y,z,x)
    glb.position.set(0, 0, 0);
    // 设置模型缩放比例
    glb.scale.set(30, 30, 30);
    this.houseData.push(glb)
    this.scene.add(glb);

    let three=await this.loadGlb('./model/tree_large.glb');
    three.position.set(30, 0, 20);
    three.scale.set(30, 30, 30);
    this.houseData.push(three)
    this.scene.add(three);

    let three2=await this.loadGlb('./model/tree_large.glb');
    three2.position.set(30, 0, 30);
    three2.scale.set(30, 50, 50);
    this.houseData.push(three2)
    this.scene.add(three2);

    let house2=await this.loadGlb('./model/house_type15.glb');
    house2.position.set(30, 0, 50);
    house2.scale.set(30, 30, 30);
    this.houseData.push(house2)
    this.scene.add(house2);
},
loadGlb(path) {
    return new Promise((resolve, reject) => {
        var loader = new GLTFLoader();
        loader.setCrossOrigin('Anonymous');//跨域问题
        loader.load(path, (glb) => {
            resolve(glb.scene);
        }, undefined, (error) => {
            reject(error);

        });
    }).catch((e) => {
        console.log("异常", e);
    });
},

同样,将模型加入到场景(Scene)后,需要交给渲染器进行渲染。最后小房子也出来了呀。

Vue+Three.js建造3D小房子

完整代码

<template>
    <div class="three_page" id="threePage">
    </div>
</template>

<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader"
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader"
export default {
    data() {
        return {
            renderer: '',
            cube: '',
            planeWidth: 150,
            planeHeight: 200,
            raycaster: new THREE.Raycaster(),
            mouse: new THREE.Vector2(),
            dialogControl: '',
            houseData: [],
            container: '',
            dialogData: '',
            modelName: []
        }
    },
    created() {

    },
    mounted() {
        this.init()
    },
    methods: {
        // 创建场景
        initScene() {
            this.scene = new THREE.Scene();
        },
        // 创建坐标
        initAxes() {
            let axes = new THREE.AxesHelper(50);
            // 将坐标加入到场景
            this.scene.add(axes)
        },
        // 创建平面
        initPlane() {
            let plane = new THREE.PlaneGeometry(this.planeWidth, this.planeHeight);
            let materialPlane = new THREE.MeshLambertMaterial({
                color: 0xcccccc
            });
            let planeMesh = new THREE.Mesh(plane, materialPlane);
            planeMesh.rotation.x = -0.5 * Math.PI;
            planeMesh.position.set(0, 0, 0);
            this.scene.add(planeMesh);
        },
        // 创建光源
        initLight() {
            this.scene.add(new THREE.AmbientLight(0x444444));//环境光,可以看到所有物体
            // 光源1
            // DirectionalLight 方向光
            let pointLight = new THREE.PointLight(0xffffff);//点光源
            pointLight.position.set(20, 30, 20);
            this.scene.add(pointLight);
            // 光源2
            let pointLight2 = new THREE.PointLight(0xffffff);//点光源
            pointLight2.position.set(150, 100, 20);
            this.scene.add(pointLight2);
        },
        // 创建相机
        initCamera() {
            this.camera = new THREE.PerspectiveCamera(45, 2, 0.1, 2000);
            this.camera.position.set(120, 100, 0);
            this.camera.lookAt(this.scene.position);
        },
        // 创建渲染器
        initRenderer() {
            this.container = document.getElementById('threePage');
            this.renderer = new THREE.WebGLRenderer({
                antialias: true //消除锯齿
            });
            this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
            this.renderer.setClearColor(0xb9d3ff, 1);

            this.renderer.render(this.scene, this.camera);
            this.container.appendChild(this.renderer.domElement);
            this.container.addEventListener('click', this.onMouseClick);

            //增加鼠标拾取效果
            let controls = new OrbitControls(this.camera, this.renderer.domElement);
            controls.addEventListener('change', () => {
                this.renderer.render(this.scene, this.camera);
            });
        },
        init() {
            this.initScene()
            this.initAxes()
            this.initPlane()
            this.initLight()
            this.initCamera()
            this.initRenderer()
            this.initModel()
            setInterval(() => {
                this.renderer.render(this.scene, this.camera);
            }, 1000)
        },
        // 加载模型
        async initModel() {
            let glb = await this.loadGlb('./model/house_type13.glb');
            // 设置模型位置 (y,z,x)
            glb.position.set(0, 0, 0);
            // 设置模型缩放比例
            glb.scale.set(30, 30, 30);
            this.houseData.push(glb)
            this.scene.add(glb);

            let three = await this.loadGlb('./model/tree_large.glb');
            three.position.set(30, 0, 20);
            three.scale.set(30, 30, 30);
            this.houseData.push(three)
            this.scene.add(three);

            let three2 = await this.loadGlb('./model/tree_large.glb');
            three2.position.set(30, 0, 30);
            three2.scale.set(30, 50, 50);
            this.houseData.push(three2)
            this.scene.add(three2);

            let house2 = await this.loadGlb('./model/house_type15.glb');
            house2.position.set(30, 0, 50);
            house2.scale.set(30, 30, 30);
            this.houseData.push(house2)
            this.scene.add(house2);
        },
        // 加载DLB
        loadGlb(path) {
            return new Promise((resolve, reject) => {
                var loader = new GLTFLoader();
                loader.setCrossOrigin('Anonymous');//跨域问题
                loader.load(path, (glb) => {
                    resolve(glb.scene);
                }, undefined, (error) => {
                    reject(error);

                });
            }).catch((e) => {
                console.log("异常", e);
            });
        },
        // 加载gltf
        addGltfItem() {
            let that = this;
            let loader = new GLTFLoader();
            loader.load("./glb/model.gltf", function (gltf) {
                gltf.scene.position.set(0, 0, 95);
                gltf.scene.scale.set(16, 12, 12);
                that.scene.add(gltf.scene);
            });
        },
        // 加载obj
        addObjItem() {
            var loader = new OBJLoader();
            var mat = new MTLLoader();
            let that = this;
            mat.load("./glb/house_type01.mtl", function (materials) {
                materials.preload();
                loader.setMaterials(materials);
                loader.load(
                    "./glb/house_type01.obj",
                    function (object) {
                        console.log("数据==>", object);
                        object.position.set(0, 0, 0);
                        object.scale.set(13, 13, 13);
                        that.scene.add(object);
                    }
                );
            });
        },
        // 点击事件
        onMouseClick(event) {
            event.preventDefault();
            this.dialogControl = {
                show: false,
                top: 0,
                left: 0
            };
            let mou = new THREE.Vector2()
            // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
            mou.x = (event.clientX / this.container.clientWidth) * 2 - 1;
            mou.y = -(event.clientY / this.container.clientHeight) * 2 + 1;
            console.log("x", "y", this.mouse.x, this.mouse.y);
            this.raycaster.setFromCamera(mou, this.camera);
            let intersects = this.raycaster.intersectObjects(this.scene.children, true);
            // 获取选中最近的 Mesh 对象
            if (intersects.length !== 0 && intersects[0].object.type === "Mesh") {
                let selectName = intersects[0].object.name;
                console.log("模型名字", intersects[0].object.name);
                this.houseData.forEach(h => {
                    console.log(h.name);
                    if (h.name === selectName) {
                        this.dialogData = h;
                        this.dialogControl = {
                            show: true,
                            top: event.clientY,
                            left: event.clientX
                        };
                        console.log("模型被点击--", h);
                    }
                });
            }
            console.log(this.dialogData);
        }

    }
}
</script>

<style>
.three_page {
    width: 100%;
    height: 100%;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
</style>

总结

第一次接触Three.js做3D,可能也存在很多错误,希望小伙伴多多指点。刚收到要做3D的需求时觉得自己根本做不出来,但是看了一下Three.js的官方文档以后还是慢慢做出来了,以前接触过OpenGL,所以也大概了解流程,总是要逼自己一把才能进步。文章来源地址https://www.toymoban.com/news/detail-465694.html

到了这里,关于Vue+Three.js建造3D小房子的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue中如何进行3D场景展示与交互(如Three.js)

    随着WebGL技术的发展,越来越多的网站开始使用3D场景来展示产品、游戏等内容。在Vue中,我们可以使用第三方库Three.js来实现3D场景的展示与交互。本文将介绍如何在Vue中使用Three.js来创建3D场景,并实现交互功能。 Three.js是一个用于创建3D图形的JavaScript库。它基于WebGL技术,

    2024年02月09日
    浏览(74)
  • vue2+three.js+blender(实现3d 模型引入并可点击效果)

    2023.9.13今天我学习了如何把3d建模里面的模型引入到vue中,并可以实现拖动,点击的效果: 首先安装: npm install three 相关代码如下:  如果没有图片可以去 Three.js--》建模软件如何加载外部3D模型?_threejs加载3d模型_亦世凡华、的博客-CSDN博客

    2024年02月03日
    浏览(61)
  • vue3中使用Three.js及ROS2绘制机器人3D图形

    要实现机器人3D位置的显示,你需要使用ROS2和Vue3结合开发。 首先,在Vue3中创建一个3D场景,你可以使用Three.js库来创建。Three.js是一个用于创建和渲染3D图形的JavaScript库,可以轻松创建3D场景、3D对象、光线等。 接下来,在Vue3中使用ROS2提供的 roslibjs 库,订阅机器人的位置信

    2024年02月03日
    浏览(45)
  • 【可视化大屏-3d机房监控】Vue与three.js搭建可视化机房监控

    演示网址:http://jstopo.top网站地址 3d机房地址:http://jstopo.top/threeTopo/#/monitor/index

    2024年03月10日
    浏览(64)
  • THREE.JS使用详细(three.js创建3d物体,three.js的使用方式)

    简述:three.js封装了WebGL的底层细节,是一款运行在浏览器中的 3D 引擎,可以用它创建各种三维场景,包括了摄影机、光影、材质等各种对象,目前在Git上已经拥有90k+的star,今天用three.js来构建一个三维模型; 1、首先,在项目中需要下载threejs的相关依赖; 2、在js页面引入使

    2024年01月23日
    浏览(76)
  • three.js(一):认识three.js并创建第一个3D应用

    1-three.js 是什么? three.js是用JavaScript编写的WebGL第三方库; three.js 提供了非常多的3D显示和编辑功能; 具体而言,three.js 是一款运行在浏览器中的 3D 引擎,可以用three.js 创建各种三维场景,并对其进行编辑; 在three.js 的官网上看到许多精彩的演示和文档 three.js 官网:https://thre

    2024年02月11日
    浏览(87)
  • three.js添加3d模型

    three官方的几何体也就那么几个,想要生成各种各样的模型,其难度十分之大,这时引入外部模型也不失为一种选择。具体引入办法如下。 虽然名字为GLTFLoader,但实际上glb文件也是能加载的。 其中需要注意的是调节相机参数与相机位置,否则很有可能导致场景中看不见任何东

    2024年02月04日
    浏览(85)
  • Three.js 3D建模必备基础

    在 three.js 中,可见对象由几何体和材质构成。 我们已经了解了如何创建适用于点和线图元的简单几何图形,并且遇到了各种标准网格几何图形,例如 THREE.CylinderGeometry 和 THREE.IcosahedronGeometry。 在本节中,我们将了解如何从头开始创建新的网格几何体。 我们还将了解 three.js

    2023年04月09日
    浏览(34)
  • Three.js之创建3D场景

    【G】Three.js官方文档:https://threejs.org/docs/ Three.js是一个流行的WebGL库,官方文档提供了详细的API参考和示例,适合学习和参考。 【G】Three.js GitHub链接:https://github.com/mrdoob/three.js 这是一个流行的基于WebGL的3D图形库,提供了丰富的功能和工具,用于创建交互式的3D场景和应用。

    2024年02月14日
    浏览(75)
  • Three.js中的3D文字效果

    对于一些设计网页中经常会出现一些3D的文字效果,本文将利用Three.js实现各种动画WebGL文本输入效果。 示例效果 原文章 通常情况下,文本网格是2D的平面形状,我们所要实现的3D文本形状则是要在2D的平面下,再生成z值形成一个立体的效果。 首先,我们创建一个canvas元素,

    2024年02月02日
    浏览(100)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包