ohzi-core 5.18.2 → 5.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ohzi-core",
3
- "version": "5.18.2",
3
+ "version": "5.21.0",
4
4
  "description": "OHZI Core Library",
5
5
  "module": "build/index.module.js",
6
6
  "source": "src/index.js",
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "homepage": "https://github.com/ohzinteractive/core#readme",
42
42
  "dependencies": {
43
- "pit-js": "1.5.2",
43
+ "pit-js": "1.7.0",
44
44
  "three": "^0.134.0"
45
45
  },
46
46
  "devDependencies": {
@@ -17,4 +17,7 @@ export default class BaseApplication
17
17
 
18
18
  on_pre_render()
19
19
  {}
20
+
21
+ on_frame_end()
22
+ {}
20
23
  }
package/src/Graphics.js CHANGED
@@ -32,7 +32,7 @@ class Graphics
32
32
  stencil: false,
33
33
  antialias: false,
34
34
  premultipliedAlpha: true,
35
- preserveDrawingBuffer: true,
35
+ preserveDrawingBuffer: false,
36
36
  powerPreference: 'high-performance',
37
37
  logarithmicDepthBuffer: false
38
38
  };
@@ -51,7 +51,7 @@ class Graphics
51
51
 
52
52
  this.is_webgl2 = this.canvas_context.constructor.name === 'WebGL2RenderingContext';
53
53
 
54
- console.log(`Using WebGL ${this.is_webgl2 ? 2 : 1}`);
54
+ // console.log(`Using WebGL ${this.is_webgl2 ? 2 : 1}`);
55
55
 
56
56
  this._renderer = new WebGLRenderer({
57
57
  canvas: canvas,
@@ -82,6 +82,9 @@ class Graphics
82
82
  this.generateDepthNormalTexture = false;
83
83
 
84
84
  this.depth_and_normals_renderer = new DepthAndNormalsRenderer();
85
+
86
+ this.resize_observer = new ResizeObserver(this.on_resize.bind(this));
87
+ this.resize_observer.observe(this.canvas);
85
88
  }
86
89
 
87
90
  get dom_element()
@@ -105,8 +108,6 @@ class Graphics
105
108
 
106
109
  update()
107
110
  {
108
- this.check_for_resize();
109
-
110
111
  if (this.generateDepthNormalTexture)
111
112
  {
112
113
  this.depth_and_normals_renderer.render(this);
@@ -196,22 +197,13 @@ class Graphics
196
197
  !!clear_stencil);
197
198
  }
198
199
 
199
- check_for_resize()
200
+ on_resize(entries)
200
201
  {
201
- let current_width = this.canvas.clientWidth;
202
- let current_height = this.canvas.clientHeight;
203
-
204
- if (
205
- current_width !== Screen.width ||
206
- current_height !== Screen.height ||
207
- Configuration.dpr !== Screen.dpr
208
- )
202
+ for (let entry of entries)
209
203
  {
210
- let canvas_rect = this.canvas.getBoundingClientRect();
211
-
212
204
  Screen.dpr = Configuration.dpr;
213
- Screen.update_position(canvas_rect.x, canvas_rect.y);
214
- Screen.update_size(current_width, current_height);
205
+ Screen.update_position(entry.contentRect.x, entry.contentRect.y);
206
+ Screen.update_size(entry.contentRect.width, entry.contentRect.height);
215
207
 
216
208
  this.canvas.width = Screen.render_width;
217
209
  this.canvas.height = Screen.render_height;
@@ -222,11 +214,6 @@ class Graphics
222
214
  }
223
215
  }
224
216
 
225
- on_resize()
226
- {
227
- console.error('Graphics.on_resize call no longer needed.');
228
- }
229
-
230
217
  material_pass(mat, dst)
231
218
  {
232
219
  this.blitter.material_pass(mat, dst);
package/src/OS.js CHANGED
@@ -10,6 +10,15 @@ class OS
10
10
  MAC: 'mac',
11
11
  WINDOWS: 'windows'
12
12
  };
13
+
14
+ this.is_mobile = !!(navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/));
15
+ this.is_ipad = !!(navigator.userAgent.match(/Mac/) && navigator.maxTouchPoints && navigator.maxTouchPoints > 2);
16
+ this.is_ios = !!navigator.userAgent.match(/(iPhone|iPod|iPad)/) || this.is_ipad;
17
+
18
+ this.is_android = this.get_os() === this.operating_systems.ANDROID;
19
+ this.is_linux = this.get_os() === this.operating_systems.LINUX;
20
+ this.is_mac = this.get_os() === this.operating_systems.MAC;
21
+ this.is_windows = this.get_os() === this.operating_systems.WINDOWS;
13
22
  }
