I have an orthographic camera that is looking perpendicular at a sprite
the intersection with some point on the sprite is at intersects[0].point
NDC is computed from intersects[0].point.
In my case:
the camera is orthographic
the camera view is perpendicualr to the sprite
the aspect ratio of the sprite is equal to the aspect ratio of the camera fustrum
To get from uv to NDC_Coord I have to transform uv → worldCoords → NDC_Coord
Why is it that uv and NDC_Coord are not mapped to each other up to shift and scale?
ThreejsUtil.js:368 uv2 Vector2 {x: 0.46508622967278285, y: 0.5292560967357548}
ThreejsUtil.js:375 threejsViewport Vector4 {x: -0, y: -815, z: 2469, w: 2276}
ThreejsUtil.js:379 sprite.position Vector3 {x: 468, y: 0, z: 431.5}
ThreejsUtil.js:380 sprite.scale Vector3 {x: 936, y: 863, z: 1}
ThreejsUtil.js:387 worldCoord3 Vector3 {x: 435.3207109737248, y: 0, z: 456.7480114829564}
ThreejsUtil.js:389 NDC_Coord3 Vector3 {x: -0.0198460915350345, y: -0.016695957737587717, z: -0.9800020305980534}
ThreejsUtil.js:391 camera.zoom 0.2842158172697181
ThreejsUtil.js:393 intersects[0].point Vector3 {x: 435.32071097372483, y: -0.002524801135450616, z: 456.74801135671635}
ThreejsUtil.js:396 NDC_Coord Vector3 {x: -0.019846091535034464, y: -0.01669595782073819, z: -0.9800019801019801}
related functions are
static GetPositionRelativeToViewportInPixels(mouseNDC, camera, threejsViewport, children) {
// clientX, clientY - screen coordinates in pixel of the client window, e.g. 2461
console.log('xxxxxxxxxxxxxxxxxxxxxxxxxxx');
let raycaster = new THREE_Raycaster();
console.log('mouseNDC', mouseNDC);
raycaster.setFromCamera(mouseNDC, camera);
let intersects = raycaster.intersectObjects(children);
if (intersects.length > 0 && intersects[0].uv) {
// https://threejs.org/docs/#api/en/core/Raycaster.intersectObject
// The intesectionPoint intersects[0] contains:
// point - point of interection in world coordinates
// uv - U,V coordinates at point of intersection in respect to the object
// e.g. if intersecting with circle object (laid on a surface (sprite)) on the left part of the circle, then x will be 0
// and if intersecting with circle object on the right part of the circle, then x will be 1
// this is unrelated to the position of the circle on the surface (sprite)
var uv = intersects[0].uv;
// Transform the uv based on the value of this texture's
// .offset, .repeat, .wrapS, .wrapT and .flipY properties.
// The value of uv changes in-place.
intersects[0].object.material.map.transformUv(uv);
// console.log('intersects[0]', intersects[0]);
console.log('uv2', uv);
let point2d_relativeToViewportInPixels = new THREE_Vector2(threejsViewport.z * uv.x,
threejsViewport.w * uv.y);
{
console.log('threejsViewport', threejsViewport);
let sprite = COL.model.selectedSite.selectedLayer.getPlanViewSurface();
// console.log('sprite', sprite);
console.log('sprite.position', sprite.position);
console.log('sprite.scale', sprite.scale);
let worldX3 = sprite.position.x + (uv.x - 0.5) * sprite.scale.x;
let worldY3 = sprite.position.y; // Assuming the sprite lies in the XZ plane
let worldZ3 = sprite.position.z + (uv.y - 0.5) * sprite.scale.y;
let worldCoord3 = new THREE_Vector3(worldX3, worldY3, worldZ3);
console.log('worldCoord3', worldCoord3);
let NDC_Coord3 = worldCoord3.project(camera);
console.log('NDC_Coord3', NDC_Coord3);
console.log('camera.zoom', camera.zoom);
console.log('intersects[0].point', intersects[0].point);
let NDC_Coord = ThreejsUtil.WorldCoord_to_NDC_coord(camera, intersects[0].point);
console.log('NDC_Coord', NDC_Coord);
let worldCoord2 = ThreejsUtil.NDC_Coord_to_WorldCoord(camera, NDC_Coord);
console.log('worldCoord2', worldCoord2);
}
console.log('xxxxxxxxxxxxxxxxxxxxxxxxxxx');
return point2d_relativeToViewportInPixels;
}
return null;
}
static WorldCoord_to_NDC_coord(camera, worldCoord) {
// If you transform the camera in 3D space and you directly use Vector3.project() or Vector3.unproject(), you have to call updateMatrixWorld().
// https://discourse.threejs.org/t/ortho-camera-pixel-to-world-coordinate-world-coordinate-to-pixel/20719
let NDC_coord = new THREE_Vector3( worldCoord.x, worldCoord.y, worldCoord.z ).project( camera );
return NDC_coord;
};