/** * Fetch bounding box data from a JSON file in the specified directory. * @param {string} dirUrl - The directory URL where the boundingBox.json is located. * @returns {Promise>} - Returns a promise resolving to an array of 2D vectors. */ async function fetchBoundingBox(dirUrl) { try { // Extract the base directory by removing everything after the last "/" const baseDir = dirUrl.split('/')[0]; // Construct the full path for the boundingBox.json const boundingBoxPath = `${baseDir}/boundingBox.json`; // Use the loadJSONFile function to fetch the bounding box const jsonData = await loadJSONFile(boundingBoxPath); // Extract the sphere positions from the boundingBox data const spheres = jsonData.boundingBox.spheres || []; const vertices = spheres.map(sphere => new THREE.Vector2(sphere.x, sphere.z)); return vertices; } catch (error) { console.error('Erreur lors de la récupération des données de la bounding box :', error); throw error; } } /** * Sets up camera restriction using bounding box data. * @param {THREE.Camera} gCamera - The camera to restrict. * @param {THREE.Renderer} gRenderer - The renderer for rendering the scene. * @param {THREE.Scene} gRayMarchScene - The scene to which restrictions are applied. * @param {string} dirUrl - The directory URL where the boundingBox.json is located. */ async function setupCameraRestriction(gCamera, gRenderer, gRayMarchScene, dirUrl) { const fixedHeight = 0.5; // Fixed y-coordinate for the camera // Fetch the bounding box data const polygonVertices = await fetchBoundingBox(dirUrl); // Visualize the bounding box in the scene function createPolygonVisualization() { const material = new THREE.LineBasicMaterial({ color: 0x00ff00 }); const points = []; // Convert 2D points to 3D for visualization polygonVertices.forEach(vertex => { points.push(new THREE.Vector3(vertex.x, fixedHeight, vertex.y)); }); // Close the polygon by adding the first point to the end points.push(new THREE.Vector3(polygonVertices[0].x, fixedHeight, polygonVertices[0].y)); // Create a line geometry for visualization const geometry = new THREE.BufferGeometry().setFromPoints(points); const line = new THREE.Line(geometry, material); gRayMarchScene.add(line); // Add spheres to mark the vertices const sphereGeometry = new THREE.SphereGeometry(0.01, 16, 16); const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 }); polygonVertices.forEach(vertex => { const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); sphere.position.set(vertex.x, fixedHeight, vertex.y); gRayMarchScene.add(sphere); }); } createPolygonVisualization(); // Check if a point is inside the polygon function isPointInPolygon(point, vertices) { let intersects = 0; for (let i = 0; i < vertices.length; i++) { const v1 = vertices[i]; const v2 = vertices[(i + 1) % vertices.length]; if ((v1.y > point.y) !== (v2.y > point.y) && point.x < ((v2.x - v1.x) * (point.y - v1.y)) / (v2.y - v1.y) + v1.x) { intersects++; } } return intersects % 2 === 1; } // Restrict camera position based on bounding box function restrictCameraPosition() { gCamera.position.y = fixedHeight; const cameraPos2D = new THREE.Vector2(gCamera.position.x, gCamera.position.z); if (!isPointInPolygon(cameraPos2D, polygonVertices)) { let closestPoint = cameraPos2D; let minDistance = Infinity; for (let i = 0; i < polygonVertices.length; i++) { const v1 = polygonVertices[i]; const v2 = polygonVertices[(i + 1) % polygonVertices.length]; const closestPointOnEdge = closestPointOnLineSegment(cameraPos2D, v1, v2); const distance = cameraPos2D.distanceTo(closestPointOnEdge); if (distance < minDistance) { minDistance = distance; closestPoint = closestPointOnEdge; } } gCamera.position.x = closestPoint.x; gCamera.position.z = closestPoint.y; } } function closestPointOnLineSegment(point, v1, v2) { const lineVec = new THREE.Vector2().subVectors(v2, v1); const pointVec = new THREE.Vector2().subVectors(point, v1); const lineLen = lineVec.length(); const lineUnitVec = lineVec.normalize(); const projection = pointVec.dot(lineUnitVec); const t = Math.max(0, Math.min(lineLen, projection)); return new THREE.Vector2().copy(v1).add(lineUnitVec.multiplyScalar(t)); } function animate() { requestAnimationFrame(animate); restrictCameraPosition(); gRenderer.render(gRayMarchScene, gCamera); } animate(); }