babylon.js 学习笔记(4)
按上回继续,上节知道了如何用 『方块+三棱柱+贴图』结合起来,画一个简单的小房子,实际应用中可以把这3个打包在一起,组成1个house对象,这样更方便一些
const buildHouse = () => {
const box1 = buildBox();
const roof1 = buildRoof();
const house1 = BABYLON.Mesh.MergeMeshes([box1, roof1]);
house1.position.x = -0.4;
const box2 = buildBox();
const roof2 = buildRoof();
const house2 = BABYLON.Mesh.MergeMeshes([roof2, box2]);
house2.position.x = 0.4;
return [house1, house2];
}
关键在于BABYLON.Mesh.MergeMeshes 这个方法,可以把几个mesh对象组合成1个新mesh对象,来看看效果:

在线地址:https://yjmyzz.github.io/babylon_js_study/day04/01.html
贴图效果并不符合预期,[obj1, obj2...] 最终排在第1个位置的对象,其贴图应用到了整个对象上。好在MergeMeshes方法,还有其它扩展参数,其完整方法签名如下:
改成这样就可以了:
const buildHouse = () => {
const box = buildBox();
const roof = buildRoof();
//将box与roof组合
// MergeMeshes(meshes: Mesh[], disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean, multiMultiMaterials?: boolean): Nullable<Mesh>
return BABYLON.Mesh.MergeMeshes([box, roof], true, false, null, true, true);
}

在线地址:https://yjmyzz.github.io/babylon_js_study/day04/02.html
在进入下面的内容前,先把代码再整理下:
//创建屋顶
const buildRoof = (width) => {
const roofMat = new BABYLON.StandardMaterial("roofMat");
roofMat.diffuseTexture = new BABYLON.Texture("../assets/img/roof.jpg");
const roof = BABYLON.MeshBuilder.CreateCylinder("roof", { diameter: 0.7, height: 0.6, tessellation: 3 });
roof.scaling.x = 0.75;
roof.scaling.y = width;
roof.rotation.z = Math.PI / 2;
roof.position.y = 0.63;
roof.material = roofMat;
return roof;
} //创建屋身
const buildBox = (width) => {
const boxMat = new BABYLON.StandardMaterial("boxMat"); const faceUV = [];
if (width == 1) {
boxMat.diffuseTexture = new BABYLON.Texture("../assets/img/cubehouse.png")
faceUV[0] = new BABYLON.Vector4(0.5, 0.0, 0.75, 1.0); //后面
faceUV[1] = new BABYLON.Vector4(0.0, 0.0, 0.25, 1.0); //前面
faceUV[2] = new BABYLON.Vector4(0.25, 0, 0.5, 1.0); //右面
faceUV[3] = new BABYLON.Vector4(0.75, 0, 1.0, 1.0); //左面
}
else {
boxMat.diffuseTexture = new BABYLON.Texture("../assets/img/semihouse.png")
faceUV[0] = new BABYLON.Vector4(0.6, 0.0, 1.0, 1.0); //后面
faceUV[1] = new BABYLON.Vector4(0.0, 0.0, 0.4, 1.0); //前面
faceUV[2] = new BABYLON.Vector4(0.4, 0, 0.6, 1.0); //右面
faceUV[3] = new BABYLON.Vector4(0.4, 0, 0.6, 1.0); //左面
} const box = BABYLON.MeshBuilder.CreateBox("box", { size: 0.5, width: 0.5 * width, faceUV: faceUV, wrap: true });
box.material = boxMat;
box.position.y = 0.25; return box;
} //根据传入的参数width,生成2种不同风格的房屋
const buildHouse = (width) => {
const box = buildBox(width);
const roof = buildRoof(width);
return BABYLON.Mesh.MergeMeshes([box, roof], true, false, null, true, true);
} //在这里添加自己的核心代码
const createScene = function () {
const scene = new BABYLON.Scene(engine); const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 3, new BABYLON.Vector3(0, 0, 0));
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0.5, 0.5, 0)); const ground = buildGround(); //创建房子
const house1 = buildHouse(1);
const house2 = buildHouse(2); house1.position.x = -0.5
house2.position.x = 0.5 return scene;
};
这样buildHouse(width)方法,根据width值的不同,可以生成2种不同风格的房屋

