前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >用Three.js构建三维世界的房子

用Three.js构建三维世界的房子

作者头像
青年码农
发布于 2022-12-13 10:31:47
发布于 2022-12-13 10:31:47
2K00
代码可运行
举报
文章被收录于专栏:青年码农青年码农
运行总次数:0
代码可运行

文章篇幅会比较长,请耐心看完,但是一定会收货满满。

最近在学习Three.js,无奈不知道从哪里下手,查阅大部分资料都是先介绍渲染器(Renderer)、场景(Scene)、照相机(Camera),其实这些概念确实需要了解,如果不给你立体模型,你始终是无法理解的。网上看了一个大佬(神说要有光)的教程,感觉算是一只脚已经入了门,接下来我们通过这篇文章,从造物主的视角开始创建一个房子。我们先看下最终效果。

http://mpvideo.qpic.cn/0bc33maggaaawuagincjwvrvbw6dmpnqayya.f10002.mp4?

1 创造世界

很好理解,就是我们现在看到的世界,用Three.js做出来。效果如下

http://mpvideo.qpic.cn/0bc35iafqaaaceaishkirzrvb2wdldvaawaa.f10002.mp4? 首先对Three.js还是要了解其一些概念的,这样才能看的更明白。新建一个项目,引入Three.js,网上不好js找没关系,我会在最后提供本篇文章的完整demo。

创建场景
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 const scene = new THREE.Scene();
创建透视相机
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 获取窗口文档区域的宽度
const width = window.innerWidth;
// 获取窗口文档区域的高度
const height = window.innerHeight;
// 创建透视相机
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
// 相机位置
camera.position.set(500, 60, 0)
// 相机焦点方向
camera.lookAt(scene.position);
创建渲染器
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建WebGL渲染
const renderer = new THREE.WebGLRenderer();
// 设置canvas的大小
renderer.setSize(width, height);
//设置背景颜色
renderer.setClearColor(0xcce0ff, 1);
// 添加到body
document.body.appendChild(renderer.domElement);
渲染相机和场景
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 renderer.render(scene, camera);
 requestAnimationFrame(render)
场景贴图
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let urls = [
     './img/skyBox6/posx.jpg',
     './img/skyBox6/negx.jpg',
    './img/skyBox6/posy.jpg',
    './img/skyBox6/negy.jpg',
    './img/skyBox6/posz.jpg',
    './img/skyBox6/negz.jpg'
];
let cubeTexture = new THREE.CubeTextureLoader().load(urls);
scene.background = cubeTexture;

最终我们会看到上面的一个旋转的世界。

2 创建一个地面

上面的步骤只是创建了全景的世界,但是我们需要有个地面来放置我们之后要创建的房子,因此,这个地面要比较大。

创建

为了方便,我们新建一个方法来创建,后面只需要调用这个方法即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function createGrass() {
  // 创建一个平面缓冲几何体
  const geometry = new THREE.PlaneGeometry(10000, 10000);
  // 加载草地图片
  const texture = new THREE.TextureLoader().load("img/grass.jpg");
  texture.wrapS = THREE.RepeatWrapping;
  texture.wrapT = THREE.RepeatWrapping;
  // 纹理对象阵列
  texture.repeat.set(100, 100);
  // 基础网格材质
  const grassMaterial = new THREE.MeshBasicMaterial({ map: texture });
  // 网格
  const grass = new THREE.Mesh(geometry, grassMaterial);
  // 旋转
  grass.rotation.x = -0.5 * Math.PI;
  // 添加到场景
  scene.add(grass);
}

效果

3 建房子

我们先说说现实中如何新建房子 1 选一个地方当作地基 2 垒墙(墙面) 3 封顶(房顶) 其实用Threejs也是一样

