@needle-tools/engine 4.10.0-beta.2 → 4.10.0-beta.3

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.
@@ -3,7 +3,7 @@ import { Camera, PerspectiveCamera, Vector2, Vector3 } from "three";
3
3
  import { isDevEnvironment } from "../../engine/debug/debug.js";
4
4
  import { Gizmos } from "../../engine/engine_gizmos.js";
5
5
  import { serializable } from "../../engine/engine_serialization_decorator.js";
6
- import { getTempVector } from "../../engine/engine_three_utils.js";
6
+ import { getTempQuaternion, getTempVector } from "../../engine/engine_three_utils.js";
7
7
  import { registerType } from "../../engine/engine_typestore.js";
8
8
  import { getParam } from "../../engine/engine_utils.js";
9
9
  import { Behaviour } from "../Component.js";
@@ -21,20 +21,24 @@ export class ViewBox extends Behaviour {
21
21
  @serializable()
22
22
  debug: boolean = false;
23
23
 
24
- awake() {
25
- // this.referenceFieldOfView = (this.context.mainCamera as PerspectiveCamera)?.fov || 60;
26
- // setInterval(()=>{
27
- // this.enabled = !this.enabled
28
- // }, 1000)
29
- }
24
+ // awake() {
25
+ // // this.referenceFieldOfView = (this.context.mainCamera as PerspectiveCamera)?.fov || 60;
26
+ // setInterval(()=>{
27
+ // if(Math.random() > .5)
28
+ // this.enabled = !this.enabled
29
+ // }, 1000)
30
+ // }
31
+
30
32
  onEnable(): void {
31
33
  if (debugParam || this.debug || isDevEnvironment()) console.debug("[ViewBox] Using camera fov:", this.referenceFieldOfView);
32
34
  ViewBox.instances.push(this);
33
35
  }
34
36
 
35
37
  onDisable(): void {
38
+ if (debugParam || this.debug) console.debug("[ViewBox] Disabled");
36
39
  const idx = ViewBox.instances.indexOf(this);
37
40
  if (idx !== -1) ViewBox.instances.splice(idx, 1);
41
+ this._projectedBoxElement?.remove();
38
42
  }
39
43
 
40
44
  onBeforeRender() {
@@ -80,44 +84,80 @@ export class ViewBox extends Behaviour {
80
84
  diffHeight = domHeight / rectHeight;
81
85
  }
82
86
 
83
- // const view = camera.view;
87
+
84
88
  const view = camera.view;
85
89
  const zoom = camera.zoom;
86
90
  const aspect = camera.aspect;
87
91
  const fov = camera.fov;
88
92
  camera.view = null;
89
93
  camera.zoom = 1;
90
- // camera.aspect = rectWidth / rectHeight;
91
94
  camera.fov = this.referenceFieldOfView;
92
95
  camera.updateProjectionMatrix();
93
96
 
94
97
  const boxPosition = this.gameObject.worldPosition;
95
98
  const boxScale = this.gameObject.worldScale;
96
99
 
100
+ const cameraPosition = camera.worldPosition;
101
+ const distance = cameraPosition.distanceTo(boxPosition);
102
+
103
+
104
+ // #region camera fixes
105
+ // If the camera is inside the box, move it out
106
+ const boxSizeMax = Math.max(boxScale.x, boxScale.y, boxScale.z);
107
+ const direction = getTempVector(cameraPosition).sub(boxPosition);
108
+ if (distance < boxSizeMax) {
109
+ // move camera out of bounds
110
+ if (this.debug || debugParam) console.warn("[ViewBox] Moving camera out of bounds", distance, "<", boxSizeMax);
111
+ const positionDirection = getTempVector(direction);
112
+ positionDirection.y *= .00000001; // stay on horizontal plane mostly
113
+ positionDirection.normalize();
114
+ const lengthToMove = (boxSizeMax - distance) * 10; // move a bit more than needed
115
+ const newPosition = cameraPosition.add(positionDirection.multiplyScalar(lengthToMove));
116
+ camera.worldPosition = newPosition.lerp(cameraPosition, 1 - this.context.time.deltaTime);
117
+ }
118
+
119
+ // Ensure the camera looks at the ViewBox
120
+ // TOOD: smooth lookat over multiple frames if we have multiple viewboxes
121
+ // const dot = direction.normalize().dot(camera.worldForward);
122
+ // if (dot < .9) {
123
+ // console.log(dot);
124
+ // const targetRotation = direction;
125
+ // const rotation = getTempQuaternion();
126
+ // rotation.setFromUnitVectors(camera.worldForward.multiplyScalar(-1), targetRotation);
127
+ // camera.worldQuaternion = rotation;
128
+ // camera.updateMatrixWorld();
129
+ // }
130
+ const boxPositionInCameraSpace = getTempVector(boxPosition);
131
+ camera.worldToLocal(boxPositionInCameraSpace);
132
+ camera.lookAt(boxPosition);
133
+ camera.updateMatrixWorld();
97
134
 
98
135
 
99
- // const fov = this.referenceFieldOfView
100
- const distance = camera.worldPosition.distanceTo(boxPosition);
136
+ // #region calculate fit
101
137
  const vFOV = this.referenceFieldOfView * Math.PI / 180; // convert vertical fov to radians
102
138
  const height = 2 * Math.tan(vFOV / 2) * distance; // visible height
103
139
  const width = height * camera.aspect; // visible width
104
140
 
105
- const projectedBox = this.projectBoxIntoCamera(boxPosition, boxScale, camera, height * .5);
141
+ const projectedBox = this.projectBoxIntoCamera(boxPosition, boxScale, camera, 1);
142
+ // return
106
143
  const boxWidth = (projectedBox.maxX - projectedBox.minX);
107
144
  const boxHeight = (projectedBox.maxY - projectedBox.minY);
108
145
 
109
- // TODO: take the rect size different into account
110
146
  const scale = this.fit(
111
147
  boxWidth * camera.aspect,
112
148
  boxHeight,
113
149
  width / diffWidth,
114
150
  height / diffHeight
115
151
  );
152
+ // console.log({ scale, width, height, boxWidth: boxWidth * camera.aspect, boxHeight, diffWidth, diffHeight, aspect: camera.aspect, distance })
153
+ // this.context.focusRectSettings.zoom = 1.39;
154
+ // if (!this.context.focusRect) this.context.setCameraFocusRect(this.context.domElement);
155
+ // return
116
156
  const vec = getTempVector(boxPosition);
117
157
  vec.project(camera);
118
158
  this.context.focusRectSettings.offsetX = vec.x;
119
159
  this.context.focusRectSettings.offsetY = vec.y;
120
- this.context.focusRectSettings.zoom = scale;
160
+ this.context.focusRectSettings.zoom = scale / (height * .5);
121
161
  // if we don't have a focus rect yet, set it to the dom element
122
162
  if (!this.context.focusRect) this.context.setCameraFocusRect(this.context.domElement);
123
163
 
@@ -149,9 +189,8 @@ export class ViewBox extends Behaviour {
149
189
 
150
190
 
151
191
 
152
- private projectBoxIntoCamera(position: Vector3, scale: Vector3, camera: Camera, diff: number) {
153
-
154
- const factor = .5 * diff;
192
+ private projectBoxIntoCamera(position: Vector3, scale: Vector3, camera: Camera, _factor: number) {
193
+ const factor = .5 * _factor;
155
194
 
156
195
  const corners = [
157
196
  getTempVector(-scale.x * factor, -scale.y * factor, -scale.z * factor),
@@ -177,18 +216,21 @@ export class ViewBox extends Behaviour {
177
216
  if (c.y > maxY) maxY = c.y;
178
217
  }
179
218
 
180
- // if(!this._projectedBoxElement) {
181
- // this._projectedBoxElement = document.createElement("div");
182
- // this.context.domElement.appendChild(this._projectedBoxElement);
183
- // }
184
- // this._projectedBoxElement.style.position = "fixed";
185
- // this._projectedBoxElement.style.outline = "10px solid red";
186
- // this._projectedBoxElement.style.left = ((minX * .5 + .5) * this.context.domWidth) + "px";
187
- // this._projectedBoxElement.style.top = ((-maxY * .5 + .5) * this.context.domHeight) + "px";
188
- // this._projectedBoxElement.style.width = ((maxX - minX) * .5 * this.context.domWidth) + "px";
189
- // this._projectedBoxElement.style.height = ((maxY - minY) * .5 * this.context.domHeight) + "px";
190
- // this._projectedBoxElement.style.pointerEvents = "none";
191
- // this._projectedBoxElement.style.zIndex = "1000";
219
+ if (debugParam) {
220
+ if (!this._projectedBoxElement) {
221
+ this._projectedBoxElement = document.createElement("div");
222
+ }
223
+ if (this._projectedBoxElement.parentElement !== this.context.domElement)
224
+ this.context.domElement.appendChild(this._projectedBoxElement);
225
+ this._projectedBoxElement.style.position = "fixed";
226
+ this._projectedBoxElement.style.outline = "5px dotted red";
227
+ this._projectedBoxElement.style.left = ((minX * .5 + .5) * this.context.domWidth) + "px";
228
+ this._projectedBoxElement.style.top = ((-maxY * .5 + .5) * this.context.domHeight) + "px";
229
+ this._projectedBoxElement.style.width = ((maxX - minX) * .5 * this.context.domWidth) + "px";
230
+ this._projectedBoxElement.style.height = ((maxY - minY) * .5 * this.context.domHeight) + "px";
231
+ this._projectedBoxElement.style.pointerEvents = "none";
232
+ this._projectedBoxElement.style.zIndex = "1000";
233
+ }
192
234
 
193
235
 
194
236
  return { minX, maxX, minY, maxY };