2天赚了4个W,手把手教你用Threejs搭建一个Web3D汽车展厅!(下)

简介: 接上文

加载模型


3d模型的文件格式有很多,但threejs里常用的基本是


  • OBJ格式


老牌通用3d模型文件,不包含贴图,材质,动画等信息。


  • GLTF格式(图形语言传输格式)


由OpenGL官方维护团队推出的现代3d模型通用格式,可以包含几何体、材质、动画及场景、摄影机等信息,并且文件量还小。有3D模型界的JPEG之称。


原项目中我使用的是OBJ格式,本文里我们使用GLTF格式。利用threejs提供的editor,我们可以将模型的格式进行转换并导出。


image.png


通过GLTFLoader,我们可以加载一个.gltf格式的3d模型文件。需要注意的是,这些Loader都以插件的形式存在,需要引入相应的XXXLoader.js才能使用


//<script src="js/GLTFLoader.js"></script>
//放到之前添加立方体的代码处
const loader = new THREE.GLTFLoader();
loader.load(
    'images/model.gltf',
    function ( gltf ) {
        scene.add( gltf.scene );
    },
    function ( xhr ) {
        //侦听模型加载进度
        console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
    },
    function ( error ) {
        //加载出错时的回调
        console.log( 'An error happened' );
    }
);


image.png


通过这个代码可以遍历查看模型里的几何体列表


console.log(gltf.scene.children);
//可以用for,也可以用traverse api
//gltf.scene.children.traverse((child){});


贴图和材质


现在我们来给几何体添加贴图,贴图怎么做是设计师的专业。这里不过多的说,我们只需要知道,这些贴图如何使用即可。