14
23
 
15
24
  get_os()
@@ -44,41 +53,6 @@ class OS
44
53
 
45
54
  return os;
46
55
  }
47
-
48
- get is_android()
49
- {
50
- return this.get_os() === this.operating_systems.ANDROID;
51
- }
52
-
53
- get is_ios()
54
- {
55
- return navigator.userAgent.match(/(iPhone|iPod|iPad)/) || this.is_ipad;
56
- }
57
-
58
- get is_ipad()
59
- {
60
- return (navigator.userAgent.match(/Mac/) && navigator.maxTouchPoints && navigator.maxTouchPoints > 2);
61
- }
62
-
63
- get is_mobile()
64
- {
65
- return !!(navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/));
66
- }
67
-
68
- get is_linux()
69
- {
70
- return this.get_os() === this.operating_systems.LINUX;
71
- }
72
-
73
- get is_mac()
74
- {
75
- return this.get_os() === this.operating_systems.MAC;
76
- }
77
-
78
- get is_windows()
79
- {
80
- return this.get_os() === this.operating_systems.WINDOWS;
81
- }
82
56
  }
83
57
 
84
58
  export default new OS();
package/src/RenderLoop.js CHANGED
@@ -49,20 +49,20 @@ export default class RenderLoop
49
49
  Debug.render(this.graphics); // render debug layer
50
50
 
51
51
  // ###### END CYCLE #######
52
- Input.clear();
53
- UI.clear();
54
- Debug.clear();
55
52
 
56
53
  this._frame_id = requestAnimationFrame(this.update.bind(this));
54
+ this.target_application.on_frame_end();
57
55
  this.frames_passed++;
56
+
57
+ Input.clear();
58
+ UI.clear();
59
+ Debug.clear();
58
60
  }
59
61
 
60
62
  start()