创建地基(地板)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建地板方法
function createFloor() {
    // 创建一个平面缓冲几何体
    const geometry = new THREE.PlaneGeometry(200, 300);
    // 加载地板图片
    const texture = new THREE.TextureLoader().load('img/wood.jpg');
    texture.wrapS = THREE.RepeatWrapping;
    texture.wrapT = THREE.RepeatWrapping;
    // 纹理对象阵列
    texture.repeat.set(2, 2);
    // 基础网格材质
    const material = new THREE.MeshBasicMaterial({ map: texture });
    // 网格
    const floor = new THREE.Mesh(geometry, material);

    floor.rotation.x = -0.5 * Math.PI;
    floor.position.y = 1;
    floor.position.z = 150;
    // 地板添加到房间
    house.add(floor);
}
创建侧墙
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建测墙方法
function createSideWall() {
    // 创建形状
    const shape = new THREE.Shape();
    shape.moveTo(-100, 0);
    shape.lineTo(100, 0);
    shape.lineTo(100, 100);
    shape.lineTo(0, 150);
    shape.lineTo(-100, 100);
    shape.lineTo(-100, 0);
    // 挤压缓冲几何体
    const extrudeGeometry = new THREE.ExtrudeGeometry(shape, {
        depth: 5
    });
    // 加载墙面图片
    const texture = new THREE.TextureLoader().load('./img/wall.jpg');
    texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
    texture.repeat.set(0.01, 0.005);
    // 基础网格材质
    var material = new THREE.MeshBasicMaterial({ map: texture });
    // 网格
    const sideWall = new THREE.Mesh(extrudeGeometry, material);
    // 增加墙面
    house.add(sideWall);

    return sideWall;
}

侧墙有两个是一样的,只不过是位置(坐标)不一样,我们只需要挪下位置即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建侧墙
const sideWall2 = createSideWall();
// 侧墙向z轴移动
sideWall2.position.z = 295;
创建前面的墙

因为前面的墙上有门和窗户,因此我们单独创建

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 前面墙的方法
function createFrontWall() {
    // 创建形状
    const shape = new THREE.Shape();
    shape.moveTo(-150, 0);
    shape.lineTo(150, 0);
    shape.lineTo(150, 100);
    shape.lineTo(-150, 100);
    shape.lineTo(-150, 0);
    // 创建窗户
    const window = new THREE.Path();
    window.moveTo(30, 30)
    window.lineTo(80, 30)
    window.lineTo(80, 80)
    window.lineTo(30, 80);
    window.lineTo(30, 30);
    // 形状上的孔洞
    shape.holes.push(window);

    // 创建门
    const door = new THREE.Path();
    door.moveTo(-30, 0)
    door.lineTo(-30, 80)
    door.lineTo(-80, 80)
    door.lineTo(-80, 0);
    door.lineTo(-30, 0);
    // 形状上的孔洞
    shape.holes.push(door);
    // 挤压缓冲几何体
    const extrudeGeometry = new THREE.ExtrudeGeometry(shape, {
        depth: 5
    })
    // 贴图
    const texture = new THREE.TextureLoader().load('./img/wall.jpg');
    texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
    texture.repeat.set(0.01, 0.005);
    // 基础网格材质
    const material = new THREE.MeshBasicMaterial({ map: texture });
    // 网格
    const frontWall = new THREE.Mesh(extrudeGeometry, material);

    frontWall.position.z = 150;
    frontWall.position.x = 95;
    frontWall.rotation.y = Math.PI * 0.5;
    // 前墙添加到房间
    house.add(frontWall);
}

