From 9c9c44ec5fdbcd98295de48cd12b03f32778eebc Mon Sep 17 00:00:00 2001 From: Dmitry Romanov Date: Tue, 21 May 2024 12:49:24 -0400 Subject: [PATCH] Updates --- .../calorimetry.prettifier.ts | 94 ++++++++++++++++++- firebird-ng/src/app/geometry.service.ts | 3 +- .../main-display/main-display.component.ts | 91 ++++++++++++------ .../src/app/root-geometry.processor.ts | 22 +++-- .../src/app/three-geometry.processor.ts | 47 +++++----- .../src/app/utils/three-geometry-merge.ts | 2 +- firebird-ng/src/app/utils/three.utils.ts | 14 ++- 7 files changed, 205 insertions(+), 68 deletions(-) diff --git a/firebird-ng/src/app/geometry-prettifiers/calorimetry.prettifier.ts b/firebird-ng/src/app/geometry-prettifiers/calorimetry.prettifier.ts index 0fe62c4..3191349 100644 --- a/firebird-ng/src/app/geometry-prettifiers/calorimetry.prettifier.ts +++ b/firebird-ng/src/app/geometry-prettifiers/calorimetry.prettifier.ts @@ -26,10 +26,6 @@ export class CalorimetryGeometryPrettifier { // Support let innerSupport = findObject3DNodes(node, "**/inner_support*", "Mesh").nodes[0]; let ring = findObject3DNodes(node, "**/ring*", "Mesh").nodes[0]; - - // Ring is pretty with dark blue outline - createOutline(ring, 0x002a42); - const supportMaterial = new THREE.MeshStandardMaterial({ color: 0x19a5f5, roughness: 0.7, @@ -40,8 +36,98 @@ export class CalorimetryGeometryPrettifier { }); mergeResult = mergeMeshList([innerSupport, ring], node, "support", supportMaterial); + disposeOriginalMeshesAfterMerge(mergeResult); + + + // Cleanup. Removing useless nodes that were left without geometries speeds up overall rendering + pruneEmptyNodes(node); + } + + /** + * DRICH + * + * ---------------------------------------------------- + * */ + doDRICH(node: THREE.Mesh) { + + let sensors = findObject3DNodes(node, "**/*cooling*", "Mesh").nodes; + let aeroGel = findObject3DNodes(node, "**/*aerogel*", "Mesh").nodes[0]; + sensors.push(aeroGel); + let mergeResult = mergeMeshList(sensors, node, "sensors"); disposeOriginalMeshesAfterMerge(mergeResult) + let filter = findObject3DNodes(node, "**/*filter*", "Mesh").nodes[0]; + filter.visible = false; + let airGap = findObject3DNodes(node, "**/*airgap*", "Mesh").nodes[0]; + airGap.visible = false; + + + let mirrors = findObject3DNodes(node, "**/*mirror*", "Mesh").nodes; + const mirrorsMaterial = new THREE.MeshPhysicalMaterial({ + color: 0xfafafa, + roughness: 0.1, + metalness: 0.2, + reflectivity: 1.5, + clearcoat: 1, + depthTest: true, + depthWrite: true, + transparent: true, + envMapIntensity: 0.8, + opacity: 1, + side: THREE.DoubleSide + }); + + // Merge crystals together + mergeResult = mergeMeshList(mirrors, node, "mirrors", mirrorsMaterial); + disposeOriginalMeshesAfterMerge(mergeResult) + + // Cleanup. Removing useless nodes that were left without geometries speeds up overall rendering + pruneEmptyNodes(node); + } + + /** + * DIRC + * + * ---------------------------------------------------- + * */ + doDIRC(node: THREE.Mesh) { + + let bars = findObject3DNodes(node, "**/*box*", "Mesh").nodes; + let prisms = findObject3DNodes(node, "**/*prism*", "Mesh").nodes; + const barsPrisms = bars.concat(prisms); + + const barMat = new THREE.MeshPhysicalMaterial({ + color: 0xe5ba5d, + metalness: .9, + roughness: .05, + envMapIntensity: 0.9, + clearcoat: 1, + transparent: true, + //transmission: .60, + opacity: .6, + reflectivity: 0.2, + //refr: 0.985, + ior: 0.9, + side: THREE.DoubleSide, + }); + + + let mergeResult = mergeMeshList(barsPrisms, node, "barsPrisms", barMat); + disposeOriginalMeshesAfterMerge(mergeResult); + + createOutline(mergeResult.mergedMesh); + + // Rails + let rails = findObject3DNodes(node, "**/*rail*", "Mesh").nodes; + mergeResult = mergeMeshList(rails, node, "rails"); + disposeOriginalMeshesAfterMerge(mergeResult); + createOutline(mergeResult.mergedMesh); + + // MCPs + let mcps = findObject3DNodes(node, "**/*mcp*", "Mesh").nodes; + mergeResult = mergeMeshList(mcps, node, "mcps"); + disposeOriginalMeshesAfterMerge(mergeResult); + // Cleanup. Removing useless nodes that were left without geometries speeds up overall rendering pruneEmptyNodes(node); } diff --git a/firebird-ng/src/app/geometry.service.ts b/firebird-ng/src/app/geometry.service.ts index 27c8c34..57e5195 100644 --- a/firebird-ng/src/app/geometry.service.ts +++ b/firebird-ng/src/app/geometry.service.ts @@ -85,7 +85,8 @@ export class GeometryService { console.time('[GeoSrv]: Reading geometry from file'); const rootGeoManager = await findGeoManager(file) // await file.readObject(objectName); - // >oO console.log(geoManager); + // >oO + console.log(rootGeoManager); console.timeEnd('[GeoSrv]: Reading geometry from file'); diff --git a/firebird-ng/src/app/main-display/main-display.component.ts b/firebird-ng/src/app/main-display/main-display.component.ts index 67ee177..3d7de3c 100644 --- a/firebird-ng/src/app/main-display/main-display.component.ts +++ b/firebird-ng/src/app/main-display/main-display.component.ts @@ -103,6 +103,8 @@ export class MainDisplayComponent implements OnInit { side: side, transparent: true, opacity: 0.5, + depthTest: true, + depthWrite: true, clippingPlanes: openThreeManager.clipPlanes, clipIntersection: true, clipShadows: false @@ -214,8 +216,8 @@ export class MainDisplayComponent implements OnInit { const spherical = new THREE.Spherical().setFromVector3(currentPosition); // Adjusting spherical coordinates - spherical.theta -= xAxis * 0.05; // Azimuth angle change - spherical.phi += yAxis * 0.05; // Polar angle change, for rotating up/down + spherical.theta -= xAxis * 0.01; // Azimuth angle change + spherical.phi += yAxis * 0.01; // Polar angle change, for rotating up/down // Ensure phi is within bounds to avoid flipping spherical.phi = Math.max(0.1, Math.min(Math.PI - 0.1, spherical.phi)); @@ -228,6 +230,61 @@ export class MainDisplayComponent implements OnInit { camera.lookAt(controls.target); controls.update(); } + + // // Assume button indices 4 and 5 are the shoulder buttons + // const zoomInButton = gamepad.buttons[0]; + // const zoomOutButton = gamepad.buttons[2]; + // + // if (zoomInButton.pressed) { + // camera.zoom *= 1.05; + // console.log(camera); + // // Updating camera clipping planes dynamically + // //camera.near = 0.1; // Be cautious with making this too small, which can cause z-fighting + // //camera.far = 100000; // Large value to ensure distant objects are rendered + // + // camera.updateProjectionMatrix(); + // } + // + // if (zoomOutButton.pressed) { + // camera.zoom /= 1.05; + // // Updating camera clipping planes dynamically + // //camera.near = 0.1; // Be cautious with making this too small, which can cause z-fighting + // //camera.far = 100000; // Large value to ensure distant objects are rendered + // camera.updateProjectionMatrix(); + // console.log(camera); + // } + // + // // Optionally: Map other axes/buttons to other camera controls like zoom or pan + // if (gamepad.axes.length > 2) { + // // Additional axes for more control, e.g., zoom with third axis + // const zoomAxis = gamepad.axes[2]; // Typically the right stick vertical + // camera.position.z += zoomAxis * 0.1; // Adjust zoom sensitivity + // } + + // Zooming using buttons + const zoomInButton = gamepad.buttons[2]; + const zoomOutButton = gamepad.buttons[0]; + + if (zoomInButton.pressed) { + controls.object.position.subVectors(camera.position, controls.target).multiplyScalar(0.99).add(controls.target); + controls.update(); + } + + if (zoomOutButton.pressed) { + controls.object.position.subVectors(camera.position, controls.target).multiplyScalar(1.01).add(controls.target); + controls.update(); + } + + // Zooming using the third axis of the gamepad + const zoomAxis = gamepad.axes[2]; // Typically the right stick vertical + if (Math.abs(zoomAxis) > 0.1) { + let zoomFactor = zoomAxis < 0 ? 0.95 : 1.05; + controls.object.position.subVectors(camera.position, controls.target).multiplyScalar(zoomFactor).add(controls.target); + controls.update(); + } + + break; // Only use the first connected gamepad + // // // if (Math.abs(xAxis) > 0.1 || Math.abs(yAxis) > 0.1) { @@ -257,35 +314,7 @@ export class MainDisplayComponent implements OnInit { // controls.update(); // } - // Assume button indices 4 and 5 are the shoulder buttons - const zoomInButton = gamepad.buttons[0]; - const zoomOutButton = gamepad.buttons[2]; - - if (zoomInButton.pressed) { - camera.zoom *= 1.05; - // Updating camera clipping planes dynamically - //camera.near = 0.1; // Be cautious with making this too small, which can cause z-fighting - //camera.far = 100000; // Large value to ensure distant objects are rendered - - camera.updateProjectionMatrix(); - } - - if (zoomOutButton.pressed) { - camera.zoom /= 1.05; - // Updating camera clipping planes dynamically - //camera.near = 0.1; // Be cautious with making this too small, which can cause z-fighting - //camera.far = 100000; // Large value to ensure distant objects are rendered - camera.updateProjectionMatrix(); - } - - // Optionally: Map other axes/buttons to other camera controls like zoom or pan - if (gamepad.axes.length > 2) { - // Additional axes for more control, e.g., zoom with third axis - const zoomAxis = gamepad.axes[2]; // Typically the right stick vertical - camera.position.z += zoomAxis * 0.1; // Adjust zoom sensitivity - } - break; // Only use the first connected gamepad // // //console.log(`Using gamepad at index ${gamepad.index}: ${gamepad.id}`); // gamepad.axes.forEach((axis, index) => { @@ -371,7 +400,7 @@ export class MainDisplayComponent implements OnInit { - // threeManager.setAnimationLoop(()=>{this.handleGamepadInput()}); + threeManager.setAnimationLoop(()=>{this.handleGamepadInput()}); //const events_url = "https://eic.github.io/epic/artifacts/sim_dis_10x100_minQ2=1000_epic_craterlake.edm4hep.root/sim_dis_10x100_minQ2=1000_epic_craterlake.edm4hep.root" diff --git a/firebird-ng/src/app/root-geometry.processor.ts b/firebird-ng/src/app/root-geometry.processor.ts index dbcc982..1475349 100644 --- a/firebird-ng/src/app/root-geometry.processor.ts +++ b/firebird-ng/src/app/root-geometry.processor.ts @@ -49,15 +49,15 @@ export class RootGeometryProcessor { */ removeDetectorNames: string[] = [ "Lumi", - "Magnet", - "B0", + //"Magnet", + //"B0", "B1", "B2", - "Q0", - "Q1", + //"Q0", + //"Q1", "Q2", - "BeamPipe", - "Pipe", + //"BeamPipe", + //"Pipe", "ForwardOffM", "Forward", "Backward", @@ -88,6 +88,16 @@ export class RootGeometryProcessor { {pattern: "*/DRICH_cooling*", action: EditActions.RemoveSiblings}, ] }, + { + namePattern: "*/DIRC*", + editRules: [ + {pattern: "*/Envelope_box*", action: EditActions.RemoveChildren}, + {pattern: "*/Envelope_box*", action: EditActions.SetGeoBit, geoBit: GeoAttBits.kVisThis}, + {pattern: "*/Envelope_box*", action: EditActions.UnsetGeoBit, geoBit: GeoAttBits.kVisNone}, + {pattern: "*/Envelope_box*", action: EditActions.UnsetGeoBit, geoBit: GeoAttBits.kVisDaughters}, + {pattern: "*/Envelope_lens_vol*", action: EditActions.Remove}, + ] + }, { namePattern: "*/EcalEndcapN*", editRules: [ diff --git a/firebird-ng/src/app/three-geometry.processor.ts b/firebird-ng/src/app/three-geometry.processor.ts index a9a5983..552eb1b 100644 --- a/firebird-ng/src/app/three-geometry.processor.ts +++ b/firebird-ng/src/app/three-geometry.processor.ts @@ -10,8 +10,9 @@ import {color} from "three/examples/jsm/nodes/shadernode/ShaderNode"; import {getGeoNodesByLevel} from "./utils/cern-root.utils"; import {produceRenderOrder} from "jsrootdi/geom"; import {wildCardCheck} from "./utils/wildcard"; -import {disposeHierarchy, findObject3DNodes} from "./utils/three.utils"; +import {createOutline, disposeHierarchy, findObject3DNodes, pruneEmptyNodes} from "./utils/three.utils"; import {CalorimetryGeometryPrettifier} from "./geometry-prettifiers/calorimetry.prettifier"; +import {mergeBranchGeometries} from "./utils/three-geometry-merge"; export class ThreeGeometryProcessor { @@ -111,26 +112,30 @@ export class ThreeGeometryProcessor { // uiManager.addGeometry(obj3dNode, obj3dNode.name); if(detNode.name == "EcalEndcapN_21") { - this.calorimetry.doEndcapEcalN(detNode) - } else { - - try { - detNode.removeFromParent(); - } - catch (e) { - console.error(e); - } - - - try { - console.log("disposeHierarchy: ", detNode.name, detNode); - disposeHierarchy(detNode); - } catch (e) { - console.error(e); - } - - - //mergeBranchGeometries(obj3dNode, obj3dNode.name + "_merged"); + this.calorimetry.doEndcapEcalN(detNode); + } else if(detNode.name == "DRICH_16") { + this.calorimetry.doDRICH(detNode); + } else if(detNode.name.startsWith("DIRC")) { + this.calorimetry.doDIRC(detNode); + } else{ + + // try { + // detNode.removeFromParent(); + // } + // catch (e) { + // console.error(e); + // } + // + // try { + // // console.log("disposeHierarchy: ", detNode.name, detNode); + // disposeHierarchy(detNode); + // } catch (e) { + // console.error(e); + // } + + let result = mergeBranchGeometries(detNode, detNode.name + "_merged"); + createOutline(result.mergedMesh); + pruneEmptyNodes(detNode); } } diff --git a/firebird-ng/src/app/utils/three-geometry-merge.ts b/firebird-ng/src/app/utils/three-geometry-merge.ts index f6b6054..d238490 100644 --- a/firebird-ng/src/app/utils/three-geometry-merge.ts +++ b/firebird-ng/src/app/utils/three-geometry-merge.ts @@ -30,7 +30,7 @@ export class NoMaterialError extends Error { * @param material Material to assign to the merged geometry, if empty the first material found will be used * @returns MergeResult object containing the merged geometry, material, children to remove, and parent node */ -export function mergeBranchGeometries(parentNode: THREE.Object3D, name: string, material: THREE.Material | undefined): MergeResult { +export function mergeBranchGeometries(parentNode: THREE.Object3D, name: string, material?: THREE.Material | undefined): MergeResult { const geometries: THREE.BufferGeometry[] = []; const childrenToRemove: THREE.Object3D[] = []; diff --git a/firebird-ng/src/app/utils/three.utils.ts b/firebird-ng/src/app/utils/three.utils.ts index a3d020c..36a590a 100644 --- a/firebird-ng/src/app/utils/three.utils.ts +++ b/firebird-ng/src/app/utils/three.utils.ts @@ -153,19 +153,25 @@ class NoGeometryError extends Error { } } +export interface CreateOutlineOptions { + color?: THREE.ColorRepresentation; + material?: THREE.Material; + thresholdAngle?: number; +} /** * Applies an outline mesh from lines to a mesh and adds the outline to the mesh's parent. * @param mesh A THREE.Object3D (expected to be a Mesh) to process. - * @param material Optional material provided by the user. If not provided, a default material is created. - * @param color Color of material + * @param options */ -export function createOutline(mesh: any, color?: THREE.ColorRepresentation, material?: THREE.Material): void { +export function createOutline(mesh: any, options: CreateOutlineOptions = {}): void { if (!mesh?.geometry) { throw new NoGeometryError(mesh); } - let edges = new THREE.EdgesGeometry(mesh.geometry, 30); + let { color = 0x555555, material, thresholdAngle = 40 } = options || {}; + + let edges = new THREE.EdgesGeometry(mesh.geometry, thresholdAngle); let lineMaterial = material as THREE.LineBasicMaterial; if (!lineMaterial) {