61
63
  {
62
64
  if (this.is_running) return; // sanity check
63
65
 
64
- this.graphics.check_for_resize();
65
-
66
66
  if (this.frames_passed === 0)
67
67
  {
68
68
  this.target_application.on_enter();
@@ -6,7 +6,7 @@ export default class ActionSequencer
6
6
  constructor(context)
7
7
  {
8
8
  this.elapsed_time = -0.00001;
9
-
9
+ this.playback_speed = 1;
10
10
  this.playing = false;
11
11
 
12
12
  this.action_events = [];
@@ -52,8 +52,8 @@ export default class ActionSequencer
52
52
  {
53
53
  if (this.playing)
54
54
  {
55
- this.__play_clips(this.elapsed_time, this.elapsed_time + delta_time);
56
- this.elapsed_time = this.elapsed_time + delta_time;
55
+ this.__play_clips(this.elapsed_time, this.elapsed_time + delta_time * this.playback_speed);
56
+ this.elapsed_time = this.elapsed_time + delta_time * this.playback_speed;
57
57
  }
58
58
  }
59
59
 
@@ -1,22 +1,36 @@
1
- import { Audio as THREEAudio } from 'three';
1
+ import { Audio as TAudio } from 'three';
2
+ import { PositionalAudio as TPositionalAudio } from 'three';
2
3
 
3
4
  export default class AudioClip
4
5
  {
5
- constructor(buffer, loop = true, volume = 1)
6
+ constructor(buffer, loop = true, volume = 1, positional = false)
6
7
  {
7
8
  this.buffer = buffer;
8
9
  this.loop = loop;
9
10
  this.volume = volume;
11
+ this.positional = positional;
10
12
 
11
13
  this.audio = undefined;
12
14
  }
13
15
 
14
16
  init(audio_listener)
15
17
  {
16
- this.audio = new THREEAudio(audio_listener);
18
+ if (this.positional)
19
+ {
20
+ this.audio = new TPositionalAudio(audio_listener);
21
+ }
22
+ else
23
+ {
24
+ this.audio = new TAudio(audio_listener);
25
+ }
26
+
17
27
  this.audio.setBuffer(this.buffer);
18
28
  this.audio.setLoop(this.loop);
19
- this.audio.setVolume(this.volume);
29
+
30
+ // This prevents undesired volume at the beginning of playing
31
+ this.audio.gain.gain.value = 0;
32
+
33
+ this.audio.setVolume(this.loop ? 0 : this.volume);
20
34
  }
21
35
 
22
36
  play()
@@ -1,42 +1,47 @@
1
1
  import AbstractLoader from './AbstractLoader';
2
2
 
3
3
  import AudioClip from '../components/AudioClip';
4
- import { AudioLoader as THREEAudioLoader } from 'three';
4
+
5
+ import { AudioContext } from 'three';
5
6
 
6
7
  export default class AudioLoader extends AbstractLoader
7
8
  {
8
- constructor(resource_id, url, loop = true, volume = 1, size)
9
+ constructor(resource_id, url, loop = true, volume = 0, size, positional = false)
9
10
  {
10
11
  super(resource_id, url, size);
11
- this.loader = new THREEAudioLoader();
12
12
  this.loop = loop;
13
13
  this.volume = volume;
14
+ this.positional = positional;
14
15
  }
15
16
 
16
- on_preloaded_finished(resource_container)
17
+ on_preloaded_finished(resource_container, response)
17
18
  {
18
- let ctx = this;
19
-
20
- this.loader.load(this.url, (buffer) =>
19
+ if (!window.user_interaction_for_audio)
21
20
  {
22
- resource_container.set_resource(ctx.resource_id, ctx.url, new AudioClip(buffer, this.loop, this.volume));
23
-
24
- ctx.__update_downloaded_bytes(1, 1);
25
- ctx.__loading_ended();
26
- },
27
- (xhr) =>
21
+ setTimeout(this.on_preloaded_finished.bind(this, resource_container, response), 100);
22
+ }
23
+ else
28
24
  {
29
- // if (xhr)
30
- // {
31
- // let total = xhr.total || this.total_bytes;
25
+ this.instantiate_audio(resource_container, response);
26
+ }
27
+ }
32
28
 
33
- // ctx.__update_downloaded_bytes(xhr.loaded, total);
34
- // }
35
- },
36
- (error) =>
29
+ instantiate_audio(resource_container, response)
30
+ {
31
+ response.arrayBuffer().then((array_buffer) =>
37
32
  {
38
- ctx.__set_error('Audio could not be loaded. Maybe wrong name or path, I don\'t know' + '¯\\_(ツ)_/¯', error);
39
- ctx.__loading_ended();
33
+ const context = AudioContext.getContext();
34
+ context.decodeAudioData(array_buffer, (audio_buffer) =>
35
+ {
36
+ resource_container.set_resource(
37
+ this.resource_id,
38
+ this.url,
39
+ new AudioClip(audio_buffer, this.loop, this.volume, this.positional)
40
+ );
41
+
42
+ this.__update_downloaded_bytes(1, 1);
43
+ this.__loading_ended();
44
+ });
40
45
  });
41
46
  }
42
47
  }
@@ -69,9 +69,9 @@ export default class ResourceBatch
69
69
  this.resource_loaders.push(new CubemapLoader(resource_id, url, size));
70
70
  }
71
71
 
72
- add_audio(resource_id, url, loop, volume, size)
72
+ add_audio(resource_id, url, loop, volume, size, positional)
73
73
  {
74
- this.resource_loaders.push(new AudioLoader(resource_id, url, loop, volume, size));
74
+ this.resource_loaders.push(new AudioLoader(resource_id, url, loop, volume, size, positional));
75
75
  }
76
76
 
77
77
  add_video(resource_id, url, size)
@@ -1,3 +1,4 @@
1
+ import { Vector3 } from 'three';
1
2
  class MeshSampler
2
3
  {
3
4
  constructor()
@@ -5,25 +6,80 @@ class MeshSampler
5
6
 
6
7
  }
7
8
 
8
- sample(geometry, sample_count)
9
+ sample(buffer_geometry, sample_count)
9
10
  {
10
11
  let face_areas = [];
11
12
 
12
13
  let min_area = 99999999;
13
- for (let i = 0; i < geometry.faces.length; i++)
14
+
15
+ let vertices = buffer_geometry.getAttribute('position');
16
+ let normals = buffer_geometry.getAttribute('normal');
17
+ let indices = buffer_geometry.index;
18
+
19
+ let faces = [];
20
+
21
+ for (let i = 0; i < indices.count; i += 3)
14
22
  {
15
- let area = this.get_face_area(geometry.faces[i], geometry.vertices);
23
+ let index_0 = indices.array[i + 0];
24
+ let index_1 = indices.array[i + 1];
25
+ let index_2 = indices.array[i + 2];
26
+
27
+ let v1 = new Vector3();
28
+ v1.x = vertices.getX(index_0);
29
+ v1.y = vertices.getY(index_0);
30
+ v1.z = vertices.getZ(index_0);
31
+
32
+ let v2 = new Vector3();
33
+ v2.x = vertices.getX(index_1);
34
+ v2.y = vertices.getY(index_1);
35
+ v2.z = vertices.getZ(index_1);
36
+
37
+ let v3 = new Vector3();
38
+ v3.x = vertices.getX(index_2);
39
+ v3.y = vertices.getY(index_2);
40
+ v3.z = vertices.getZ(index_2);
41
+
42
+ let face = {
43
+ a: v1,
44
+ b: v2,
45
+ c: v3
46
+ };
47
+
48
+ if (normals)
49
+ {
50
+ let n1 = new Vector3();
51
+ n1.x = normals.getX(index_0);
52
+ n1.y = normals.getY(index_0);
53
+ n1.z = normals.getZ(index_0);
54
+
55
+ let n2 = new Vector3();
56
+ n2.x = normals.getX(index_1);
57
+ n2.y = normals.getY(index_1);
58
+ n2.z = normals.getZ(index_1);
59
+
60
+ let n3 = new Vector3();
61
+ n3.x = normals.getX(index_2);
62
+ n3.y = normals.getY(index_2);
63
+ n3.z = normals.getZ(index_2);
64
+
65
+ let normal = n1.clone().add(n2).add(n3).normalize();
66
+ face.normal = normal;
67
+ }
68
+
69
+ faces.push(face);
70
+
71
+ let area = this.get_face_area(face);
16
72
  min_area = Math.min(area, min_area);
17
73
  face_areas.push(area);
18
74
  }
19
75
 
20
- let normalized_faces_array = this.get_uniform_face_distribution(face_areas, min_area, geometry.faces);
76
+ let normalized_faces_array = this.get_uniform_face_distribution(face_areas, min_area, faces);
21
77
  let selected_faces = this.select_random_faces(normalized_faces_array, sample_count);
22
- let sampled_data = this.sample_data_from_faces(selected_faces, geometry.vertices);
78
+ let sampled_data = this.sample_data_from_faces(selected_faces);
23
79
  return sampled_data;
24
80
  }
25
81
 
26
- sample_data_from_faces(faces, vertices)
82
+ sample_data_from_faces(faces)
27
83
  {
28
84
  let sampled_points = [];
29
85
  let sampled_normals = [];
@@ -34,8 +90,8 @@ class MeshSampler
34
90
  let w1 = Math.random();
35
91
  let w2 = Math.random();
36
92
 
37
- sampled_points.push(this.sample_point_in_face(w1, w2, vertices[face.a], vertices[face.b], vertices[face.c]).clone());
38
- if (sampled_normals && face.normal)
93
+ sampled_points.push(this.sample_point_in_face(w1, w2, face.a, face.b, face.c).clone());
94
+ if (face.normal)
39
95
  {
40
96
  sampled_normals.push(face.normal.clone());
41
97
  }
@@ -48,7 +104,7 @@ class MeshSampler
48
104
  let selected_faces = [];
49
105
  for (let i = 0; i < amount; i++)
50
106
  {
51
- let random = parseInt(Math.random() * (faces.length - 1));
107
+ let random = Math.floor(Math.random() * faces.length);
52
108
  let selected_face = faces[random];
53
109
 
54
110
  selected_faces.push(selected_face);
@@ -63,7 +119,7 @@ class MeshSampler
63
119
  for (let i = 0; i < face_areas.length; i++)
64
120
  {
65
121
  face_areas[i] /= minimum_area;
66
- let repetitions_needed = parseInt(Math.round(face_areas[i]));
122
+ let repetitions_needed = Math.floor(Math.round(face_areas[i]));
67
123
  for (let j = 0; j < repetitions_needed; j++)
68
124
  {
69
125
  extended_triangle_indices.push(faces[i]);
@@ -72,14 +128,10 @@ class MeshSampler
72
128
  return extended_triangle_indices;
73
129
  }
74
130
 
75
- get_face_area(face, vertices)
131
+ get_face_area(face)
76
132
  {
77
- let v1 = vertices[face.a].clone();
78
- let v2 = vertices[face.b].clone();
79
- let v3 = vertices[face.c].clone();
80
-
81
- let vec1 = v2.clone().sub(v1);
82
- let vec2 = v3.clone().sub(v1);
133
+ let vec1 = face.b.clone().sub(face.a);
134
+ let vec2 = face.c.clone().sub(face.a);
83
135
  return vec1.cross(vec2).length() / 2;
84
136
  }
85
137
 
@@ -21,7 +21,6 @@ export class Graphics {
21
21
  static __apply_override_material(scene: any, mat: any): void;
22
22
  static readback_RT(RT: any, buffer: any): void;
23
23
  static clear(RT: any, camera: any, clear_depth: any, clear_stencil: any): void;
24
- static check_for_resize(): void;
25
24
  static on_resize(): void;
26
25
  static material_pass(mat: any, dst: any): void;
27
26
  static blit(src_RT: any, dst_RT: any, mat: any): void;
package/types/index.d.ts CHANGED
@@ -45,7 +45,7 @@ export * from './utilities/EasingFunctions';
45
45
  export * from './utilities/FrustumPointFitter';
46
46
  export * from './utilities/GeometryUtilities';
47
47
  export * from './utilities/ImageUtilities';
48
- export * from './utilities/MathUtilities';
48
+ export * from './utilities/OMath';
49
49
  export * from './utilities/MeshSampler';
50
50
  export * from './utilities/ModelUtilities';
51
51
  export * from './utilities/ObjectUtilities';
@@ -1,4 +1,4 @@
1
- export class MathUtilities {
1
+ export class OMath {
2
2
  static linear_map(value: any, from_range_start_value: any, from_range_end_value: any, to_range_start_value: any, to_range_end_value: any): any;
3
3
  static between(value: any, min: any, max: any): boolean;
4
4
  static mod(number: any, divisor: any): number;
@@ -6,7 +6,16 @@ export class MathUtilities {
6
6
  static project_points_on_plane(points: any, plane: any): any[];
7
7
  static matrix4_lerp(from: any, to: any, target: any, t: any): void;
8
8
  static equals(x1: any, x2: any): boolean;
9
+ static lerp(x: number, y: number, t: number): number;
10
+ static clamp(value: number, min: number, max: number): number;
11
+ static euclideanModulo(n: number, m: number): number;
12
+ static pingpong(x: number, length: number): number;
13
+ static degToRad(degrees: number): number;
14
+ static deg_to_rad(degrees: number): number;
15
+ static radToDeg(radians: number): number;
16
+ static rad_to_deg(radians: number): number;
9
17
  static perspective_divide(v: any): any;
10
18
  static points_average(points: any): any;
11
19
  static get_random_color(): string;
20
+ static saturate(x: number): number;
12
21
  }