在线地址:https://yjmyzz.github.io/babylon_js_study/day04/03.html
接下来,我们画1片住宅区(也就是要有一堆房屋),这里就要用到createInstance 这个方法:
//创建一片住宅区
const buildDwellings = () => {
const ground = buildGround(); const detached_house = buildHouse(1);
detached_house.rotation.y = -Math.PI / 16;
detached_house.position.x = -6.8;
detached_house.position.z = 2.5; const semi_house = buildHouse(2);
semi_house.rotation.y = -Math.PI / 16;
semi_house.position.x = -4.5;
semi_house.position.z = 3; //定义房子的[风格/位置]列表 [house type, rotation, x, z]
const places = [];
places.push([1, -Math.PI / 16, -6.8, 2.5]);
places.push([2, -Math.PI / 16, -4.5, 3]);
places.push([2, -Math.PI / 16, -1.5, 4]);
places.push([2, -Math.PI / 3, 1.5, 6]);
places.push([2, 15 * Math.PI / 16, -6.4, -1.5]);
places.push([1, 15 * Math.PI / 16, -4.1, -1]);
places.push([2, 15 * Math.PI / 16, -2.1, -0.5]);
places.push([1, 5 * Math.PI / 4, 0, -1]);
places.push([1, Math.PI + Math.PI / 2.5, 0.5, -3]);
places.push([2, Math.PI + Math.PI / 2.1, 0.75, -5]);
places.push([1, Math.PI + Math.PI / 2.25, 0.75, -7]);
places.push([2, Math.PI / 1.9, 4.75, -1]);
places.push([1, Math.PI / 1.95, 4.5, -3]);
places.push([2, Math.PI / 1.9, 4.75, -5]);
places.push([1, Math.PI / 1.9, 4.75, -7]);
places.push([2, -Math.PI / 3, 5.25, 2]);
places.push([1, -Math.PI / 3, 6, 4]); //根据places建一堆房子
const houses = [];
for (let i = 0; i < places.length; i++) {
if (places[i][0] === 1) {
houses[i] = detached_house.createInstance("house" + i);
}
else {
houses[i] = semi_house.createInstance("house" + i);
}
houses[i].rotation.y = places[i][1];
houses[i].position.x = places[i][2];
houses[i].position.z = places[i][3];
}
}

在线地址:https://yjmyzz.github.io/babylon_js_study/day04/04.html
可以借助playground把这片住宅区的所有对象都导出,方便后续复用,也能简化代码,参考下图:

代码可以简化为:
BABYLON.SceneLoader.ImportMeshAsync("", "../assets/glb/", "village.glb");
注意glb的目录位置,参考下图:

前面我们还学习过,可以直接用<babylon />将model嵌入网页:
<div id="renderCanvas">
<h1>Village(import glb to page)</h1>
<babylon model="../assets/glb/village.glb"></babylon>
</div>

在线地址:https://yjmyzz.github.io/babylon_js_study/day04/06.html
发现1个问题:绿色的ground一直在不停闪烁。要解决这个问题,可以加上extends="minimal"
<babylon model="../assets/glb/village.glb" extends="minimal"></babylon>
这回到是不闪了,但是页面刚打开时,摄像机的视角比较奇怪,参考下图:

在线地址:https://yjmyzz.github.io/babylon_js_study/day04/07.html
可以再加一段脚本校正:
<div id="renderCanvas">
<h1>Village(import glb to page)</h1>
<babylon extends="minimal" id="myViewer"></babylon>
</div> <script>
BabylonViewer.viewerManager.getViewerPromiseById('myViewer').then((viewer) => {
viewer.onSceneInitObservable.add(() => {
viewer.sceneManager.camera.radius = 15;
viewer.sceneManager.camera.beta = Math.PI / 2.2;
});
viewer.onEngineInitObservable.add((scene) => {
viewer.loadModel({
url: "../assets/glb/village.glb"
});
});
});
</script>
效果如下:

在线地址:https://yjmyzz.github.io/babylon_js_study/day04/08.html
参考文档:
https://doc.babylonjs.com/features/introductionToFeatures/chap2/copies
https://doc.babylonjs.com/features/introductionToFeatures/chap2/viewer2
babylon.js 学习笔记(4)的更多相关文章
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- Vue.js学习笔记(2)vue-router
vue中vue-router的使用:
- JS 学习笔记--9---变量-作用域-内存相关
JS 中变量和其它语言中变量最大的区别就是,JS 是松散型语言,决定了它只是在某一个特定时间保存某一特定的值的一个名字而已.由于在定义变量的时候不需要显示规定必须保存某种类型的值,故变量的值以及保存的 ...
- WebGL three.js学习笔记 使用粒子系统模拟时空隧道(虫洞)
WebGL three.js学习笔记 使用粒子系统模拟时空隧道 本例的运行结果如图: 时空隧道demo演示 Demo地址:https://nsytsqdtn.github.io/demo/sprite ...
- WebGL three.js学习笔记 法向量网格材质MeshNormalMaterial的介绍和创建360度全景天空盒的方法
WebGL学习----Three.js学习笔记(5) 点击查看demo演示 Demo地址:https://nsytsqdtn.github.io/demo/360/360 简单网格材质 MeshNor ...
- WebGL three.js学习笔记 创建three.js代码的基本框架
WebGL学习----Three.js学习笔记(1) webgl介绍 WebGL是一种3D绘图协议,它把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的 ...
- vue.js 学习笔记3——TypeScript
目录 vue.js 学习笔记3--TypeScript 工具 基础类型 数组 元组 枚举 字面量 接口 类类型 类类型要素 函数 函数参数 this对象和类型 重载 迭代器 Symbol.iterat ...
- 2019-4-29 js学习笔记
js学习笔记一:js数据类型 1:基本数据类型 number类型(整数,小数) String类型 boolean类型 NaN类型其实是一个nu ...
- 一点感悟:《Node.js学习笔记》star数突破1000+
写作背景 笔者前年开始撰写的<Node.js学习笔记> github star 数突破了1000,算是个里程碑吧. 从第一次提交(2016.11.03)到现在,1年半过去了.突然有些感慨, ...
- JS学习笔记5_DOM
1.DOM节点的常用属性(所有节点都支持) nodeType:元素1,属性2,文本3 nodeName:元素标签名的大写形式 nodeValue:元素节点为null,文本节点为文本内容,属性节点为属性 ...
随机推荐
- Java编程--多例设计模式
多例设计模式 多例设计模式(Multiton Pattern),有时也被称为对象池(Object Pool)模式,是一种创建型设计模式.与单例模式不同,多例模式允许创建并管理多个实例,每个实例都有一个 ...
- Ubuntu 中通过源码安装 Python3.x 环境
最近在个人前后端分离项目时候, 后端接口程序 fastapi, 在部署的时候, 需要 Pyhton3.8 以上的环境, 但 ubuntu 默认的是 2.7 于是想通过源码安装的方式进行环境搭建. 下载 ...
- React错误边界:原理、实现与应用
@charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...
- 全网资源无水印下载!支持抖音、视频号、小红书等,Rubik下载介绍
在日常生活和工作中,我们经常要用到一些优质的影音或图片素材,然而,随着各种平台的限制越来越多,不是需要付费订阅后才能下载,就是完全不提供下载渠道,想要找到一个广泛又好用的下载工具变得格外困难 Rubi ...
- ubuntu20.04下VSCode无法输入中文解决方法
解决方法:重新安装VSCode. 我一开始是在ubuntu商店下载的,结果上网查了了下,商店里的VSCode是阉割版的,想要输入中文就要重新安装. 安装流程:先删除再安装. 1.可以在商店里已安装界面 ...
- System.Runtime.Serialization.SerializationException:“二进制流“0”不包含有效的 BinaryHeader。这可能是由于无效流,或由于在序列化和反序列化之间的对象版本更改。
var buffer = new byte[1024]; using (var ms = new MemoryStream(buffer)) { //xxx } 原因是buffer的长度过短,当接受到 ...
- ListBox横向排布Item
<Window x:Class="TwoColumnListBox.MainWindow" xmlns="http://schemas.microsoft.com/ ...
- 安装Scikit-learn 0.24.2版本
安装Scikit-learn 0.24.2版本 Anaconda 安装scikit-learn是0.19版本,目前最新版本是0.24.2,之前的版本与现在的版本之间差距还是比较大,因此有必要对scik ...
- Java线程状态和状态切换
背景 先来探讨一个关于多线程的基础知识:java线程有多少种状态?根据JDK定义,答案是六种!为什么很多人给出的答案却是五种呢?这极有可能是将操作系统层面的线程状态和Java线程状态混为一谈了.因 ...
- CSP-S 2020全国开放赛前冲刺模拟训练题1信友队集训队员周镇东出题 小结
题目&官方题解下载 我的题解 CSP-S 2020模拟训练题1-信友队T1 四平方和 CSP-S 2020模拟训练题1-信友队T2 挑战NPC 我仍未看懂那天所看到的T3的题解 CSP-S 2 ...