image.png


  • 普通贴图(_col


material.map,替代颜色


  • 法线贴图(_nor


material.normalMap,让细节程度较低的表面生成高细节程度的精确光照方向和反射效果


  • 环境光遮蔽贴图(_occ


material.aoMap,用来描绘物体和物体相交或靠近的时候遮挡周围漫反射光线的效果


  • 环境反射贴图


material.envMap,用于模拟材质反射周围环境的效果


我们现在先把这些贴图文件统一加载到内存里


var allTexture;
function loadAllTexture(cb){
    allTexture = {};
    var loadIndex = 0;
    var textures = [
        "skymap",
        "shache_occ",
        "shache_nor",
        "shache_col",
        "neishi_occ",
        "neishi_nor",
        "mennei_col",
        "luntai_nor",
        "luntai_col",
        "lungu_occ",
        "lungu_nor",
        "lungu_col",
        "linjian_occ",
        "linjian_nor",
        "linjian_col",
        "floor",
        "deng_occ",
        "deng_nor",
        "deng_col",
        "cheshen_occ",
        "cheshen_nor",
        "chejia_occ",
        "chejia_nor",
        "chedengzhao_nor"
    ];
    function loadNextTexture(){
        var textureName = textures[loadIndex];
        loadTexture("images/textures/"+textureName+".jpg",function(texture){
            if(loadIndex<textures.length-1){
                allTexture[textureName] = {
                    texture:texture
                };
                loadIndex++;
                loadNextTexture();
            }else{
                if(cb)cb();
            }
        });
    }
    loadNextTexture();
}
function loadTexture(filepath,cb){
    const textureLoader = new THREE.TextureLoader();
    textureLoader.load(filepath,cb);
}


然后根据名称手动一一对应,比如我们先把车轮毂的贴图给加上


image.png


for(var i=0;i<gltf.scene.children[0].children.length;i++){
    var modelObj = gltf.scene.children[0].children[i];
    if(modelObj.name=="smart_lungu0"||modelObj.name=="smart_lungu1"||modelObj.name=="smart_lungu2"||modelObj.name=="smart_lungu3"){
        modelObj.material = new THREE.MeshStandardMaterial();
        modelObj.material.map = allTexture["lungu_col"].texture;
        modelObj.material.normalMap = allTexture["lungu_nor"].texture;
        modelObj.material.aoMap = allTexture["lungu_occ"].texture;
    }
}


我们继续把车轮的贴图给加上


image.png


else if(modelObj.name=="smart_chelun0"||modelObj.name=="smart_chelun1"||modelObj.name=="smart_chelun2"||modelObj.name=="smart_chelun3"){
    modelObj.material = new THREE.MeshStandardMaterial();
    modelObj.material.map = allTexture["luntai_col"].texture;
    modelObj.material.normalMap = allTexture["luntai_nor"].texture;
}


其余的材质贴图都如此添加上,后续当然还有很多材质的细节是可以去调整的,但这是个细活儿,这里主要重点分享下玻璃的反射和透明金属漆的反光


  • 透明的玻璃


天窗和前挡风玻璃的透明度以及基底颜色是不同的


else if(child.name=="smart_boli"){
    child.material=new THREE.MeshPhongMaterial();
    child.material.color = new THREE.Color( 0x333333 );
    child.material.transparent=true;
    child.material.opacity=.2;
}else if(child.name=="smart_tianchuang"){
    child.material=new THREE.MeshPhongMaterial();
    child.material.color = new THREE.Color( 0x000 );
    child.material.transparent=true;
    child.material.opacity=.5;
}


仔细看看动图里前挡风和天窗透明度的差异


image.png


  • 玻璃的反射


想真的去反射真实的环境?你别想多了,用envMap做个假的看起来就很可以了...


child.material.envMap=allTexture["skymap"].texture;
//环境反射贴图envMap的映射方式,这里用的是一个叫等量矩形投影的映射方法
child.material.envMap.mapping = THREE.EquirectangularReflectionMapping;
//环境反射贴图的强度
child.material.envMapIntensity=1;


image.png


仔细看动图里的前挡风玻璃,是不是反射了什么东西?看过《三种前端实现VR全景看房的方案!说不定哪天就用得上!》的小伙伴们,记得这张图么?


image.png


  • 车身漆面质感


使用MeshStandardMaterial材质,通过调节metalnessroughness的值来调节金属的质感


child.material = new THREE.MeshStandardMaterial();
child.material.color=new THREE.Color(0x70631B);
child.material.metalness = 0.44;
child.material.roughness = 0;


image.png


信息点


毕竟是个在线展厅,在车身周围得呈现一些信息点,点击后可以弹窗显示更多信息对吧。实现方式同样在VR全景的文章中提到过了,就是Sprite+Raycast


image.png


//frame只是一个标记,叫什么都行
var poiPosArray=[
    {x:-1.47,y:0.87,z:-0.36,frame:1},
    {x:-1.46,y:0.49,z:-0.69,frame:2},
    {x:1.5,y:.7,z:0,frame:8},
    {x:0.33,y:1.79,z:0,frame:3},
    {x:0,y:0.23,z:0.96,frame:4},
    {x:0.73,y:1.38,z:-0.8,frame:5},
    {x:-.1,y:1.17,z:0.88,frame:6},
    {x:-1.16,y:0.16,z:0.89,frame:7}
],poiObjects=[];
function setupInfoPoint(){
    const pointTexture = new THREE.TextureLoader().load("images/point.png");
    var group = new THREE.Group();
    var materialC = new THREE.SpriteMaterial( { map: pointTexture, color: 0xffffff, fog: false } );
    for ( var a = 0; a < poiPosArray.length; a ++ ) {
        var x = poiPosArray[a].x;
        var y = poiPosArray[a].y-.5;
        var z = poiPosArray[a].z;
        var sprite = new THREE.Sprite( materialC );
        sprite.scale.set( .15, .15, 1 );
        sprite.position.set( x, y, z );
        sprite.idstr="popup_"+poiPosArray[a].frame;
        group.add( sprite );
        poiObjects.push(sprite);
    }
    scene.add( group );
    document.body.addEventListener("click",function (event) {
        event.preventDefault();
        var raycaster = new THREE.Raycaster();
        var mouse = new THREE.Vector2();
        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
        raycaster.setFromCamera( mouse, camera );
        var intersects = raycaster.intersectObjects( poiObjects );
        if(intersects.length>0){
            var popIndex=parseInt(intersects[ 0 ].object.idstr.substr(6,1));
            console.log(popIndex);
        }
    });
}


UI怎么做


image.png



既然我们用了threejs,所以我们就要在threejs里把UI做出来吗?这么想的话,会把自己累死。要知道在3d场景里做2d的UI可不算是一件容易的事,还要实现UI的一些用户行为(点击,拖动等)的话就更麻烦了...所以我们直接用html来做UI就好啦~


到这里,这个3D汽车展厅的核心部分你已经学会(fei)了吧!


结语


以上只是对threejs一个非常粗浅的使用,threejs能实现的酷炫效果远远不止于此,希望本文能让你开始对Web3D开发产生兴趣,如果觉得本文还不错,请点赞收藏关注吧~




相关文章
|
2月前
|
移动开发 JavaScript 前端开发
ThreeJs搭建web3D场景
这篇文章讲解了如何使用Three.js来搭建web端的3D场景,并介绍了创建3D项目的基本要素。
74 1
|
7月前
|
JavaScript 前端开发 CDN
Threejs搭建web3D场景
这是一个基本的Three.js 3D场景的示例。你可以根据自己的需求添加更多的3D元素、纹理、光照和交互功能。
95 4
|
安全 图形学 数据安全/隐私保护
基于云服务器发布Web虚拟中药展厅
通过Unity3D结合3d建模技术,实现对学校的中药博物馆的虚拟重建,并且通过阿里云服务器将项目部署到云服务器。实践课题研究旨在学习虚拟博物馆的构建过程,对中医中药文化传播,虚拟博物馆建设具有中药意义。用户可通过访问Web的端的实现对学校博物馆的漫游交互,在一定程度上打破了实体博物馆的时间、空间、人员等的限制。
基于云服务器发布Web虚拟中药展厅
|
API 容器
2天赚了4个W,手把手教你用Threejs搭建一个Web3D汽车展厅!(上)
事情是这样的,前段时间外包工头老杨又来找我了,说某汽车大品牌要开发一个网页展厅,希望可以在网页里360度展示它家新款汽车的3d模型,还要可以让用户DIY汽车部件的颜色 嘿嘿,时间紧,预算多! 我心想报价四个W,再给他留点砍价空间, 谁知道老杨一口答应,还说完事要请我去XX人间 我猜他起码要从客户那赚10个W
709 0
2天赚了4个W,手把手教你用Threejs搭建一个Web3D汽车展厅!(上)
|
2月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
158 3
|
1月前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
169 45
|
15天前
|
前端开发 安全 JavaScript
2025年,Web3开发学习路线全指南
本文提供了一条针对Dapp应用开发的学习路线,涵盖了Web3领域的重要技术栈,如区块链基础、以太坊技术、Solidity编程、智能合约开发及安全、web3.js和ethers.js库的使用、Truffle框架等。文章首先分析了国内区块链企业的技术需求,随后详细介绍了每个技术点的学习资源和方法,旨在帮助初学者系统地掌握Dapp开发所需的知识和技能。
2025年,Web3开发学习路线全指南
|
22天前
|
存储 前端开发 JavaScript
如何在项目中高效地进行 Web 组件化开发
高效地进行 Web 组件化开发需要从多个方面入手,通过明确目标、合理规划、规范开发、加强测试等一系列措施,实现组件的高效管理和利用,从而提高项目的整体开发效率和质量,为用户提供更好的体验。
27 7
|
26天前
|
开发框架 搜索推荐 数据可视化
Django框架适合开发哪种类型的Web应用程序?
Django 框架凭借其强大的功能、稳定性和可扩展性,几乎可以适应各种类型的 Web 应用程序开发需求。无论是简单的网站还是复杂的企业级系统,Django 都能提供可靠的支持,帮助开发者快速构建高质量的应用。同时,其活跃的社区和丰富的资源也为开发者在项目实施过程中提供了有力的保障。
|
25天前
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
35 2