这样门和窗户就有了,我们还需要加点装饰

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 窗户修饰
function createWindow() {
    const shape = new THREE.Shape();
    shape.moveTo(0, 0);
    shape.lineTo(0, 50)
    shape.lineTo(50, 50)
    shape.lineTo(50, 0);
    shape.lineTo(0, 0);

    const hole = new THREE.Path();
    hole.moveTo(5, 5)
    hole.lineTo(5, 45)
    hole.lineTo(45, 45)
    hole.lineTo(45, 5);
    hole.lineTo(5, 5);
    shape.holes.push(hole);
    // 挤压缓冲几何体
    const extrudeGeometry = new THREE.ExtrudeGeometry(shape, {
        depth: 5
    });
    // 基础网格材质
    var extrudeMaterial = new THREE.MeshBasicMaterial({ color: 'silver' });

    var window = new THREE.Mesh(extrudeGeometry, extrudeMaterial);
    window.rotation.y = Math.PI / 2;
    window.position.y = 30;
    window.position.x = 95;
    window.position.z = 120;

    house.add(window);

    return window;
}
// 门修饰
function createDoor() {
    const shape = new THREE.Shape();
    shape.moveTo(0, 0);
    shape.lineTo(0, 80);
    shape.lineTo(50, 80);
    shape.lineTo(50, 0);
    shape.lineTo(0, 0);

    const hole = new THREE.Path();
    hole.moveTo(5, 5);
    hole.lineTo(5, 75);
    hole.lineTo(45, 75);
    hole.lineTo(45, 5);
    hole.lineTo(5, 5);
    shape.holes.push(hole);
    // 挤压缓冲几何体
    const extrudeGeometry = new THREE.ExtrudeGeometry(shape, {
        depth: 5
    });
    // 基础网格材质
    const material = new THREE.MeshBasicMaterial({ color: 'silver' });

    const door = new THREE.Mesh(extrudeGeometry, material);

    door.rotation.y = Math.PI / 2;
    door.position.y = 0;
    door.position.x = 95;
    door.position.z = 230;

    house.add(door);
}
创建后墙
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建后墙方法
function createBackWall() {
    // 创建形状
    const shape = new THREE.Shape();
    shape.moveTo(-150, 0)
    shape.lineTo(150, 0)
    shape.lineTo(150, 100)
    shape.lineTo(-150, 100);
    // 挤压缓冲几何体
    const extrudeGeometry = new THREE.ExtrudeGeometry(shape)
    // 贴图
    const texture = new THREE.TextureLoader().load('./img/wall.jpg');
    texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
    texture.repeat.set(0.01, 0.005);
    // 基础网格材质
    const material = new THREE.MeshBasicMaterial({ map: texture });
    // 网格
    const backWall = new THREE.Mesh(extrudeGeometry, material);

    backWall.position.z = 150;
    backWall.position.x = -100;
    backWall.rotation.y = Math.PI * 0.5;
    // 后墙添加到房间中
    house.add(backWall);
}
屋顶
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建屋顶方法
function createRoof() {
    // 立方缓冲几何体
    const geometry = new THREE.BoxGeometry(120, 320, 5);

    const texture = new THREE.TextureLoader().load('./img/tile.jpg');
    texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
    texture.repeat.set(5, 1);
    texture.rotation = Math.PI / 2;
    // 基础网格材质 - 瓦片
    const textureMaterial = new THREE.MeshBasicMaterial({ map: texture });
    // 基础网格材质 - 其他
    const colorMaterial = new THREE.MeshBasicMaterial({ color: 'grey' });

    const materials = [
        colorMaterial,
        colorMaterial,
        colorMaterial,
        colorMaterial,
        colorMaterial,
        textureMaterial
    ];

    const roof = new THREE.Mesh(geometry, materials);

    house.add(roof);

    roof.rotation.x = Math.PI / 2;
    roof.rotation.y = - Math.PI / 4 * 0.6;
    roof.position.y = 125;
    roof.position.x = 50;
    roof.position.z = 150;

    return roof;
}

屋顶也是有两个,只不过是空间上不一样,我们稍微调整下位置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const roof2 = createRoof();
roof2.rotation.x = Math.PI / 2;
roof2.rotation.y = (Math.PI / 4) * 0.6;
roof2.position.y = 125;
roof2.position.x = -50;
roof2.position.z = 150;
克隆

一个房子太单调,我们克隆几个

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// clone
const house1 = house.clone();
house1.position.set(300, 0, 0);
scene.add(house1);
// clone2
const house2 = house.clone();
house2.position.set(-300, 0, 0);
scene.add(house2);
// clone3
const house3 = house.clone();
house3.position.set(0, 0, -350);
scene.add(house3);

// clone4
const house4 = house.clone();
house4.position.set(300, 0, -350);
scene.add(house4);

