6. 盒子模型

  1 <template>
  2   <div class="badylon-canvas2">
  3     <canvas ref="renderCanvas2" id="render-canvas2"></canvas>
  4   </div>
  5 </template>
  6 
  7 <script setup lang="ts">
  8 import * as BABYLON from "babylonjs";
  9 import "babylonjs-loaders";
 10 import Assets from "../../utils/babylon/babylon-asset.js";
 11 import type { Engine, Scene } from "babylonjs";
 12 import { ref, onMounted } from "vue";
 13 
 14 type EngineType = Engine | null;
 15 type SceneType = Scene | null;
 16 
 17 const renderCanvas2 = ref<HTMLCanvasElement | null>(null);
 18 let engine: EngineType = null;
 19 let scene: SceneType = null;
 20 let sceneToRender: SceneType = null;
 21 
 22 // 渲染循环
 23 function startRenderLoop(engine: Engine) {
 24   /**
 25    * runRenderLoop(renderFunction: (() => void)): void
 26    * 注册并执行一个渲染循环。引擎可以有多个渲染函数
 27    * renderFunction: (() => void) --- 定义要持续执行的函数(不停的执行)
 28    */
 29   engine.runRenderLoop(() => {
 30     console.log("runRenderLoop...");
 31     // 如果没有runRenderLoop函数,就无法在移动图像时更新“相机”的数据,简单来说就是图像不会动了。
 32     if (sceneToRender && sceneToRender.activeCamera) {
 33       /**
 34        * render(updateCameras?: boolean, ignoreAnimations?: boolean): void
 35        * updateCameras: 定义一个布尔值,指示摄像机是否必须根据其输入进行更新(默认为true)
 36        *  ignoreAnimations: 定义一个布尔值,指示动画是否不应该执行(默认为false)
 37        */
 38       sceneToRender.render(); // 如果没有这个不会出现图像;渲染scene
 39     }
 40   });
 41 }
 42 
 43 // 创建场景
 44 function createScene() {
 45   if (engine === null) return null;
 46 
 47   /**
 48    * new Scene(engine: Engine, options?: SceneOptions): Scene
 49    * 表示要由引擎渲染的场景。
 50    * engine: Engine --- 定义用于渲染此场景的引擎
 51    * options: 可选; https://doc.babylonjs.com/typedoc/interfaces/BABYLON.SceneOptions
 52    *
 53    */
 54   const scene = new BABYLON.Scene(engine);
 55 
 56   /**
 57    * new ArcRotateCamera(name: string, alpha: number, beta: number, radius: number, target: Vector3, scene?: Scene, setActiveOnSceneIfNoneActive?: boolean): ArcRotateCamera
 58    *   在给定的场景中实例化一个新的ArcRotateCamera
 59    * name: 名字
 60    * alpha: 定义相机沿纵向轴的旋转---一开始显示的角度
 61    * beta: 定义相机沿纬度轴的旋转---一开始显示的角度
 62    * radius: 定义相机与目标的距离
 63    * target: Vector3 // 控制相机的视角
 64    * setActiveOnSceneIfNoneActive: 定义如果未定义其他活动相机,则是否应将该相机标记为活动的
 65    *
 66    * new Tools(): Tools
 67    *  ToRadians(angle: number): number
 68    *    将角度的角度转换为弧度
 69    */
 70   const camera = new BABYLON.ArcRotateCamera(
 71     "camera",
 72     -Math.PI / 2,
 73     Math.PI / 2.5,
 74     3,
 75     new BABYLON.Vector3(0, 0, 0),
 76     scene
 77   );
 78   // https://doc.babylonjs.com/typedoc/classes/BABYLON.ArcRotateCamera#constructor
 79   camera.attachControl(renderCanvas2.value, true);
 80 
 81   /**
 82    * new HemisphericLight(name: string, direction: Vector3, scene: Scene): HemisphericLight
 83    * 根据传递的方向(Vector3)在场景中创建一个半球光对象。
 84     半球光模拟周围环境光,所以通过的方向是光的反射方向,而不是入射方向。
 85     半球光不能投射阴影。
 86    */
 87 
 88   /**
 89    * name: 灯光的名字
 90    * direction: 光反射的方向
 91    * scene: 灯光所属的场景
 92    */
 93   const light = new BABYLON.HemisphericLight(
 94     "light",
 95     /**
 96      * new Vector3(x?: number, y?: number, z?: number): Vector3
 97      * 从给定的x, y, z (float)坐标创建一个新的Vector3对象。三维向量
 98      * x: number; 定义第一个坐标(在X轴上)
 99      * y: number
100      * z: number
101      */
102     new BABYLON.Vector3(0, 1, 0),
103     scene
104   );
105 
106   /**
107    * 光的强度。
108     注意:默认情况下它是在框架自己的单元中定义的。
109     注:在PBR材料中,intensityMode可用于选择强度的定义单位。
110    */
111   light.intensity = 0.7;
112 
113   const box = BABYLON.MeshBuilder.CreateBox("box", {});
114 
115   return scene;
116 }
117 
118 function createDefaultEngine() {
119   /**
120    * new Engine(canvas, antialias, options, adaptToDeviceRatio) 创建一个引擎
121    * canvas: 现实容器,可以是Canvas标签...
122    * antialias: boolean, 默认是false,启动后可以防止图像出现“锯齿”
123    * optiosn: 选项,
124    *    adaptToDeviceRatio: false, // 定义是否适应设备的视口特征
125         audioEngine: false, // 定义是否也应该初始化webaudio
126         audioEngineOptions: {}, // 指定音频引擎的选项
127         autoEnableWebVR: false, // 定义是否应该自动启用webvr
128         deterministicLockstep: false, // 定义动画是否应该使用确定性锁定步骤运行
129    *    adaptoToDeviceRatio: boolean,默认false;定义是否适应视口
130         ....
131         https://doc.babylonjs.com/typedoc/interfaces/BABYLON.EngineOptions
132    */
133   return new BABYLON.Engine(renderCanvas2.value, true, {});
134 }
135 
136 async function initFunction() {
137   async function asyncEngineCreation() {
138     try {
139       return createDefaultEngine(); // 先创建容器
140     } catch (e) {
141       console.log(
142         "the available createEngine function failed. Creating the default engine instead"
143       );
144 
145       return createDefaultEngine();
146     }
147   }
148 
149   engine = await asyncEngineCreation(); // 先创建容器
150   if (!engine) throw "engine should not be null.";
151   startRenderLoop(engine); // 如果没有这个不会出现图像
152   scene = createScene(); // 再创建渲染场景
153   // 创建容器 ---> 再创建渲染场景放进容器 ---> 再创建"相机","灯光","球体","地面"放进场景
154   scene && scene.render();
155 }
156 
157 onMounted(() => {
158   if (renderCanvas2.value) {
159     console.log("ttttt");
160     initFunction().then(() => {
161       sceneToRender = scene;
162     });
163 
164     // Resize
165     window.addEventListener("resize", function () {
166       engine && engine.resize();
167     });
168   }
169 });
170 </script>
171 
172 <style lang="scss" scoped>
173 .badylon-canvas2 {
174   width: 100%;
175   height: 100%;
176 
177   #render-canvas2 {
178     width: 100%;
179     height: 100%;
180     // touch-action 用在触摸屏,缩放
181     touch-action: none;
182   }
183 }
184 </style>

 

posted @ 2022-10-18 15:39  sky-su  阅读(42)  评论(0)    收藏  举报