Skip to content

Commit be9cc89

Browse files
committed
Screen Space Inspect Placement
Calculating NDC placement for objects - -Inspector View (druid rabbit close-up position) -Left & Right Hoodoo (yet to be made)
1 parent f6cc61b commit be9cc89

1 file changed

Lines changed: 140 additions & 12 deletions

File tree

docs/js/pxlRooms/SaltFlatsEnvironment/SaltFlatsEnvironment.js

Lines changed: 140 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ import {
3131
LinearSRGBColorSpace,
3232
SRGBColorSpace,
3333
FrontSide,
34-
DoubleSide
34+
DoubleSide,
35+
SphereGeometry,
36+
MeshBasicMaterial,
37+
Mesh
3538
} from "three";
3639

3740
import { RoomEnvironment, pxlEffects } from "pxlNav";
@@ -119,6 +122,25 @@ export class SaltFlatsEnvironment extends RoomEnvironment{
119122
'releaseTime':0,
120123
};
121124

125+
// Calculated Camera Space NDC locations
126+
// Updated on Resize
127+
this.toRadians = Math.PI / 180;
128+
this.ndcPositions = {
129+
'inspectorPosition': {
130+
basePosition: new Vector3( -0.662, -.6, 28 ),
131+
ndcPosition: null
132+
},
133+
'leftHoodooPosition': {
134+
basePosition: new Vector3( -.9, 0.5, 200 ),
135+
ndcPosition: null
136+
},
137+
'rightHoodooPosition': {
138+
basePosition: new Vector3( .9, 0.5, 200 ),
139+
ndcPosition: null
140+
},
141+
};
142+
143+
this.precalculations = {};
122144

123145
}
124146

@@ -175,6 +197,8 @@ export class SaltFlatsEnvironment extends RoomEnvironment{
175197
coreCanvas.addEventListener("mousedown", (e)=>{ this.mapOnDown(e); }, false);
176198
coreCanvas.addEventListener("mousemove", (e)=>{ this.mapOnMove(e); }, false);
177199
coreCanvas.addEventListener("mouseup", (e)=>{ this.mapOnUp(e); }, false);
200+
201+
setTimeout(()=>{ this.setCameraSpaceNDC(); }, 0);
178202
}
179203

