From 7659ba6c1868195a1a362d58dce4ec69e94d87fc Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sat, 15 Jun 2024 08:29:24 +0200 Subject: [PATCH 01/19] fixed issue with intersection_pos --- interaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interaction.js b/interaction.js index 92541f4..98b6c63 100644 --- a/interaction.js +++ b/interaction.js @@ -188,7 +188,7 @@ function createJSON(objectArray) { objectArray.forEach((object) => { const real_pos = get2DCoords(C, object.position); - if (object.userData.intersection == null) intersection_pos = real_pos; + //if (object.userData.intersection == null) intersection_pos = real_pos; const intersection_pos = get2DCoords(C, object.userData.intersection); json.push({ name: object.name, From e75237375289b98a2c936847115b427858124c59 Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sat, 15 Jun 2024 08:30:29 +0200 Subject: [PATCH 02/19] Fixed image_path for windows --- single-image-loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/single-image-loader.js b/single-image-loader.js index 7b64db7..80f5334 100644 --- a/single-image-loader.js +++ b/single-image-loader.js @@ -25,7 +25,7 @@ function loadImage(scene, R, t, zoom, image_name, image_loader) { // Afegir imatge const SCALE = 5 * imageSize; - const image_path = "/images/low_res/" + image_name; + const image_path = "./images/low_res/" + image_name; const image_texture = image_loader.load(image_path, function () { image_texture.colorSpace = THREE.SRGBColorSpace; const isLandscape = image_texture.image.width > image_texture.image.height; From 3c8bd60928900bc4b6536fabcf878ac817716a5f Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sat, 15 Jun 2024 08:48:26 +0200 Subject: [PATCH 03/19] Added href to all anchors (to prevent edit cursor to show on hover) --- openseadragon.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openseadragon.html b/openseadragon.html index 8779264..2f2e795 100644 --- a/openseadragon.html +++ b/openseadragon.html @@ -8,12 +8,12 @@
From 0efcba5aa248651134b23bcb298ac07a8f4d1121 Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sat, 15 Jun 2024 09:27:44 +0200 Subject: [PATCH 05/19] Add some margin --- openseadragon.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openseadragon.js b/openseadragon.js index 0cae8ae..fa801cf 100644 --- a/openseadragon.js +++ b/openseadragon.js @@ -50,7 +50,7 @@ var viewer = OpenSeadragon({ preserveViewport: true, }); -viewer.zoomPerClick = 1; +viewer.zoomPerClick = 1; viewer.addHandler("open", function () { if (mode === "single" || parsedImages.size == 1) return; @@ -128,6 +128,12 @@ function getIntersection(a, b) { var right = min(getRight(a), getRight(b)); var bottom = max(getBottom(a), getBottom(b)); + const margin = 0.01; + left -= margin; + right += margin; + top += margin; + bottom -= margin; + if (bottom < top && right > left) { return { top: top, From 7863f595a967392ac793b634c71d954302f44cab Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sat, 15 Jun 2024 15:16:48 +0200 Subject: [PATCH 06/19] prevent openImagesToOpenSeaDragon from clearing the selection --- interaction.js | 2 +- openseadragon.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/interaction.js b/interaction.js index 98b6c63..291f18e 100644 --- a/interaction.js +++ b/interaction.js @@ -128,7 +128,7 @@ function openImagesToOpenSeaDragon() { localStorage.setItem("images", jsonContent); const url = "openseadragon.html?mode=multiple"; window.open(url, "_blank"); - clearSelection(); + // clearSelection(); } function clearSelection() { diff --git a/openseadragon.js b/openseadragon.js index fa801cf..fd0a686 100644 --- a/openseadragon.js +++ b/openseadragon.js @@ -85,6 +85,7 @@ viewer.addHandler("canvas-click", function (event) { }); function distribute(images) { + return; overlapping = true; for (let i = 0; overlapping; i++) { console.log("i: " + i); @@ -184,6 +185,7 @@ function togglePosition() { } function recalculate() { + console.log("Recalculating. Real position: " + realPosition + ". Regular zoom: " + regularZoom + "."); for (let i = 0; i < parsedImages.length; i++) { const a = parsedImages[i]; var item = viewer.world.getItemAt(i); From 07d099a6bcfdc2d4468fca2a1cd9306a2e086399 Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sat, 15 Jun 2024 21:14:22 +0200 Subject: [PATCH 07/19] Fixed small offset issue with mouse clicks --- index.html | 13 +++++++++++-- interaction.js | 31 +++++++++++++++++++++++++++---- main.js | 6 +++--- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/index.html b/index.html index 8414e6a..845e948 100644 --- a/index.html +++ b/index.html @@ -4,9 +4,18 @@ My first three.js app diff --git a/interaction.js b/interaction.js index 291f18e..13f090a 100644 --- a/interaction.js +++ b/interaction.js @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { render } from "./main.js"; +import { render, renderer } from "./main.js"; import { getAllImages } from "./single-image-loader.js"; import { createPlane, setScene as setPlaneScene } from "./plane.js"; import { createSphere, setScene as setSphereScene } from "./sphere.js"; @@ -78,12 +78,24 @@ function onClick() { event.preventDefault(); // Avoid clicking images behind GUI if (event.target.tagName !== "CANVAS") return; - mouse.x = (event.clientX / window.innerWidth) * 2 - 1; + // get x,y coords into canvas where click occurred + var rect = event.target.getBoundingClientRect(); + var x = event.clientX - rect.left; + var y = event.clientY - rect.top; + mouse.x = ( (x / event.target.clientWidth ) * 2) - 1; + mouse.y = (-(y / event.target.clientHeight) * 2) + 1; + + /*mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; + */ raycaster.setFromCamera(mouse, camera); var intersects = raycaster.intersectObject(scene, true); - if (intersects.length == 0) return; + if (intersects.length == 0) + { + console.log("No intersection detected."); + return; + } if (!authoringMode) { openFigure(intersects); @@ -153,8 +165,19 @@ function onHover() { event.preventDefault(); // Avoid clicking images behind GUI if (event.target.tagName !== "CANVAS") return; + + // get x,y coords into canvas where click occurred + var rect = event.target.getBoundingClientRect(); + var x = event.clientX - rect.left; + var y = event.clientY - rect.top; + mouse.x = ( (x / event.target.clientWidth ) * 2) - 1; + mouse.y = (-(y / event.target.clientHeight) * 2) + 1; + + /* mouse.x = (event.clientX / window.innerWidth) * 2 - 1; - mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; + mouse.y = -(event.clientY / (window.innerHeight)) * 2 + 1; + */ + console.log(mouse); raycaster.setFromCamera(mouse, camera); var intersects = raycaster.intersectObject(scene, true); if (intersects.length > 0) { diff --git a/main.js b/main.js index e49e335..c2a1eb9 100644 --- a/main.js +++ b/main.js @@ -25,7 +25,7 @@ camera.position.set(5, 5, 5); const renderer = new THREE.WebGLRenderer({ antialias: true, }); -renderer.setSize(window.innerWidth, window.innerHeight - 25); +renderer.setSize(window.innerWidth, window.innerHeight - 25, false); // -25 to avoid scroll bar document.body.appendChild(renderer.domElement); const controls = new OrbitControls(camera, renderer.domElement); @@ -90,7 +90,7 @@ gltfLoader.load("models/pedret/pedret_XII_text4K.glb", (object) => { object.scene.name = "model"; const wrapper = new THREE.Object3D(); - wrapper.name = "model"; + wrapper.name = "wrapper"; wrapper.add(object.scene); wrapper.rotateX(-Math.PI / 2); @@ -131,4 +131,4 @@ function render() { animate(); -export { render }; +export { render, renderer }; From 06f4021617ce16a57bc757b97adea3793b4baa11 Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sat, 15 Jun 2024 21:17:57 +0200 Subject: [PATCH 08/19] removed mouse logs --- interaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interaction.js b/interaction.js index 13f090a..6ed7ede 100644 --- a/interaction.js +++ b/interaction.js @@ -177,7 +177,7 @@ function onHover() { mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / (window.innerHeight)) * 2 + 1; */ - console.log(mouse); + //console.log(mouse); raycaster.setFromCamera(mouse, camera); var intersects = raycaster.intersectObject(scene, true); if (intersects.length > 0) { From cba4e48dc223c079880b9338eede1a36d0260d1a Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sat, 15 Jun 2024 23:51:13 +0200 Subject: [PATCH 09/19] increased max zoom level --- openseadragon.js | 1 + 1 file changed, 1 insertion(+) diff --git a/openseadragon.js b/openseadragon.js index fd0a686..c1a833f 100644 --- a/openseadragon.js +++ b/openseadragon.js @@ -48,6 +48,7 @@ var viewer = OpenSeadragon({ showNavigator: true, preserveViewport: true, + maxZoomPixelRatio: 3, // for videos }); viewer.zoomPerClick = 1; From 712be20e72a73bd1cce97ced84307ca64abf75f0 Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sat, 15 Jun 2024 23:51:42 +0200 Subject: [PATCH 10/19] scene move to window for debug purposes --- main.js | 1 + 1 file changed, 1 insertion(+) diff --git a/main.js b/main.js index c2a1eb9..67b1e55 100644 --- a/main.js +++ b/main.js @@ -12,6 +12,7 @@ import { setScene } from "./inspect.js"; THREE.Cache.enabled = true; const scene = new THREE.Scene(); +window.scene = scene; // debug from console scene.background = new THREE.Color(0xdadada); const camera = new THREE.PerspectiveCamera( From 64ef4fa17e8e1d2a0db8b953a5e891ed26638fc4 Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sun, 16 Jun 2024 08:54:31 +0200 Subject: [PATCH 11/19] Updated to threejs 165 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index dd4c73c..7d215e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "": { "dependencies": { "mathjs": "^12.3.1", - "three": "^0.161.0" + "three": "^0.165.0" }, "devDependencies": { "vite": "^5.0.12" @@ -783,9 +783,9 @@ } }, "node_modules/three": { - "version": "0.161.0", - "resolved": "https://registry.npmjs.org/three/-/three-0.161.0.tgz", - "integrity": "sha512-LC28VFtjbOyEu5b93K0bNRLw1rQlMJ85lilKsYj6dgTu+7i17W+JCCEbvrpmNHF1F3NAUqDSWq50UD7w9H2xQw==" + "version": "0.165.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.165.0.tgz", + "integrity": "sha512-cc96IlVYGydeceu0e5xq70H8/yoVT/tXBxV/W8A/U6uOq7DXc4/s1Mkmnu6SqoYGhSRWWYFOhVwvq6V0VtbplA==" }, "node_modules/tiny-emitter": { "version": "2.1.0", diff --git a/package.json b/package.json index 7114204..01743bb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "dependencies": { "mathjs": "^12.3.1", - "three": "^0.161.0" + "three": "^0.165.0" }, "devDependencies": { "vite": "^5.0.12" From 1fe615bbfcb6c6f7de7bc461291acb58dce95ec5 Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sun, 16 Jun 2024 15:22:38 +0200 Subject: [PATCH 12/19] Applied -PI/2 rotX directly to the model without wrapper object --- main.js | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/main.js b/main.js index 67b1e55..13a8051 100644 --- a/main.js +++ b/main.js @@ -56,6 +56,12 @@ scene.add(axesHelper); createPanel(); +await loadImages( + scene, + "out-files/MNAC-AbsidiolaSud/MNAC-AbsSud-CamerasList-converted.lst", + "out-files/MNAC-AbsidiolaSud/MNAC-AbsSud-CamerasRegistration.out" +); + //MODEL LOADER const gltfLoader = new GLTFLoader(); //gltfLoader.load("models/pedret10/MNAC-AbsSud-LowPoly.glb", (object) => { @@ -78,32 +84,31 @@ gltfLoader.load("models/pedret/pedret_XII_text4K.glb", (object) => { 0.0, 1.0 ); - const pos = new THREE.Vector3().setFromMatrixPosition(matrix); - const scale = new THREE.Vector3().setFromMatrixScale(matrix); - const rotation = new THREE.Quaternion().setFromRotationMatrix(matrix); + const rotMat = new THREE.Matrix4().copy(matrix); + rotMat.premultiply(new THREE.Matrix4().makeRotationX(-Math.PI / 2)); + const pos = new THREE.Vector3().setFromMatrixPosition(rotMat); + const scale = new THREE.Vector3().setFromMatrixScale(rotMat); + const rotation = new THREE.Quaternion().setFromRotationMatrix(rotMat); console.log(object.scene); object.scene.position.copy(pos); object.scene.scale.copy(scale); object.scene.quaternion.copy(rotation); - object.scene.name = "model"; - + //console.log("Before:", object.scene.matrixWorld); + /* const wrapper = new THREE.Object3D(); wrapper.name = "wrapper"; wrapper.add(object.scene); - wrapper.rotateX(-Math.PI / 2); - - scene.add(wrapper); + //wrapper.rotateX(-Math.PI / 2); + scene.add(wrapper);*/ + scene.add(object.scene); + //setIntersectionPosition(object.scene); setIntersectionPosition(scene); }); -await loadImages( - scene, - "out-files/MNAC-AbsidiolaSud/MNAC-AbsSud-CamerasList-converted.lst", - "out-files/MNAC-AbsidiolaSud/MNAC-AbsSud-CamerasRegistration.out" -); + addInteraction(camera, scene, controls); From ecda48d382a53d3a940cde53bd1b445646c6eea3 Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sun, 16 Jun 2024 15:29:02 +0200 Subject: [PATCH 13/19] fixed intersections + BVH --- package-lock.json | 11 +++++- package.json | 3 +- single-image-loader.js | 79 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 83 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7d215e7..e0a6f41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,8 @@ "": { "dependencies": { "mathjs": "^12.3.1", - "three": "^0.165.0" + "three": "^0.165.0", + "three-mesh-bvh": "^0.7.5" }, "devDependencies": { "vite": "^5.0.12" @@ -787,6 +788,14 @@ "resolved": "https://registry.npmjs.org/three/-/three-0.165.0.tgz", "integrity": "sha512-cc96IlVYGydeceu0e5xq70H8/yoVT/tXBxV/W8A/U6uOq7DXc4/s1Mkmnu6SqoYGhSRWWYFOhVwvq6V0VtbplA==" }, + "node_modules/three-mesh-bvh": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.7.5.tgz", + "integrity": "sha512-WDd77RklE52pZSKZx8sDXzrd2JCF/gL/hugFvsIBylpMRlJxxwesKn2rW7TcQZ809NocDVkQx1UJo9pJtVAPYg==", + "peerDependencies": { + "three": ">= 0.151.0" + } + }, "node_modules/tiny-emitter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", diff --git a/package.json b/package.json index 01743bb..3283552 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,8 @@ { "dependencies": { "mathjs": "^12.3.1", - "three": "^0.165.0" + "three": "^0.165.0", + "three-mesh-bvh": "^0.7.5" }, "devDependencies": { "vite": "^5.0.12" diff --git a/single-image-loader.js b/single-image-loader.js index 80f5334..95522bf 100644 --- a/single-image-loader.js +++ b/single-image-loader.js @@ -1,14 +1,26 @@ import * as THREE from "three"; import { create, all } from "mathjs"; +import { MeshBVH, acceleratedRaycast, computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh'; // BVH +THREE.Mesh.prototype.raycast = acceleratedRaycast; +THREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree; +THREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree; + + const math = create(all, {}); var raycaster = new THREE.Raycaster(); +raycaster.params.Line.threshold = 0.001; + var imageOffset = 0.2; var imageSize = 1; var images = []; + +const pickableObjects = []; + + function loadImage(scene, R, t, zoom, image_name, image_loader) { const pos = math.multiply(math.unaryMinus(math.transpose(R)), t); //View direction @@ -23,6 +35,7 @@ function loadImage(scene, R, t, zoom, image_name, image_loader) { -view_direction.get([2]) ); + // Afegir imatge const SCALE = 5 * imageSize; const image_path = "./images/low_res/" + image_name; @@ -60,7 +73,7 @@ function loadImage(scene, R, t, zoom, image_name, image_loader) { color: 0x0000ff, transparent: true, opacity: 0.5, - linewidth: 0.1, + linewidth: 0.2, }); const line = new THREE.Line(geometry, material); line.name = "wireframe-line"; @@ -95,7 +108,10 @@ function loadImage(scene, R, t, zoom, image_name, image_loader) { isLandscape: isLandscape, heightToWidthRatio: heightToWidthRelation, }; + console.log("Image: ", image_name, " Position: ", image_plane.position, " Direction: ", image_plane.userData.direction); + images.push(image_plane); + }); } @@ -132,24 +148,71 @@ function setWireframe(enable) { } function setIntersectionPosition(scene) { + console.log(scene); + + + var gltf = scene.getObjectByName("model"); + gltf.updateMatrixWorld(true); + gltf.traverse(function (child) { + if (child.isMesh) { + const m = child; // as THREE.Mesh + m.geometry.computeBoundsTree(); // BVH + pickableObjects.push(m); + } + }); + console.log("Pick:", pickableObjects); + + + var model = scene.getObjectByName("model"); + //var model = scene; + console.log(model); + console.log("Setting intersection positions for ", images.length, " images..."); + images.forEach((i) => { const intersectionPosition = getIntersectionPosition( - scene, + scene, + model, + pickableObjects, i.position, i.userData.direction ); i.userData.intersection = new THREE.Vector3().copy(intersectionPosition); }); + console.log("Setting intersection positions: done!"); } -function getIntersectionPosition(scene, position, direction) { +function getIntersectionPosition(scene, model, objs, position, direction) { raycaster.set(position, direction); - var intersections = raycaster.intersectObject(scene, true); - if (intersections.length == 0) return position; - for (let i = 0; i < intersections.length; i++) { - if (intersections[i].object.name != "wireframe") return intersections[i].point; + console.log("Position: ", position, " Direction: ", direction); + raycaster.firstHitOnly = true; // BVH + //var intersections = raycaster.intersectObjects(model, true); // BVH + /* + const invMat = new THREE.Matrix4(); + invMat.copy(model.matrixWorld).invert(); + raycaster.ray.applyMatrix4(invMat); + */ + + var intersections = raycaster.intersectObjects(objs, true); // BVH + + if (intersections.length == 0) + { + console.log("No intersection found"); + return position; + } + var i = 0; + var j = -1; + for ( ; i < intersections.length; i++) { + //if (intersections[i].object.name != "wireframe" && intersections[i].object.name != "wireframe-line" && intersections[i].object.name != "" && intersections[i].object.name[0] != "S") break; // return intersections[i].point; + console.log("Intersected:", intersections[i].object); + //if (intersections[i].object.name != "wireframe") j = i; + if (intersections[i].object.name[0] == "P") + { + j=i; + break; // return intersections[i].point; + } } - return position; + if (j!=-1) console.log("Position: ", position, " Intersection", intersections[j].point, intersections[j].object.name); + return intersections[j].point; } function setImageVisibility(show) { From de67fb8a99c0866b5c363c81e50533acca992cd2 Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sun, 16 Jun 2024 19:07:52 +0200 Subject: [PATCH 14/19] fixed spherical coords --- sphere.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphere.js b/sphere.js index 64aa7f2..b2d71b0 100644 --- a/sphere.js +++ b/sphere.js @@ -56,7 +56,7 @@ function get2DCoords(P) { const V = new THREE.Vector3().subVectors(P, C).normalize(); const phi = math.acos(V.y); const theta = math.atan2(V.x, V.z); - return { x: theta, y: phi }; + return { x: -theta, y: phi }; // TODO: Check if it is correct } function applySphericalRadius(r) { From a6c55ab16c650331d76c0d42408823fc5fb99f6f Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sun, 16 Jun 2024 19:08:21 +0200 Subject: [PATCH 15/19] minor changes for testing... --- multiple-image-loader.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/multiple-image-loader.js b/multiple-image-loader.js index cb227b7..b8a4e7b 100644 --- a/multiple-image-loader.js +++ b/multiple-image-loader.js @@ -5,6 +5,9 @@ import { create, all } from "mathjs"; const math = create(all, {}); + + + //Read Images file function read_image_list(filePath) { return new Promise((resolve) => { @@ -24,7 +27,7 @@ async function loadImages(scene, images_file, cameras_file) { const out_file_loader = new THREE.FileLoader(); out_file_loader.load(cameras_file, function (data) { const lines = data.split("\n"); - const num_cameras = lines[1].split(" ")[0]; + const num_cameras = Math.min(200, lines[1].split(" ")[0]) ; // TODO for (let i = 0; i < num_cameras; i++) { const line_number = 2 + 5 * i; @@ -34,6 +37,8 @@ async function loadImages(scene, images_file, cameras_file) { const focalLength = lines[line_number].split(" ").map(parseFloat)[0]; const zoom = math.sqrt(focalLength / min_focal); + //zoom *= 2; // TODO testing + const R = math.matrix([ lines[line_number + 1].split(" ").map(parseFloat), @@ -41,6 +46,9 @@ async function loadImages(scene, images_file, cameras_file) { lines[line_number + 3].split(" ").map(parseFloat), ]); const t = math.matrix(lines[line_number + 4].split(" ").map(parseFloat)); + + //if (!image_list[i].includes("0098")) continue; // TODO + loadImage(scene, R, t, zoom, image_list[i], image_loader); } }); From f5219f2b1f65b80742117821b6e273ca0fabc6e0 Mon Sep 17 00:00:00 2001 From: Carlos Andujar Date: Sun, 16 Jun 2024 19:09:03 +0200 Subject: [PATCH 16/19] Added a menu option for manually executing "distribute" --- openseadragon.html | 6 ++++++ openseadragon.js | 16 +++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/openseadragon.html b/openseadragon.html index 0fc2fb7..338dfa3 100644 --- a/openseadragon.html +++ b/openseadragon.html @@ -35,6 +35,12 @@ title="Use camera targets" > Use camera targets + Distribute
diff --git a/openseadragon.js b/openseadragon.js index c1a833f..20ffe7c 100644 --- a/openseadragon.js +++ b/openseadragon.js @@ -55,7 +55,7 @@ viewer.zoomPerClick = 1; viewer.addHandler("open", function () { if (mode === "single" || parsedImages.size == 1) return; - distribute(parsedImages); + //distribute(parsedImages); // testing }); viewer.addHandler("canvas-click", function (event) { @@ -85,8 +85,13 @@ viewer.addHandler("canvas-click", function (event) { } }); +function distrib() +{ + distribute(parsedImages); +} + function distribute(images) { - return; + //return; // TODO overlapping = true; for (let i = 0; overlapping; i++) { console.log("i: " + i); @@ -151,8 +156,9 @@ function getIntersection(a, b) { } function moveImage(a, output, i) { - a.x += output.x; - a.y += output.y; + const speed = 1.0; // testing + a.x += output.x*speed; + a.y += output.y*speed; var item = viewer.world.getItemAt(i); item.setPosition(new OpenSeadragon.Point(a.x - getWidth(a) / 2, a.y - getHeight(a) / 2)); } @@ -196,7 +202,7 @@ function recalculate() { item.setHeight(getHeight(a)); item.setPosition(new OpenSeadragon.Point(a.x - getWidth(a) / 2, a.y - getHeight(a) / 2)); } - distribute(parsedImages); + //distribute(parsedImages); } function max(a, b) { From 6932837243d0b54d936420989d3c94a715040c8c Mon Sep 17 00:00:00 2001 From: BernatBC Date: Wed, 26 Jun 2024 19:29:03 +0200 Subject: [PATCH 17/19] Improve Distribute-Overlapp button --- openseadragon.html | 19 +++++++------------ openseadragon.js | 33 +++++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/openseadragon.html b/openseadragon.html index 338dfa3..be69895 100644 --- a/openseadragon.html +++ b/openseadragon.html @@ -9,8 +9,6 @@ diff --git a/openseadragon.js b/openseadragon.js index 20ffe7c..db9fe6a 100644 --- a/openseadragon.js +++ b/openseadragon.js @@ -8,6 +8,7 @@ const parsedImages = JSON.parse(retrievedObject); var overlapping; var regularZoom = true; var realPosition = true; +var overlappingSet = false; console.log(mode); console.log(image); @@ -37,8 +38,6 @@ if (mode === "single") { } var viewer = OpenSeadragon({ - zoomInButton: "zoom-in", - zoomOutButton: "zoom-out", homeButton: "home", fullPageButton: "full-page", @@ -51,7 +50,7 @@ var viewer = OpenSeadragon({ maxZoomPixelRatio: 3, // for videos }); -viewer.zoomPerClick = 1; +viewer.zoomPerClick = 1; viewer.addHandler("open", function () { if (mode === "single" || parsedImages.size == 1) return; @@ -85,13 +84,25 @@ viewer.addHandler("canvas-click", function (event) { } }); -function distrib() -{ +function distrib() { + if (mode === "single" || parsedImages.size == 1) return; + overlappingSet = !overlappingSet; + + if (overlappingSet) { + document.getElementById("overlap").style.display = "inline"; + document.getElementById("distribute").style.display = "none"; + } else { + document.getElementById("overlap").style.display = "none"; + document.getElementById("distribute").style.display = "inline"; + } + + recalculate(); distribute(parsedImages); } function distribute(images) { - //return; // TODO + if (!overlappingSet) return; + //return; // TODO overlapping = true; for (let i = 0; overlapping; i++) { console.log("i: " + i); @@ -157,8 +168,8 @@ function getIntersection(a, b) { function moveImage(a, output, i) { const speed = 1.0; // testing - a.x += output.x*speed; - a.y += output.y*speed; + a.x += output.x * speed; + a.y += output.y * speed; var item = viewer.world.getItemAt(i); item.setPosition(new OpenSeadragon.Point(a.x - getWidth(a) / 2, a.y - getHeight(a) / 2)); } @@ -192,7 +203,9 @@ function togglePosition() { } function recalculate() { - console.log("Recalculating. Real position: " + realPosition + ". Regular zoom: " + regularZoom + "."); + console.log( + "Recalculating. Real position: " + realPosition + ". Regular zoom: " + regularZoom + "." + ); for (let i = 0; i < parsedImages.length; i++) { const a = parsedImages[i]; var item = viewer.world.getItemAt(i); @@ -202,7 +215,7 @@ function recalculate() { item.setHeight(getHeight(a)); item.setPosition(new OpenSeadragon.Point(a.x - getWidth(a) / 2, a.y - getHeight(a) / 2)); } - //distribute(parsedImages); + distribute(parsedImages); } function max(a, b) { From 235436e49ccbf548fe04653ae1a8d6d01c704349 Mon Sep 17 00:00:00 2001 From: BernatBC Date: Wed, 26 Jun 2024 19:41:29 +0200 Subject: [PATCH 18/19] Add all images --- multiple-image-loader.js | 6 +---- single-image-loader.js | 49 ++++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/multiple-image-loader.js b/multiple-image-loader.js index b8a4e7b..a9fbec8 100644 --- a/multiple-image-loader.js +++ b/multiple-image-loader.js @@ -5,9 +5,6 @@ import { create, all } from "mathjs"; const math = create(all, {}); - - - //Read Images file function read_image_list(filePath) { return new Promise((resolve) => { @@ -27,7 +24,7 @@ async function loadImages(scene, images_file, cameras_file) { const out_file_loader = new THREE.FileLoader(); out_file_loader.load(cameras_file, function (data) { const lines = data.split("\n"); - const num_cameras = Math.min(200, lines[1].split(" ")[0]) ; // TODO + const num_cameras = lines[1].split(" ")[0]; // TODO for (let i = 0; i < num_cameras; i++) { const line_number = 2 + 5 * i; @@ -39,7 +36,6 @@ async function loadImages(scene, images_file, cameras_file) { const zoom = math.sqrt(focalLength / min_focal); //zoom *= 2; // TODO testing - const R = math.matrix([ lines[line_number + 1].split(" ").map(parseFloat), lines[line_number + 2].split(" ").map(parseFloat), diff --git a/single-image-loader.js b/single-image-loader.js index 95522bf..c0d23d4 100644 --- a/single-image-loader.js +++ b/single-image-loader.js @@ -1,12 +1,11 @@ import * as THREE from "three"; import { create, all } from "mathjs"; -import { MeshBVH, acceleratedRaycast, computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh'; // BVH +import { MeshBVH, acceleratedRaycast, computeBoundsTree, disposeBoundsTree } from "three-mesh-bvh"; // BVH THREE.Mesh.prototype.raycast = acceleratedRaycast; THREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree; THREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree; - const math = create(all, {}); var raycaster = new THREE.Raycaster(); @@ -17,10 +16,8 @@ var imageSize = 1; var images = []; - const pickableObjects = []; - function loadImage(scene, R, t, zoom, image_name, image_loader) { const pos = math.multiply(math.unaryMinus(math.transpose(R)), t); //View direction @@ -35,10 +32,9 @@ function loadImage(scene, R, t, zoom, image_name, image_loader) { -view_direction.get([2]) ); - // Afegir imatge const SCALE = 5 * imageSize; - const image_path = "./images/low_res/" + image_name; + const image_path = "/images/low_res/" + image_name; const image_texture = image_loader.load(image_path, function () { image_texture.colorSpace = THREE.SRGBColorSpace; const isLandscape = image_texture.image.width > image_texture.image.height; @@ -108,10 +104,16 @@ function loadImage(scene, R, t, zoom, image_name, image_loader) { isLandscape: isLandscape, heightToWidthRatio: heightToWidthRelation, }; - console.log("Image: ", image_name, " Position: ", image_plane.position, " Direction: ", image_plane.userData.direction); + console.log( + "Image: ", + image_name, + " Position: ", + image_plane.position, + " Direction: ", + image_plane.userData.direction + ); images.push(image_plane); - }); } @@ -150,7 +152,6 @@ function setWireframe(enable) { function setIntersectionPosition(scene) { console.log(scene); - var gltf = scene.getObjectByName("model"); gltf.updateMatrixWorld(true); gltf.traverse(function (child) { @@ -161,16 +162,15 @@ function setIntersectionPosition(scene) { } }); console.log("Pick:", pickableObjects); - var model = scene.getObjectByName("model"); //var model = scene; console.log(model); - console.log("Setting intersection positions for ", images.length, " images..."); + console.log("Setting intersection positions for ", images.length, " images..."); images.forEach((i) => { const intersectionPosition = getIntersectionPosition( - scene, + scene, model, pickableObjects, i.position, @@ -193,25 +193,30 @@ function getIntersectionPosition(scene, model, objs, position, direction) { */ var intersections = raycaster.intersectObjects(objs, true); // BVH - - if (intersections.length == 0) - { + + if (intersections.length == 0) { console.log("No intersection found"); return position; } var i = 0; var j = -1; - for ( ; i < intersections.length; i++) { + for (; i < intersections.length; i++) { //if (intersections[i].object.name != "wireframe" && intersections[i].object.name != "wireframe-line" && intersections[i].object.name != "" && intersections[i].object.name[0] != "S") break; // return intersections[i].point; console.log("Intersected:", intersections[i].object); //if (intersections[i].object.name != "wireframe") j = i; - if (intersections[i].object.name[0] == "P") - { - j=i; - break; // return intersections[i].point; - } + if (intersections[i].object.name[0] == "P") { + j = i; + break; // return intersections[i].point; + } } - if (j!=-1) console.log("Position: ", position, " Intersection", intersections[j].point, intersections[j].object.name); + if (j != -1) + console.log( + "Position: ", + position, + " Intersection", + intersections[j].point, + intersections[j].object.name + ); return intersections[j].point; } From 6d4f925ddc2b7149067c4426bd9986a756d35335 Mon Sep 17 00:00:00 2001 From: BernatBC Date: Wed, 26 Jun 2024 20:10:19 +0200 Subject: [PATCH 19/19] Clear selection after multi select --- interaction.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/interaction.js b/interaction.js index 6ed7ede..c199d75 100644 --- a/interaction.js +++ b/interaction.js @@ -82,8 +82,8 @@ function onClick() { var rect = event.target.getBoundingClientRect(); var x = event.clientX - rect.left; var y = event.clientY - rect.top; - mouse.x = ( (x / event.target.clientWidth ) * 2) - 1; - mouse.y = (-(y / event.target.clientHeight) * 2) + 1; + mouse.x = (x / event.target.clientWidth) * 2 - 1; + mouse.y = -(y / event.target.clientHeight) * 2 + 1; /*mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; @@ -91,8 +91,7 @@ function onClick() { raycaster.setFromCamera(mouse, camera); var intersects = raycaster.intersectObject(scene, true); - if (intersects.length == 0) - { + if (intersects.length == 0) { console.log("No intersection detected."); return; } @@ -140,7 +139,7 @@ function openImagesToOpenSeaDragon() { localStorage.setItem("images", jsonContent); const url = "openseadragon.html?mode=multiple"; window.open(url, "_blank"); - // clearSelection(); + clearSelection(); } function clearSelection() { @@ -170,8 +169,8 @@ function onHover() { var rect = event.target.getBoundingClientRect(); var x = event.clientX - rect.left; var y = event.clientY - rect.top; - mouse.x = ( (x / event.target.clientWidth ) * 2) - 1; - mouse.y = (-(y / event.target.clientHeight) * 2) + 1; + mouse.x = (x / event.target.clientWidth) * 2 - 1; + mouse.y = -(y / event.target.clientHeight) * 2 + 1; /* mouse.x = (event.clientX / window.innerWidth) * 2 - 1;