• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import scene3d from '@ohos.graphics.scene'
17import router from '@ohos.router';
18import Logger from '../util/Logger';
19
20let fovFlag: number = 0;
21let enabledFlag: number = 0;
22let TonemapTypeFlag: number = 0;
23let clearColorFlag: number = 0;
24
25@Entry
26@Component
27struct nodeCamera {
28  scene: scene3d.Scene | null = null;
29  @State sceneOpt: SceneOptions | null = null;
30  cam: scene3d.Camera | null = null;
31  @State nearPlaneValue: number = 0.1;
32  @State farPlaneValue: number = 100;
33  @State tonemapExposure: number = 1;
34
35  onPageShow(): void {
36    this.init();
37  }
38
39  onPageHide(): void {
40    if (this.scene) {
41      this.scene.destroy();
42    }
43
44    this.cam = null;
45    this.scene = null;
46  }
47
48  init(): void {
49    if (this.scene === null) {
50      scene3d.Scene.load($rawfile("gltf/DamagedHelmet/glTF/DamagedHelmet.glb"))
51        .then(async (result: scene3d.Scene) => {
52          this.scene = result;
53          this.sceneOpt = { scene: this.scene, modelType: ModelType.SURFACE } as SceneOptions;
54          let rf: scene3d.SceneResourceFactory = this.scene.getResourceFactory();
55          this.cam = await rf.createCamera({ "name": "Camera1" });
56          this.cam.position.z = 5;  // move camera to position 5 on z
57          this.cam.enabled = true;
58          this.cam.postProcess = {
59            toneMapping: {
60              type: scene3d.ToneMappingType.ACES,
61              exposure: 1.0,
62            } as scene3d.ToneMappingSettings
63          }
64          let env = await rf.createEnvironment({ "name": "Env" });
65          this.scene.environment.backgroundType = scene3d.EnvironmentBackgroundType.BACKGROUND_NONE;
66        })
67        .catch((reason: string) => {
68          Logger.error("init error", reason);
69        });
70    }
71  }
72
73  build() {
74    Row() {
75      Column() {
76        Stack() {
77          Text('HELLO WORLD').height('100%').width('100%').backgroundColor(Color.Green)
78
79          if (this.sceneOpt) {
80            Component3D(this.sceneOpt)
81              .renderWidth('60%')
82              .renderHeight('60%')
83              .backgroundColor(Color.Transparent)
84              .width("90%")
85              .height('100%')
86          }
87          else {
88            Text("loading 1...");
89          }
90        }
91        .height('30%')
92
93        Button('change fov').onClick(() => {
94          if (!this.scene || !this.cam) {
95            return;
96          }
97          const RADIAN: number = Math.PI / 180;
98          const FOV_COUNT: number = 3;
99          const FOV_0: number = 0;
100          const FOV_1: number = 1;
101          const FOV_2: number = 2;
102          fovFlag = ++fovFlag % FOV_COUNT;
103          if (fovFlag === FOV_0) {
104            let degree = 60; // 60 degree
105            this.cam.fov = degree *RADIAN;
106          }
107          else if (fovFlag === FOV_1) {
108            let degree = 90; // 90 degree
109            this.cam.fov = degree * RADIAN;
110          }
111          else if (fovFlag === FOV_2) {
112            let degree = 45; // 45 degree
113            this.cam.fov = degree * RADIAN;
114          }
115        }).id('change_fov');
116
117        Column() {
118          Text("nearPlane: " + this.nearPlaneValue.toFixed(1)).fontSize(12)
119          Slider({
120            value: this.nearPlaneValue,
121            min: 0.1, // near plane min
122            max: 10, // near plane far
123            step: 0.1, // step
124            style: SliderStyle.OutSet
125          })
126            .showTips(false)
127            .onChange((value: number, mode: SliderChangeMode) => {
128              this.nearPlaneValue = value;
129              if (mode === SliderChangeMode.End) {
130                if (!this.scene || !this.cam) {
131                  return;
132                }
133                this.cam.nearPlane = value;
134              }
135            })
136            .width("100%")
137        }
138        .alignItems(HorizontalAlign.Start)
139        .width('100%')
140
141        Column() {
142          Text("farPlane: " + this.farPlaneValue.toFixed(1)).fontSize(12)
143          Slider({
144            value: this.farPlaneValue,
145            min: 0.1, // far plane min
146            max: 100, // far plane max
147            step: 1, // step
148            style: SliderStyle.OutSet
149          })
150            .showTips(false)
151            .onChange((value: number, mode: SliderChangeMode) => {
152              this.farPlaneValue = value;
153              if (mode === SliderChangeMode.End) {
154                if (!this.scene || !this.cam) {
155                  return;
156                }
157                this.cam.farPlane = value;
158              }
159            })
160            .width("100%")
161        }
162        .alignItems(HorizontalAlign.Start)
163        .width('100%')
164
165        Button('enabled').onClick(() => {
166          if (!this.scene || !this.cam) {
167            return;
168          }
169          this.cam.enabled = !this.cam.enabled;
170        }).id('camera_enabled');
171
172        Button('Change Tonemap Type').onClick(() => {
173          if (!this.scene || !this.cam || !this.cam.postProcess || !this.cam.postProcess.toneMapping) {
174            return;
175          }
176          let type: scene3d.ToneMappingType = scene3d.ToneMappingType.ACES;
177          const TONE_MAPPING_COUNT: number = 3;
178          const TONE_MAPPING_0: number = 0;
179          const TONE_MAPPING_1: number = 1;
180          const TONE_MAPPING_2: number = 2;
181          TonemapTypeFlag = ++TonemapTypeFlag % TONE_MAPPING_COUNT;
182          if (TonemapTypeFlag === TONE_MAPPING_0) {
183            type = scene3d.ToneMappingType.ACES;
184          } else if (TonemapTypeFlag === TONE_MAPPING_1) {
185            type = scene3d.ToneMappingType.ACES_2020;
186          } else if (TonemapTypeFlag === TONE_MAPPING_2) {
187            type = scene3d.ToneMappingType.FILMIC;
188          }
189          this.cam.postProcess = {
190            toneMapping: {
191              exposure: this.cam.postProcess.toneMapping.exposure,
192              type: type
193            }
194          };
195        }).id('change_tonemapping');
196
197        Column() {
198          Text("Tonemap Exposure: " + this.tonemapExposure.toFixed(1)).fontSize(12)
199          Slider({
200            value: this.tonemapExposure,
201            min: 0, // tone mapping exposure min
202            max: 10, // tone mapping exposure max
203            step: 0.1, // tone mapping exposure step
204            style: SliderStyle.OutSet
205          })
206            .showTips(false)
207            .onChange((value: number, mode: SliderChangeMode) => {
208              this.tonemapExposure = value;
209              if (mode === SliderChangeMode.End) {
210                if (!this.scene || !this.cam || !this.cam.postProcess || !this.cam.postProcess.toneMapping) {
211                  return;
212                }
213                this.cam.postProcess = {
214                  toneMapping: {
215                    exposure: value,
216                    type: this.cam.postProcess.toneMapping.type
217                  }
218                }
219              }
220            })
221            .width("100%")
222        }
223        .alignItems(HorizontalAlign.Start)
224        .width('100%')
225
226        Button('set clearColor').onClick(() => {
227          if (!this.scene || !this.cam) {
228            return;
229          }
230          const CLEAR_COLOR_COUNT: number = 3;
231          const CLEAR_COLOR_0: number = 0;
232          const CLEAR_COLOR_1: number = 1;
233          const CLEAR_COLOR_2: number = 2;
234
235          clearColorFlag = ++clearColorFlag % CLEAR_COLOR_COUNT;
236          if (clearColorFlag === CLEAR_COLOR_0) {
237            this.cam.clearColor = null;
238          }
239          else if (clearColorFlag === CLEAR_COLOR_1) {
240            this.cam.clearColor = { r: 0, g: 0, b: 0, a: 0.0 };
241          }
242          else if (clearColorFlag === CLEAR_COLOR_2) {
243            this.cam.clearColor = { r: 1, g: 0, b: 0, a: 1 };
244          }
245        }).id('clear_color');
246
247        Button('back').onClick(() => {
248          router.back()
249        }).id('camera_back')
250      }
251      .width('100%')
252    }
253    .height('100%')
254  }
255}