180204
stop(){
@@ -186,6 +210,97 @@ export class SaltFlatsEnvironment extends RoomEnvironment{
186210

187211
// -- -- -- -- -- -- -- --
188212

213+
preCalculateCameraData( sw=null, sh=null ){
214+
if( sw===null ) sw = this.pxlDevice.sW || window.innerWidth;
215+
if( sh===null ) sh = this.pxlDevice.sH || window.innerHeight;
216+
217+
// Pre-calculate half-height for the current camera FOV
218+
let camera = this.pxlCamera.camera;
219+
let fov = camera.fov * this.toRadians; // Convert to radians
220+
this.precalculations["fovTanHalfHeight_"+fov] = Math.tan( fov * 0.5 ); // Using a default depth of 150
221+
222+
this.texelRatio.set( 1/sw, 1/sh );
223+
224+
// Let the camera resolve, wait to next update
225+
setTimeout(()=>{
226+
this.setCameraSpaceNDC( sw, sh );
227+
this.setInspectMarkerPos();
228+
this.checkInspectorUpdate();
229+
}, 0);
230+
}
231+
232+
// Find Camera Space positions to place specific objects in the scene
233+
setCameraSpaceNDC( sw=null, sh=null ){
234+
if( sw===null ) sw = this.pxlDevice.sW || window.innerWidth;
235+
if( sh===null ) sh = this.pxlDevice.sH || window.innerHeight;
236+
237+
let aspect = sw / sh;
238+
// Using Three.js PerspectiveCamera - this.pxlCamera.camera
239+
let camera = this.pxlCamera.camera;
240+
let fov = camera.fov * this.toRadians; // Convert to radians
241+
242+
// Offsets in camera space -- ( x: -1 left to 1 right, y: -1 bottom to 1 top, z: distance from camera in units )
243+
// Tweak these while testing marker placements
244+
let leftHoodooOffset = this.ndcPositions.leftHoodooPosition.basePosition.clone();
245+
let rightHoodooOffset = this.ndcPositions.rightHoodooPosition.basePosition.clone();
246+
let inspectOffset = this.ndcPositions.inspectorPosition.basePosition.clone();
247+
248+
// Find Left and Right Hoodoo locations
249+
// Left Hoodoo Position
250+
this.ndcPositions.leftHoodooPosition.ndcPosition = this.cameraOffsetToWorld( camera, fov, aspect, leftHoodooOffset );
251+
252+
// Right Hoodoo Position
253+
this.ndcPositions.rightHoodooPosition.ndcPosition = this.cameraOffsetToWorld( camera, fov, aspect, rightHoodooOffset );
254+
255+
// Inspect Rabbit Druid Position
256+
this.ndcPositions.inspectorPosition.ndcPosition = this.cameraOffsetToWorld( camera, fov, aspect, inspectOffset );
257+
258+
//this.debugPlaceMarkers();
259+
}
260+
261+
262+
cameraOffsetToWorld( camera, fov, aspect, offset ){
263+
let depth = Math.abs( offset.z );
264+
let tanHalfFov = 0;
265+
266+
if( this.precalculations.hasOwnProperty("fovTanHalfHeight_"+fov)){
267+
tanHalfFov = this.precalculations["fovTanHalfHeight_"+fov];
268+
}else{
269+
tanHalfFov = Math.tan( fov * 0.5 );
270+
this.precalculations["fovTanHalfHeight_"+fov] = tanHalfFov;
271+
}
272+
273+
// Actual half-height/width of the frustum at this depth
274+
let halfHeight = depth * tanHalfFov;
275+
let halfWidth = halfHeight * aspect;
276+
277+
let localPos = new Vector3( offset.x * halfWidth, offset.y * halfHeight, -depth );
278+
return camera.localToWorld( localPos );
279+
}
280+
281+
// Temp visual markers to verify calculated NDC placements in-scene
282+
debugPlaceMarkers(){
283+
if( !this.scene ) return;
284+
285+
let markerColors = { 'leftHoodooPosition':0xff0000, 'rightHoodooPosition':0x0000ff, 'inspectorPosition':0x00ff00 };
286+
let markerGeo = null;
287+
288+
for( let key in this.ndcPositions ){
289+
let entry = this.ndcPositions[key];
290+
if( !entry.ndcPosition ) continue;
291+
292+
if( !entry.marker ){
293+
if( !markerGeo ) markerGeo = new SphereGeometry( 5, 12, 12 );
294+
entry.marker = new Mesh( markerGeo, new MeshBasicMaterial( { color:markerColors[key] } ) );
295+
this.scene.add( entry.marker );
296+
}
297+
298+
entry.marker.position.copy( entry.ndcPosition );
299+
}
300+
}
301+
302+
// -- -- -- -- -- -- -- --
303+
189304

190305
mapOnDown(e){
191306
//let target= e.path ? e.path[0] : e.target; // Chrome or Firefox
@@ -313,18 +428,27 @@ export class SaltFlatsEnvironment extends RoomEnvironment{
313428
console.log(this.inspectController.matrixWorld.elements)
314429
console.log(this.inspectController.matrix[12],this.inspectController.matrix[13],this.inspectController.matrix[14])
315430
console.log(this.inspectorBasePos)*/
431+
this.setCameraSpaceNDC( this.pxlDevice.sW, this.pxlDevice.sH );
316432
this.setInspectMarkerPos();
317433
}
318434

319435
setInspectMarkerPos(){
436+
this.inspectMarkerPos.copy( this.ndcPositions.inspectorPosition.ndcPosition );
437+
return;
320438
let targetInspectPos = new Vector3();
321439
targetInspectPos.x = 105;
322440
targetInspectPos.y = 14;
323441

324-
let screenRatio = this.pxlDevice.sW / this.pxlDevice.sH;
325-
targetInspectPos.z = 2.1 + 3.00 * (screenRatio*screenRatio);
326-
442+
let screenRatio = 0;// this.pxlDevice.sW / this.pxlDevice.sH;
327443

444+
// Use predetermined position if it exists
445+
// It should exist, but who knows, maybe the environment doesn't load propperly or changes in the future.
446+
if( this.ndcPositions.inspectorPosition.ndcPosition ){
447+
targetInspectPos.copy( this.ndcPositions.inspectorPosition.ndcPosition );
448+
}else{
449+
screenRatio = this.pxlDevice.sW / this.pxlDevice.sH;
450+
targetInspectPos.z = 2.1 + 3.00 * (screenRatio*screenRatio);
451+
}
328452
this.inspectMarkerPos.copy( targetInspectPos );
329453
}
330454

@@ -351,7 +475,8 @@ export class SaltFlatsEnvironment extends RoomEnvironment{
351475
this.inspectMode = this.inspectToMode;
352476
this.inspectBlend.x = this.inspectMode ? 1 : 0;
353477

354-
let targetPos = this.inspectMode ? this.inspectMarkerPos : this.inspectorBasePos;
478+
//let targetPos = this.inspectMode ? this.inspectMarkerPos : this.inspectorBasePos;
479+
let targetPos = this.inspectMode ? this.ndcPositions.inspectorPosition.ndcPosition : this.inspectorBasePos;
355480
this.inspectController.position.copy( targetPos );
356481

357482
if( !this.inspectToMode ){
@@ -366,18 +491,18 @@ export class SaltFlatsEnvironment extends RoomEnvironment{
366491
this.inspectBlend.x = this.inspectToMode ? inspectProgress : 1 - inspectProgress;
367492

368493
let targetPos = new Vector3().copy( this.inspectController.position );
369-
let blendPos = this.inspectToMode ? this.inspectMarkerPos : this.inspectorBasePos;
494+
//let blendPos = this.inspectToMode ? this.inspectMarkerPos : this.inspectorBasePos;
495+
let blendPos = this.inspectToMode ? this.ndcPositions.inspectorPosition.ndcPosition : this.inspectorBasePos;
370496
targetPos.lerp( blendPos, inspectProgress );
371497
this.inspectController.position.copy( targetPos );
372-
373498
}
374-
375499
}
376500
}
377501

378502
checkInspectorUpdate(){
379503
if( !this.inspectTransition && this.inspectMode ){
380-
this.inspectController.position.copy( this.inspectMarkerPos );
504+
//this.inspectController.position.copy( this.inspectMarkerPos );
505+
this.inspectController.position.copy( this.ndcPositions.inspectorPosition.ndcPosition );
381506
}
382507
}
383508

@@ -408,9 +533,12 @@ export class SaltFlatsEnvironment extends RoomEnvironment{
408533
// -- -- --
409534

410535
resize( sw, sh){
411-
this.setInspectMarkerPos();
412-
this.checkInspectorUpdate();
413-
this.texelRatio.set( 1/this.pxlDevice.sW, 1/this.pxlDevice.sH );
536+
this.preCalculateCameraData( sw, sh);
537+
if( this.inspectToMode && this.inspectController && this.ndcPositions.inspectorPosition.ndcPosition ){
538+
setTimeout(()=>{
539+
this.inspectController.position.copy( this.ndcPositions.inspectorPosition.ndcPosition );
540+
});
541+
}
414542
super.resize( sw, sh );
415543
}
416544

0 commit comments

Comments
 (0)