// clone5
const house5 = house.clone();
house5.position.set(-300, 0, -350);
scene.add(house5);
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 青年码农 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
[1133]flink问题集锦
原因:flink1.8版本之后已弃用该参数,ResourceManager将自动启动所需的尽可能多的容器,以满足作业请求的并行性。解决方法:去掉即可
周小董
2022/04/28
4.4K0
[1133]flink问题集锦
flink-sql 流计算可视化 UI 平台
朋友多年自主研发的flink-sql 流计算可视化 UI 平台,细细品味一番确实很好用,做到真正的MSP(混合云场景)多数据多复用的情况实现,下面是这个产品的使用说明看看大家有没有使用场景。
怀朔
2022/05/29
2.3K0
flink-sql 流计算可视化 UI 平台
Caused by: java.net.ConnectException: Call From master/192.168.199.130 to master:9000 failed on conn
别先生
2018/01/02
1.5K0
Sqoop导入数据时异常java.net.ConnectException: Connection refused
java.net.ConnectException: Call From node4/192.168.179.143 to node4:8032 failed on connection exception: java.net.ConnectException: Connection refused; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused
时间静止不是简史
2020/07/24
1.9K0
【Hadoop学起来】分布式Hadoop的搭建(Ubuntu 17.04)
正文之前 作为一个以后肯定要做大数据的人,至今还没玩过Java 和 Hadoop 会不会被老师打死?所以就想着,在我的国外的云主机上搭建个Hadoop ,以后在 dell 电脑的ubuntu系统下也搭
用户1687088
2018/05/07
7780
【Hadoop学起来】分布式Hadoop的搭建(Ubuntu 17.04)
2.X版本的一个通病问题
对于配置了HA模式的RM或者NN,客户端如果向standby的节点发送请求,会因为不可连接或standby拒绝提供服务导致请求失败,转而向Active的节点发送请求,这个转换是hadoop客户端内部自动完成的,无须上层业务感知(本质上是向其中一个节点发送请求,如果失败则继续向另外一个节点发送请求)。
陈猿解码
2023/02/28
7800
2.X版本的一个通病问题
hbase_异常_05_End of File Exception between local host is: "rayner/127.0.1.1"; destination host is: "l
ERROR master.HMasterCommandLine: Master not running
shirayner
2018/08/10
2.1K0
一文讲透hdfs的delegation token
前一段时间总结了hadoop中的token认证、yarn任务运行中的token,其中也都提到了delegation token。而最近也遇到了一个问题,问题现象是:flink任务运行超过七天后,由于宿主机异常导致任务失败,继而触发任务的重试,但接连重试几次都是失败的,并且任务的日志也没有聚合,导致无法分析问题失败的原因。最后发现是和delegation token有关,本文就来总结下相关的原理。
陈猿解码
2023/02/28
2.1K3
一文讲透hdfs的delegation token
学习Spark——那些让你精疲力尽的坑
这一个月我都干了些什么…… 工作上,还是一如既往的写bug并不亦乐乎的修bug。学习上,最近看了一些非专业书籍,时常在公众号(JackieZheng)上写点小感悟,我刚稍稍瞄了下,最近五篇居然都跟技术无关,看来我与本行业已经是渐行渐远了。 所以,趁着这篇博客,重拾自己,认清自己,要时刻谨记我是一名码农。不过,摸着良心说,最近的技术方面也是有所感悟和积累的,比如如何写好设计文档,如何使用延时队列,如何使用防刷技术等等。当然了,今天我们还是沿着“学习Spark”这条路继续走下去。 上篇主要介绍了在Mac下如
JackieZheng
2018/01/16
2.3K0
学习Spark——那些让你精疲力尽的坑
超详细步骤!整合Apache Hudi + Flink + CDH
使用Idea打开Hudi项目,更改packging/hudi-flink-bundle的pom.xml文件,修改flink-bundle-shade-hive2 profile下的hive-version为chd6.3.0的版本
ApacheHudi
2021/11/19
3.7K0
超详细步骤!整合Apache Hudi + Flink + CDH
Flink在大规模状态数据集下的checkpoint调优
众所周知,Flink内部为了实现它的高可用性,实现了一套强大的checkpoint机制,还能保证作用的Exactly Once的快速恢复。对此,围绕checkpoint过程本身做了很多的工作。在官方文档中,也为用户解释了checkpoint的部分原理以及checkpoint在实际生产中(尤其是大规模状态集下)的checkpoint调优参数。笔者结合官方文档,给大家做个总结,也算是对Flink checkpoint机理的一个学习。
王知无-import_bigdata
2019/08/01
4.3K3
Flink在大规模状态数据集下的checkpoint调优
Hive 终于等来了 Flink
其实比较也没啥意义,不同社区发展的目标总是会有差异,而且 Flink 在真正的实时流计算方面投入的精力很多。不过笔者想表达的是,Apache Hive 已经成为数据仓库生态系统的焦点,它不仅是一个用于大数据分析和 ETL 的 SQL 引擎,也是一个数据管理平台,所以无论是 Spark,还是 Flink,或是 Impala、Presto 等,都会积极地支持集成 Hive 的功能。
Fayson
2020/02/10
2.6K0
Hive 终于等来了 Flink
Flink * 转
Flink on yarn 常见错误 1 Retrying connect to server 2 Unable to get ClusterClient status from Application Client 3 Cannot instantiate user function 4 Could not resolve substitution to a value: ${akka.stream.materializer} 5 java.lang.NoClassDefFoundError: org/
stys35
2019/03/05
3.4K0
hbase_异常_03_java.io.EOFException: Premature EOF: no length prefix available
更改了hadoop的配置文件:core-site.xml  和   mapred-site.xml  之后,重启hadoop 和 hbase 之后,发现hbase日志中抛出了如下异常:
shirayner
2018/08/10
4K0
如何通过Cloudera Manager配置Spark1和Spark2的运行环境
大部分用户在使用CDH集群做Spark开发的时候,由于开发环境的JDK版本比CDH集群默认使用的JDK1.7.0_67-cloudera版本新,可能会出现Spark代码依赖的Java API不兼容问题,解决这个问题方法有两个:一是升级CDH集群的JDK版本;二是指定Spark运行环境JDK版本。本文章主要讲述如何通过Cloudera Manager来指定Spark1和Spark2的运行环境(包含JDK环境、Spark Local Dir等的配置)。
Fayson
2018/03/29
3.2K0
如何通过Cloudera Manager配置Spark1和Spark2的运行环境
添加kerberos后,Flink任务的运行认证及各组件的认证
https://www.psvmc.cn/article/2022-11-08-bigdata-kerberos-centos.html
码客说
2023/08/11
1.6K0
第三篇:Centos7 Flink 1.12.2 on yarn 部署
http://192.168.123.156:8088/cluster/scheduler
文末丶
2021/12/27
9190
Flink问题汇总
将hadoop 3.2.1中自带的guava-27.0-jre.jar拷贝到flink的lib目录下即可。
从大数据到人工智能
2022/01/18
1K0
Flink问题汇总
Flink Yarn Cluster & HA
在一个企业中,为了最大化的利用集群资源,一般都会在一个集群中同时运行多种类型的 Workload。因此 Flink 也支持在 Yarn 上面运行。首先,让我们了解下 Yarn 和 Flink 的关系。
编程那点事
2023/02/25
9810
Flink Yarn Cluster & HA
【已解决】Flink连接JDBC报错 org.apache.flink.runtime.client.JobExecutionException: Job execution failed.
Flink1.13.6 MySQL5.7.27 JDK8 Hadoop3.1.4 集成环境Idea2020
火之高兴
2024/07/25
6010
【已解决】Flink连接JDBC报错 org.apache.flink.runtime.client.JobExecutionException: Job execution failed.
推荐阅读
相关推荐
[1133]flink问题集锦
更多 >
LV.0
这个人很懒,什么都没有留下~
目录
  • 1 创造世界
    • 创建场景
    • 创建透视相机
    • 创建渲染器
    • 渲染相机和场景
    • 场景贴图
  • 2 创建一个地面
    • 创建
  • 3 建房子
    • 创建地基(地板)
    • 创建侧墙
    • 创建前面的墙
    • 创建后墙
    • 屋顶
    • 克隆
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档