From ec236b7f49204138ca8233ef825dbc1038a156c3 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Sat, 6 Nov 2021 00:21:44 -0700 Subject: [PATCH 01/84] Update to RenderCore release from github. --- tutorials/eve7/event_demo.C | 6 +- ui5/eve7/lib/EveElementsRCore.js | 72 +- ui5/eve7/lib/GlViewerRCore.js | 124 +- ui5/eve7/lib/REveCameraControls.js | 1191 ++++++++++++++++++ ui5/eve7/lib/REveRenderCore.js | 4 + ui5/eve7/lib/RendeQuTor.js | 206 +-- ui5/eve7/shaders/custom/copyDepth2RReve.frag | 18 +- 7 files changed, 1419 insertions(+), 202 deletions(-) create mode 100644 ui5/eve7/lib/REveCameraControls.js create mode 100644 ui5/eve7/lib/REveRenderCore.js diff --git a/tutorials/eve7/event_demo.C b/tutorials/eve7/event_demo.C index dd3e64005ac88..e06766a7c2483 100644 --- a/tutorials/eve7/event_demo.C +++ b/tutorials/eve7/event_demo.C @@ -140,7 +140,7 @@ void addJets() jet->AddEllipticCone(r.Uniform(-3.5, 3.5), r.Uniform(0, TMath::TwoPi()), r.Uniform(0.02, 0.2), r.Uniform(0.02, 0.3)); jet->SetFillColor(kPink - 8); - jet->SetLineColor(kViolet - 7); + jet->SetLineColor(kBlack); jetHolder->AddElement(jet); } @@ -199,7 +199,9 @@ void projectScenes(bool geomp, bool eventp) { for (auto &ie : eveMng->GetGlobalScene()->RefChildren()) { + mngRhoPhi->SetCurrentDepth(0); mngRhoPhi->ImportElements(ie, rPhiGeomScene); + mngRhoZ ->SetCurrentDepth(0); mngRhoZ ->ImportElements(ie, rhoZGeomScene); } } @@ -207,7 +209,9 @@ void projectScenes(bool geomp, bool eventp) { for (auto &ie : eveMng->GetEventScene()->RefChildren()) { + mngRhoPhi->SetCurrentDepth(10); mngRhoPhi->ImportElements(ie, rPhiEventScene); + mngRhoZ ->SetCurrentDepth(10); mngRhoZ ->ImportElements(ie, rhoZEventScene); } } diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index d17468ebde608..d490d17aa9d57 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -9,8 +9,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // EveElemControl //============================================================================== - class EveElemControl { - + class EveElemControl + { constructor(o3d) { @@ -47,10 +47,6 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } // class EveElemControl - /// is it necessary? - EveElemControl.prototype.separateDraw = false; - - //============================================================================== // EveElements @@ -66,8 +62,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) //------------------------------------------------------------------------------ - class EveElements { - + class EveElements + { constructor(rc) { console.log("EveElements -- RCore"); @@ -75,6 +71,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) this.POINT_SIZE_FAC = 1; this.LINE_WIDTH_FAC = 1; + this.ColorWhite = new RC.Color(0xFFFFFF); + this.ColorBlack = new RC.Color(0x000000); } SetupPointLineFacs(pf, lf) @@ -104,12 +102,34 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return mat; } + RcFlatMaterial(color, opacity, props) + { + let mat = new RC.MeshBasicMaterial; + mat._color = color; + mat._emissive = color; // mat.emissive.offsetHSL(0, 0.1, 0); + + if (opacity !== undefined && opacity < 1.0) + { + mat._opacity = opacity; + mat._transparent = true; + mat._depthWrite = false; + } + if (props !== undefined) + { + mat.update(props); + } + return mat; + } + RcFancyMaterial(color, opacity, props) { let mat = new RC.MeshPhongMaterial; // let mat = new RC.MeshBasicMaterial; mat._color = color; + mat._specular = new RC.Color(0xFFFFFF); // mat._specular.offsetHSL(0, 0, 0.4); + mat._shininess = 32; + if (opacity !== undefined && opacity < 1.0) { mat._opacity = opacity; @@ -127,7 +147,10 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) { if (el.fPickable) { obj3d.get_ctrl = function() { return new ctrl_class(obj3d); } - obj3d.colorID = el.fElementId; + obj3d.pickable = true; + for (let i = 0; i < obj3d.children.length; ++i) + obj3d.children[i].pickable = true; + // using auto-id now obj3d.colorID = el.fElementId; // console.log("YES Pickable for", el.fElementId, el.fName) return true; } else { @@ -174,9 +197,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) pm.usePoints = true; pm.drawCircles = true; - // mesh.get_ctrl = function() { return new EveElemControl(this); } - this.RcPickable(hit, pnts); + pnts.dispose = function() { delete this; } // ???? return pnts; } @@ -254,6 +276,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) //line.hightlightWidthScale = 2; this.RcPickable(track, line); + line.dispose = function() { /*delete this.geometry; delete this.material;*/ }; return line; } @@ -310,9 +333,13 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) mesh.add(line1); mesh.add(line2); - - // mesh.get_ctrl = function () { return new EveElemControl(this); } this.RcPickable(jet, mesh); + + mesh.dispose = function() { + //this.children.forEach(c => { delete c.geometry; delete c.material; }); + //delete this.geometry; delete this.material; + }; + return mesh; } @@ -354,7 +381,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // console.log("cols", fcol, lcol); // double-side material required for correct tracing of colors - otherwise points sequence should be changed - let mesh = new RC.Mesh(geo_body, this.RcFancyMaterial(fcol, 0.5)); + let mesh = new RC.Mesh(geo_body, this.RcFlatMaterial(fcol, 0.5)); let line1 = new RC.Line(geo_rim, this.RcLineMaterial(lcol, 0.8, 2)); @@ -363,9 +390,13 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) mesh.add(line1); mesh.add(line2); - - // mesh.get_ctrl = function () { return new EveElemControl(this); } this.RcPickable(jet, mesh); + + mesh.dispose = function() { + //this.children.forEach(c => { delete c.geometry; delete c.material; }); + //delete this.geometry; delete this.material; + }; + return mesh; } @@ -430,10 +461,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let fcol = RcCol(psp.fMainColor); - let material = this.RcFancyMaterial(fcol, 0.4); + let material = this.RcFlatMaterial(fcol, 0.4); material.side = RC.FRONT_AND_BACK_SIDE; - material.specular = new RC.Color(1, 1, 1); - material.shininess = 50; let line_mat = this.RcLineMaterial(fcol); @@ -473,6 +502,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } } + this.RcPickable(psp, psp_ro); return psp_ro; } @@ -552,8 +582,4 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } // class EveElements - //============================================================================== - - return EveElements; - }); diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index eac9058485557..2a8c790597332 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -45,23 +45,11 @@ sap.ui.define([ // // console.log(window.location.pathname); // where are we loading from? // import("https://desire.physics.ucsd.edu/matevz/alja.github.io/rootui5/eve7/rnr_core/RenderCore.js").then((module) => { - import("../../eve7/rnr_core/RenderCore.js").then((module) => { + import("../../eve7/lib/REveRenderCore.js").then((module) => { console.log("GlViewerRCore.onInit - RenderCore.js loaded"); RC = module; - if (this.UseRenderQueue) - { - import("../../eve7/lib/RendeQuTor.js").then((module) => { - console.log("GlViewerRCore.onInit - RenderPassesRCore.js loaded"); - - RP = module; - RendeQuTor = RP.RendeQuTor; - - pthis.bootstrap(); - }); - } else { - pthis.bootstrap(); - } + pthis.bootstrap(); }); } @@ -70,10 +58,12 @@ sap.ui.define([ this.creator = new EveElements(RC); // this.creator.useIndexAsIs = EVE.JSR.decodeUrl().has('useindx'); + RC.Object3D.sDefaultPickable = false; + this.createRCoreRenderer(); this.controller.createScenes(); this.controller.redrawScenes(); - this.setupRCoreDomAndEventHandlers(); + this.setupEventHandlers(); this.controller.glViewerInitDone(); @@ -110,16 +100,17 @@ sap.ui.define([ this.canvas.id = "rcore-canvas"; this.canvas.width = w; this.canvas.height = h; + this.get_view().getDomRef().appendChild(this.canvas); + + this.canvas.canvasDOM = this.canvas; // RCore wants this in GLManager ctor ? - // Enable EXT_color_buffer_float for picking depth extraction - // let gl = this.canvas.getContext("webgl2"); - // let ex = gl.getExtension("EXT_color_buffer_float"); - // console.log("Create RCore, gl, float_color_buff:", gl, ex); + let gl = this.canvas.getContext("webgl2"); this.renderer = new RC.MeshRenderer(this.canvas, RC.WEBGL2, {antialias: false, stencil: true}); this.renderer.clearColor = "#FFFFFFFF"; - this.renderer.addShaderLoaderUrls("rootui5sys/eve7/rnr_core/shaders"); + this.renderer.addShaderLoaderUrls("rootui5sys/eve7/lib/RC/shaders"); this.renderer.addShaderLoaderUrls("rootui5sys/eve7/shaders"); + this.renderer.pickObject3D = true; this.renderer.pickDoNotRender = true; this.scene = new RC.Scene(); @@ -135,7 +126,7 @@ sap.ui.define([ if (this.controller.isEveCameraPerspective()) { - this.camera = new RC.PerspectiveCamera(75, w / h, 1, 5000); + this.camera = new RC.PerspectiveCamera(75, w / h, 20, 4000); this.camera.position = new RC.Vector3(-500, 0, 0); this.camera.lookAt(new RC.Vector3(0, 0, 0), new RC.Vector3(0, 1, 0)); this.camera.isPerspectiveCamera = true; @@ -148,39 +139,41 @@ sap.ui.define([ // Lights are positioned in resetRenderer. - for (let i = 1; i <= 4; ++i) - { - let l = this.lights.children[i]; - l.add( new RC.IcoSphere(1, 1, 10.0, l.color.clone().multiplyScalar(0.5), false) ); - } + // Markers on light positions (screws up bounding box / camera reset calculations) + // for (let i = 1; i <= 4; ++i) + // { + // let l = this.lights.children[i]; + // l.add( new RC.IcoSphere(1, 1, 10.0, l.color.clone().multiplyScalar(0.5), false) ); + // } } else { - this.camera = new RC.OrthographicCamera(-w/2, w/2, -h/2, h/2, 0, 2000); - this.camera.position = new RC.Vector3(0, 0, 500); + this.camera = new RC.OrthographicCamera(-w/2, w/2, -h/2, h/2, 20, 2000); + this.camera.position = new RC.Vector3(0, 0, 50); this.camera.lookAt(new RC.Vector3(0, 0, 0), new RC.Vector3(0, 1, 0)); this.camera.isOrthographicCamera = true; - this.lights.add(new light_class_2d( 0xffffff, 1 )); // white front - this.lights.add(new light_class_2d( 0xffffff, 1 )); // white back + let l_int = 0.85; + this.lights.add(new light_class_2d( 0xffffff, l_int )); // white front + this.lights.add(new light_class_2d( 0xffffff, l_int )); // white back // Lights are positioned in resetRenderer. } // Test objects - if (this.controller.kind === "3D") + if (this.controller.isEveCameraPerspective()) { - /* - let c = new RC.Cube(100, new RC.Color(1,.6,.2)); + let c = new RC.Cube(40, new RC.Color(0.2,.4,.8)); c.material = new RC.MeshPhongMaterial(); c.material.transparent = true; - c.material.opacity = 0.5; + c.material.opacity = 0.8; c.material.depthWrite = false; this.scene.add(c); - */ - let ss = new RC.Stripe([0,0,0, 100,50,50, 100,200,200]); + + let ss = new RC.Stripe([0,0,0, 100,50,50, 100,200,200, 300,300,300]); ss.material.lineWidth = 20.0; ss.material.color = new RC.Color(0xff0000); + ss.material.emissive = new RC.Color(0x008080); this.scene.add(ss); } @@ -188,7 +181,7 @@ sap.ui.define([ if (this.UseRenderQueue) { - this.rqt = new RendeQuTor(this.renderer, this.scene, this.camera); + this.rqt = new RC.RendeQuTor(this.renderer, this.scene, this.camera); if (this.RQ_Mode == "Direct") { this.rqt.initDirectToScreen(); @@ -207,10 +200,9 @@ sap.ui.define([ } } - setupRCoreDomAndEventHandlers() + setupEventHandlers() { let dome = this.get_view().getDomRef(); - dome.appendChild(this.canvas); // Setup tooltip this.ttip = document.createElement('div'); @@ -277,7 +269,6 @@ sap.ui.define([ // Key-handlers go on window ... window.addEventListener('keydown', function(event) { - // console.log("GLC::keydown", event.key, event.code, event); let handled = true; @@ -359,7 +350,7 @@ sap.ui.define([ console.log("GlViewerRenderCore.resetRenderer", sbbox, posV, negV, extV, extR); - if (this.controller.kind === "3D") // (this.camera.isPerspectiveCamera) + if (this.camera.isPerspectiveCamera) { let posC = new RC.Vector3(-0.7 * extR, 0.5 * extR, -0.7 * extR); @@ -374,7 +365,7 @@ sap.ui.define([ lc[3].position.set( extR, extR, extR); lc[3].decay = 4 * extR; lc[4].position.set(-extR, extR, -extR); lc[4].decay = 4 * extR; - // console.log("resetThreejsRenderer 3D scene bbox ", sbbox, ", camera_pos ", posC, ", look_at ", this.rot_center); + // console.log("resetRenderer 3D scene bbox ", sbbox, ", camera_pos ", posC, ", look_at ", this.rot_center); } else { @@ -400,7 +391,7 @@ sap.ui.define([ lc[1].position.set( 0, 0, extR); lc[2].position.set( 0, 0, -extR); - // console.log("resetThreejsRenderer 2D scene bbox ex ey", sbbox, ex, ey, ", camera_pos ", posC, ", look_at ", this.rot_center); + // console.log("resetRenderer 2D scene bbox ex ey", sbbox, ex, ey, ", camera_pos ", posC, ", look_at ", this.rot_center); } this.controls.target.copy( this.rot_center ); @@ -415,6 +406,8 @@ sap.ui.define([ { // console.log("RENDER", this.scene, this.camera, this.canvas, this.renderer); + if (this.canvas.width <= 0 || this.canvas.height <= 0) return; + if (this.UseRenderQueue) this.rqt.render(); else @@ -427,13 +420,15 @@ sap.ui.define([ render_for_picking(x, y) { console.log("RENDER FOR PICKING", this.scene, this.camera, this.canvas, this.renderer); - let o3d; - this.renderer.pick(x, y, function(id) { o3d = id; } ); + if (this.canvas.width <= 0 || this.canvas.height <= 0) return; + + this.renderer.pick(x, y); this.rqt.pick(this.scene, this.camera); + let o3d = this.renderer.pickedObject3D; // Render to FBO or texture would work. - // let d = pthis.renderer.pickedDepth; + // let d = this.renderer.pickedDepth; console.log("pick result", o3d /* , d */); return o3d; } @@ -445,6 +440,11 @@ sap.ui.define([ let w = this.get_width(); let h = this.get_height(); + if ( ! this.canvas) { + console.log("GlViewerRCore onResizeTimeout", w, h, "canvas IS NOT SET, STOP CALLING ME!"); + return; + } + //console.log("GlViewerRCore onResizeTimeout", w, h, "canvas=", this.canvas, this.canvas.width, this.canvas.height); this.canvas.width = w; @@ -495,37 +495,17 @@ sap.ui.define([ console.log("GLC::onMouseMoveTimeout", x, y); let o3d = this.render_for_picking(x, y); - if (o3d) - { + if (!o3d) return null; + if (!o3d.get_ctrl) o3d = o3d.parent; + if (o3d.get_ctrl) { + if (!o3d.get_ctrl) o3d = o3d.parent; let w = this.get_width(); let h = this.get_height(); let mouse = new RC.Vector2( ((x + 0.5) / w) * 2 - 1, -((y + 0.5) / h) * 2 + 1 ); return { object: o3d, mouse: mouse, w: w, h: h }; } - else - return null; - - /* - let mouse = new RC.Vector2( ((x + 0.5) / w) * 2 - 1, -((y + 0.5) / h) * 2 + 1 ); - - this.raycaster.setFromCamera(mouse, this.camera); - - let intersects = this.raycaster.intersectObjects(this.scene.children, true); - - let o = null, c = null; - - for (let i = 0; i < intersects.length; ++i) - { - if (intersects[i].object.get_ctrl) - { - intersects[i].mouse = mouse; - intersects[i].w = w; - intersects[i].h = h; - return intersects[i]; - } - } - */ - } + return null; + }, onMouseMoveTimeout(x, y) { diff --git a/ui5/eve7/lib/REveCameraControls.js b/ui5/eve7/lib/REveCameraControls.js new file mode 100644 index 0000000000000..c4084dc5c85c0 --- /dev/null +++ b/ui5/eve7/lib/REveCameraControls.js @@ -0,0 +1,1191 @@ +/** Taken from THREE OrbitCameraControls + * @author qiao / https://github.com/qiao + * @author mrdoob / http://mrdoob.com + * @author alteredq / http://alteredqualia.com/ + * @author WestLangley / http://github.com/WestLangley + * @author erich666 / http://erichaines.com + * @author ScieCode / http://github.com/sciecode + * @author osschar + */ + +// This set of controls performs orbiting, dollying (zooming), and panning. +// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). +// +// Orbit - left mouse / touch: one-finger move +// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish +// Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move + +// Requires the following to be set on Camera passed. +// this.camera.isPerspectiveCamera = true; +// or +// this.camera.isOrthographicCamera = true; + +// This should be further cleaned up and classed ... + +import {EventDispatcher} from './RC/core/EventDispatcher.js'; +import {Vector3} from './RC/math/Vector3.js'; +import {Vector2} from './RC/math/Vector2.js'; +import {Quaternion} from './RC/math/Quaternion.js'; +import {Spherical} from './RC/math/Spherical.js'; + + +export class REveCameraControls extends EventDispatcher +{ + constructor( object, domElement ) + { + var MOUSE = { ROTATE: 0, DOLLY: 1, PAN: 2 }; + var TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; + + super(EventDispatcher); + + this.object = object; + + this.domElement = ( domElement !== undefined ) ? domElement : document; + + // Set to false to disable this control + this.enabled = true; + + // "target" sets the location of focus, where the object orbits around + this.target = new Vector3(); + + // How far you can dolly in and out ( PerspectiveCamera only ) + this.minDistance = 0; + this.maxDistance = Infinity; + + // How far you can zoom in and out ( OrthographicCamera only ) + this.minZoom = 0; + this.maxZoom = Infinity; + + // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. + this.minPolarAngle = 0; // radians + this.maxPolarAngle = Math.PI; // radians + + // How far you can orbit horizontally, upper and lower limits. + // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. + this.minAzimuthAngle = - Infinity; // radians + this.maxAzimuthAngle = Infinity; // radians + + // Set to true to enable damping (inertia) + // If damping is enabled, you must call controls.update() in your animation loop + this.enableDamping = false; + this.dampingFactor = 0.05; + + // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. + // Set to false to disable zooming + this.enableZoom = true; + this.zoomSpeed = 1.0; + + // Set to false to disable rotating + this.enableRotate = true; + this.rotateSpeed = 1.0; + + // Set to false to disable panning + this.enablePan = true; + this.panSpeed = 1.0; + this.screenSpacePanning = false; // if true, pan in screen-space + this.keyPanSpeed = 7.0; // pixels moved per arrow key push + + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, you must call controls.update() in your animation loop + this.autoRotate = false; + this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 + + // Set to false to disable use of the keys + this.enableKeys = true; + + // The four arrow keys + this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; + + // Mouse buttons + this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN }; + + // Touch fingers + this.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN }; + + // for reset + this.target0 = this.target.clone(); + this.position0 = this.object.position.clone(); + this.zoom0 = this.object.zoom; + + // + // public methods + // + + this.getPolarAngle = function () { + + return spherical.phi; + + }; + + this.getAzimuthalAngle = function () { + + return spherical.theta; + + }; + + this.saveState = function () { + + scope.target0.copy( scope.target ); + scope.position0.copy( scope.object.position ); + scope.zoom0 = scope.object.zoom; + + }; + + this.reset = function () { + + scope.target.copy( scope.target0 ); + scope.object.position.copy( scope.position0 ); + scope.object.zoom = scope.zoom0; + + scope.object.updateProjectionMatrix(); + scope.dispatchEvent( changeEvent ); + + scope.update(); + + state = STATE.NONE; + + }; + + // osschar - need to reset internal panOffset + this.resetOrthoPanZoom = function () + { + return function resetOrthoPan() { + panOffset.set(0,0,0); + scope.object.zoom = 1; + scope.object.updateProjectionMatrix(); + zoomChanged = true; + } + }(); + + // osschar - fake mouse up event, needed for context menu on M3 down + this.resetMouseDown = function (event) + { + return function resetMouseDown(event) { + onMouseUp(event); + } + }(); + + // this method is exposed, but perhaps it would be better if we can make it private... + this.update = function () { + + var offset = new Vector3(); + + // so camera.up is the orbit axis + var quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) ); + var quatInverse = quat.clone().inverse(); + + var lastPosition = new Vector3(); + var lastQuaternion = new Quaternion(); + + return function update() { + + var position = scope.object.position; + + offset.copy( position ).sub( scope.target ); + + // rotate offset to "y-axis-is-up" space + offset.applyQuaternion( quat ); + + // angle from z-axis around y-axis + spherical.setFromVector3( offset ); + + if ( scope.autoRotate && state === STATE.NONE ) { + + rotateLeft( getAutoRotationAngle() ); + + } + + if ( scope.enableDamping ) { + + spherical.theta += sphericalDelta.theta * scope.dampingFactor; + spherical.phi += sphericalDelta.phi * scope.dampingFactor; + + } else { + + spherical.theta += sphericalDelta.theta; + spherical.phi += sphericalDelta.phi; + + } + + // restrict theta to be between desired limits + spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) ); + + // restrict phi to be between desired limits + spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) ); + + spherical.makeSafe(); + + + spherical.radius *= scale; + + // restrict radius to be between desired limits + spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); + + // move target to panned location + + if ( scope.enableDamping === true ) { + + scope.target.addScaledVector( panOffset, scope.dampingFactor ); + + } else { + + scope.target.add( panOffset ); + + } + + offset.setFromSpherical( spherical ); + + // rotate offset back to "camera-up-vector-is-up" space + offset.applyQuaternion( quatInverse ); + + position.copy( scope.target ).add( offset ); + + scope.object.lookAt( scope.target, scope.object.up ); + + if ( scope.enableDamping === true ) { + + sphericalDelta.theta *= ( 1 - scope.dampingFactor ); + sphericalDelta.phi *= ( 1 - scope.dampingFactor ); + + panOffset.multiplyScalar( 1 - scope.dampingFactor ); + + } else { + + sphericalDelta.set( 0, 0, 0 ); + + panOffset.set( 0, 0, 0 ); + + } + + scale = 1; + + // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + + if ( zoomChanged || + lastPosition.distanceToSquared( scope.object.position ) > EPS || + 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { + + scope.dispatchEvent( changeEvent ); + + lastPosition.copy( scope.object.position ); + lastQuaternion.copy( scope.object.quaternion ); + zoomChanged = false; + + return true; + + } + + return false; + + }; + + }(); + + this.dispose = function () { + + scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false ); + scope.domElement.removeEventListener( 'mousedown', onMouseDown, false ); + scope.domElement.removeEventListener( 'wheel', onMouseWheel, false ); + + scope.domElement.removeEventListener( 'touchstart', onTouchStart, false ); + scope.domElement.removeEventListener( 'touchend', onTouchEnd, false ); + scope.domElement.removeEventListener( 'touchmove', onTouchMove, false ); + + document.removeEventListener( 'mousemove', onMouseMove, false ); + document.removeEventListener( 'mouseup', onMouseUp, false ); + + window.removeEventListener( 'keydown', onKeyDown, false ); + + //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? + + }; + + // + // internals + // + + var scope = this; + + var changeEvent = { type: 'change' }; + var startEvent = { type: 'start' }; + var endEvent = { type: 'end' }; + + var STATE = { + NONE: - 1, + ROTATE: 0, + DOLLY: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_PAN: 4, + TOUCH_DOLLY_PAN: 5, + TOUCH_DOLLY_ROTATE: 6 + }; + + var state = STATE.NONE; + + var EPS = 0.000001; + + // current position in spherical coordinates + var spherical = new Spherical(); + var sphericalDelta = new Spherical(); + + var scale = 1; + var panOffset = new Vector3(); + var zoomChanged = false; + + var rotateStart = new Vector2(); + var rotateEnd = new Vector2(); + var rotateDelta = new Vector2(); + + var panStart = new Vector2(); + var panEnd = new Vector2(); + var panDelta = new Vector2(); + + var dollyStart = new Vector2(); + var dollyEnd = new Vector2(); + var dollyDelta = new Vector2(); + + function getAutoRotationAngle() { + + return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; + + } + + function getZoomScale() { + + return Math.pow( 0.95, scope.zoomSpeed ); + + } + + function rotateLeft( angle ) { + + sphericalDelta.theta -= angle; + + } + + function rotateUp( angle ) { + + sphericalDelta.phi -= angle; + + } + + var panLeft = function () { + + var v = new Vector3(); + + return function panLeft( distance, objectMatrix ) { + + v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix + v.multiplyScalar( - distance ); + + panOffset.add( v ); + + }; + + }(); + + var panUp = function () { + + var v = new Vector3(); + + return function panUp( distance, objectMatrix ) { + + if ( scope.screenSpacePanning === true ) { + + v.setFromMatrixColumn( objectMatrix, 1 ); + + } else { + + v.setFromMatrixColumn( objectMatrix, 0 ); + v.crossVectors( scope.object.up, v ); + + } + + v.multiplyScalar( distance ); + + panOffset.add( v ); + + }; + + }(); + + // deltaX and deltaY are in pixels; right and down are positive + var pan = function () { + + var offset = new Vector3(); + + return function pan( deltaX, deltaY ) { + + var element = scope.domElement === document ? scope.domElement.body : scope.domElement; + + if ( scope.object.isPerspectiveCamera ) { + + // perspective + var position = scope.object.position; + offset.copy( position ).sub( scope.target ); + var targetDistance = offset.length(); + + // half of the fov is center to top of screen + targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 ); + + // we use only clientHeight here so aspect ratio does not distort speed + panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); + panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); + + } else if ( scope.object.isOrthographicCamera ) { + + // orthographic + panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix ); + panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix ); + + } else { + + // camera neither orthographic nor perspective + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); + scope.enablePan = false; + + } + + }; + + }(); + + function dollyIn( dollyScale ) { + + if ( scope.object.isPerspectiveCamera ) { + + scale /= dollyScale; + + } else if ( scope.object.isOrthographicCamera ) { + + scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + + } else { + + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + scope.enableZoom = false; + + } + + } + + function dollyOut( dollyScale ) { + + if ( scope.object.isPerspectiveCamera ) { + + scale *= dollyScale; + + } else if ( scope.object.isOrthographicCamera ) { + + scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + + } else { + + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + scope.enableZoom = false; + + } + + } + + // + // event callbacks - update the object state + // + + function handleMouseDownRotate( event ) { + + rotateStart.set( event.clientX, event.clientY ); + + } + + function handleMouseDownDolly( event ) { + + dollyStart.set( event.clientX, event.clientY ); + + } + + function handleMouseDownPan( event ) { + + panStart.set( event.clientX, event.clientY ); + + } + + function handleMouseMoveRotate( event ) { + + rotateEnd.set( event.clientX, event.clientY ); + + rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + + var element = scope.domElement === document ? scope.domElement.body : scope.domElement; + + rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + + rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + + rotateStart.copy( rotateEnd ); + + scope.update(); + + } + + function handleMouseMoveDolly( event ) { + + dollyEnd.set( event.clientX, event.clientY ); + + dollyDelta.subVectors( dollyEnd, dollyStart ); + + if ( dollyDelta.y > 0 ) { + + dollyIn( getZoomScale() ); + + } else if ( dollyDelta.y < 0 ) { + + dollyOut( getZoomScale() ); + + } + + dollyStart.copy( dollyEnd ); + + scope.update(); + + } + + function handleMouseMovePan( event ) { + + panEnd.set( event.clientX, event.clientY ); + + panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + + pan( panDelta.x, panDelta.y ); + + panStart.copy( panEnd ); + + scope.update(); + + } + + function handleMouseUp( /*event*/ ) { + + // no-op + + } + + function handleMouseWheel( event ) { + + if ( event.deltaY < 0 ) { + + dollyOut( getZoomScale() ); + + } else if ( event.deltaY > 0 ) { + + dollyIn( getZoomScale() ); + + } + + scope.update(); + + } + + function handleKeyDown( event ) { + + var needsUpdate = false; + + switch ( event.keyCode ) { + + case scope.keys.UP: + pan( 0, scope.keyPanSpeed ); + needsUpdate = true; + break; + + case scope.keys.BOTTOM: + pan( 0, - scope.keyPanSpeed ); + needsUpdate = true; + break; + + case scope.keys.LEFT: + pan( scope.keyPanSpeed, 0 ); + needsUpdate = true; + break; + + case scope.keys.RIGHT: + pan( - scope.keyPanSpeed, 0 ); + needsUpdate = true; + break; + + } + + if ( needsUpdate ) { + + // prevent the browser from scrolling on cursor keys + event.preventDefault(); + // and prevent others from consuming the event + event.stopImmediatePropagation(); + scope.update(); + + } + + + } + + function handleTouchStartRotate( event ) { + + if ( event.touches.length == 1 ) { + + rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + rotateStart.set( x, y ); + + } + + } + + function handleTouchStartPan( event ) { + + if ( event.touches.length == 1 ) { + + panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + panStart.set( x, y ); + + } + + } + + function handleTouchStartDolly( event ) { + + var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + + var distance = Math.sqrt( dx * dx + dy * dy ); + + dollyStart.set( 0, distance ); + + } + + function handleTouchStartDollyPan( event ) { + + if ( scope.enableZoom ) handleTouchStartDolly( event ); + + if ( scope.enablePan ) handleTouchStartPan( event ); + + } + + function handleTouchStartDollyRotate( event ) { + + if ( scope.enableZoom ) handleTouchStartDolly( event ); + + if ( scope.enableRotate ) handleTouchStartRotate( event ); + + } + + function handleTouchMoveRotate( event ) { + + if ( event.touches.length == 1 ) { + + rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + rotateEnd.set( x, y ); + + } + + rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + + var element = scope.domElement === document ? scope.domElement.body : scope.domElement; + + rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + + rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + + rotateStart.copy( rotateEnd ); + + } + + function handleTouchMovePan( event ) { + + if ( event.touches.length == 1 ) { + + panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + + panEnd.set( x, y ); + + } + + panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + + pan( panDelta.x, panDelta.y ); + + panStart.copy( panEnd ); + + } + + function handleTouchMoveDolly( event ) { + + var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + + var distance = Math.sqrt( dx * dx + dy * dy ); + + dollyEnd.set( 0, distance ); + + dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) ); + + dollyIn( dollyDelta.y ); + + dollyStart.copy( dollyEnd ); + + } + + function handleTouchMoveDollyPan( event ) { + + if ( scope.enableZoom ) handleTouchMoveDolly( event ); + + if ( scope.enablePan ) handleTouchMovePan( event ); + + } + + function handleTouchMoveDollyRotate( event ) { + + if ( scope.enableZoom ) handleTouchMoveDolly( event ); + + if ( scope.enableRotate ) handleTouchMoveRotate( event ); + + } + + function handleTouchEnd( /*event*/ ) { + + // no-op + + } + + // + // event handlers - FSM: listen for events and reset state + // + + function onMouseDown( event ) { + + if ( scope.enabled === false ) return; + + // Prevent the browser from scrolling. + + event.preventDefault(); + + // Manually set the focus since calling preventDefault above + // prevents the browser from setting it automatically. + + scope.domElement.focus ? scope.domElement.focus() : window.focus(); + + switch ( event.button ) { + + case 0: + + switch ( scope.mouseButtons.LEFT ) { + + case MOUSE.ROTATE: + + if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + + if ( scope.enablePan === false ) return; + + handleMouseDownPan( event ); + + state = STATE.PAN; + + } else { + + if ( scope.enableRotate === false ) return; + + handleMouseDownRotate( event ); + + state = STATE.ROTATE; + + } + + break; + + case MOUSE.PAN: + + if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + + if ( scope.enableRotate === false ) return; + + handleMouseDownRotate( event ); + + state = STATE.ROTATE; + + } else { + + if ( scope.enablePan === false ) return; + + handleMouseDownPan( event ); + + state = STATE.PAN; + + } + + break; + + default: + + state = STATE.NONE; + + } + + break; + + + case 1: + + switch ( scope.mouseButtons.MIDDLE ) { + + case MOUSE.DOLLY: + + if ( scope.enableZoom === false ) return; + + handleMouseDownDolly( event ); + + state = STATE.DOLLY; + + break; + + + default: + + state = STATE.NONE; + + } + + break; + + case 2: + + switch ( scope.mouseButtons.RIGHT ) { + + case MOUSE.ROTATE: + + if ( scope.enableRotate === false ) return; + + handleMouseDownRotate( event ); + + state = STATE.ROTATE; + + break; + + case MOUSE.PAN: + + if ( scope.enablePan === false ) return; + + handleMouseDownPan( event ); + + state = STATE.PAN; + + break; + + default: + + state = STATE.NONE; + + } + + break; + + } + + if ( state !== STATE.NONE ) { + + document.addEventListener( 'mousemove', onMouseMove, false ); + document.addEventListener( 'mouseup', onMouseUp, false ); + + scope.dispatchEvent( startEvent ); + + } + + } + + function onMouseMove( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + + switch ( state ) { + + case STATE.ROTATE: + + if ( scope.enableRotate === false ) return; + + handleMouseMoveRotate( event ); + + break; + + case STATE.DOLLY: + + if ( scope.enableZoom === false ) return; + + handleMouseMoveDolly( event ); + + break; + + case STATE.PAN: + + if ( scope.enablePan === false ) return; + + handleMouseMovePan( event ); + + break; + + } + + } + + function onMouseUp( event ) { + + if ( scope.enabled === false ) return; + + handleMouseUp( event ); + + document.removeEventListener( 'mousemove', onMouseMove, false ); + document.removeEventListener( 'mouseup', onMouseUp, false ); + + scope.dispatchEvent( endEvent ); + + state = STATE.NONE; + + } + + function onMouseWheel( event ) { + + if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return; + + event.preventDefault(); + event.stopPropagation(); + + scope.dispatchEvent( startEvent ); + + handleMouseWheel( event ); + + scope.dispatchEvent( endEvent ); + + } + + function onKeyDown( event ) { + + if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return; + + handleKeyDown( event ); + + } + + function onTouchStart( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + + switch ( event.touches.length ) { + + case 1: + + switch ( scope.touches.ONE ) { + + case TOUCH.ROTATE: + + if ( scope.enableRotate === false ) return; + + handleTouchStartRotate( event ); + + state = STATE.TOUCH_ROTATE; + + break; + + case TOUCH.PAN: + + if ( scope.enablePan === false ) return; + + handleTouchStartPan( event ); + + state = STATE.TOUCH_PAN; + + break; + + default: + + state = STATE.NONE; + + } + + break; + + case 2: + + switch ( scope.touches.TWO ) { + + case TOUCH.DOLLY_PAN: + + if ( scope.enableZoom === false && scope.enablePan === false ) return; + + handleTouchStartDollyPan( event ); + + state = STATE.TOUCH_DOLLY_PAN; + + break; + + case TOUCH.DOLLY_ROTATE: + + if ( scope.enableZoom === false && scope.enableRotate === false ) return; + + handleTouchStartDollyRotate( event ); + + state = STATE.TOUCH_DOLLY_ROTATE; + + break; + + default: + + state = STATE.NONE; + + } + + break; + + default: + + state = STATE.NONE; + + } + + if ( state !== STATE.NONE ) { + + scope.dispatchEvent( startEvent ); + + } + + } + + function onTouchMove( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + event.stopPropagation(); + + switch ( state ) { + + case STATE.TOUCH_ROTATE: + + if ( scope.enableRotate === false ) return; + + handleTouchMoveRotate( event ); + + scope.update(); + + break; + + case STATE.TOUCH_PAN: + + if ( scope.enablePan === false ) return; + + handleTouchMovePan( event ); + + scope.update(); + + break; + + case STATE.TOUCH_DOLLY_PAN: + + if ( scope.enableZoom === false && scope.enablePan === false ) return; + + handleTouchMoveDollyPan( event ); + + scope.update(); + + break; + + case STATE.TOUCH_DOLLY_ROTATE: + + if ( scope.enableZoom === false && scope.enableRotate === false ) return; + + handleTouchMoveDollyRotate( event ); + + scope.update(); + + break; + + default: + + state = STATE.NONE; + + } + + } + + function onTouchEnd( event ) { + + if ( scope.enabled === false ) return; + + handleTouchEnd( event ); + + scope.dispatchEvent( endEvent ); + + state = STATE.NONE; + + } + + function onContextMenu( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + + } + + // + + scope.domElement.addEventListener( 'contextmenu', onContextMenu, false ); + + scope.domElement.addEventListener( 'mousedown', onMouseDown, false ); + scope.domElement.addEventListener( 'wheel', onMouseWheel, false ); + + scope.domElement.addEventListener( 'touchstart', onTouchStart, false ); + scope.domElement.addEventListener( 'touchend', onTouchEnd, false ); + scope.domElement.addEventListener( 'touchmove', onTouchMove, false ); + + scope.domElement.addEventListener( 'mouseenter', function (event) { + window.addEventListener( 'keydown', onKeyDown ); + }); + scope.domElement.addEventListener( 'mouseleave', function (event) { + window.removeEventListener( 'keydown', onKeyDown ); + }); + + // force an update at start + + this.update(); + + } +}; diff --git a/ui5/eve7/lib/REveRenderCore.js b/ui5/eve7/lib/REveRenderCore.js new file mode 100644 index 0000000000000..23a9cbe35c90a --- /dev/null +++ b/ui5/eve7/lib/REveRenderCore.js @@ -0,0 +1,4 @@ +export * from './RC/RenderCore.js'; + +export {RendeQuTor} from './RendeQuTor.js'; +export {REveCameraControls} from './REveCameraControls.js'; \ No newline at end of file diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index fcde8a65e0c07..137e750a87d4d 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -1,4 +1,12 @@ -import * as RC from "../rnr_core/RenderCore.js"; +import {RenderQueue} from './RC/renderers/RenderQueue.js'; +import {RenderPass} from './RC/renderers/RenderPass.js'; +import {CustomShaderMaterial} from './RC/materials/CustomShaderMaterial.js'; +import {Text2D} from './RC/objects/Text2D.js'; +import {IcoSphere} from './RC/objects/IcoSphere.js'; + +import {FRONT_AND_BACK_SIDE, HIGHPASS_MODE_BRIGHTNESS, HIGHPASS_MODE_DIFFERENCE} + from './RC/constants.js'; +// import {} from ''; function iterateSceneR(object, callback) { @@ -20,14 +28,11 @@ export class RendeQuTor this.renderer = renderer; this.scene = scene; this.camera = camera; - this.queue = new RC.RenderQueue(renderer); - this.pqueue = new RC.RenderQueue(renderer); - this.make_PRP_plain(); + this.queue = new RenderQueue(renderer); + this.pqueue = new RenderQueue(renderer); - // Depth extraction somewhat works , get float but in some unknown coordinates :) - // If you enable this, also enable EXT_color_buffer_float in GlViewerRCore.createRCoreRenderer - // this.make_PRP_depth2r(); - // See also comments in shaders/custom/copyDepth2RReve.frag + this.make_PRP_plain(); + this.make_PRP_depth2r(); this.SSAA_value = 1; @@ -94,9 +99,9 @@ export class RendeQuTor pick() { let foo = this.pqueue.render(); - console.log(foo); + console.log("RenderQuTor::pick", this.renderer.pickedObject3D, foo); - { + if (true) { let glman = this.renderer.glManager; let gl = this.renderer.gl; let texref = this.pqueue._textureMap["depthr32f_picking"]; @@ -110,16 +115,16 @@ export class RendeQuTor let x = this.renderer._pickCoordinateX; let y = this.renderer._canvas.height - this.renderer._pickCoordinateY; - console.log(x, y); let d = new Float32Array(9); gl.readPixels(x-1, y-1, 3, 3, gl.RED, gl.FLOAT, d); + + let near = this.camera.near; + let far = this.camera.far; + for (let i = 0; i < 9; ++i) + d[i] = (2.0 * near * far) / (far + near - d[i] * (far - near)); + console.log("Pick depth at", x, ",", y, ":", d); - /* - let d = new Uint32Array(9); - gl.readPixels(x-1, y-1, 3, 3, gl.RED, gl.UNSIGNED_INT, d); - console.log("Pick depth:", d; - */ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); gl.deleteFramebuffer(fb); @@ -135,14 +140,15 @@ export class RendeQuTor { var pthis = this; - this.PRP_plain = new RC.RenderPass( - RC.RenderPass.BASIC, + this.PRP_plain = new RenderPass( + RenderPass.BASIC, function (textureMap, additionalData) {}, function (textureMap, additionalData) { return { scene: pthis.scene, camera: pthis.camera }; }, - RC.RenderPass.TEXTURE, + function (textureMap, additionalData) {}, + RenderPass.TEXTURE, null, - "depth_picking", - [ { id: "color_picking", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG } ] + "depth_picking", //null, // "depth_picking", // + [ { id: "color_picking", textureConfig: RenderPass.DEFAULT_R32UI_TEXTURE_CONFIG } ] ); this.PRP_plain.view_setup = function (vport) { this.viewport = vport; }; @@ -151,21 +157,21 @@ export class RendeQuTor make_PRP_depth2r() { - this.PRP_depth2r_mat = new RC.CustomShaderMaterial("copyDepth2RReve"); + this.PRP_depth2r_mat = new CustomShaderMaterial("copyDepth2RReve"); this.PRP_depth2r_mat.lights = false; var pthis = this; - this.PRP_depth2r = new RC.RenderPass( - RC.RenderPass.POSTPROCESS, + this.PRP_depth2r = new RenderPass( + RenderPass.POSTPROCESS, function (textureMap, additionalData) {}, function (textureMap, additionalData) { return { material: pthis.PRP_depth2r_mat, textures: [ textureMap["depth_picking"] ] }; }, - RC.RenderPass.TEXTURE, + function (textureMap, additionalData) {}, + RenderPass.TEXTURE, null, null, - [ { id: "depthr32f_picking", textureConfig: RC.RenderPass.FULL_FLOAT_R32F_TEXTURE_CONFIG } ] - // [ { id: "depthr32f_picking", textureConfig: RC.RenderPass.DEFAULT_R32UI_TEXTURE_CONFIG } ] + [ { id: "depthr32f_picking", textureConfig: RenderPass.FULL_FLOAT_R32F_TEXTURE_CONFIG } ] ); this.PRP_depth2r.view_setup = function (vport) { this.viewport = vport; }; @@ -178,11 +184,12 @@ export class RendeQuTor { var pthis = this; - this.RP_DirectToScreen = new RC.RenderPass( - RC.RenderPass.BASIC, + this.RP_DirectToScreen = new RenderPass( + RenderPass.BASIC, function (textureMap, additionalData) {}, function (textureMap, additionalData) { return { scene: pthis.scene, camera: pthis.camera }; }, - RC.RenderPass.SCREEN, + function (textureMap, additionalData) {}, + RenderPass.SCREEN, null ); this.RP_DirectToScreen.view_setup = function (vport) { this.viewport = vport; }; @@ -196,39 +203,42 @@ export class RendeQuTor { var pthis = this; - this.RP_SSAA_Super = new RC.RenderPass( + this.RP_SSAA_Super = new RenderPass( // Rendering pass type - RC.RenderPass.BASIC, + RenderPass.BASIC, // Initialize function function (textureMap, additionalData) { iterateSceneR(pthis.scene, function(object){ - if (object.pickable === false || object instanceof RC.Text2D || object instanceof RC.IcoSphere) { + if (object.pickable === false || object instanceof Text2D || object instanceof IcoSphere) { object.visible = true; return; } - pthis.OriginalMats.push(object.material); + // pthis.OriginalMats.push(object.material); }); }, // Preprocess function function (textureMap, additionalData) { - let m_index = 0; + // let m_index = 0; iterateSceneR(pthis.scene, function(object) { - if(object.pickable === false || object instanceof RC.Text2D || object instanceof RC.IcoSphere) { + if(object.pickable === false || object instanceof Text2D || object instanceof IcoSphere) { object.visible = true; return; } - object.material = pthis.OriginalMats[m_index]; - m_index++; + // object.material = pthis.OriginalMats[m_index]; + // m_index++; }); return { scene: pthis.scene, camera: pthis.camera }; }, + // Postprocess + function (textureMap, additionalData) {}, + // Target - RC.RenderPass.TEXTURE, + RenderPass.TEXTURE, // Viewport null, @@ -236,7 +246,7 @@ export class RendeQuTor // Bind depth texture to this ID "depthDefaultDefaultMaterials", - [ { id: "color_ssaa_super", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG } ] + [ { id: "color_ssaa_super", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG } ] ); this.RP_SSAA_Super.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; @@ -245,24 +255,25 @@ export class RendeQuTor make_RP_SSAA_Down() { - this.RP_SSAA_Down_mat = new RC.CustomShaderMaterial("copyTexture"); + this.RP_SSAA_Down_mat = new CustomShaderMaterial("copyTexture"); this.RP_SSAA_Down_mat.lights = false; var pthis = this; - this.RP_SSAA_Down = new RC.RenderPass( + this.RP_SSAA_Down = new RenderPass( // Rendering pass type - RC.RenderPass.POSTPROCESS, + RenderPass.POSTPROCESS, // Initialize function function (textureMap, additionalData) {}, - // Preprocess function function (textureMap, additionalData) { return { material: pthis.RP_SSAA_Down_mat, textures: [textureMap[pthis.input_texture]] }; }, + // Postprocess function + function (textureMap, additionalData) {}, // Target - RC.RenderPass.TEXTURE, + RenderPass.TEXTURE, // Viewport null, @@ -270,7 +281,7 @@ export class RendeQuTor // Bind depth texture to this ID null, - [ { id: "color_ssaa_down", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG } ] + [ { id: "color_ssaa_down", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG } ] ); this.RP_SSAA_Down.input_texture = "color_ssaa_super"; this.RP_SSAA_Down.view_setup = function(vport) { this.viewport = vport; }; @@ -282,17 +293,18 @@ export class RendeQuTor make_RP_ToScreen() { - this.RP_ToScreen_mat = new RC.CustomShaderMaterial("copyTexture"); + this.RP_ToScreen_mat = new CustomShaderMaterial("copyTexture"); this.RP_ToScreen_mat.lights = false; var pthis = this; - this.RP_ToScreen = new RC.RenderPass( - RC.RenderPass.POSTPROCESS, + this.RP_ToScreen = new RenderPass( + RenderPass.POSTPROCESS, function (textureMap, additionalData) {}, function (textureMap, additionalData) { return { material: pthis.RP_ToScreen_mat, textures: [ textureMap[this.input_texture] ] }; // XXXX pthis or this ???? }, - RC.RenderPass.SCREEN, + function (textureMap, additionalData) {}, + RenderPass.SCREEN, null ); this.RP_ToScreen.input_texture = "color_ssaa_down"; @@ -306,76 +318,80 @@ export class RendeQuTor make_RP_HighPassGaussBloom() { var pthis = this; - // let hp = new RC.CustomShaderMaterial("highPass", {MODE: RC.HIGHPASS_MODE_BRIGHTNESS, targetColor: [0.2126, 0.7152, 0.0722], threshold: 0.75}); - let hp = new RC.CustomShaderMaterial("highPass", { MODE: RC.HIGHPASS_MODE_DIFFERENCE, + // let hp = new CustomShaderMaterial("highPass", {MODE: HIGHPASS_MODE_BRIGHTNESS, targetColor: [0.2126, 0.7152, 0.0722], threshold: 0.75}); + let hp = new CustomShaderMaterial("highPass", { MODE: HIGHPASS_MODE_DIFFERENCE, targetColor: [0x0/255, 0x0/255, 0xff/255], threshold: 0.1}); console.log("XXXXXXXX", hp); - // let hp = new RC.CustomShaderMaterial("highPassReve"); + // let hp = new CustomShaderMaterial("highPassReve"); this.RP_HighPass_mat = hp; this.RP_HighPass_mat.lights = false; - this.RP_HighPass = new RC.RenderPass( - RC.RenderPass.POSTPROCESS, + this.RP_HighPass = new RenderPass( + RenderPass.POSTPROCESS, function (textureMap, additionalData) {}, function (textureMap, additionalData) { return { material: pthis.RP_HighPass_mat, textures: [textureMap["color_ssaa_super"]] }; }, - RC.RenderPass.TEXTURE, + function (textureMap, additionalData) {}, + RenderPass.TEXTURE, null, // XXXXXX MT: this was "dt", why not null ???? null, // "dt", - [ {id: "color_high_pass", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] + [ {id: "color_high_pass", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] ); this.RP_HighPass.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; this.queue.pushRenderPass(this.RP_HighPass); - this.RP_Gauss1_mat = new RC.CustomShaderMaterial("gaussBlur", {horizontal: true, power: 1.0}); + this.RP_Gauss1_mat = new CustomShaderMaterial("gaussBlur", {horizontal: true, power: 1.0}); this.RP_Gauss1_mat.lights = false; - this.RP_Gauss1 = new RC.RenderPass( - RC.RenderPass.POSTPROCESS, + this.RP_Gauss1 = new RenderPass( + RenderPass.POSTPROCESS, function (textureMap, additionalData) {}, function (textureMap, additionalData) { return { material: pthis.RP_Gauss1_mat, textures: [textureMap["color_high_pass"]] }; }, - RC.RenderPass.TEXTURE, + function (textureMap, additionalData) {}, + RenderPass.TEXTURE, null, null, - [ {id: "color_gauss_half", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] + [ {id: "color_gauss_half", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] ); this.RP_Gauss1.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; this.queue.pushRenderPass(this.RP_Gauss1); - this.RP_Gauss2_mat = new RC.CustomShaderMaterial("gaussBlur", {horizontal: false, power: 1.0}); + this.RP_Gauss2_mat = new CustomShaderMaterial("gaussBlur", {horizontal: false, power: 1.0}); this.RP_Gauss2_mat.lights = false; - this.RP_Gauss2 = new RC.RenderPass( - RC.RenderPass.POSTPROCESS, + this.RP_Gauss2 = new RenderPass( + RenderPass.POSTPROCESS, function (textureMap, additionalData) {}, function (textureMap, additionalData) { return { material: pthis.RP_Gauss2_mat, textures: [textureMap["color_gauss_half"]] }; }, - RC.RenderPass.TEXTURE, + function (textureMap, additionalData) {}, + RenderPass.TEXTURE, null, null, - [ {id: "color_gauss_full", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] + [ {id: "color_gauss_full", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] ); this.RP_Gauss2.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; this.queue.pushRenderPass(this.RP_Gauss2); - this.RP_Bloom_mat = new RC.CustomShaderMaterial("bloom"); + this.RP_Bloom_mat = new CustomShaderMaterial("bloom"); this.RP_Bloom_mat.lights = false; - this.RP_Bloom = new RC.RenderPass( - RC.RenderPass.POSTPROCESS, + this.RP_Bloom = new RenderPass( + RenderPass.POSTPROCESS, function (textureMap, additionalData) {}, function (textureMap, additionalData) { return { material: pthis.RP_Bloom_mat, textures: [textureMap["color_gauss_full"], textureMap["color_ssaa_super"]] }; }, - RC.RenderPass.TEXTURE, + function (textureMap, additionalData) {}, + RenderPass.TEXTURE, null, null, - [ {id: "color_bloom", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] + [ {id: "color_bloom", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] ); this.RP_Bloom.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; this.queue.pushRenderPass(this.RP_Bloom); @@ -384,21 +400,21 @@ export class RendeQuTor /* -export const RenderPass_MainMulti = new RC.RenderPass( +export const RenderPass_MainMulti = new RenderPass( // Rendering pass type - RC.RenderPass.BASIC, + RenderPass.BASIC, // Initialize function function (textureMap, additionalData) { iterateSceneR(scene, function(object){ - if(object.pickable === false || object instanceof RC.Text2D || object instanceof RC.IcoSphere) { + if(object.pickable === false || object instanceof Text2D || object instanceof IcoSphere) { object.visible = false; //GL_INVALID_OPERATION : glDrawElementsInstancedANGLE: buffer format and fragment output variable type incompatible //Program has no frag output at location 1, but destination draw buffer has an attached image. return; } - const multi = new RC.CustomShaderMaterial("multi", {near: nearPlane, far: farPlane}); - multi.side = RC.FRONT_AND_BACK_SIDE; //reather use depth from default materials + const multi = new CustomShaderMaterial("multi", {near: nearPlane, far: farPlane}); + multi.side = FRONT_AND_BACK_SIDE; //reather use depth from default materials MultiMats.push(multi); }); }, @@ -408,7 +424,7 @@ export const RenderPass_MainMulti = new RC.RenderPass( let m_index = 0; iterateSceneR(scene, function(object){ - if(object.pickable === false || object instanceof RC.Text2D || object instanceof RC.IcoSphere) { + if(object.pickable === false || object instanceof Text2D || object instanceof IcoSphere) { object.visible = false; return; } @@ -421,7 +437,7 @@ export const RenderPass_MainMulti = new RC.RenderPass( }, // Target - RC.RenderPass.TEXTURE, + RenderPass.TEXTURE, // Viewport { width: predef_width*SSAA_value, height: predef_height*SSAA_value }, @@ -430,20 +446,20 @@ export const RenderPass_MainMulti = new RC.RenderPass( "depthDefaultMultiMaterials", [ - {id: "depth", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG}, - {id: "normal", textureConfig: RC.RenderPass.DEFAULT_RGB_TEXTURE_CONFIG}, - {id: "viewDir", textureConfig: RC.RenderPass.DEFAULT_RGB_TEXTURE_CONFIG}, - {id: "camDist", textureConfig: RC.RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} + {id: "depth", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG}, + {id: "normal", textureConfig: RenderPass.DEFAULT_RGB_TEXTURE_CONFIG}, + {id: "viewDir", textureConfig: RenderPass.DEFAULT_RGB_TEXTURE_CONFIG}, + {id: "camDist", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} ] ); */ /* -const outline = new RC.CustomShaderMaterial("outline", {scale: 1.0*SSAA_value, edgeColor: [1.0, 1.0, 1.0, 1.0]}); +const outline = new CustomShaderMaterial("outline", {scale: 1.0*SSAA_value, edgeColor: [1.0, 1.0, 1.0, 1.0]}); outline.lights = false; -export const RenderPass_Outline = new RC.RenderPass( +export const RenderPass_Outline = new RenderPass( // Rendering pass type - RC.RenderPass.POSTPROCESS, + RenderPass.POSTPROCESS, // Initialize function function (textureMap, additionalData) { @@ -454,8 +470,11 @@ export const RenderPass_Outline = new RC.RenderPass( return {material: outline, textures: [textureMap["depthDefaultMultiMaterials"], textureMap["normal"], textureMap["viewDir"], textureMap["color_bloom"]]}; }, + // Postprocess function + function (textureMap, additionalData) {}, + // Target - RC.RenderPass.TEXTURE, + RenderPass.TEXTURE, // Viewport { width: predef_width*SSAA_value, height: predef_height*SSAA_value }, @@ -464,15 +483,16 @@ export const RenderPass_Outline = new RC.RenderPass( null, [ - {id: "color_outline", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} + {id: "color_outline", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] ); -const fog = new RC.CustomShaderMaterial("fog", {MODE: 1, fogColor: [0.5, 0.4, 0.45, 0.8]}); +const fog = new CustomShaderMaterial("fog", {MODE: 1, fogColor: [0.5, 0.4, 0.45, 0.8]}); fog.lights = false; -export const RenderPass_Fog = new RC.RenderPass( +export const RenderPass_Fog = new RenderPass( + // Rendering pass type - RC.RenderPass.POSTPROCESS, + RenderPass.POSTPROCESS, // Initialize function function (textureMap, additionalData) { @@ -485,7 +505,7 @@ export const RenderPass_Fog = new RC.RenderPass( }, // Target - RC.RenderPass.TEXTURE, + RenderPass.TEXTURE, // Viewport { width: predef_width*SSAA_value, height: predef_height*SSAA_value }, @@ -494,7 +514,7 @@ export const RenderPass_Fog = new RC.RenderPass( null, [ - {id: "color_fog", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} + {id: "color_fog", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] ); */ \ No newline at end of file diff --git a/ui5/eve7/shaders/custom/copyDepth2RReve.frag b/ui5/eve7/shaders/custom/copyDepth2RReve.frag index c95c4605eddb2..17f60b2ea2258 100644 --- a/ui5/eve7/shaders/custom/copyDepth2RReve.frag +++ b/ui5/eve7/shaders/custom/copyDepth2RReve.frag @@ -1,10 +1,9 @@ #version 300 es precision highp float; -precision highp usampler2D; +precision highp sampler2D; struct Material { #if (TEXTURE) - // usampler2D texture0; // this fails in MeshRenderer, uniform setter for material sampler2D texture0; #fi }; @@ -15,22 +14,15 @@ uniform Material material; in vec2 fragUV; #fi -out vec4 color; +out float color; void main() { #if (TEXTURE) + // TEST, write known numbers into result // color.r = 0.5370; // color.r = fragUV.x; - // Logarithmic: (?) - // color.r = texture(material.texture0, fragUV).r; - // Linearize: (?) - color.r = pow(2.0, texture(material.texture0, fragUV).r) - 1.0; - // Or is this something with 1/z or w or what. Argh. - // Perhaphs the best way forward is to: - // 1. Implement picking on reduced target, say 16x16 or even 8x8 - // 2. Attach float buffer to picking shader and write z that you want in there. - // Or be a total pig and attach 3 buffers and store world xyz :) + color = texture(material.texture0, fragUV).r; #fi -} \ No newline at end of file +} From 7efa18e1da74b1f489da1e77737544d3f9180726 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Fri, 28 Jan 2022 11:10:30 -0800 Subject: [PATCH 02/84] Getting render core colors, lights to reason. --- ui5/eve7/lib/EveElementsRCore.js | 53 ++++++++++++++++++++------------ ui5/eve7/lib/GlViewerRCore.js | 16 +++++----- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index d490d17aa9d57..9917533fbfc7c 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -81,22 +81,37 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) this.LINE_WIDTH_FAC = lf; } + RcPointMaterial(color, opacity, point_size, props) + { + let mat = new RC.PointBasicMaterial; + mat._color = this.ColorBlack; // color; + mat._emissive = color; + if (opacity !== undefined && opacity < 1.0) { + mat._opacity = opacity; + mat._transparent = true; + mat._depthWrite = false; + } + mat._pointSize = this.POINT_SIZE_FAC; + if (point_size !== undefined) mat._pointSize *= point_size; + if (props !== undefined) { + mat.update(props); + } + return mat; + } + RcLineMaterial(color, opacity, line_width, props) { let mat = new RC.MeshBasicMaterial; // StripeBasicMaterial - mat._color = color; - if (opacity !== undefined && opacity < 1.0) - { + mat._color = this.ColorBlack; + mat._emissive = color; + if (opacity !== undefined && opacity < 1.0) { mat._opacity = opacity; mat._transparent = true; mat._depthWrite = false; } - if (line_width !== undefined) - { - mat._lineWidth = this.LINE_WIDTH_FAC * line_width; - } - if (props !== undefined) - { + mat._lineWidth = this.LINE_WIDTH_FAC; + if (line_width !== undefined) mat._lineWidth *= line_width; + if (props !== undefined) { mat.update(props); } return mat; @@ -181,19 +196,17 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let geo = new RC.Geometry(); geo.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); - let size = 2 * this.POINT_SIZE_FAC * hit.fMarkerSize; // scaled by distance down to half size (basic_template.vert) + // see vert-shader in old bitbucket -- scaled by distance down to half size (basic_template.vert) let col = RcCol(hit.fMarkerColor); + console.log("COLOR", hit.fMarkerColor, EVE.JSR.Painter.getColor(hit.fMarkerColor), col); - let mat = new RC.MeshBasicMaterial; - mat.color = col; - mat.pointSize = size; - mat.usePoints = true; + let mat = this.RcPointMaterial(col, 1, hit.fMarkerSize); mat.drawCircles = true; let pnts = new RC.Point(geo, mat); let pm = pnts.pickingMaterial; - pm.pointSize = size; + pm.pointSize = mat.pointSize; pm.usePoints = true; pm.drawCircles = true; @@ -551,10 +564,10 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) p_geom.vertices = new RC.BufferAttribute(p_buf, 3); let p_mat = new RC.MeshBasicMaterial; - p_mat.color = fcol; - p_mat.pointSize = 2 * el.fMarkerSize; - p_mat.usePoints = true; - p_mat.drawCircles = true; + p_mat._color = this.ColorBlack; + p_mat._emissive = fcol; + p_mat._pointSize = 2 * el.fMarkerSize; + // p_mat.drawCircles = true; let marker = new RC.Point(p_geom, p_mat); marker.pickingMaterial.pointSize = 2 * el.fMarkerSize;; @@ -562,7 +575,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) this.RcPickable(el, marker); obj3d.add(marker); - // ???? + // For secondary selection, see EveElements.js obj3d.eve_idx_buf = rnr_data.idxBuff; /* diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 2a8c790597332..22816bd385762 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -118,7 +118,7 @@ sap.ui.define([ this.lights = this.make_object("Light container"); this.scene.add(this.lights); - let a_light = new RC.AmbientLight(new RC.Color(0xffffff), 0.1); + let a_light = new RC.AmbientLight(new RC.Color(0xffffff), 0.05); this.lights.add(a_light); let light_class_3d = RC.PointLight; // RC.DirectionalLight; // RC.PointLight; @@ -131,7 +131,7 @@ sap.ui.define([ this.camera.lookAt(new RC.Vector3(0, 0, 0), new RC.Vector3(0, 1, 0)); this.camera.isPerspectiveCamera = true; - let l_int = 0.85; + let l_int = 1.4; this.lights.add(new light_class_3d(0xaa8888, l_int )); // R this.lights.add(new light_class_3d(0x88aa88, l_int )); // G this.lights.add(new light_class_3d(0x8888aa, l_int )); // B @@ -155,7 +155,7 @@ sap.ui.define([ let l_int = 0.85; this.lights.add(new light_class_2d( 0xffffff, l_int )); // white front - this.lights.add(new light_class_2d( 0xffffff, l_int )); // white back + // this.lights.add(new light_class_2d( 0xffffff, l_int )); // white back // Lights are positioned in resetRenderer. } @@ -360,10 +360,10 @@ sap.ui.define([ this.controls.screenSpacePanning = true; let lc = this.lights.children; - lc[1].position.set( extR, extR, -extR); lc[1].decay = 4 * extR; - lc[2].position.set(-extR, extR, extR); lc[2].decay = 4 * extR; - lc[3].position.set( extR, extR, extR); lc[3].decay = 4 * extR; - lc[4].position.set(-extR, extR, -extR); lc[4].decay = 4 * extR; + lc[1].position.set( extR, extR, -extR); lc[1].decay = 0.5 * extR; lc[1].distance = 3 * extR; + lc[2].position.set(-extR, extR, extR); lc[2].decay = 0.5 * extR; lc[2].distance = 3 * extR; + lc[3].position.set( extR, extR, extR); lc[3].decay = 0.5 * extR; lc[3].distance = 3 * extR; + lc[4].position.set(-extR, extR, -extR); lc[4].decay = 0.5 * extR; lc[4].distance = 3 * extR; // console.log("resetRenderer 3D scene bbox ", sbbox, ", camera_pos ", posC, ", look_at ", this.rot_center); } @@ -389,7 +389,7 @@ sap.ui.define([ let lc = this.lights.children; lc[1].position.set( 0, 0, extR); - lc[2].position.set( 0, 0, -extR); + // lc[2].position.set( 0, 0, -extR); // console.log("resetRenderer 2D scene bbox ex ey", sbbox, ex, ey, ", camera_pos ", posC, ", look_at ", this.rot_center); } From e3642cb96ba0335d019e124b153a55e34cea987b Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Fri, 18 Mar 2022 12:26:33 -0700 Subject: [PATCH 03/84] Get rcore uint picking to work again, improve point rendering. --- graf3d/eve7/src/REveStraightLineSet.cxx | 2 + tutorials/eve7/lineset.C | 10 +++-- ui5/eve7/lib/EveElementsRCore.js | 59 +++++++++++++------------ ui5/eve7/lib/GlViewerRCore.js | 11 ++--- ui5/eve7/lib/RendeQuTor.js | 2 +- 5 files changed, 45 insertions(+), 39 deletions(-) diff --git a/graf3d/eve7/src/REveStraightLineSet.cxx b/graf3d/eve7/src/REveStraightLineSet.cxx index 2ff64a80cc34e..dac4393604e8b 100644 --- a/graf3d/eve7/src/REveStraightLineSet.cxx +++ b/graf3d/eve7/src/REveStraightLineSet.cxx @@ -162,8 +162,10 @@ Int_t REveStraightLineSet::WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) j["fLinePlexSize"] = fLinePlex.Size(); j["fMarkerPlexSize"] = fMarkerPlex.Size(); + // j["fLineColor"] = fLineColor; // streamed as fMainColor j["fLineWidth"] = fLineWidth; j["fLineStyle"] = fLineStyle; + j["fMarkerColor"] = fMarkerColor; j["fMarkerSize"] = fMarkerSize; j["fMarkerStyle"] = fMarkerStyle; j["fSecondarySelect"] = fAlwaysSecSelect; diff --git a/tutorials/eve7/lineset.C b/tutorials/eve7/lineset.C index b40bfc03893d6..2c6f931f01afa 100644 --- a/tutorials/eve7/lineset.C +++ b/tutorials/eve7/lineset.C @@ -26,11 +26,11 @@ REX::REveStraightLineSet* makeLineSet(Int_t nlines = 40, Int_t nmarkers = 4, boo ls->AddLine( r.Uniform(-s,s), r.Uniform(-s,s), r.Uniform(-s,s), r.Uniform(-s,s), r.Uniform(-s,s), r.Uniform(-s,s)); // add random number of markers - Int_t nm = Int_t(nmarkers* r.Rndm()); + Int_t nm = 1 + Int_t(nmarkers * r.Rndm()); for (Int_t m = 0; m < nm; m++) ls->AddMarker(i, r.Rndm()); } - ls->SetMarkerSize(0.5); + ls->SetMarkerSize(5); ls->SetMarkerStyle(1); ls->SetAlwaysSecSelect(sc); REX::gEve->GetEventScene()->AddElement(ls); @@ -42,12 +42,14 @@ void lineset(bool secondarySelect = true) { auto eveMng = REX::REveManager::Create(); - auto ls1 = makeLineSet(10, 5, secondarySelect); + auto ls1 = makeLineSet(50, 10, secondarySelect); ls1->SetMainColor(kViolet); + ls1->SetMarkerColor(kGreen + 3); ls1->SetName("LineSet_1"); - auto ls2 = makeLineSet(300, 4, secondarySelect); + auto ls2 = makeLineSet(200, 20, secondarySelect); ls2->SetMainColor(kBlue); + ls2->SetMarkerColor(kCyan + 2); ls2->SetName("LineSet_2"); ls2->InitMainTrans(); ls2->RefMainTrans().Move3LF(40, 200, 200); diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 9917533fbfc7c..11b201eaa5585 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -81,6 +81,16 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) this.LINE_WIDTH_FAC = lf; } + UpdatePointPickingMaterial(obj) + { + let m = obj.material; + let p = obj.pickingMaterial; + p.usePoints = m.usePoints; + p.pointSize = m.pointSize; + p.pointsScale = m.pointsScale; + p.drawCircles = m.drawCircles; + } + RcPointMaterial(color, opacity, point_size, props) { let mat = new RC.PointBasicMaterial; @@ -122,15 +132,17 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let mat = new RC.MeshBasicMaterial; mat._color = color; mat._emissive = color; // mat.emissive.offsetHSL(0, 0.1, 0); + // Something is strange here. Tried also white (no change) / black (no fill -- ?). + // mat._emissive = new RC.Color(color); + // mat.emissive.multiplyScalar(0.1); + // offsetHSL(0, -0.5, -0.5); - if (opacity !== undefined && opacity < 1.0) - { + if (opacity !== undefined && opacity < 1.0) { mat._opacity = opacity; mat._transparent = true; mat._depthWrite = false; } - if (props !== undefined) - { + if (props !== undefined) { mat.update(props); } return mat; @@ -142,17 +154,15 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // let mat = new RC.MeshBasicMaterial; mat._color = color; - mat._specular = new RC.Color(0xFFFFFF); // mat._specular.offsetHSL(0, 0, 0.4); + mat._specular = this.ColorWhite; mat._shininess = 32; - if (opacity !== undefined && opacity < 1.0) - { + if (opacity !== undefined && opacity < 1.0) { mat._opacity = opacity; mat._transparent = true; mat._depthWrite = false; } - if (props !== undefined) - { + if (props !== undefined) { mat.update(props); } return mat; @@ -200,17 +210,13 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let col = RcCol(hit.fMarkerColor); console.log("COLOR", hit.fMarkerColor, EVE.JSR.Painter.getColor(hit.fMarkerColor), col); - let mat = this.RcPointMaterial(col, 1, hit.fMarkerSize); - mat.drawCircles = true; - - let pnts = new RC.Point(geo, mat); - - let pm = pnts.pickingMaterial; - pm.pointSize = mat.pointSize; - pm.usePoints = true; - pm.drawCircles = true; + let mat = this.RcPointMaterial(col, 1, hit.fMarkerSize, + { pointsScale: false, drawCircles: true }); + let pnts = new RC.Point( {geometry: geo, material: mat} ); + this.UpdatePointPickingMaterial(pnts) this.RcPickable(hit, pnts); + pnts.dispose = function() { delete this; } // ???? return pnts; } @@ -528,15 +534,13 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let obj3d = new RC.Group(); - let fcol = RcCol(el.fMainColor); - let buf = new Float32Array(el.fLinePlexSize * 6); for (let i = 0; i < el.fLinePlexSize * 6; ++i) { buf[i] = rnr_data.vtxBuff[i]; } - let line_mat = new this.RcLineMaterial(fcol); + let line_mat = this.RcLineMaterial(RcCol(el.fMainColor)); let geom = new RC.Geometry(); geom.vertices = new RC.BufferAttribute(buf, 3); @@ -563,15 +567,12 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let p_geom = new RC.Geometry(); p_geom.vertices = new RC.BufferAttribute(p_buf, 3); - let p_mat = new RC.MeshBasicMaterial; - p_mat._color = this.ColorBlack; - p_mat._emissive = fcol; - p_mat._pointSize = 2 * el.fMarkerSize; - // p_mat.drawCircles = true; - - let marker = new RC.Point(p_geom, p_mat); - marker.pickingMaterial.pointSize = 2 * el.fMarkerSize;; + let p_mat = this.RcPointMaterial(RcCol(el.fMarkerColor), 1, el.fMarkerSize); + p_mat.pointsScale = false; + p_mat.drawCircles = true; + let marker = new RC.Point({ geometry: p_geom, material: p_mat }); + this.UpdatePointPickingMaterial(marker); this.RcPickable(el, marker); obj3d.add(marker); diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 22816bd385762..5b11d5ad2dea8 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -15,7 +15,8 @@ sap.ui.define([ const urlParams = new URLSearchParams(window.location.search); - console.log("XXXX", window.location.search, urlParams.get('UseRenderQueue'), urlParams.get('NoRenderQueue')); + console.log("XXXX window.location.search='", window.location.search, "', ", + "URL params UseRenderQueue NoRenderQueue = ", urlParams.get('UseRenderQueue'), urlParams.get('NoRenderQueue')); this.UseRenderQueue = true; if (urlParams.get('UseRenderQueue') != null) this.UseRenderQueue = true; if (urlParams.get('NoRenderQueue' ) != null) this.UseRenderQueue = false; @@ -45,7 +46,7 @@ sap.ui.define([ // // console.log(window.location.pathname); // where are we loading from? // import("https://desire.physics.ucsd.edu/matevz/alja.github.io/rootui5/eve7/rnr_core/RenderCore.js").then((module) => { - import("../../eve7/lib/REveRenderCore.js").then((module) => { + import(window.location.origin + '/rootui5sys/eve7/lib/REveRenderCore.js').then((module) => { console.log("GlViewerRCore.onInit - RenderCore.js loaded"); RC = module; @@ -112,6 +113,7 @@ sap.ui.define([ this.renderer.addShaderLoaderUrls("rootui5sys/eve7/shaders"); this.renderer.pickObject3D = true; this.renderer.pickDoNotRender = true; + RC.PickingShaderMaterial.DEFAULT_PICK_MODE = RC.PickingShaderMaterial.PICK_MODE.UINT; this.scene = new RC.Scene(); @@ -322,8 +324,7 @@ sap.ui.define([ } }); - // Was RC.ReveCameraControls - this.controls = new THREE.OrbitControls(this.camera, this.get_view().getDomRef()); + this.controls = new RC.REveCameraControls(this.camera, this.get_view().getDomRef()); this.controls.addEventListener('change', this.render.bind(this)); // This will also call render(). @@ -424,7 +425,7 @@ sap.ui.define([ if (this.canvas.width <= 0 || this.canvas.height <= 0) return; this.renderer.pick(x, y); - this.rqt.pick(this.scene, this.camera); + this.rqt.pick(); let o3d = this.renderer.pickedObject3D; // Render to FBO or texture would work. diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index 137e750a87d4d..3f4fcdfbd2aea 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -147,7 +147,7 @@ export class RendeQuTor function (textureMap, additionalData) {}, RenderPass.TEXTURE, null, - "depth_picking", //null, // "depth_picking", // + "depth_picking", [ { id: "color_picking", textureConfig: RenderPass.DEFAULT_R32UI_TEXTURE_CONFIG } ] ); this.PRP_plain.view_setup = function (vport) { this.viewport = vport; }; From d807fd77eec56c022ad3d3de60b351a9ebe6c699 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Tue, 29 Mar 2022 11:49:07 -0700 Subject: [PATCH 04/84] Trying out secondary select. --- tutorials/eve7/points.C | 2 +- ui5/eve7/lib/RendeQuTor.js | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tutorials/eve7/points.C b/tutorials/eve7/points.C index 8e51cedaa0e77..26e09dcf8e1b3 100644 --- a/tutorials/eve7/points.C +++ b/tutorials/eve7/points.C @@ -33,7 +33,7 @@ void points() auto eveMng = REX::REveManager::Create(); REX::REveElement *event = eveMng->GetEventScene(); - auto ps = createPointSet(100); + auto ps = createPointSet(100, 300); event->AddElement(ps); eveMng->Show(); diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index 3f4fcdfbd2aea..16518f5f4704a 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -1,6 +1,7 @@ import {RenderQueue} from './RC/renderers/RenderQueue.js'; import {RenderPass} from './RC/renderers/RenderPass.js'; import {CustomShaderMaterial} from './RC/materials/CustomShaderMaterial.js'; +import {PickingShaderMaterial} from './RC/materials/PickingShaderMaterial.js'; import {Text2D} from './RC/objects/Text2D.js'; import {IcoSphere} from './RC/objects/IcoSphere.js'; @@ -129,6 +130,15 @@ export class RendeQuTor gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); gl.deleteFramebuffer(fb); } + + if (this.renderer.pickedObject3D) { + console.log("RenderQuTor::pick going for secondary select"); + this.renderer._pickSecondaryEnabled = true; + + this.renderer.pickedObject3D.pickingMaterial.pickMode = PickingShaderMaterial.PICK_MODE.UINT_PRIM; + this.pqueue.render(); + this.renderer.pickedObject3D.pickingMaterial.pickMode = PickingShaderMaterial.PICK_MODE.UINT; + } } From 67ba8c39ed7a854913e4602697d580ae83a5c9c6 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Thu, 14 Apr 2022 12:38:29 -0700 Subject: [PATCH 05/84] Re-call RenderCore::render from when some shaders have not yet been loaded. Prototype secondary selection. --- ui5/eve7/lib/EveElementsRCore.js | 8 ++++++-- ui5/eve7/lib/GlViewerRCore.js | 14 +++++++------- ui5/eve7/lib/RendeQuTor.js | 8 +++++++- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 11b201eaa5585..21a81dacf2074 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -206,9 +206,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let geo = new RC.Geometry(); geo.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); - // see vert-shader in old bitbucket -- scaled by distance down to half size (basic_template.vert) let col = RcCol(hit.fMarkerColor); - console.log("COLOR", hit.fMarkerColor, EVE.JSR.Painter.getColor(hit.fMarkerColor), col); + // console.log("COLOR", hit.fMarkerColor, EVE.JSR.getColor(hit.fMarkerColor), col); let mat = this.RcPointMaterial(col, 1, hit.fMarkerSize, { pointsScale: false, drawCircles: true }); @@ -596,4 +595,9 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } // class EveElements + //============================================================================== + + EVE.EveElements = EveElements; + + return EveElements; }); diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 5b11d5ad2dea8..724bdbf56b869 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -67,12 +67,6 @@ sap.ui.define([ this.setupEventHandlers(); this.controller.glViewerInitDone(); - - // XXXX MT: HACK ... give RCore some time to load shaders. - // Would be better to have some onShadersLoaded thing but - // this is probably problematic later on,k if we add objects with - // custom shaders later on. - setTimeout(this.render.bind(this), 500); } //============================================================================== @@ -414,6 +408,12 @@ sap.ui.define([ else this.renderer.render( this.scene, this.camera ); + if (this.renderer.used == false) { + // RCRC Ideally there would be an onShadersLoaded callback. + console.log("GlViewerRCore render: not all programs compiled -- setting up render timer"); + setTimeout(this.render.bind(this), 200); + } + // if (this.controller.kind === "3D") // window.requestAnimationFrame(this.render.bind(this)); } @@ -506,7 +506,7 @@ sap.ui.define([ return { object: o3d, mouse: mouse, w: w, h: h }; } return null; - }, + } onMouseMoveTimeout(x, y) { diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index 16518f5f4704a..09252f51fba67 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -131,13 +131,19 @@ export class RendeQuTor gl.deleteFramebuffer(fb); } - if (this.renderer.pickedObject3D) { + // RCRC Proto-proto-secondary-selection. Requires branch: + // https://github.com/osschar/RenderCore/tree/secondary-selection-emulate-vert-id-plus-flat-shading + if (false && this.renderer.pickedObject3D) { console.log("RenderQuTor::pick going for secondary select"); this.renderer._pickSecondaryEnabled = true; this.renderer.pickedObject3D.pickingMaterial.pickMode = PickingShaderMaterial.PICK_MODE.UINT_PRIM; this.pqueue.render(); this.renderer.pickedObject3D.pickingMaterial.pickMode = PickingShaderMaterial.PICK_MODE.UINT; + + // Reset pick state - in case shaders needed to be loaded and picking + // was not actually done the flag does not get reset. + this.renderer._pickSecondaryEnabled = false; } } From c286a512b75290ddae0d71322a6782690651885e Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Wed, 15 Jun 2022 12:25:45 -0700 Subject: [PATCH 06/84] [REve] Support RCore instanced rendering through texture data - Use RC.ZSprite for REvePointSet rendering. - REvePointSet - export point-data in RGBA32F texture for RC. - REveRenderData - add static CalcTextureSize() to calculate texture width and height. - Add flag IsRCore to REveManager. - GlViewerRCore.js - always use RenderQueue rendering. --- graf3d/eve7/inc/ROOT/REveManager.hxx | 2 + graf3d/eve7/inc/ROOT/REvePointSet.hxx | 1 + graf3d/eve7/inc/ROOT/REveRenderData.hxx | 4 ++ graf3d/eve7/src/REveManager.cxx | 3 ++ graf3d/eve7/src/REvePointSet.cxx | 21 +++++++- graf3d/eve7/src/REveRenderData.cxx | 18 +++++++ ui5/eve7/lib/EveElements.js | 2 + ui5/eve7/lib/EveElementsRCore.js | 59 +++++++++++++++++++- ui5/eve7/lib/EveScene.js | 6 +-- ui5/eve7/lib/GlViewerRCore.js | 72 ++++++++++++------------- 10 files changed, 145 insertions(+), 43 deletions(-) diff --git a/graf3d/eve7/inc/ROOT/REveManager.hxx b/graf3d/eve7/inc/ROOT/REveManager.hxx index 022de4f4d7fbc..ddd28fb636455 100644 --- a/graf3d/eve7/inc/ROOT/REveManager.hxx +++ b/graf3d/eve7/inc/ROOT/REveManager.hxx @@ -155,6 +155,7 @@ protected: Logger fLogger; REveServerStatus fServerStatus; + bool fIsRCore{false}; void WindowConnect(unsigned connid); void WindowData(unsigned connid, const std::string &arg); @@ -266,6 +267,7 @@ public: void Show(const RWebDisplayArgs &args = ""); void GetServerStatus(REveServerStatus&); + bool IsRCore() const { return fIsRCore; } }; R__EXTERN REveManager* gEve; diff --git a/graf3d/eve7/inc/ROOT/REvePointSet.hxx b/graf3d/eve7/inc/ROOT/REvePointSet.hxx index c09ccbbd8be94..be81c77c58f7f 100644 --- a/graf3d/eve7/inc/ROOT/REvePointSet.hxx +++ b/graf3d/eve7/inc/ROOT/REvePointSet.hxx @@ -45,6 +45,7 @@ protected: std::vector fPoints; int fCapacity{0}; int fSize{0}; + int fTexX{0}, fTexY{0}; public: REvePointSet(const std::string& name="", const std::string& title="", Int_t n_points = 0); diff --git a/graf3d/eve7/inc/ROOT/REveRenderData.hxx b/graf3d/eve7/inc/ROOT/REveRenderData.hxx index cb33c190e3df3..9b9c4a019c1d3 100644 --- a/graf3d/eve7/inc/ROOT/REveRenderData.hxx +++ b/graf3d/eve7/inc/ROOT/REveRenderData.hxx @@ -90,6 +90,8 @@ public: const std::string GetRnrFunc() const { return fRnrFunc; } + void ResizeV(int s) { fVertexBuffer.resize(s); } + int SizeV() const { return fVertexBuffer.size(); } int SizeN() const { return fNormalBuffer.size(); } int SizeI() const { return fIndexBuffer.size(); } @@ -98,6 +100,8 @@ public: int GetBinarySize() { return (SizeV() + SizeN() + SizeT()) * sizeof(float) + SizeI() * sizeof(int); } int Write(char *msg, int maxlen); + + static void CalcTextureSize(int nel, int align, int &sx, int &sy); }; } // namespace Experimental diff --git a/graf3d/eve7/src/REveManager.cxx b/graf3d/eve7/src/REveManager.cxx index f0def3d183695..550b6734c4de5 100644 --- a/graf3d/eve7/src/REveManager.cxx +++ b/graf3d/eve7/src/REveManager.cxx @@ -149,6 +149,9 @@ REveManager::REveManager() fWebWindow->SetUserArgs(Form("{ GLViewer: \"%s\", DblClick: \"%s\", HTimeout: %d, TableRowHeight: %d }", gl_viewer, gl_dblclick, htimeout, table_row_height)); + if (strcmp(gl_viewer, "RCore") == 0) + fIsRCore = true; + // this is call-back, invoked when message received via websocket fWebWindow->SetCallBacks([this](unsigned connid) { WindowConnect(connid); }, [this](unsigned connid, const std::string &arg) { WindowData(connid, arg); }, diff --git a/graf3d/eve7/src/REvePointSet.cxx b/graf3d/eve7/src/REvePointSet.cxx index 5d1fbf7969ee0..298f0843018ae 100644 --- a/graf3d/eve7/src/REvePointSet.cxx +++ b/graf3d/eve7/src/REvePointSet.cxx @@ -208,8 +208,16 @@ TClass* REvePointSet::ProjectedClass(const REveProjection*) const Int_t REvePointSet::WriteCoreJson(nlohmann::json& j, Int_t rnr_offset) { + if (gEve->IsRCore()) + REveRenderData::CalcTextureSize(fSize, 1, fTexX, fTexY); + Int_t ret = REveElement::WriteCoreJson(j, rnr_offset); + if (gEve->IsRCore()) { + j["fSize"] = fSize; + j["fTexX"] = fTexX; + j["fTexY"] = fTexY; + } j["fMarkerSize"] = GetMarkerSize(); j["fMarkerColor"] = GetMarkerColor(); @@ -223,8 +231,17 @@ void REvePointSet::BuildRenderData() { if (fSize > 0) { - fRenderData = std::make_unique("makeHit", 3*fSize); - fRenderData->PushV(&fPoints[0].fX, 3*fSize); + if (gEve->IsRCore()) { + fRenderData = std::make_unique("makeHit", 4*fTexX*fTexY); + for (int i = 0; i < fSize; ++i) { + fRenderData->PushV(&fPoints[i].fX, 3); + fRenderData->PushV(0); + } + fRenderData->ResizeV(4*fTexX*fTexY); + } else { + fRenderData = std::make_unique("makeHit", 3*fSize); + fRenderData->PushV(&fPoints[0].fX, 3*fSize); + } } } diff --git a/graf3d/eve7/src/REveRenderData.cxx b/graf3d/eve7/src/REveRenderData.cxx index 10516ac79c5fe..f4dd21b6d2207 100644 --- a/graf3d/eve7/src/REveRenderData.cxx +++ b/graf3d/eve7/src/REveRenderData.cxx @@ -80,3 +80,21 @@ void REveRenderData::SetMatrix(const double *arr) fMatrix.push_back(arr[i]); } } + +///////////////////////////////////////////////////////////////////////////////////////// +/// Calculate texture dimensions to hold nel elements with given alignment on x axis. +/// Static function. +/// +/// Implementation could be improved -- now it simply goes for near-square-root(size) +/// dimensions that satisfy the alignment requirement. + +void REveRenderData::CalcTextureSize(int nel, int align, int &sx, int &sy) +{ + if (nel <= 0) { sx = sy = 0; return; } + + sx = (int) std::ceil(std::sqrt(nel)); + int rx = sx % align; + if (rx > 0) sx += align - rx; + sy = nel / sx; + if (nel % sx > 0) sy += 1; +} diff --git a/ui5/eve7/lib/EveElements.js b/ui5/eve7/lib/EveElements.js index 9e1d8cbb9dcbe..fc12012756c52 100644 --- a/ui5/eve7/lib/EveElements.js +++ b/ui5/eve7/lib/EveElements.js @@ -595,6 +595,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(/*EveManager*/) { constructor() { } + GenerateTypename(obj) { return "THREE." + obj.type; } + /** Test if render data has vertex buffer. Make logging if not. Only for debug purposes */ TestRnr(name, obj, rnrData) { diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 21a81dacf2074..30f1d39a73ab1 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -64,10 +64,15 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) class EveElements { - constructor(rc) { + constructor(rc, viewer) { console.log("EveElements -- RCore"); RC = rc; + this.viewer = viewer; + + RC.Cache.enabled = true; + + this.tex_cache = new RC.TextureCache; this.POINT_SIZE_FAC = 1; this.LINE_WIDTH_FAC = 1; @@ -75,6 +80,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) this.ColorBlack = new RC.Color(0x000000); } + GenerateTypeName(obj) { return "RC." + obj.type; } + SetupPointLineFacs(pf, lf) { this.POINT_SIZE_FAC = pf; @@ -194,6 +201,22 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return true; } + GetLumAlphaTexture(name, callback) + { + let url = window.location.origin + '/rootui5sys/eve7/textures/' + name; + + this.tex_cache.deliver(url, + callback, + (image) => { + return new RC.Texture + (image, RC.Texture.ClampToEdgeWrapping, RC.Texture.ClampToEdgeWrapping, + RC.Texture.LinearFilter, RC.Texture.LinearFilter, + RC.Texture.LUMINANCE_ALPHA, RC.Texture.LUMINANCE_ALPHA, RC.Texture.UNSIGNED_BYTE, + image.width, image.height); + }, + () => { this.viewer.request_render() } + ); + } //============================================================================== // makeHit @@ -203,6 +226,40 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) { if (this.TestRnr("hit", hit, rnr_data)) return null; + let col = RcCol(hit.fMarkerColor); + const msize = this.POINT_SIZE_FAC * hit.fMarkerSize; + let sm = new RC.ZSpriteBasicMaterial( { + SpriteMode: RC.SPRITE_SPACE_SCREEN, SpriteSize: [msize, msize], + color: this.ColorBlack, + emissive: col, + diffuse: col.clone().multiplyScalar(0.5) } ); + sm.transparent = true; + // sm.depthWrite = false; + this.GetLumAlphaTexture("star5-32a.png", (tex) => { + sm.addMap(tex); + }); + + sm.instanceData = new RC.Texture(rnr_data.vtxBuff, + RC.Texture.ClampToEdgeWrapping, RC.Texture.ClampToEdgeWrapping, + RC.Texture.NearestFilter, RC.Texture.NearestFilter, + // RC.Texture.R32F, RC.Texture.R32F, RC.Texture.FLOAT, + RC.Texture.RGBA32F, RC.Texture.RGBA, RC.Texture.FLOAT, + hit.fTexX, hit.fTexY); + + let s = new RC.ZSprite(null, sm); + s.frustumCulled = false; // need a way to speciy bounding box/sphere !!! + s.instanced = true; + s.instanceCount = hit.fSize; + + s.dispose = () => { delete this; } // ??? RCRC instanceData texture ??? + + return s; + } + + makeHitOrig(hit, rnr_data) + { + if (this.TestRnr("hit", hit, rnr_data)) return null; + let geo = new RC.Geometry(); geo.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index dc959f1644043..4c328571bec27 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -40,8 +40,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { let obj3d = this.creator[fname](elem, elem.render_data); if (obj3d) { - // MT ??? why?, it can really be anything, even just container Object3D - obj3d._typename = "THREE.Mesh"; + // Used by JSRoot + obj3d._typename = this.creator.GenerateTypeName(obj3d); // add reference to a streamed eve element to obj3d obj3d.eve_el = elem; @@ -252,7 +252,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { this.id2obj_map.delete(elId); if (typeof obj3d.dispose !== 'function') - console.log("EveScene.elementsRemoved no dispose function for " + this.mgr.GetElement(elId)._typename, ", rnr obj ", obj3d._typename); + console.log("EveScene.elementsRemoved no dispose function for " + this.mgr.GetElement(elId)._typename, ", rnr obj ", obj3d._typename, obj3d); else obj3d.dispose(); } diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 724bdbf56b869..ce49a854e1d82 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -15,22 +15,15 @@ sap.ui.define([ const urlParams = new URLSearchParams(window.location.search); - console.log("XXXX window.location.search='", window.location.search, "', ", - "URL params UseRenderQueue NoRenderQueue = ", urlParams.get('UseRenderQueue'), urlParams.get('NoRenderQueue')); - this.UseRenderQueue = true; - if (urlParams.get('UseRenderQueue') != null) this.UseRenderQueue = true; - if (urlParams.get('NoRenderQueue' ) != null) this.UseRenderQueue = false; + let mode_mm = /^(?:Direct|Simple|Full)$/.exec(urlParams.get('RQ_Mode')); + let ssaa_mm = /^(1|2|4)$/. exec(urlParams.get('RQ_SSAA')); - if (this.UseRenderQueue) - { - let mode_mm = /^(?:Direct|Simple|Full)$/.exec(urlParams.get('RQ_Mode')); - let ssaa_mm = /^(1|2|4)$/. exec(urlParams.get('RQ_SSAA')); + this.RQ_Mode = (mode_mm) ? mode_mm[0] : "Simple"; + this.RQ_SSAA = (ssaa_mm) ? ssaa_mm[0] : 2; - this.RQ_Mode = (mode_mm) ? mode_mm[0] : "Simple"; - this.RQ_SSAA = (ssaa_mm) ? ssaa_mm[0] : 2; - } + console.log("GlViewerRCore RQ_Mode:", this.RQ_Mode, "RQ_SSAA:", this.RQ_SSAA); - console.log("UseRenderQueue", this.UseRenderQueue, "RQ_Mode", this.RQ_Mode, "RQ_SSAA", this.RQ_SSAA); + this._logLevel = 1; // 0 - error, 1 - warning, 2 - info, 3 - debug } init(controller) @@ -56,7 +49,7 @@ sap.ui.define([ bootstrap() { - this.creator = new EveElements(RC); + this.creator = new EveElements(RC, this); // this.creator.useIndexAsIs = EVE.JSR.decodeUrl().has('useindx'); RC.Object3D.sDefaultPickable = false; @@ -102,6 +95,7 @@ sap.ui.define([ let gl = this.canvas.getContext("webgl2"); this.renderer = new RC.MeshRenderer(this.canvas, RC.WEBGL2, {antialias: false, stencil: true}); + this.renderer._logLevel = 0; this.renderer.clearColor = "#FFFFFFFF"; this.renderer.addShaderLoaderUrls("rootui5sys/eve7/lib/RC/shaders"); this.renderer.addShaderLoaderUrls("rootui5sys/eve7/shaders"); @@ -175,25 +169,22 @@ sap.ui.define([ this.rot_center = new RC.Vector3(0,0,0); - if (this.UseRenderQueue) + this.rqt = new RC.RendeQuTor(this.renderer, this.scene, this.camera); + if (this.RQ_Mode == "Direct") { - this.rqt = new RC.RendeQuTor(this.renderer, this.scene, this.camera); - if (this.RQ_Mode == "Direct") - { - this.rqt.initDirectToScreen(); - } - else if (this.RQ_Mode == "Simple") - { - this.rqt.initSimple(this.RQ_SSAA); - this.creator.SetupPointLineFacs(this.RQ_SSAA, this.RQ_SSAA); - } - else - { - this.rqt.initFull(this.RQ_SSAA); - this.creator.SetupPointLineFacs(this.RQ_SSAA, this.RQ_SSAA); - } - this.rqt.updateViewport(w, h); + this.rqt.initDirectToScreen(); } + else if (this.RQ_Mode == "Simple") + { + this.rqt.initSimple(this.RQ_SSAA); + this.creator.SetupPointLineFacs(this.RQ_SSAA, this.RQ_SSAA); + } + else + { + this.rqt.initFull(this.RQ_SSAA); + this.creator.SetupPointLineFacs(this.RQ_SSAA, this.RQ_SSAA); + } + this.rqt.updateViewport(w, h); } setupEventHandlers() @@ -397,20 +388,27 @@ sap.ui.define([ //============================================================================== + request_render() + { + if (this.render_requested) return; + setTimeout(this.render.bind(this), 0); + this.render_requested = true; + } + render() { // console.log("RENDER", this.scene, this.camera, this.canvas, this.renderer); + this.render_requested = false; + if (this.canvas.width <= 0 || this.canvas.height <= 0) return; - if (this.UseRenderQueue) - this.rqt.render(); - else - this.renderer.render( this.scene, this.camera ); + this.rqt.render(); if (this.renderer.used == false) { // RCRC Ideally there would be an onShadersLoaded callback. - console.log("GlViewerRCore render: not all programs compiled -- setting up render timer"); + if (this._logLevel >= 2) + console.log("GlViewerRCore render: not all programs compiled -- setting up render timer"); setTimeout(this.render.bind(this), 200); } @@ -455,7 +453,7 @@ sap.ui.define([ this.renderer.updateViewport(w, h); - if (this.UseRenderQueue) this.rqt.updateViewport(w, h); + this.rqt.updateViewport(w, h); this.controls.update(); this.render(); From fbc374c2def3de31c698c092e38c2f8e4662e277 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Wed, 29 Jun 2022 13:48:15 -0700 Subject: [PATCH 07/84] Pickable zsprite as points. --- ui5/eve7/lib/EveElementsRCore.js | 2 ++ ui5/eve7/lib/RendeQuTor.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 30f1d39a73ab1..df434202b1e39 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -251,6 +251,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) s.instanced = true; s.instanceCount = hit.fSize; + this.RcPickable(hit, s); + s.dispose = () => { delete this; } // ??? RCRC instanceData texture ??? return s; diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index 09252f51fba67..5d3ab0136b1ac 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -108,7 +108,7 @@ export class RendeQuTor let texref = this.pqueue._textureMap["depthr32f_picking"]; let tex = glman.getTexture(texref); - console.log("Dumper:", glman, gl, texref, tex); + // console.log("Dumper:", glman, gl, texref, tex); const fb = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, fb); From 2ac0cb9a9ea338fb54116c11b5e05d6523f79045 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Tue, 5 Jul 2022 15:20:53 -0700 Subject: [PATCH 08/84] [REve] Initial steps for secondary selection with RCore. - Make REvePointSet secondary-selectable. - EveScene.js: pass eve_element instead of object3d in some cases that simplify the code. - RenderCore -- steps towards secondary selection --- graf3d/eve7/inc/ROOT/REvePointSet.hxx | 4 +- graf3d/eve7/src/REvePointSet.cxx | 1 + ui5/eve7/lib/EveElements.js | 4 +- ui5/eve7/lib/EveElementsRCore.js | 83 ++++++++++-------- ui5/eve7/lib/EveScene.js | 29 ++++--- ui5/eve7/lib/GlViewerRCore.js | 118 +++++++++++++------------- ui5/eve7/lib/RendeQuTor.js | 71 +++++++--------- 7 files changed, 161 insertions(+), 149 deletions(-) diff --git a/graf3d/eve7/inc/ROOT/REvePointSet.hxx b/graf3d/eve7/inc/ROOT/REvePointSet.hxx index be81c77c58f7f..520e5726c5b10 100644 --- a/graf3d/eve7/inc/ROOT/REvePointSet.hxx +++ b/graf3d/eve7/inc/ROOT/REvePointSet.hxx @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -34,7 +35,8 @@ namespace Experimental { class REvePointSet : public REveElement, public REveProjectable, public TAttMarker, - public TAttBBox + public TAttBBox, + public REveSecondarySelectable { friend class REvePointSetArray; diff --git a/graf3d/eve7/src/REvePointSet.cxx b/graf3d/eve7/src/REvePointSet.cxx index 298f0843018ae..b9119e612141b 100644 --- a/graf3d/eve7/src/REvePointSet.cxx +++ b/graf3d/eve7/src/REvePointSet.cxx @@ -220,6 +220,7 @@ Int_t REvePointSet::WriteCoreJson(nlohmann::json& j, Int_t rnr_offset) } j["fMarkerSize"] = GetMarkerSize(); j["fMarkerColor"] = GetMarkerColor(); + j["fSecondarySelect"] = fAlwaysSecSelect; return ret; } diff --git a/ui5/eve7/lib/EveElements.js b/ui5/eve7/lib/EveElements.js index fc12012756c52..563edec36f87e 100644 --- a/ui5/eve7/lib/EveElements.js +++ b/ui5/eve7/lib/EveElements.js @@ -27,7 +27,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(/*EveManager*/) { let s = this.obj3d.scene; if (s && (typeof s[fname] == "function")) - return s[fname](this.obj3d, arg, this.event); + return s[fname](this.obj3d.eve_el, arg, this.event); return false; } @@ -595,7 +595,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(/*EveManager*/) { constructor() { } - GenerateTypename(obj) { return "THREE." + obj.type; } + GenerateTypeName(obj) { return "THREE." + obj.type; } /** Test if render data has vertex buffer. Make logging if not. Only for debug purposes */ TestRnr(name, obj, rnrData) { diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index df434202b1e39..56c2aeed02324 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -12,37 +12,43 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) class EveElemControl { - constructor(o3d) + constructor(pick_state) { - this.obj3d = o3d; + this.state = pick_state; + // event property can be set by handlers } invokeSceneMethod(fname, arg) { - if ( ! this.obj3d) return false; + if ( ! this.state.top_object || ! this.state.eve_el) return false; - let s = this.obj3d.scene; + let s = this.state.top_object.scene; if (s && (typeof s[fname] == "function")) - return s[fname](this.obj3d, arg, this.event); + return s[fname](this.state.eve_el, arg, this.event); return false; } - getTooltipText(intersect) + getTooltipText() { - let el = this.obj3d.eve_el; + let el = this.state.eve_el; return el.fTitle || el.fName || ""; } + extractIndex() + { + return this.state.instance; + } + elementHighlighted(indx) { // default is simple selection, we ignore the indx - this.invokeSceneMethod("processElementHighlighted"); // , indx); + this.invokeSceneMethod("processElementHighlighted", indx); } elementSelected(indx) { // default is simple selection, we ignore the indx - this.invokeSceneMethod("processElementSelected"); //, indx); + this.invokeSceneMethod("processElementSelected", indx); } } // class EveElemControl @@ -61,6 +67,24 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } //------------------------------------------------------------------------------ + // Builder functions of this class are called by EveScene to create RCore + // objects representing an EveElement. They can have children if multiple RCore + // objects are required (e.g., mesh + lines + points). + // + // The top-level object returned by these builder functions will get additional + // properties injected by EveScene: + // - eve_el + // - scene. + // + // Object picking functions in GlViewerRCore will navigate up the parent hierarchy + // until an object with eve_el property is set. + // If secondary selection is enabled on the eve_el, instance picking will be called + // as well and the returned ID will be used as the index for secondary selection. + // This can be overriden by setting get_ctrl property of any RCore object to a function + // that takes a reference to the said argument and returns an instance of class + // EveElemControl. + // If get_ctrl is not found on the upwards traversal to object with eve_el property set + // the base EveElemControl is created with the top-level as the argument. class EveElements { @@ -80,6 +104,10 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) this.ColorBlack = new RC.Color(0x000000); } + //---------------------------------------------------------------------------- + // Helper functions + //---------------------------------------------------------------------------- + GenerateTypeName(obj) { return "RC." + obj.type; } SetupPointLineFacs(pf, lf) @@ -175,13 +203,15 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return mat; } - RcPickable(el, obj3d, ctrl_class = EveElemControl) + RcPickable(el, obj3d, do_children = true, ctrl_class = EveElemControl) { if (el.fPickable) { - obj3d.get_ctrl = function() { return new ctrl_class(obj3d); } + obj3d.get_ctrl = function(state) { return new ctrl_class(state); } obj3d.pickable = true; - for (let i = 0; i < obj3d.children.length; ++i) - obj3d.children[i].pickable = true; + if (do_children) { + for (let i = 0; i < obj3d.children.length; ++i) + obj3d.children[i].pickable = true; + } // using auto-id now obj3d.colorID = el.fElementId; // console.log("YES Pickable for", el.fElementId, el.fName) return true; @@ -218,6 +248,10 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) ); } + //---------------------------------------------------------------------------- + // Builder functions + //---------------------------------------------------------------------------- + //============================================================================== // makeHit //============================================================================== @@ -258,28 +292,6 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return s; } - makeHitOrig(hit, rnr_data) - { - if (this.TestRnr("hit", hit, rnr_data)) return null; - - let geo = new RC.Geometry(); - geo.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); - - let col = RcCol(hit.fMarkerColor); - // console.log("COLOR", hit.fMarkerColor, EVE.JSR.getColor(hit.fMarkerColor), col); - - let mat = this.RcPointMaterial(col, 1, hit.fMarkerSize, - { pointsScale: false, drawCircles: true }); - - let pnts = new RC.Point( {geometry: geo, material: mat} ); - this.UpdatePointPickingMaterial(pnts) - this.RcPickable(hit, pnts); - - pnts.dispose = function() { delete this; } // ???? - return pnts; - } - - //============================================================================== // makeTrack //============================================================================== @@ -404,6 +416,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let mesh = new RC.Mesh(geo_body, this.RcFancyMaterial(mcol, 0.5, { side: RC.FRONT_AND_BACK_SIDE })); let line1 = new RC.Line(geo_rim, this.RcLineMaterial(lcol, 0.8, 4)); + line1.renderingPrimitive = RC.LINE_LOOP; let line2 = new RC.Line(geo_rays, this.RcLineMaterial(lcol, 0.8, 1)); line2.renderingPrimitive = RC.LINES; diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index 4c328571bec27..c1c6672191e64 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -43,13 +43,12 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { // Used by JSRoot obj3d._typename = this.creator.GenerateTypeName(obj3d); - // add reference to a streamed eve element to obj3d - obj3d.eve_el = elem; + obj3d.eve_el = elem; // reference to the EveElement + obj3d.scene = this; // required for change processing, esp. highlight/selection // SL: this is just identifier for highlight, required to show items on other places, set in creator obj3d.geo_object = elem.fMasterId || elem.fElementId; obj3d.geo_name = elem.fName; // used for highlight - obj3d.scene = this; // required for get changes when highlight/selection is changed if (elem.render_data.matrix) { obj3d.matrixAutoUpdate = false; @@ -301,12 +300,12 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { return undefined; } - sendSelectMIR(sel_id, obj3d, is_multi, indx) + sendSelectMIR(sel_id, eve_el, is_multi, indx) { indx = this.sanitizeIndx(indx); let is_secsel = indx !== undefined; - let fcall = "NewElementPickedStr(" + (obj3d ? obj3d.eve_el.fElementId : 0) + `, ${is_multi}, ${is_secsel}`; + let fcall = "NewElementPickedStr(" + (eve_el ? eve_el.fElementId : 0) + `, ${is_multi}, ${is_secsel}`; if (is_secsel) { fcall += ", \"" + indx.join(",") + "\""; @@ -317,32 +316,32 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { } /** interactive handler. Calculates selection state, apply to element and distribute to other scene */ - processElementSelected(obj3d, indx, event) + processElementSelected(eve_el, indx, event) { // console.log("EveScene.processElementSelected", obj3d, col, indx, evnt); let is_multi = event && event.ctrlKey ? true : false; - this.sendSelectMIR(this.mgr.global_selection_id, obj3d, is_multi, indx); + this.sendSelectMIR(this.mgr.global_selection_id, eve_el, is_multi, indx); return true; } /** interactive handler */ - processElementHighlighted(obj3d, indx, evnt) + processElementHighlighted(eve_el, indx, event) { - if (this.mgr.MatchSelection(this.mgr.global_selection_id, obj3d.eve_el, indx)) + if (this.mgr.MatchSelection(this.mgr.global_selection_id, eve_el, indx)) return true; // Need check for duplicates before call server, else server will un-higlight highlighted element // console.log("EveScene.processElementHighlighted", obj3d.eve_el.fElementId, indx, evnt); - if (this.mgr.MatchSelection(this.mgr.global_highlight_id, obj3d.eve_el, indx)) + if (this.mgr.MatchSelection(this.mgr.global_highlight_id, eve_el, indx)) return true; // when send queue below threshold, ignre highlight if (this.mgr.CheckSendThreshold()) return true; - this.sendSelectMIR(this.mgr.global_highlight_id, obj3d, false, indx); + this.sendSelectMIR(this.mgr.global_highlight_id, eve_el, false, indx); return true; } @@ -400,6 +399,14 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { let obj3d = this.getObj3D( element_id ); if (!obj3d) return; + // XXXXX To be properly structured and implemented. + if (this.glctrl.viewer.constructor.name == "GlViewerRCore") { + obj3d._material._color.r = Math.random(); + obj3d._material._color.g = Math.random(); + obj3d._material._color.b = Math.random(); + return; + } + let opass = this.glctrl.viewer.outline_pass; opass.id2obj_map[element_id] = opass.id2obj_map[element_id] || []; diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index ce49a854e1d82..2a87989ff1557 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -100,9 +100,11 @@ sap.ui.define([ this.renderer.addShaderLoaderUrls("rootui5sys/eve7/lib/RC/shaders"); this.renderer.addShaderLoaderUrls("rootui5sys/eve7/shaders"); this.renderer.pickObject3D = true; - this.renderer.pickDoNotRender = true; RC.PickingShaderMaterial.DEFAULT_PICK_MODE = RC.PickingShaderMaterial.PICK_MODE.UINT; + this.outline_pass = {}; + this.outline_pass.id2obj_map = {}; + this.scene = new RC.Scene(); this.lights = this.make_object("Light container"); @@ -226,7 +228,7 @@ sap.ui.define([ dome.addEventListener('pointerdown', function(event) { glc.removeMouseMoveTimeout(); - if (event.buttons != 1 && event.buttons != 2) glc.clearHighlight(); + if (event.button != 0 && event.button != 2) glc.clearHighlight(); glc.removeMouseupListener(); // console.log("GLC::mousedown", this, glc, event, event.offsetX, event.offsetY); @@ -235,11 +237,11 @@ sap.ui.define([ { this.removeEventListener('pointerup', glc.mouseup_listener); - if (event2.buttons == 1) // Selection on mouseup without move + if (event2.button == 0) // Selection on mouseup without move { glc.handleMouseSelect(event2); } - else if (event.buttons == 2) // Context menu on delay without move + else if (event2.button == 2) // Context menu on delay without move { EVE.JSR.createMenu(event2, glc).then(menu => glc.showContextMenu(event2, menu)); } @@ -416,20 +418,39 @@ sap.ui.define([ // window.requestAnimationFrame(this.render.bind(this)); } - render_for_picking(x, y) + render_for_picking(x, y, detect_depth) { console.log("RENDER FOR PICKING", this.scene, this.camera, this.canvas, this.renderer); - if (this.canvas.width <= 0 || this.canvas.height <= 0) return; + if (this.canvas.width <= 0 || this.canvas.height <= 0) return null; + + let state = this.rqt.pick(x, y, detect_depth); + + if (state.object === null) return null; + + let top_obj = state.object; + while (top_obj.eve_el === undefined) + top_obj = top_obj.parent; + + state.top_object = top_obj; + state.eve_el = top_obj.eve_el; + + if (state.eve_el.fSecondarySelect) + this.rqt.pick_instance(state); - this.renderer.pick(x, y); - this.rqt.pick(); + state.w = this.get_width();; + state.h = this.get_height(); + state.mouse = new RC.Vector2( ((x + 0.5) / state.w) * 2 - 1, + -((y + 0.5) / state.h) * 2 + 1 ); - let o3d = this.renderer.pickedObject3D; - // Render to FBO or texture would work. - // let d = this.renderer.pickedDepth; - console.log("pick result", o3d /* , d */); - return o3d; + let ctrl_obj = state.object; + while (ctrl_obj.get_ctrl === undefined) + ctrl_obj = ctrl_obj.parent; + + state.ctrl = ctrl_obj.get_ctrl(state) + + console.log("pick result", state); + return state; } //============================================================================== @@ -488,61 +509,42 @@ sap.ui.define([ } } - /** Get three.js intersect object at specified mouse position */ - getIntersectAt(x, y) - { - console.log("GLC::onMouseMoveTimeout", x, y); - - let o3d = this.render_for_picking(x, y); - if (!o3d) return null; - if (!o3d.get_ctrl) o3d = o3d.parent; - if (o3d.get_ctrl) { - if (!o3d.get_ctrl) o3d = o3d.parent; - let w = this.get_width(); - let h = this.get_height(); - let mouse = new RC.Vector2( ((x + 0.5) / w) * 2 - 1, -((y + 0.5) / h) * 2 + 1 ); - return { object: o3d, mouse: mouse, w: w, h: h }; - } - return null; - } - onMouseMoveTimeout(x, y) { delete this.mousemove_timeout; - let intersect = this.getIntersectAt(x,y); + let pstate = this.render_for_picking(x, y, false); - if ( ! intersect) + if ( ! pstate) return this.clearHighlight(); - let c = intersect.object.get_ctrl(); - - let mouse = intersect.mouse; + let c = pstate.ctrl; - // c.elementHighlighted(c.extractIndex(intersect)); + c.elementHighlighted(c.extractIndex()); - this.highlighted_scene = c.obj3d.scene; + this.highlighted_scene = pstate.top_object.scene; - if (c.obj3d && c.obj3d.eve_el) - this.ttip_text.innerHTML = c.getTooltipText(intersect); + if (pstate.object && pstate.eve_el) + this.ttip_text.innerHTML = c.getTooltipText(); else this.ttip_text.innerHTML = ""; - let dome = this.controller.getView().getDomRef(); - let offs = (mouse.x > 0 || mouse.y < 0) ? this.getRelativeOffsets(dome) : null; + let dome = this.controller.getView().getDomRef(); + let mouse = pstate.mouse; + let offs = (mouse.x > 0 || mouse.y < 0) ? this.getRelativeOffsets(dome) : null; if (mouse.x <= 0) { this.ttip.style.left = (x + dome.offsetLeft + 10) + "px"; this.ttip.style.right = null; } else { - this.ttip.style.right = (intersect.w - x + offs.right + 10) + "px"; + this.ttip.style.right = (pstate.w - x + offs.right + 10) + "px"; this.ttip.style.left = null; } if (mouse.y >= 0) { this.ttip.style.top = (y + dome.offsetTop + 10) + "px"; this.ttip.style.bottom = null; } else { - this.ttip.style.bottom = (intersect.h - y + offs.bottom + 10) + "px"; + this.ttip.style.bottom = (pstate.h - y + offs.bottom + 10) + "px"; this.ttip.style.top = null; } @@ -591,13 +593,13 @@ sap.ui.define([ // See js/modules/menu/menu.mjs createMenu(), menu.add() - let intersect = this.getIntersectAt(event.offsetX, event.offsetY); + let pstate = this.render_for_picking(event.offsetX, event.offsetY, true); menu.add("header:Context Menu"); - if (intersect) { - if (intersect.object.eve_el) - menu.add("Browse to " + (intersect.object.eve_el.fName || "element"), intersect.object.eve_el.fElementId, this.controller.invokeBrowseOf.bind(this.controller)); + if (pstate) { + if (pstate.eve_el) + menu.add("Browse to " + (pstate.eve_el.fName || "element"), pstate.eve_el.fElementId, this.controller.invokeBrowseOf.bind(this.controller)); } menu.add("Reset camera", this.resetRenderer); @@ -605,11 +607,11 @@ sap.ui.define([ menu.add("separator"); let fff = this.defaultContextMenuAction; - menu.add("sub:Sub Test"); - menu.add("Foo", 'foo', fff); - menu.add("Bar", 'bar', fff); - menu.add("Baz", 'baz', fff); - menu.add("endsub:"); + // menu.add("sub:Sub Test"); + // menu.add("Foo", 'foo', fff); + // menu.add("Bar", 'bar', fff); + // menu.add("Baz", 'baz', fff); + // menu.add("endsub:"); menu.show(event); } @@ -621,13 +623,13 @@ sap.ui.define([ handleMouseSelect(event) { - let intersect = this.getIntersectAt(event.offsetX, event.offsetY); + let pstate = this.render_for_picking(event.offsetX, event.offsetY, false); - if (intersect) { - let c = intersect.object.get_ctrl(); + if (pstate) { + let c = pstate.ctrl; c.event = event; - c.elementSelected(c.extractIndex(intersect)); - this.highlighted_scene = intersect.object.scene; + c.elementSelected(c.extractIndex()); + this.highlighted_scene = pstate.top_object.scene; } else { // XXXX HACK - handlersMIR senders should really be in the mgr diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index 5d3ab0136b1ac..94e4df56abec0 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -97,12 +97,18 @@ export class RendeQuTor this.queue.render(); } - pick() + pick(x, y, detect_depth = false) { - let foo = this.pqueue.render(); - console.log("RenderQuTor::pick", this.renderer.pickedObject3D, foo); + this.renderer.pick_setup(x, y); - if (true) { + let state = this.pqueue.render(); + state.x = x; + state.y = y; + state.depth = -1.0; + state.object = this.renderer.pickedObject3D; + // console.log("RenderQuTor::pick", state); + + if (detect_depth && this.renderer.pickedObject3D !== null) { let glman = this.renderer.glManager; let gl = this.renderer.gl; let texref = this.pqueue._textureMap["depthr32f_picking"]; @@ -129,22 +135,27 @@ export class RendeQuTor gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); gl.deleteFramebuffer(fb); + + state.depth = d[4]; } + return state; + } + + pick_instance(state) { // RCRC Proto-proto-secondary-selection. Requires branch: - // https://github.com/osschar/RenderCore/tree/secondary-selection-emulate-vert-id-plus-flat-shading - if (false && this.renderer.pickedObject3D) { + // https://github.com/osschar/RenderCore/tree/img-tex-cache + if (state.object !== this.renderer.pickedObject3D || ! state.object.instanced) { + console.error("RendeQuTor::pick_instance state mismatch", state, this.renderer.pickedObject3D); + } else { console.log("RenderQuTor::pick going for secondary select"); - this.renderer._pickSecondaryEnabled = true; - this.renderer.pickedObject3D.pickingMaterial.pickMode = PickingShaderMaterial.PICK_MODE.UINT_PRIM; + this.renderer._pickSecondaryEnabled = true; this.pqueue.render(); - this.renderer.pickedObject3D.pickingMaterial.pickMode = PickingShaderMaterial.PICK_MODE.UINT; - // Reset pick state - in case shaders needed to be loaded and picking - // was not actually done the flag does not get reset. - this.renderer._pickSecondaryEnabled = false; + state.instance = this.renderer._pickedID; } + return state; } @@ -194,6 +205,9 @@ export class RendeQuTor this.pqueue.pushRenderPass(this.PRP_depth2r); } + + //============================================================================= + // Regular RenderPasses //============================================================================= make_RP_DirectToScreen() @@ -222,46 +236,19 @@ export class RendeQuTor this.RP_SSAA_Super = new RenderPass( // Rendering pass type RenderPass.BASIC, - // Initialize function - function (textureMap, additionalData) { - iterateSceneR(pthis.scene, function(object){ - if (object.pickable === false || object instanceof Text2D || object instanceof IcoSphere) { - object.visible = true; - return; - } - // pthis.OriginalMats.push(object.material); - }); - }, - + function (textureMap, additionalData) {}, // Preprocess function - function (textureMap, additionalData) { - // let m_index = 0; - - iterateSceneR(pthis.scene, function(object) { - if(object.pickable === false || object instanceof Text2D || object instanceof IcoSphere) { - object.visible = true; - return; - } - // object.material = pthis.OriginalMats[m_index]; - // m_index++; - }); - - return { scene: pthis.scene, camera: pthis.camera }; - }, - + function (textureMap, additionalData) { return { scene: pthis.scene, camera: pthis.camera }; }, // Postprocess function (textureMap, additionalData) {}, - // Target RenderPass.TEXTURE, - // Viewport null, - // Bind depth texture to this ID "depthDefaultDefaultMaterials", - + // Outputs [ { id: "color_ssaa_super", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG } ] ); this.RP_SSAA_Super.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; From ae35b0de24eb49b70f013c406b709fe665dd3c4c Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Thu, 14 Jul 2022 17:32:22 -0700 Subject: [PATCH 09/84] [REve] Implement RCore selection, secondary-selection; preliminary outline. * event_demo.C: sec-select points, jet title include pT. * EveElementsRCore.js: implement control classes for selection. * EveScene.js, GlViewer classes: Cleamup highlite/selection management so it can be abstracted for RCore. --- tutorials/eve7/event_demo.C | 3 +- tutorials/eve7/points.C | 2 +- ui5/eve7/lib/EveElementsRCore.js | 56 +++++--- ui5/eve7/lib/EveScene.js | 60 ++++---- ui5/eve7/lib/GlViewerJSRoot.js | 7 +- ui5/eve7/lib/GlViewerRCore.js | 63 ++++++--- ui5/eve7/lib/GlViewerThree.js | 2 + ui5/eve7/lib/RendeQuTor.js | 230 ++++++++++++++----------------- 8 files changed, 210 insertions(+), 213 deletions(-) diff --git a/tutorials/eve7/event_demo.C b/tutorials/eve7/event_demo.C index e06766a7c2483..07d6683980857 100644 --- a/tutorials/eve7/event_demo.C +++ b/tutorials/eve7/event_demo.C @@ -81,6 +81,7 @@ void addPoints() auto ps2 = getPointSet(10, 200, 4); ps2->SetName("Points_2"); ps2->SetTitle("Points_2 title"); // used as tooltip + ps2->SetAlwaysSecSelect(true); pntHolder->AddElement(ps2); event->AddElement(pntHolder); @@ -135,7 +136,7 @@ void addJets() for (int i = 0; i < N_Jets; i++) { auto jet = new REX::REveJetCone(Form("Jet_%d", i)); - jet->SetTitle(Form("Jet_%d title", i)); // used as tooltip + jet->SetTitle(Form("Jet_%d\n pT = %.2f", i, r.Uniform(1, 40))); // used as tooltip jet->SetCylinder(2*kR_max, 2*kZ_d); jet->AddEllipticCone(r.Uniform(-3.5, 3.5), r.Uniform(0, TMath::TwoPi()), r.Uniform(0.02, 0.2), r.Uniform(0.02, 0.3)); diff --git a/tutorials/eve7/points.C b/tutorials/eve7/points.C index 26e09dcf8e1b3..914b465a90fff 100644 --- a/tutorials/eve7/points.C +++ b/tutorials/eve7/points.C @@ -23,7 +23,7 @@ REX::REvePointSet *createPointSet(int npoints = 2, float s = 2, int color = 28) ps->SetNextPoint(r.Uniform(-s,s), r.Uniform(-s,s), r.Uniform(-s,s)); ps->SetMarkerColor(color); - ps->SetMarkerSize(3+r.Uniform(1, 2)); + ps->SetMarkerSize(5 + r.Uniform(1, 15)); ps->SetMarkerStyle(4); return ps; } diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 56c2aeed02324..ac8bec33add8a 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -12,43 +12,48 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) class EveElemControl { - constructor(pick_state) + constructor(iobj, tobj) { - this.state = pick_state; - // event property can be set by handlers + this.invoke_obj = iobj; + this.top_obj = tobj ? tobj : iobj; } - invokeSceneMethod(fname, arg) + invokeSceneMethod(fname, arg, event) { - if ( ! this.state.top_object || ! this.state.eve_el) return false; + if ( ! this.top_obj || ! this.top_obj.eve_el) return false; - let s = this.state.top_object.scene; + let s = this.top_obj.scene; if (s && (typeof s[fname] == "function")) - return s[fname](this.state.eve_el, arg, this.event); + return s[fname](this.top_obj.eve_el, arg, event); return false; } getTooltipText() { - let el = this.state.eve_el; + let el = this.top_obj.eve_el; return el.fTitle || el.fName || ""; } - extractIndex() + extractIndex(instance) { - return this.state.instance; + return instance; } - elementHighlighted(indx) + elementHighlighted(indx, event) { // default is simple selection, we ignore the indx - this.invokeSceneMethod("processElementHighlighted", indx); + return this.invokeSceneMethod("processElementHighlighted", indx, event); } - elementSelected(indx) + elementSelected(indx, event) { // default is simple selection, we ignore the indx - this.invokeSceneMethod("processElementSelected", indx); + return this.invokeSceneMethod("processElementSelected", indx, event); + } + + DrawForSelection(sec_idcs, res) + { + res.geom.push(this.invoke_obj); } } // class EveElemControl @@ -83,8 +88,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // This can be overriden by setting get_ctrl property of any RCore object to a function // that takes a reference to the said argument and returns an instance of class // EveElemControl. - // If get_ctrl is not found on the upwards traversal to object with eve_el property set - // the base EveElemControl is created with the top-level as the argument. + // get_ctrl property needs to be set at least at the top-level object. class EveElements { @@ -212,11 +216,9 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) for (let i = 0; i < obj3d.children.length; ++i) obj3d.children[i].pickable = true; } - // using auto-id now obj3d.colorID = el.fElementId; - // console.log("YES Pickable for", el.fElementId, el.fName) + // using RCore auto-id to get Object3D that got picked. return true; } else { - // console.log("NOT Pickable for", el.fElementId, el.fName) return false; } } @@ -248,6 +250,13 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) ); } + AddMapToAllMaterials(o3d, tex) + { + if (o3d.material) o3d.material.addMap(tex); + if (o3d.pickingMaterial) o3d.pickingMaterial.addMap(tex); + if (o3d.outlineMaterial) o3d.outlineMaterial.addMap(tex); + } + //---------------------------------------------------------------------------- // Builder functions //---------------------------------------------------------------------------- @@ -269,9 +278,9 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) diffuse: col.clone().multiplyScalar(0.5) } ); sm.transparent = true; // sm.depthWrite = false; - this.GetLumAlphaTexture("star5-32a.png", (tex) => { - sm.addMap(tex); - }); + // this.GetLumAlphaTexture("star5-32a.png", (tex) => { + // sm.addMap(tex); + // }); sm.instanceData = new RC.Texture(rnr_data.vtxBuff, RC.Texture.ClampToEdgeWrapping, RC.Texture.ClampToEdgeWrapping, @@ -279,12 +288,15 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // RC.Texture.R32F, RC.Texture.R32F, RC.Texture.FLOAT, RC.Texture.RGBA32F, RC.Texture.RGBA, RC.Texture.FLOAT, hit.fTexX, hit.fTexY); + sm.instanceData.flipy = false; let s = new RC.ZSprite(null, sm); s.frustumCulled = false; // need a way to speciy bounding box/sphere !!! s.instanced = true; s.instanceCount = hit.fSize; + this.GetLumAlphaTexture("star5-32a.png", this.AddMapToAllMaterials.bind(this, s)); + this.RcPickable(hit, s); s.dispose = () => { delete this; } // ??? RCRC instanceData texture ??? diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index c1c6672191e64..44e647a001d7f 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -337,7 +337,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { if (this.mgr.MatchSelection(this.mgr.global_highlight_id, eve_el, indx)) return true; - // when send queue below threshold, ignre highlight + // when send queue below threshold, ignore highlight if (this.mgr.CheckSendThreshold()) return true; @@ -399,62 +399,56 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { let obj3d = this.getObj3D( element_id ); if (!obj3d) return; - // XXXXX To be properly structured and implemented. - if (this.glctrl.viewer.constructor.name == "GlViewerRCore") { - obj3d._material._color.r = Math.random(); - obj3d._material._color.g = Math.random(); - obj3d._material._color.b = Math.random(); - return; - } + let id2obj_map = this.glctrl.viewer.outline_map; + // console.log("EveScene.SelectElement ", selection_obj.fName, element_id, selection_obj.fElementId, id2obj_map); - let opass = this.glctrl.viewer.outline_pass; - opass.id2obj_map[element_id] = opass.id2obj_map[element_id] || []; + id2obj_map[element_id] = id2obj_map[element_id] || []; - if (opass.id2obj_map[element_id][selection_obj.fElementId] !== undefined) - { + if (id2obj_map[element_id][selection_obj.fElementId] !== undefined) { return; } - let stype = selection_obj.fName.endsWith("Selection") ? "select" : "highlight"; - let estype = THREE.OutlinePassEve.selection_enum[stype]; + const ST_Selection = 0; // Matching THREE.OutlinePassEve.selection_enum + const ST_Highlight = 1; + let stype = selection_obj.fName.endsWith("Selection") ? ST_Selection : ST_Highlight; let oe = this.mgr.GetElement(element_id); - // console.log("EveScene.SelectElement ", selection_obj.fName, oe.fName, selection_obj.fElementId, this.glctrl.viewer.outline_pass.id2obj_map); let res = { - "sel_type" : estype, - "sec_sel" : (oe.fSecondarySelect && sec_idcs.length > 0) ? true: false, + "sel_type" : stype, + "sec_sel" : (oe.fSecondarySelect && sec_idcs.length > 0) ? true : false, "geom" : [] }; - // exit if you try to highlight an object that has already been selected - if (estype == THREE.OutlinePassEve.selection_enum["highlight"] && - opass.id2obj_map[element_id][this.mgr.global_selection_id] !== undefined) + // Exit if we are trying to highlight an object that has already been selected. + if (stype == ST_Highlight && + id2obj_map[element_id][this.mgr.global_selection_id] !== undefined) { if (!res.sec_sel) return; } - if (!res.sec_sel) opass.id2obj_map[element_id] = []; + if (!res.sec_sel) id2obj_map[element_id] = []; - if (obj3d.get_ctrl) - { - let ctrl = obj3d.get_ctrl(); + if (obj3d.get_ctrl) { + let ctrl = obj3d.get_ctrl(obj3d); ctrl.DrawForSelection(sec_idcs, res, extra); - opass.id2obj_map[element_id][selection_obj.fElementId] = res; + } else { + res.geom.push(obj3d); + } + id2obj_map[element_id][selection_obj.fElementId] = res; - if (stype == "highlight" && selection_obj.sel_list) { - this.glctrl.viewer.remoteToolTip(selection_obj.sel_list[0].tooltip); - } + if (stype == ST_Highlight && selection_obj.sel_list) { + this.glctrl.viewer.remoteToolTip(selection_obj.sel_list[0].tooltip); } } UnselectElement(selection_obj, element_id) { - let opass = this.glctrl.viewer.outline_pass; - // console.log("EveScene.UnselectElement ", selection_obj.fName, element_id, selection_obj.fElementId, this.glctrl.viewer.outline_pass.id2obj_map); - if (opass.id2obj_map[element_id] !== undefined) - { - delete opass.id2obj_map[element_id][selection_obj.fElementId]; + let id2obj_map = this.glctrl.viewer.outline_map; + // console.log("EveScene.UnselectElement ", selection_obj.fName, element_id, selection_obj.fElementId, id2obj_map); + + if (id2obj_map[element_id] !== undefined) { + delete id2obj_map[element_id][selection_obj.fElementId]; } } diff --git a/ui5/eve7/lib/GlViewerJSRoot.js b/ui5/eve7/lib/GlViewerJSRoot.js index 3b8beeedd91b2..dbf35b70c21af 100644 --- a/ui5/eve7/lib/GlViewerJSRoot.js +++ b/ui5/eve7/lib/GlViewerJSRoot.js @@ -41,6 +41,8 @@ sap.ui.define([ return this.geo_painter.getExtrasContainer(); } + get outline_map() { return this.outline_pass.id2obj_map; } + //============================================================================== createGeoPainter() @@ -69,11 +71,6 @@ sap.ui.define([ this.outline_pass.usePatternTexture = false; this.outline_pass.downSampleRatio = 1; this.outline_pass.glowDownSampleRatio = 3; - // this.outline_pass.id2obj_map = {}; - - // const sh = THREE.OutlinePassEve.selection_enum["select"]; // doesnt stand for spherical harmonics :P - // THREE.OutlinePassEve.selection_atts[sh].visibleEdgeColor.set('#dd1111'); - // THREE.OutlinePassEve.selection_atts[sh].hiddenEdgeColor.set('#1111dd'); this._effectComposer.addPass( this.outline_pass ); diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 2a87989ff1557..75c2002d30d3d 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -23,6 +23,8 @@ sap.ui.define([ console.log("GlViewerRCore RQ_Mode:", this.RQ_Mode, "RQ_SSAA:", this.RQ_SSAA); + this._outline_map = {}; + this._logLevel = 1; // 0 - error, 1 - warning, 2 - info, 3 - debug } @@ -76,6 +78,8 @@ sap.ui.define([ return this.scene; } + get outline_map() { return this._outline_map; } + //============================================================================== createRCoreRenderer() @@ -95,19 +99,18 @@ sap.ui.define([ let gl = this.canvas.getContext("webgl2"); this.renderer = new RC.MeshRenderer(this.canvas, RC.WEBGL2, {antialias: false, stencil: true}); - this.renderer._logLevel = 0; + this.renderer._logLevel = 1; this.renderer.clearColor = "#FFFFFFFF"; this.renderer.addShaderLoaderUrls("rootui5sys/eve7/lib/RC/shaders"); this.renderer.addShaderLoaderUrls("rootui5sys/eve7/shaders"); this.renderer.pickObject3D = true; RC.PickingShaderMaterial.DEFAULT_PICK_MODE = RC.PickingShaderMaterial.PICK_MODE.UINT; - - this.outline_pass = {}; - this.outline_pass.id2obj_map = {}; + RC.GLManager.sCheckFrameBuffer = false; this.scene = new RC.Scene(); - this.lights = this.make_object("Light container"); + this.lights = new RC.Group; + this.lights.name = "Light container"; this.scene.add(this.lights); let a_light = new RC.AmbientLight(new RC.Color(0xffffff), 0.05); @@ -210,11 +213,11 @@ sap.ui.define([ glc.removeMouseupListener(); - if (event.buttons === 0) { + if (event.buttons === 0 && event.srcElement === glc.canvas) { glc.removeMouseMoveTimeout(); glc.mousemove_timeout = setTimeout(glc.onMouseMoveTimeout.bind(glc, event.offsetX, event.offsetY), glc.controller.htimeout); } else { - glc.clearHighlight(); + // glc.clearHighlight(); } }); @@ -392,6 +395,8 @@ sap.ui.define([ request_render() { + // console.log("REQUEST RENDER"); + if (this.render_requested) return; setTimeout(this.render.bind(this), 0); this.render_requested = true; @@ -405,8 +410,15 @@ sap.ui.define([ if (this.canvas.width <= 0 || this.canvas.height <= 0) return; + let omap = this.outline_map; + let sel_objs = Object.values(omap).flat(); + // console.log("WOOF", omap, sel_objs); + sel_objs.map(res => this.rqt.RP_GBuffer.obj_list.push(res.geom[0])); + this.rqt.render(); + this.rqt.RP_GBuffer.obj_list = []; + if (this.renderer.used == false) { // RCRC Ideally there would be an onShadersLoaded callback. if (this._logLevel >= 2) @@ -447,7 +459,7 @@ sap.ui.define([ while (ctrl_obj.get_ctrl === undefined) ctrl_obj = ctrl_obj.parent; - state.ctrl = ctrl_obj.get_ctrl(state) + state.ctrl = ctrl_obj.get_ctrl(ctrl_obj, top_obj); console.log("pick result", state); return state; @@ -491,10 +503,10 @@ sap.ui.define([ clearHighlight() { - if (this.highlighted_scene) + if (this.highlighted_top_object) { - this.highlighted_scene.clearHighlight(); // XXXX should go through manager - this.highlighted_scene = 0; + this.highlighted_top_object.scene.clearHighlight(); // XXXX should go through manager + this.highlighted_top_object = null; this.ttip.style.display = "none"; } @@ -520,14 +532,16 @@ sap.ui.define([ let c = pstate.ctrl; - c.elementHighlighted(c.extractIndex()); - - this.highlighted_scene = pstate.top_object.scene; + c.elementHighlighted(c.extractIndex(pstate.instance), null); - if (pstate.object && pstate.eve_el) - this.ttip_text.innerHTML = c.getTooltipText(); - else - this.ttip_text.innerHTML = ""; + if (this.highlighted_top_object !== pstate.top_object) + { + if (pstate.object && pstate.eve_el) + this.ttip_text.innerHTML = c.getTooltipText(); + else + this.ttip_text.innerHTML = ""; + } + this.highlighted_top_object = pstate.top_object; let dome = this.controller.getView().getDomRef(); let mouse = pstate.mouse; @@ -551,6 +565,14 @@ sap.ui.define([ this.ttip.style.display= "block"; } + remoteToolTip(msg) + { + if (this.ttip_text) + this.ttip_text.innerHTML = msg; + if (this.highlighted_top_object && this.ttip) + this.ttip.style.display = "block"; + } + getRelativeOffsets(elem) { // Based on: @@ -627,9 +649,8 @@ sap.ui.define([ if (pstate) { let c = pstate.ctrl; - c.event = event; - c.elementSelected(c.extractIndex()); - this.highlighted_scene = pstate.top_object.scene; + c.elementSelected(c.extractIndex(pstate.instance), event); + // WHY ??? this.highlighted_scene = pstate.top_object.scene; } else { // XXXX HACK - handlersMIR senders should really be in the mgr diff --git a/ui5/eve7/lib/GlViewerThree.js b/ui5/eve7/lib/GlViewerThree.js index f1c413fa2037a..348adfdbd4413 100644 --- a/ui5/eve7/lib/GlViewerThree.js +++ b/ui5/eve7/lib/GlViewerThree.js @@ -65,6 +65,8 @@ sap.ui.define([ return this.scene; } + get outline_map() { return this.outline_pass.id2obj_map; } + //============================================================================== // THREE renderer creation, DOM/event handler setup, reset //============================================================================== diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index 94e4df56abec0..435abc29550ef 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -7,6 +7,7 @@ import {IcoSphere} from './RC/objects/IcoSphere.js'; import {FRONT_AND_BACK_SIDE, HIGHPASS_MODE_BRIGHTNESS, HIGHPASS_MODE_DIFFERENCE} from './RC/constants.js'; +import { Scene } from './RC/RenderCore.js'; // import {} from ''; function iterateSceneR(object, callback) @@ -61,9 +62,16 @@ export class RendeQuTor this.SSAA_value = ssaa_val; this.make_RP_SSAA_Super(); - //this.make_RP_SSAA_Down(); + this.make_RP_SSAA_Down(); + + this.make_RP_GBuffer(); + this.make_RP_Outline(); + this.make_RP_ToScreen(); - this.RP_ToScreen.input_texture = "color_ssaa_super"; + this.RP_ToScreen.input_texture = "color_outline"; + // this.RP_ToScreen.input_texture = "color_ssaa_super"; + + this.RP_GBuffer.obj_list = []; } initFull(ssaa_val) @@ -170,7 +178,10 @@ export class RendeQuTor this.PRP_plain = new RenderPass( RenderPass.BASIC, function (textureMap, additionalData) {}, - function (textureMap, additionalData) { return { scene: pthis.scene, camera: pthis.camera }; }, + function (textureMap, additionalData) { + // pthis.renderer._specialRenderFoo = "Choopacabra"; + return { scene: pthis.scene, camera: pthis.camera }; + }, function (textureMap, additionalData) {}, RenderPass.TEXTURE, null, @@ -247,7 +258,7 @@ export class RendeQuTor // Viewport null, // Bind depth texture to this ID - "depthDefaultDefaultMaterials", + "depthDefaultSuper", // Outputs [ { id: "color_ssaa_super", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG } ] ); @@ -260,7 +271,7 @@ export class RendeQuTor { this.RP_SSAA_Down_mat = new CustomShaderMaterial("copyTexture"); this.RP_SSAA_Down_mat.lights = false; - var pthis = this; + let pthis = this; this.RP_SSAA_Down = new RenderPass( // Rendering pass type @@ -270,7 +281,7 @@ export class RendeQuTor function (textureMap, additionalData) {}, // Preprocess function function (textureMap, additionalData) { - return { material: pthis.RP_SSAA_Down_mat, textures: [textureMap[pthis.input_texture]] }; + return { material: pthis.RP_SSAA_Down_mat, textures: [textureMap[this.input_texture]] }; }, // Postprocess function function (textureMap, additionalData) {}, @@ -298,13 +309,13 @@ export class RendeQuTor { this.RP_ToScreen_mat = new CustomShaderMaterial("copyTexture"); this.RP_ToScreen_mat.lights = false; - var pthis = this; + let pthis = this; this.RP_ToScreen = new RenderPass( RenderPass.POSTPROCESS, function (textureMap, additionalData) {}, function (textureMap, additionalData) { - return { material: pthis.RP_ToScreen_mat, textures: [ textureMap[this.input_texture] ] }; // XXXX pthis or this ???? + return { material: pthis.RP_ToScreen_mat, textures: [ textureMap[this.input_texture] ] }; }, function (textureMap, additionalData) {}, RenderPass.SCREEN, @@ -399,125 +410,84 @@ export class RendeQuTor this.RP_Bloom.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; this.queue.pushRenderPass(this.RP_Bloom); } -}; - - -/* -export const RenderPass_MainMulti = new RenderPass( - // Rendering pass type - RenderPass.BASIC, - - // Initialize function - function (textureMap, additionalData) { - iterateSceneR(scene, function(object){ - if(object.pickable === false || object instanceof Text2D || object instanceof IcoSphere) { - object.visible = false; - //GL_INVALID_OPERATION : glDrawElementsInstancedANGLE: buffer format and fragment output variable type incompatible - //Program has no frag output at location 1, but destination draw buffer has an attached image. - return; - } - const multi = new CustomShaderMaterial("multi", {near: nearPlane, far: farPlane}); - multi.side = FRONT_AND_BACK_SIDE; //reather use depth from default materials - MultiMats.push(multi); - }); - }, - - // Preprocess function - function (textureMap, additionalData) { - let m_index = 0; - - iterateSceneR(scene, function(object){ - if(object.pickable === false || object instanceof Text2D || object instanceof IcoSphere) { - object.visible = false; - return; - } - object.material = MultiMats[m_index]; - m_index++; - }); - - - return { scene: scene, camera: camera }; - }, - - // Target - RenderPass.TEXTURE, - - // Viewport - { width: predef_width*SSAA_value, height: predef_height*SSAA_value }, - - // Bind depth texture to this ID - "depthDefaultMultiMaterials", - - [ - {id: "depth", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG}, - {id: "normal", textureConfig: RenderPass.DEFAULT_RGB_TEXTURE_CONFIG}, - {id: "viewDir", textureConfig: RenderPass.DEFAULT_RGB_TEXTURE_CONFIG}, - {id: "camDist", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} - ] - ); -*/ - -/* -const outline = new CustomShaderMaterial("outline", {scale: 1.0*SSAA_value, edgeColor: [1.0, 1.0, 1.0, 1.0]}); -outline.lights = false; -export const RenderPass_Outline = new RenderPass( - // Rendering pass type - RenderPass.POSTPROCESS, - - // Initialize function - function (textureMap, additionalData) { - }, - - // Preprocess function - function (textureMap, additionalData) { - return {material: outline, textures: [textureMap["depthDefaultMultiMaterials"], textureMap["normal"], textureMap["viewDir"], textureMap["color_bloom"]]}; - }, - - // Postprocess function - function (textureMap, additionalData) {}, - - // Target - RenderPass.TEXTURE, - - // Viewport - { width: predef_width*SSAA_value, height: predef_height*SSAA_value }, - - // Bind depth texture to this ID - null, - - [ - {id: "color_outline", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} - ] - ); - -const fog = new CustomShaderMaterial("fog", {MODE: 1, fogColor: [0.5, 0.4, 0.45, 0.8]}); -fog.lights = false; -export const RenderPass_Fog = new RenderPass( - - // Rendering pass type - RenderPass.POSTPROCESS, - - // Initialize function - function (textureMap, additionalData) { - }, - - // Preprocess function - function (textureMap, additionalData) { - //return {material: fog, textures: [textureMap["color_outline"], textureMap["depthDefaultDefaultMaterials"]]}; //grid jumps on depth buffer - return {material: fog, textures: [textureMap["color_outline"], textureMap["camDist"]]}; //grid has specific shader for extruding geometry, even if implemented, it would jump around - }, - - // Target - RenderPass.TEXTURE, - - // Viewport - { width: predef_width*SSAA_value, height: predef_height*SSAA_value }, - - // Bind depth texture to this ID - null, - - [ - {id: "color_fog", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} - ] - ); -*/ \ No newline at end of file + + //============================================================================= + + make_RP_GBuffer() + { + this.RP_GBuffer_mat = new CustomShaderMaterial("GBufferMini"); + this.RP_GBuffer_mat.lights = false; + this.RP_GBuffer_mat.side = FRONT_AND_BACK_SIDE; + + let pthis = this; + + this.RP_GBuffer = new RenderPass( + RenderPass.BASIC, + function (textureMap, additionalData) {}, + function (textureMap, additionalData) { + pthis.renderer._outlineEnabled = true; + pthis.renderer._outlineArray = this.obj_list; + pthis.renderer._defaultOutlineMat = pthis.RP_GBuffer_mat; + pthis.renderer._fillRequiredPrograms(pthis.RP_GBuffer_mat.requiredProgram(pthis.renderer)); + for (const o3d of this.obj_list) { + if (o3d.outlineMaterial) + pthis.renderer._fillRequiredPrograms(o3d.outlineMaterial.requiredProgram(pthis.renderer)); + } + return { scene: pthis.scene, camera: pthis.camera }; + }, + function (textureMap, additionalData) { + pthis.renderer._outlineEnabled = false; // can remain true if not all progs are loaded + pthis.renderer._outlineArray = null; + }, + RenderPass.TEXTURE, + null, + "depthDefault", + [ + {id: "normal", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG}, + {id: "viewDir", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} + ] + ); + this.RP_GBuffer.view_setup = function (vport) { this.viewport = vport; }; + + // No push, GBuffer/Outline passes are handled separately as there can be more of them. + this.queue.pushRenderPass(this.RP_GBuffer); + return this.RP_GBuffer; + } + + make_RP_Outline() + { + this.RP_Outline_mat = new CustomShaderMaterial("outline", + { scale: 1.5*Math.E, // Math.E, + edgeColor: [0.7, 0.1, 0.5, 1.0], + _DepthThreshold: 6.0, + _NormalThreshold: 0.6, // 0.4, + _DepthNormalThreshold: 0.5, + _DepthNormalThresholdScale: 7.0 }); + this.RP_Outline_mat.lights = false; + + let pthis = this; + + this.RP_Outline = new RenderPass( + RenderPass.POSTPROCESS, + function (textureMap, additionalData) {}, + function (textureMap, additionalData) { + return { material: pthis.RP_Outline_mat, + textures: [ textureMap["depthDefault"], textureMap["normal"], + textureMap["viewDir"], textureMap["color_ssaa_down"] ] }; + }, + function (textureMap, additionalData) {}, + RenderPass.TEXTURE, + null, + null, + [ + {id: "color_outline", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} + ] + ); + this.RP_Outline.view_setup = function (vport) { this.viewport = vport; }; + + // No push, GBuffer/Outline passes are handled separately as there can be more of them. + this.queue.pushRenderPass(this.RP_Outline); + return this.RP_GBuffer; + } + +} From 80928a2eb2580629e21b095ad071c59f5ba2fe60 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 15 Aug 2022 15:20:49 +0200 Subject: [PATCH 10/84] [REve] Add some sprite textures for RenderCore. --- ui5/eve7/textures/dot-32a.png | Bin 0 -> 985 bytes ui5/eve7/textures/star5-32a.png | Bin 0 -> 984 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 ui5/eve7/textures/dot-32a.png create mode 100644 ui5/eve7/textures/star5-32a.png diff --git a/ui5/eve7/textures/dot-32a.png b/ui5/eve7/textures/dot-32a.png new file mode 100644 index 0000000000000000000000000000000000000000..4690caf02260e2a8c2f7fcfca1b0fc26d8e96487 GIT binary patch literal 985 zcmV;~119{5P)kdg0003bX+uL$Nkc;* zaB^>EX>4Tx04R~2kiSa9P!z_0sYOL}secA>h~QdqF_TMG2!cY46|7Eal43E5AxSB| zfp4M@(?Jk?1Rp@b+3!XN2eWwL@clTP^L_VTXxT}amhD|gv#N0Y-r#a@WiPzZro%eh zbb_$Vd!BbfX6hW_uqSmX2)L&tlqSUL zO*K<-BP!+OavRC`eVo;s*2XLkilA=Isam5E zyg$Oq09K!2>AE3n@%P&rW}JHFpKtsE=G#zY*|^?Y00002VoOIv0063uBQgL0010qN zS#tmY3ljhU3ljkVnw%H_000McNliru<^&TLCO6sdpHKh*02p*dSad^gZEa<4bO1wg zWnpw>WFTUBAWUy+dSxUwa!4{FA^d7pCX)}rIuqKB68U&PqBa$^oqC7z4!hPC=)TrPC2li}Ec1{XP7p4fd_ z3>Xq>vt#1-8Phejiwu&r1aukG*Q8_Ox9L#5h%5^FMIflsp{;Y!0%bz#cvkJApl7v* zN1aeFrxs{XBcOEsgjm)R0W}%`jsgg%;N>n|zL3D9LZBN&m*AU@5I5j@`+d8F|9G^( zkprizqab@^PaHS`I08VjCq~_XYY9cn9tpx^ux5+o{Ew0JZapK}vbIZz*bt*qH&uXZ zkC+XSDZ!kq6-#y(MW}-43dN2kD}5dvvoABIERZNmL|LzGkt~=p)1;f8?jDak;Nll_ zqcQ>q-gxEZVjc(-%$X2Sriq`J(t+|G|G*!fnK0+WL^6t*k)|%9OWt_qC%;nfL_nYt z37I=o&&2Fl@XAEvB0H5+i7mfBGuH2UvE1QmyUXSJ+3Wo;`xeHl?8}*a00000NkvXX Hu0mjfRA94` literal 0 HcmV?d00001 diff --git a/ui5/eve7/textures/star5-32a.png b/ui5/eve7/textures/star5-32a.png new file mode 100644 index 0000000000000000000000000000000000000000..7da206afd254c8da51dd1e66989684090761bbe3 GIT binary patch literal 984 zcmV;}11J26P)kdg0003bX+uL$Nkc;* zaB^>EX>4Tx04R~2kiSa9P!z_0sYOL}secA>h~QdqF_TMG2!cY46|7Eal43E5AxSB| zfp4M@(?Jk?1Rp@b+3!XN2eWwL@clTP^L_VTXxT}amhD|gv#N0Y-r#a@WiPzZro%eh zbb_$Vd!BbfX6hW_uqSmX2)L&tlqSUL zO*K<-BP!+OavRC`eVo;s*2XLkilA=Isam5E zyg$Oq09K!2>AE3n@%P&rW}JHFpKtsE=G#zY*|^?Y00002VoOIv0063uBQgL0010qN zS#tmY3ljhU3ljkVnw%H_000McNliru<^&TK2?y-x{iXl_02p*dSad^gZEa<4bO1wg zWnpw>WFTUBAWUy+dSxUwayWRn#FDyf7eLhzOb zY!oc)j8zKLWsAIkjgR0%q%gInk<^kRU=swvZ6sJN1VmDpY;*VCyk3BUt z_0-t0Dp;dVg$i}n#%ZC-2Gamck3nQXU}kP^79z3|B(SHTC`hE`-XkzCydbj7BVX|d zfJvV6oGMkGP~#O5nT$4pXTf(j5(834!; z$jQh_>5%f9OD_42*znB6)XeUX=iXXAvXYsacxJew-!-j;o(Phxj$zydda=$>W9Tck=yKB?Lj_3Ej(c-o(uiY;T5o7ngw&k|> zaxlkNzVQ+6ey0&OY4Cwn=7#70>o2|=6Adg;wsR@SK;&PUDka}F-3%iD00003B=0) literal 0 HcmV?d00001 From 19c9aa64d74726624fbc319fb3c470362d6de132 Mon Sep 17 00:00:00 2001 From: alja Date: Thu, 1 Sep 2022 11:32:14 -0700 Subject: [PATCH 11/84] Add functions to create Calo3D and its controll object. --- ui5/eve7/lib/EveElementsRCore.js | 142 +++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index ac8bec33add8a..56b076ce8dd1b 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -59,6 +59,92 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } // class EveElemControl + class Calo3DControl extends EveElemControl { + + DrawForSelection(sec_idcs, res, extra) { + console.log("CALO 3d draw for selection ", extra); + // locate REveCaloData cells for this object + let cells; + for (let i = 0; i < extra.length; i++) { + if (extra[i].caloVizId == this.obj3d.eve_el.fElementId) { + cells = extra[i].cells; + break; + } + } + + let ibuff = this.obj3d.eve_el.render_data.idxBuff; + let nbox = ibuff.length / 2; + let nBoxSelected = parseInt(cells.length); + let boxIdcs = new Array; + for (let i = 0; i < cells.length; i++) { + let tower = cells[i].t; + let slice = cells[i].s; + + for (let r = 0; r < nbox; r++) { + if (ibuff[r * 2] == slice && ibuff[r * 2 + 1] == tower) { + boxIdcs.push(r); + break; + } + } + } + let rnr_data = this.obj3d.eve_el.render_data; + let protoIdcs = [0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 1, 2, 3, 1, 3, 0, 4, 7, 6, 4, 6, 5]; + let idxBuff = []; + let vtxBuff = new Float32Array(nbox * 8 * 3); + for (let i = 0; i < nBoxSelected; ++i) { + let BoxIdcs = boxIdcs[i]; + for (let c = 0; c < 8; c++) { + let off = i * 24 + c * 3; + let pos = BoxIdcs * 24 + c * 3; + vtxBuff[off] = rnr_data.vtxBuff[pos]; + vtxBuff[off + 1] = rnr_data.vtxBuff[pos + 1]; + vtxBuff[off + 2] = rnr_data.vtxBuff[pos + 2]; + } + + // fix top corners, select can be partial + for (let c = 0; c < 4; c++) { + // fix vertex 1 + let pos = BoxIdcs * 24 + c * 3; + let v1x = rnr_data.vtxBuff[pos]; + let v1y = rnr_data.vtxBuff[pos + 1]; + let v1z = rnr_data.vtxBuff[pos + 2]; + pos += 12; + let v2x = rnr_data.vtxBuff[pos]; + let v2y = rnr_data.vtxBuff[pos + 1]; + let v2z = rnr_data.vtxBuff[pos + 2]; + + let off = i * 24 + 12 + c * 3; + vtxBuff[off] = v1x + cells[i].f * (v2x - v1x); + vtxBuff[off + 1] = v1y + cells[i].f * (v2y - v1y); + vtxBuff[off + 2] = v1z + cells[i].f * (v2z - v1z); + } + + for (let c = 0; c < 36; c++) { + let off = i * 8; + idxBuff.push(protoIdcs[c] + off); + } + } // loop boxes + + let body = new RC.Geometry(); + + body.indices = new RC.BufferAttribute(idxBuff, 1); + body.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); + body.computeVertexNormals(); + // ? AMT do we need vertex colors + let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); + + let mesh = new RC.Mesh(body, mat); + + res.geom.push(mesh); + } + + + extractIndex(intersect) { + let idx = Math.floor(intersect.faceIndex / 12); + return idx; + } + }// class Calo3DControl + //============================================================================== // EveElements //============================================================================== @@ -502,6 +588,62 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return mesh; } + //============================================================================== + // make Calorimeters + //============================================================================== + + makeCalo3D(calo3D, rnr_data) + { + let body = new RC.Geometry(); + if (rnr_data.vtxBuff) { + let vBuff = rnr_data.vtxBuff; + let protoSize = 6 * 2 * 3; + let protoIdcs = [0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 1, 2, 3, 1, 3, 0, 4, 7, 6, 4, 6, 5]; + let nBox = vBuff.length / 24; + let idxBuff = new Uint32Array(nBox * protoSize); + let p = 0; + for (let i = 0; i < nBox; ++i) { + for (let c = 0; c < protoSize; c++) { + let off = i * 8; + idxBuff[p++] = protoIdcs[c] + off; + } + } + + body.indices = new RC.BufferAttribute(idxBuff, 1); + body.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); + body.computeVertexNormals(); + + let ci = rnr_data.idxBuff; + let off = 0 + let colBuff = new Float32Array(vBuff.length); + for (let x = 0; x < nBox; ++x) { + let slice = ci[x * 2]; + let sliceColor = calo3D.sliceColors[slice]; + let tc = new RC.Color(EVE.JSR.getColor(sliceColor)); + for (let i = 0; i < 8; ++i) { + colBuff[off] = tc.r; + colBuff[off + 1] = tc.g; + colBuff[off + 2] = tc.b; + colBuff[off + 3] = 1.0; + off += 4; + } + } + body.vertColor = new RC.BufferAttribute(colBuff, 4); + } + + let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); + //let mat = this.RcFlatMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); + + mat.useVertexColors = true; + let mesh = new RC.Mesh(body, mat); + + this.RcPickable(calo3D, mesh); + + // mesh.get_ctrl = function () { return new Calo3DControl(mesh); }; + mesh.dispose = function () { this.geometry.dispose(); this.material.dispose(); }; + + return mesh; + } //============================================================================== // makeEveGeometry / makeEveGeoShape From dc953ea7c05477e5131ab7e4ddbff6d80ac90dc1 Mon Sep 17 00:00:00 2001 From: alja Date: Thu, 1 Sep 2022 14:31:38 -0700 Subject: [PATCH 12/84] add function to create Calo2D and its controll object calo2DControll --- ui5/eve7/lib/EveElementsRCore.js | 209 ++++++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 3 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 56b076ce8dd1b..971552f6b961b 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -138,12 +138,157 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) res.geom.push(mesh); } - extractIndex(intersect) { let idx = Math.floor(intersect.faceIndex / 12); return idx; } - }// class Calo3DControl + + elementSelectedSendMIR(idx, selectionId) + { + let boxset = this.obj3d.eve_el; + let scene = this.obj3d.scene; + let multi = this.event?.ctrlKey ? true : false; + + let boxIdx = idx; + + let fcall = "NewShapePicked(" + boxIdx + ", " + selectionId + ", " + multi + ")" + scene.mgr.SendMIR(fcall, boxset.fElementId, "ROOT::Experimental::REveDigitSet"); + return true; + } + + elementSelected(idx) + { + return this.elementSelectedSendMIR(idx, this.obj3d.scene.mgr.global_selection_id); + } + + elementHighlighted(idx) + { + return this.elementSelectedSendMIR(idx, this.obj3d.scene.mgr.global_highlight_id); + } + + } // class Calo3DControl + + + class Calo2DControl extends EveElemControl { + + DrawForSelection(sec_idcs, res, extra) { + let cells; + for (let i = 0; i < extra.length; i++) { + if (extra[i].caloVizId == this.obj3d.eve_el.fElementId) { + cells = extra[i].cells; + break; + } + } + + let ibuff = this.obj3d.eve_el.render_data.idxBuff; + let vbuff = this.obj3d.eve_el.render_data.vtxBuff; + let nbox = ibuff.length / 2; + let nBoxSelected = cells.length; + let boxIdcs = []; + for (let i = 0; i < cells.length; i++) { + let bin = cells[i].b; + let slice = cells[i].s; + // let fraction = cells[i].f; + for (let r = 0; r < nbox; r++) { + if (ibuff[r * 2] == slice) { + + if (bin > 0 && ibuff[r * 2 + 1] == bin) { + boxIdcs.push(r); + break; + } else if (bin < 0 && ibuff[r * 2 + 1] == Math.abs(bin) && vbuff[r * 12 + 1] < 0) { + boxIdcs.push(r); + break; + } + } + } + } + let idxBuff = []; + let vtxBuff = new Float32Array(nBoxSelected * 4 * 3); + let protoIdcs = [0, 1, 2, 2, 3, 0]; + let rnr_data = this.obj3d.eve_el.render_data; + for (let i = 0; i < nBoxSelected; ++i) { + let BoxIdcs = boxIdcs[i]; + for (let v = 0; v < 4; v++) { + let off = i * 12 + v * 3; + let pos = BoxIdcs * 12 + v * 3; + vtxBuff[off] = rnr_data.vtxBuff[pos]; + vtxBuff[off + 1] = rnr_data.vtxBuff[pos + 1]; + vtxBuff[off + 2] = rnr_data.vtxBuff[pos + 2]; + } + { + // fix vertex 1 + let pos = BoxIdcs * 12; + let v1x = rnr_data.vtxBuff[pos]; + let v1y = rnr_data.vtxBuff[pos + 1]; + pos += 3; + let v2x = rnr_data.vtxBuff[pos]; + let v2y = rnr_data.vtxBuff[pos + 1]; + let off = i * 12 + 3; + vtxBuff[off] = v1x + cells[i].f * (v2x - v1x); + vtxBuff[off + 1] = v1y + cells[i].f * (v2y - v1y); + } + + { + // fix vertex 2 + let pos = BoxIdcs * 12 + 3 * 3; + let v1x = rnr_data.vtxBuff[pos]; + let v1y = rnr_data.vtxBuff[pos + 1]; + pos -= 3; + let v2x = rnr_data.vtxBuff[pos]; + let v2y = rnr_data.vtxBuff[pos + 1]; + let off = i * 12 + 3 * 2; + vtxBuff[off] = v1x + cells[i].f * (v2x - v1x); + vtxBuff[off + 1] = v1y + cells[i].f * (v2y - v1y); + } + for (let c = 0; c < 6; c++) { + let off = i * 4; + idxBuff.push(protoIdcs[c] + off); + } + } + + let body = new RC.Geometry(); + body.indices = new RC.BufferAttribute(idxBuff, 1); + body.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); + + let mesh = new THREE.Mesh(body); + res.geom.push(mesh); + } + + extractIndex(intersect) + { + let idx = Math.floor(intersect.faceIndex/2); + return idx; + } + + elementSelectedSendMIR(idx, selectionId) + { + let calo = this.obj3d.eve_el; + let idxBuff = calo.render_data.idxBuff; + let scene = this.obj3d.scene; + let multi = this.event?.ctrlKey ? true : false; + let bin = idxBuff[idx*2 + 1]; + let slice = idxBuff[idx*2]; + // get sign for the case of RhoZ projection + if (calo.render_data.vtxBuff[idx*12 + 1] < 0) bin = -bin ; + + let fcall = "NewBinPicked(" + bin + ", " + slice + ", " + selectionId + ", " + multi + ")" + scene.mgr.SendMIR(fcall, calo.fElementId, "ROOT::Experimental::REveCalo2D"); + return true; + } + + elementSelected(idx) + { + return this.elementSelectedSendMIR(idx, this.obj3d.scene.mgr.global_selection_id); + } + + elementHighlighted(idx) + { + return this.elementSelectedSendMIR(idx, this.obj3d.scene.mgr.global_highlight_id); + } + + } // class Calo2Control + + //============================================================================== // EveElements @@ -615,7 +760,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let ci = rnr_data.idxBuff; let off = 0 - let colBuff = new Float32Array(vBuff.length); + let colBuff = new Float32Array(nBox*8*4); for (let x = 0; x < nBox; ++x) { let slice = ci[x * 2]; let sliceColor = calo3D.sliceColors[slice]; @@ -645,6 +790,64 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return mesh; } + makeCalo2D(calo2D, rnrData) + { + let body = new RC.Geometry(); + if (rnrData.vtxBuff) { + let nSquares = rnrData.vtxBuff.length / 12; + let nTriang = 2 * nSquares; + + let idxBuff = new Uint32Array(nTriang * 3); + for (let s = 0; s < nSquares; ++s) { + let boff = s * 6; + let ioff = s * 4; + + // first triangle + idxBuff[boff] = ioff; + idxBuff[boff + 1] = ioff + 1; + idxBuff[boff + 2] = ioff + 2; + + // second triangle + idxBuff[boff + 3] = ioff + 2; + idxBuff[boff + 4] = ioff + 3; + idxBuff[boff + 5] = ioff; + } + + body.indices = new RC.BufferAttribute(idxBuff, 1); + body.vertices = new RC.BufferAttribute(rnrData.vtxBuff, 3); + body.computeVertexNormals(); + + let ci = rnrData.idxBuff; + let colBuff = new Float32Array(nSquares * 4 * 4); + let off = 0; + for (let x = 0; x < nSquares; ++x) { + let slice = ci[x * 2]; + let sliceColor = calo2D.sliceColors[slice]; + let tc = new THREE.Color(EVE.JSR.getColor(sliceColor)); + console.log() + for (let i = 0; i < 4; ++i) { + colBuff[off] = tc.r; + colBuff[off + 1] = tc.g; + colBuff[off + 2] = tc.b; + colBuff[off + 3] = 1.0; + off += 4; + } + } + body.vertColor = new RC.BufferAttribute(colBuff, 4); + } + + + let mat = this.RcFlatMaterial(this.ColorBlack,0.5); + mat.useVertexColors = true; + let mesh = new RC.Mesh(body, mat); + + this.RcPickable(calo2D, mesh); + //mesh.get_ctrl = function () { return new Calo2DControl(mesh); }; + mesh.dispose = function () { this.geometry.dispose(); this.material.dispose(); }; + + return mesh; + } + //============================================================================== // makeEveGeometry / makeEveGeoShape //============================================================================== From b0b01c123b42924b7b4484fb3d48cf18fd05b505 Mon Sep 17 00:00:00 2001 From: alja Date: Fri, 2 Sep 2022 16:06:05 -0700 Subject: [PATCH 13/84] Import code for rendering REveBoxSet. Add box set control class --- ui5/eve7/lib/EveElementsRCore.js | 197 ++++++++++++++++++++++++++++++- 1 file changed, 195 insertions(+), 2 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 971552f6b961b..82b3f500c5472 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -58,6 +58,86 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } // class EveElemControl + // =================================================================================== + // Digit sets control classes + // =================================================================================== + class BoxSetControl extends EveElemControl { + + DrawForSelection(atom_idcs, res, extra) + { + let sec_idcs = extra.shape_idcs; + let geobox = new RC.Geometry(); + geobox.setAttribute( 'position', this.obj3d.geometry.getAttribute("position") ); /// AMT will this work with RenderCore ?? + + let protoIdcs = [0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 1, 2, 3, 1, 3, 0, 4, 7, 6, 4, 6, 5]; + let idxBuff = new Uint16Array(sec_idcs.length * protoIdcs.length); + + let N = this.obj3d.eve_el.render_data.idxBuff.length / 2; + for (let b = 0; b < sec_idcs.length; ++b) { + let idx = sec_idcs[b] + if (this.obj3d.eve_el.fDetIdsAsSecondaryIndices) { + for (let x = 0; x < N; ++x) { + if (this.obj3d.eve_el.render_data.idxBuff[x + N] === idx) + { + idx=x; + break; + } + } + } + let idxOff = idx * 8; + for (let i = 0; i < protoIdcs.length; i++) + idxBuff.push(idxOff + protoIdcs[i]); + } + + body.indices = new RC.BufferAttribute(idxBuff, 1); + let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); + let mesh = new RC.Mesh(body, mat); + + res.geom.push(mesh); + } + + extractIndex(intersect) + { + let idx = Math.floor(intersect.faceIndex/12); + return idx; + } + + elementSelectedSendMIR(idx, selectionId) + { + let boxset = this.obj3d.eve_el; + let scene = this.obj3d.scene; + let multi = this.event?.ctrlKey ? true : false; + + let boxIdx = idx; + + let fcall = "NewShapePicked(" + boxIdx + ", " + selectionId + ", " + multi + ")" + scene.mgr.SendMIR(fcall, boxset.fElementId, "ROOT::Experimental::REveDigitSet"); + return true; + } + + elementSelected(idx) + { + return this.elementSelectedSendMIR(idx, this.obj3d.scene.mgr.global_selection_id); + } + + elementHighlighted(idx) + { + return this.elementSelectedSendMIR(idx, this.obj3d.scene.mgr.global_highlight_id); + } + + checkHighlightIndex(indx) + { + if (this.obj3d && this.obj3d.scene) + return this.invokeSceneMethod("processCheckHighlight", indx); + + return true; // means index is different + } + + } // class BoxSetControl + + // =================================================================================== + // Calorimeter control classes + // =================================================================================== class Calo3DControl extends EveElemControl { @@ -75,7 +155,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let ibuff = this.obj3d.eve_el.render_data.idxBuff; let nbox = ibuff.length / 2; let nBoxSelected = parseInt(cells.length); - let boxIdcs = new Array; + let boxIdcs = new Uint16Array; for (let i = 0; i < cells.length; i++) { let tower = cells[i].t; let slice = cells[i].s; @@ -733,6 +813,119 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return mesh; } + //============================================================================== + // make Digits + //============================================================================== + + makeBoxSet(boxset, rnr_data) + { + if (!rnr_data.vtxBuff) + return new RC.Geometry(); // AMT TODO test when digits are filtered + + let vBuff; + if (boxset.boxType == 1) // free box + { + vBuff = rnr_data.vtxBuff; + } + else if (boxset.boxType == 2) // axis aligned + { + let N = rnr_data.vtxBuff.length/6; + vBuff = new Float32Array(N*8*3); + + let off = 0; + for (let i = 0; i < N; ++i) + { + let rdoff = i*6; + let x = rnr_data.vtxBuff[rdoff]; + let y = rnr_data.vtxBuff[rdoff + 1]; + let z = rnr_data.vtxBuff[rdoff + 2]; + let dx = rnr_data.vtxBuff[rdoff + 3]; + let dy = rnr_data.vtxBuff[rdoff + 4]; + let dz = rnr_data.vtxBuff[rdoff + 5]; + + // top + vBuff[off ] = x; vBuff[off + 1] = y + dy; vBuff[off + 2] = z; + off += 3; + vBuff[off ] = x + dx; vBuff[off + 1] = y + dy; vBuff[off + 2] = z; + off += 3; + vBuff[off ] = x + dx; vBuff[off + 1] = y; vBuff[off + 2] = z; + off += 3; + vBuff[off ] = x; vBuff[off + 1] = y; vBuff[off + 2] = z; + off += 3; + // bottom + vBuff[off ] = x; vBuff[off + 1] = y + dy; vBuff[off + 2] = z + dz; + off += 3; + vBuff[off ] = x + dx; vBuff[off + 1] = y + dy; vBuff[off + 2] = z + dz; + off += 3; + vBuff[off ] = x + dx; vBuff[off + 1] = y; vBuff[off + 2] = z + dz; + off += 3; + vBuff[off ] = x; vBuff[off + 1] = y; vBuff[off + 2] = z + dz; + off += 3; + } + } + + let protoSize = 6 * 2 * 3; + let protoIdcs = [0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 1, 2, 3, 1, 3, 0, 4, 7, 6, 4, 6, 5]; + let nBox = vBuff.length / 24; + let idxBuff = new Uint32Array(nBox * protoSize); + let iCnt = 0; + for (let i = 0; i < nBox; ++i) + { + for (let c = 0; c < protoSize; c++) { + let off = i * 8; + idxBuff[iCnt++] = protoIdcs[c] + off; + } + } + + let body = new RC.Geometry(); + + body.indices = new RC.BufferAttribute(idxBuff, 1); + body.vertices = new RC.BufferAttribute(vBuff, 3); + body.computeVertexNormals(); + + // + // set material and colors + + let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); + if (!boxset.fSingleColor) + { + let ci = rnr_data.idxBuff; + let off = 0 + let colBuff = new Float32Array( nBox * 8 * 4 ); + for (let x = 0; x < ci.length; ++x) + { + let r = (ci[x] & 0x000000FF) >> 0; + let g = (ci[x] & 0x0000FF00) >> 8; + let b = (ci[x] & 0x00FF0000) >> 16; + for (let i = 0; i < 8; ++i) + { + colBuff[off ] = r/256; + colBuff[off + 1] = g/256; + colBuff[off + 2] = b/256; + colBuff[off + 3] = 1.0; + off += 4; + } + } + body.vertColor = new RC.BufferAttribute(colBuff, 4); + mat.useVertexColors = true; + } + else + { + let mcol = RcCol(boxset.fMainColor); + mat.color = mcol; + } + + let mesh = new RC.Mesh(body, mat); + + if (boxset.fSecondarySelect) + mesh.get_ctrl = function() { return new BoxSetControl(mesh); }; + else + mesh.get_ctrl = function() { return new EveElemControl(mesh); }; + + mesh.dispose = function() { this.geometry.dispose(); this.material.dispose(); }; + + return mesh; + } //============================================================================== // make Calorimeters //============================================================================== @@ -784,7 +977,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) this.RcPickable(calo3D, mesh); - // mesh.get_ctrl = function () { return new Calo3DControl(mesh); }; + mesh.get_ctrl = function () { return new Calo3DControl(mesh); }; mesh.dispose = function () { this.geometry.dispose(); this.material.dispose(); }; return mesh; From cfc608c2ca2aeb5d2659ff7449f6b1f04090147f Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Fri, 2 Sep 2022 20:14:11 -0700 Subject: [PATCH 14/84] [REve] Separate viewer-side selection processing for RCore. --- graf3d/eve7/inc/ROOT/REveSelection.hxx | 13 +++-- graf3d/eve7/src/REveManager.cxx | 4 +- graf3d/eve7/src/REveSelection.cxx | 24 ++------ ui5/eve7/lib/EveManager.js | 1 + ui5/eve7/lib/EveScene.js | 79 +++++++++++++++++++++----- ui5/eve7/lib/GlViewerRCore.js | 47 ++++++++++++--- ui5/eve7/lib/RendeQuTor.js | 6 +- 7 files changed, 126 insertions(+), 48 deletions(-) diff --git a/graf3d/eve7/inc/ROOT/REveSelection.hxx b/graf3d/eve7/inc/ROOT/REveSelection.hxx index 6bf052fe30841..8d5e6fbe01ff2 100644 --- a/graf3d/eve7/inc/ROOT/REveSelection.hxx +++ b/graf3d/eve7/inc/ROOT/REveSelection.hxx @@ -90,8 +90,9 @@ protected: Color_t fHiddenEdgeColor; /// fPickToSelect; ///& RefPickToSelect() const { return fPickToSelect; } void ClearPickToSelect() { fPickToSelect.clear(); } void AddPickToSelect(int ps) { fPickToSelect.push_back(ps); } - Bool_t GetIsMaster() const { return fIsMaster; } - void SetIsMaster(Bool_t m) { fIsMaster = m; } + bool GetIsMaster() const { return fIsMaster; } + void SetIsMaster(bool m) { fIsMaster = m; } + bool GetIsHighlight() const { return fIsHighlight; } + void SetIsHighlight(bool m) { fIsHighlight = m; } std::shared_ptr GetDeviator() const { return fDeviator; } void SetDeviator(std::shared_ptr d) { fDeviator = d; } diff --git a/graf3d/eve7/src/REveManager.cxx b/graf3d/eve7/src/REveManager.cxx index 550b6734c4de5..db5b01bcc1b7a 100644 --- a/graf3d/eve7/src/REveManager.cxx +++ b/graf3d/eve7/src/REveManager.cxx @@ -106,10 +106,12 @@ REveManager::REveManager() fSelectionList->IncDenyDestroy(); fWorld->AddElement(fSelectionList); fSelection = new REveSelection("Global Selection", "", kRed, kViolet); + fSelection->SetIsMaster(true); fSelection->IncDenyDestroy(); fSelectionList->AddElement(fSelection); fHighlight = new REveSelection("Global Highlight", "", kGreen, kCyan); - fHighlight->SetHighlightMode(); + fHighlight->SetIsMaster(true); + fHighlight->SetIsHighlight(true); fHighlight->IncDenyDestroy(); fSelectionList->AddElement(fHighlight); diff --git a/graf3d/eve7/src/REveSelection.cxx b/graf3d/eve7/src/REveSelection.cxx index fa0efce754b6c..c0fdd5fab54a1 100644 --- a/graf3d/eve7/src/REveSelection.cxx +++ b/graf3d/eve7/src/REveSelection.cxx @@ -39,9 +39,7 @@ REveSelection::REveSelection(const std::string& n, const std::string& t, Color_t col_visible, Color_t col_hidden) : REveElement (n, t), fVisibleEdgeColor (col_visible), - fHiddenEdgeColor (col_hidden), - fActive (kTRUE), - fIsMaster (kTRUE) + fHiddenEdgeColor (col_hidden) { // Managing complete selection state on element level. // @@ -86,18 +84,6 @@ void REveSelection::SetHiddenEdgeColorRGB(UChar_t r, UChar_t g, UChar_t b) StampObjProps(); } -//////////////////////////////////////////////////////////////////////////////// -/// Set to 'highlight' mode. - -void REveSelection::SetHighlightMode() -{ - // Most importantly, this sets the pointers-to-function-members in - // REveElement that are used to mark elements as (un)selected and - // implied-(un)selected. - - fIsMaster = kFALSE; -} - //////////////////////////////////////////////////////////////////////////////// /// Select element indicated by the entry and fill its /// implied-selected set. @@ -350,7 +336,7 @@ void REveSelection::ActivateSelection() { if (fActive) return; - fActive = kTRUE; + fActive = true; for (auto i = fMap.begin(); i != fMap.end(); ++i) { DoElementSelect(i); SelectionAdded(i->first); @@ -368,7 +354,7 @@ void REveSelection::DeactivateSelection() DoElementUnselect(i); } SelectionCleared(); - fActive = kFALSE; + fActive = false; } //////////////////////////////////////////////////////////////////////////////// @@ -699,6 +685,8 @@ Int_t REveSelection::WriteCoreJson(nlohmann::json &j, Int_t /* rnr_offset */) j["fVisibleEdgeColor"] = fVisibleEdgeColor; j["fHiddenEdgeColor"] = fHiddenEdgeColor; + j["fIsMater"] = fIsMaster; + j["fIsHighlight"] = fIsHighlight; nlohmann::json sel_list = nlohmann::json::array(); @@ -728,7 +716,7 @@ Int_t REveSelection::WriteCoreJson(nlohmann::json &j, Int_t /* rnr_offset */) rec["sec_idcs"] = sec; // stream tooltip in highlight type - if (!fIsMaster) + if (fIsHighlight) rec["tooltip"] = i.first->GetHighlightTooltip(i.second.f_sec_idcs); sel_list.push_back(rec); diff --git a/ui5/eve7/lib/EveManager.js b/ui5/eve7/lib/EveManager.js index 8015bf269fc5f..8e3d4096d1213 100644 --- a/ui5/eve7/lib/EveManager.js +++ b/ui5/eve7/lib/EveManager.js @@ -56,6 +56,7 @@ sap.ui.define([], function() { UseConnection(handle) { this.handle = handle; + this.is_rcore = (handle.getUserArgs("GLViewer") == "RCore"); handle.setReceiver(this); handle.connect(); diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index 44e647a001d7f..8cfc50410bdae 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -24,6 +24,13 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { // register ourself for scene events this.mgr.RegisterSceneReceiver(scene.fSceneId, this); + if(this.mgr.is_rcore) { + this.SelectElement = this.SelectElementRCore; + this.UnselectElement = this.UnselectElementRCore; + } else { + this.SelectElement = this.SelectElementStd; + this.UnselectElement = this.UnselectElementStd; + } // AMT temporary solution ... resolve with callSceneReceivers in EveManager.js scene.eve_scene = this; } @@ -394,17 +401,17 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { }); } - SelectElement(selection_obj, element_id, sec_idcs, extra) + SelectElementStd(selection_obj, element_id, sec_idcs, extra) { let obj3d = this.getObj3D( element_id ); if (!obj3d) return; - let id2obj_map = this.glctrl.viewer.outline_map; - // console.log("EveScene.SelectElement ", selection_obj.fName, element_id, selection_obj.fElementId, id2obj_map); + let outline_map = this.glctrl.viewer.outline_map; + // console.log("EveScene.SelectElement ", selection_obj.fName, element_id, selection_obj.fElementId, outline_map); - id2obj_map[element_id] = id2obj_map[element_id] || []; + outline_map[element_id] = outline_map[element_id] || []; - if (id2obj_map[element_id][selection_obj.fElementId] !== undefined) { + if (outline_map[element_id][selection_obj.fElementId] !== undefined) { return; } @@ -421,13 +428,13 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { // Exit if we are trying to highlight an object that has already been selected. if (stype == ST_Highlight && - id2obj_map[element_id][this.mgr.global_selection_id] !== undefined) + outline_map[element_id][this.mgr.global_selection_id] !== undefined) { if (!res.sec_sel) return; } - if (!res.sec_sel) id2obj_map[element_id] = []; + if (!res.sec_sel) outline_map[element_id] = []; if (obj3d.get_ctrl) { let ctrl = obj3d.get_ctrl(obj3d); @@ -435,20 +442,66 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { } else { res.geom.push(obj3d); } - id2obj_map[element_id][selection_obj.fElementId] = res; + outline_map[element_id][selection_obj.fElementId] = res; if (stype == ST_Highlight && selection_obj.sel_list) { this.glctrl.viewer.remoteToolTip(selection_obj.sel_list[0].tooltip); } } - UnselectElement(selection_obj, element_id) + UnselectElementStd(selection_obj, element_id) { - let id2obj_map = this.glctrl.viewer.outline_map; - // console.log("EveScene.UnselectElement ", selection_obj.fName, element_id, selection_obj.fElementId, id2obj_map); + let outline_map = this.glctrl.viewer.outline_map; + // console.log("EveScene.UnselectElement ", selection_obj.fName, element_id, selection_obj.fElementId, outline_map); + + if (outline_map[element_id] !== undefined) { + delete outline_map[element_id][selection_obj.fElementId]; + } + } - if (id2obj_map[element_id] !== undefined) { - delete id2obj_map[element_id][selection_obj.fElementId]; + SelectElementRCore(selection_obj, element_id, sec_idcs, extra) + { + let obj3d = this.getObj3D( element_id ); + if (!obj3d) return; + + let eve_el = this.mgr.GetElement(element_id); + + let sid = selection_obj.fElementId; + let smap = this.glctrl.viewer.selection_map; + if (smap[sid] === undefined) { + smap[sid] = {}; + } + + let res = { + "sec_sel" : (eve_el.fSecondarySelect && sec_idcs.length > 0) ? true : false, + "geom" : [] + }; + + if (obj3d.get_ctrl) { + let ctrl = obj3d.get_ctrl(obj3d); + ctrl.DrawForSelection(sec_idcs, res, extra); + } else { + res.geom.push(obj3d); + } + smap[sid][element_id] = res; + this.glctrl.viewer.make_selection_last_in_list(sid); + + // Display tooltip. + // XXXX Should check if highlight request came from this viewer. + if (selection_obj.fIsHighlight && selection_obj.sel_list) { + this.glctrl.viewer.remoteToolTip(selection_obj.sel_list[0].tooltip); + } + } + + UnselectElementRCore(selection_obj, element_id) + { + let sid = selection_obj.fElementId; + let smap = this.glctrl.viewer.selection_map; + if (smap[sid] !== undefined) { + delete smap[sid][element_id]; + if (Object.keys(smap[sid]).length == 0) { + this.glctrl.viewer.remove_selection_from_list(sid); + } } } diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 75c2002d30d3d..03e1fa806113a 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -23,7 +23,8 @@ sap.ui.define([ console.log("GlViewerRCore RQ_Mode:", this.RQ_Mode, "RQ_SSAA:", this.RQ_SSAA); - this._outline_map = {}; + this._selection_map = {}; + this._selection_list = []; this._logLevel = 1; // 0 - error, 1 - warning, 2 - info, 3 - debug } @@ -78,8 +79,6 @@ sap.ui.define([ return this.scene; } - get outline_map() { return this._outline_map; } - //============================================================================== createRCoreRenderer() @@ -410,10 +409,27 @@ sap.ui.define([ if (this.canvas.width <= 0 || this.canvas.height <= 0) return; - let omap = this.outline_map; - let sel_objs = Object.values(omap).flat(); - // console.log("WOOF", omap, sel_objs); - sel_objs.map(res => this.rqt.RP_GBuffer.obj_list.push(res.geom[0])); + for (let sel_id of this._selection_list) + { + let sel_entry = this._selection_map[ sel_id ]; + + // Extract edge color (note, root colors), width from selection object. + // let sel_object = this.get_manager().GetElement(sel_id); + // console.log("selection", sel_object.fVisibleEdgeColor, sel_object.fHiddenEdgeColor); + + for (let el_idx in sel_entry) + { + let el_entry = sel_entry[ el_idx ]; + // take all geometry objects, then we have to treat them differently, depending on type. + // and update world-matrix / check visibility + // or setup secondary indices for sub-instance drawing + + for (let geo of el_entry.geom) + { + this.rqt.RP_GBuffer.obj_list.push(geo); + } + } + } this.rqt.render(); @@ -467,6 +483,23 @@ sap.ui.define([ //============================================================================== + get selection_map() { return this._selection_map; } + + remove_selection_from_list(sid) + { + let idx = this._selection_list.indexOf(sid); + if (idx >= 0) + this._selection_list.splice(idx); + } + + make_selection_last_in_list(sid) + { + this.remove_selection_from_list(sid); + this._selection_list.push(sid); + } + + //============================================================================== + onResizeTimeout() { let w = this.get_width(); diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index 435abc29550ef..3f51b6ee9bf32 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -449,7 +449,7 @@ export class RendeQuTor ); this.RP_GBuffer.view_setup = function (vport) { this.viewport = vport; }; - // No push, GBuffer/Outline passes are handled separately as there can be more of them. + // TODO: No push, GBuffer/Outline passes should be handled separately as there can be more of them. this.queue.pushRenderPass(this.RP_GBuffer); return this.RP_GBuffer; } @@ -485,9 +485,9 @@ export class RendeQuTor ); this.RP_Outline.view_setup = function (vport) { this.viewport = vport; }; - // No push, GBuffer/Outline passes are handled separately as there can be more of them. + // TODO: No push, GBuffer/Outline passes should be handled separately as there can be more of them. this.queue.pushRenderPass(this.RP_Outline); - return this.RP_GBuffer; + return this.RP_Outline; } } From 499b1db1a04aa890bec187dcfc5efdd5265c107b Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Fri, 9 Sep 2022 11:16:24 -0700 Subject: [PATCH 15/84] [REve] Support outlining of specific instances. In GlViewerRCore, to workaround around single outline pass, merge indices from selection and highlight. --- graf3d/eve7/src/REvePointSet.cxx | 4 +++ ui5/eve7/lib/EveElementsRCore.js | 10 ++++++++ ui5/eve7/lib/GlViewerRCore.js | 42 +++++++++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/graf3d/eve7/src/REvePointSet.cxx b/graf3d/eve7/src/REvePointSet.cxx index b9119e612141b..6af817cb3efd9 100644 --- a/graf3d/eve7/src/REvePointSet.cxx +++ b/graf3d/eve7/src/REvePointSet.cxx @@ -67,6 +67,8 @@ REvePointSet::REvePointSet(const REvePointSet& e) : TAttMarker(e), TAttBBox(e) { + fAlwaysSecSelect = e.GetAlwaysSecSelect(); + ClonePoints(e); } //////////////////////////////////////////////////////////////////////////////// @@ -562,6 +564,8 @@ void REvePointSetProjected::UpdateProjection() REvePointSet &ps = * dynamic_cast(fProjectable); REveTrans *tr = ps.PtrMainTrans(kFALSE); + fAlwaysSecSelect = ps.GetAlwaysSecSelect(); + // XXXX rewrite Int_t n = ps.GetSize(); diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 82b3f500c5472..709fb5a4ff73b 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -53,6 +53,15 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) DrawForSelection(sec_idcs, res) { + if (this.invoke_obj.eve_el.fSecondarySelect) { + if (sec_idcs.length > 0) { + res.instance_object = this.invoke_obj; + res.instance_sec_idcs = sec_idcs; + // this.invoke_obj.outlineMaterial.outline_instances_setup(sec_idcs); + } else { + // this.invoke_obj.outlineMaterial.outline_instances_reset(); + } + } res.geom.push(this.invoke_obj); } @@ -61,6 +70,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // =================================================================================== // Digit sets control classes // =================================================================================== + class BoxSetControl extends EveElemControl { DrawForSelection(atom_idcs, res, extra) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 03e1fa806113a..6fb60f9ad6e42 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -409,6 +409,9 @@ sap.ui.define([ if (this.canvas.width <= 0 || this.canvas.height <= 0) return; + // Workaround to merge secondary-indices from multiple selections. See comments below. + let insta_map = new Map(); // Keep track of instanced-based secondary-seectables + for (let sel_id of this._selection_list) { let sel_entry = this._selection_map[ sel_id ]; @@ -417,6 +420,14 @@ sap.ui.define([ // let sel_object = this.get_manager().GetElement(sel_id); // console.log("selection", sel_object.fVisibleEdgeColor, sel_object.fHiddenEdgeColor); + // TODO: for now we do single outline pass, merging all objects together into + // a single list. This needs to be split into actuall separate outline passes. + // Problem: an object that uses instanced rendering and secondary selection can + // be in several selections. And we use the same object with the same + // outlineMaterial (where indicies are defined as vertex-atttrib with divisor 1) for + // all of them. So the buffer needs to be set for every pass (if needed). + // In this case, we have to merge the lists (not caring if certain index appears multiple times). + for (let el_idx in sel_entry) { let el_entry = sel_entry[ el_idx ]; @@ -424,15 +435,40 @@ sap.ui.define([ // and update world-matrix / check visibility // or setup secondary indices for sub-instance drawing - for (let geo of el_entry.geom) - { - this.rqt.RP_GBuffer.obj_list.push(geo); + if (el_entry.instance_object) { + if (insta_map.has(el_entry.instance_object)) + { + insta_map.get(el_entry.instance_object).push(...el_entry.instance_sec_idcs); + } + else + { + let arr = []; + arr.push(...el_entry.instance_sec_idcs); + insta_map.set(el_entry.instance_object, arr); + + this.rqt.RP_GBuffer.obj_list.push(el_entry.instance_object); + } + console.log("AAA", el_entry.instance_object, insta_map.get(el_entry.instance_object)); + } else { + for (let geo of el_entry.geom) + { + this.rqt.RP_GBuffer.obj_list.push(geo); + } } } } + // This would then be done per outline pass, if needed. Same for loop below render call. + for (const [obj, arr] of insta_map) { + obj.outlineMaterial.outline_instances_setup(arr); + } + this.rqt.render(); + for (const [obj, arr] of insta_map) { + obj.outlineMaterial.outline_instances_reset(); + } + this.rqt.RP_GBuffer.obj_list = []; if (this.renderer.used == false) { From 984a46de20698c1af5d3f911417c82ff69b9cbc5 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Thu, 15 Sep 2022 15:00:09 -0700 Subject: [PATCH 16/84] [REve] Get Calo objects, BoxSet and StraightLineSet to work with RCore. --- ui5/eve7/lib/EveElementsRCore.js | 360 +++++++++++++++++++------------ ui5/eve7/lib/GlViewerRCore.js | 10 +- ui5/eve7/lib/RendeQuTor.js | 2 +- 3 files changed, 228 insertions(+), 144 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 709fb5a4ff73b..5a24fc2128777 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -53,43 +53,51 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) DrawForSelection(sec_idcs, res) { - if (this.invoke_obj.eve_el.fSecondarySelect) { + if (this.top_obj.eve_el.fSecondarySelect) { if (sec_idcs.length > 0) { - res.instance_object = this.invoke_obj; + res.instance_object = this.top_obj; res.instance_sec_idcs = sec_idcs; // this.invoke_obj.outlineMaterial.outline_instances_setup(sec_idcs); } else { // this.invoke_obj.outlineMaterial.outline_instances_reset(); } } - res.geom.push(this.invoke_obj); + else + { + res.geom.push(this.top_obj); + } } } // class EveElemControl + // =================================================================================== // Digit sets control classes // =================================================================================== - class BoxSetControl extends EveElemControl { - - DrawForSelection(atom_idcs, res, extra) + class BoxSetControl extends EveElemControl + { + DrawForSelection(xsec_idcs, res, extra) { - let sec_idcs = extra.shape_idcs; - let geobox = new RC.Geometry(); - geobox.setAttribute( 'position', this.obj3d.geometry.getAttribute("position") ); /// AMT will this work with RenderCore ?? + let sec_idcs = extra.shape_idcs; // XXXX MT we have sec_idcs argument here + + console.log(xsec_idcs, res, extra); + + let body = new RC.Geometry(); + body._vertices = this.top_obj.geometry._vertices; let protoIdcs = [0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 1, 2, 3, 1, 3, 0, 4, 7, 6, 4, 6, 5]; - let idxBuff = new Uint16Array(sec_idcs.length * protoIdcs.length); + let idxBuff = []; - let N = this.obj3d.eve_el.render_data.idxBuff.length / 2; + let eve_el = this.top_obj.eve_el; + let N = eve_el.render_data.idxBuff.length / 2; for (let b = 0; b < sec_idcs.length; ++b) { - let idx = sec_idcs[b] - if (this.obj3d.eve_el.fDetIdsAsSecondaryIndices) { + let idx = sec_idcs[b]; + if (eve_el.fDetIdsAsSecondaryIndices) { for (let x = 0; x < N; ++x) { - if (this.obj3d.eve_el.render_data.idxBuff[x + N] === idx) + if (eve_el.render_data.idxBuff[x + N] === idx) { - idx=x; + idx = x; break; } } @@ -99,24 +107,26 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) idxBuff.push(idxOff + protoIdcs[i]); } - body.indices = new RC.BufferAttribute(idxBuff, 1); - let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); - let mesh = new RC.Mesh(body, mat); + body.indices = RC.Uint32Attribute(idxBuff, 1); + body.computeVertexNormals(); + + let mesh = new RC.Mesh(body, null); + mesh._modelViewMatrix = this.invoke_obj._modelViewMatrix; + mesh._normalMatrix = this.invoke_obj._normalMatrix; res.geom.push(mesh); } - extractIndex(intersect) + extractIndex(instance) { - let idx = Math.floor(intersect.faceIndex/12); - return idx; + return Math.floor(instance / 8); } - elementSelectedSendMIR(idx, selectionId) + elementSelectedSendMIR(idx, selectionId, event) { - let boxset = this.obj3d.eve_el; - let scene = this.obj3d.scene; - let multi = this.event?.ctrlKey ? true : false; + let boxset = this.top_obj.eve_el; + let scene = this.top_obj.scene; + let multi = event?.ctrlKey ? true : false; let boxIdx = idx; @@ -125,47 +135,51 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return true; } - elementSelected(idx) + elementSelected(idx, event) { - return this.elementSelectedSendMIR(idx, this.obj3d.scene.mgr.global_selection_id); + return this.elementSelectedSendMIR(idx, this.top_obj.scene.mgr.global_selection_id, event); } - elementHighlighted(idx) + elementHighlighted(idx, event) { - return this.elementSelectedSendMIR(idx, this.obj3d.scene.mgr.global_highlight_id); + return this.elementSelectedSendMIR(idx, this.top_obj.scene.mgr.global_highlight_id, event); } - checkHighlightIndex(indx) + checkHighlightIndex(idx) // XXXX ?? MT Sept-2022 { - if (this.obj3d && this.obj3d.scene) - return this.invokeSceneMethod("processCheckHighlight", indx); + if (this.top_obj && this.top_obj.scene) + return this.invokeSceneMethod("processCheckHighlight", idx); return true; // means index is different } } // class BoxSetControl + // =================================================================================== // Calorimeter control classes // =================================================================================== - class Calo3DControl extends EveElemControl { - - DrawForSelection(sec_idcs, res, extra) { + class Calo3DControl extends EveElemControl + { + DrawForSelection(sec_idcs, res, extra) + { console.log("CALO 3d draw for selection ", extra); + let eve_el = this.invoke_obj.eve_el; // locate REveCaloData cells for this object let cells; for (let i = 0; i < extra.length; i++) { - if (extra[i].caloVizId == this.obj3d.eve_el.fElementId) { + if (extra[i].caloVizId == eve_el.fElementId) { cells = extra[i].cells; break; } } - let ibuff = this.obj3d.eve_el.render_data.idxBuff; + let rnr_data = eve_el.render_data; + let ibuff = rnr_data.idxBuff; let nbox = ibuff.length / 2; let nBoxSelected = parseInt(cells.length); - let boxIdcs = new Uint16Array; + let boxIdcs = []; for (let i = 0; i < cells.length; i++) { let tower = cells[i].t; let slice = cells[i].s; @@ -177,15 +191,15 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } } } - let rnr_data = this.obj3d.eve_el.render_data; let protoIdcs = [0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 1, 2, 3, 1, 3, 0, 4, 7, 6, 4, 6, 5]; let idxBuff = []; - let vtxBuff = new Float32Array(nbox * 8 * 3); - for (let i = 0; i < nBoxSelected; ++i) { - let BoxIdcs = boxIdcs[i]; + let vtxBuff = new Float32Array(nBoxSelected * 8 * 3); + for (let i = 0; i < nBoxSelected; ++i) + { + let box_idx = boxIdcs[i]; for (let c = 0; c < 8; c++) { let off = i * 24 + c * 3; - let pos = BoxIdcs * 24 + c * 3; + let pos = box_idx * 24 + c * 3; vtxBuff[off] = rnr_data.vtxBuff[pos]; vtxBuff[off + 1] = rnr_data.vtxBuff[pos + 1]; vtxBuff[off + 2] = rnr_data.vtxBuff[pos + 2]; @@ -194,7 +208,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // fix top corners, select can be partial for (let c = 0; c < 4; c++) { // fix vertex 1 - let pos = BoxIdcs * 24 + c * 3; + let pos = box_idx * 24 + c * 3; let v1x = rnr_data.vtxBuff[pos]; let v1y = rnr_data.vtxBuff[pos + 1]; let v1z = rnr_data.vtxBuff[pos + 2]; @@ -216,62 +230,104 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } // loop boxes let body = new RC.Geometry(); + body.indices = RC.Uint32Attribute(idxBuff, 1); + body.vertices = new RC.BufferAttribute(vtxBuff, 3); // this.invoke_obj.geometry.vertices; + body.computeVertexNormals(); // XX should not need it when we have dFdx/y - body.indices = new RC.BufferAttribute(idxBuff, 1); - body.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); - body.computeVertexNormals(); - // ? AMT do we need vertex colors - let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); - - let mesh = new RC.Mesh(body, mat); + let mesh = new RC.Mesh(body, null); + mesh._modelViewMatrix = this.invoke_obj._modelViewMatrix; + mesh._normalMatrix = this.invoke_obj._normalMatrix; res.geom.push(mesh); - } - extractIndex(intersect) { - let idx = Math.floor(intersect.faceIndex / 12); - return idx; + console.log(body, mesh, res); } - elementSelectedSendMIR(idx, selectionId) + extractIndex(instance) { - let boxset = this.obj3d.eve_el; - let scene = this.obj3d.scene; - let multi = this.event?.ctrlKey ? true : false; + return Math.floor(instance / 8); + } - let boxIdx = idx; + getTooltipText(idx) + { + // let t = this.obj3d.eve_el.fTitle || this.obj3d.eve_el.fName || ""; + let eve_el = this.top_obj.eve_el; + let val = eve_el.render_data.nrmBuff[idx]; + let idxBuff = eve_el.render_data.idxBuff; + let caloData = this.top_obj.scene.mgr.GetElement(eve_el.dataId); + let slice = idxBuff[idx*2]; + + let vbuff = eve_el.render_data.vtxBuff; + let p = idx*24; + let x = vbuff[p]; + let y = vbuff[p+1]; + let z = vbuff[p+2]; + + let phi = Math.acos(x/Math.sqrt(x*x+y*y)); + let cosTheta = z/Math.sqrt(x*x + y*y + z*z); + let eta = 0; + if (cosTheta*cosTheta < 1) + { + eta = -0.5* Math.log( (1.0-cosTheta)/(1.0+cosTheta) ); + } - let fcall = "NewShapePicked(" + boxIdx + ", " + selectionId + ", " + multi + ")" - scene.mgr.SendMIR(fcall, boxset.fElementId, "ROOT::Experimental::REveDigitSet"); - return true; + return caloData.sliceInfos[slice].name + "\n" + Math.floor(val*100)/100 + + " ("+ Math.floor(eta*100)/100 + ", " + Math.floor(phi*100)/100 + ")"; } - elementSelected(idx) + elementSelected(idx, event) { - return this.elementSelectedSendMIR(idx, this.obj3d.scene.mgr.global_selection_id); + let calo = this.top_obj.eve_el; + let idxBuff = calo.render_data.idxBuff; + let scene = this.top_obj.scene; + let selectionId = scene.mgr.global_selection_id; + let multi = event?.ctrlKey ? true : false; + let fcall = "NewTowerPicked(" + idxBuff[idx*2 + 1] + ", " + idxBuff[idx*2] + ", " + + selectionId + ", " + multi + ")"; + scene.mgr.SendMIR(fcall, calo.fElementId, "ROOT::Experimental::REveCalo3D"); + return true; } - elementHighlighted(idx) + elementHighlighted(idx, event) { - return this.elementSelectedSendMIR(idx, this.obj3d.scene.mgr.global_highlight_id); + let calo = this.top_obj.eve_el; + let idxBuff = calo.render_data.idxBuff; + let scene = this.top_obj.scene; + let selectionId = scene.mgr.global_highlight_id; + let fcall = "NewTowerPicked(" + idxBuff[idx*2 + 1] + ", " + idxBuff[idx*2] + ", " + selectionId + ", false)"; + scene.mgr.SendMIR(fcall, calo.fElementId, "ROOT::Experimental::REveCalo3D"); + } + + checkHighlightIndex(idx) + { + if (this.top_obj && this.top_obj.scene) + { + console.log("check highlight idx ?????? \n"); + return this.invokeSceneMethod("processCheckHighlight", idx); + + } + + return true; // means index is different } } // class Calo3DControl - class Calo2DControl extends EveElemControl { - - DrawForSelection(sec_idcs, res, extra) { + class Calo2DControl extends EveElemControl + { + DrawForSelection(sec_idcs, res, extra) + { + let eve_el = this.invoke_obj.eve_el; let cells; for (let i = 0; i < extra.length; i++) { - if (extra[i].caloVizId == this.obj3d.eve_el.fElementId) { + if (extra[i].caloVizId == eve_el.fElementId) { cells = extra[i].cells; break; } } - - let ibuff = this.obj3d.eve_el.render_data.idxBuff; - let vbuff = this.obj3d.eve_el.render_data.vtxBuff; + let rnr_data = eve_el.render_data; + let ibuff = rnr_data.idxBuff; + let vbuff = rnr_data.vtxBuff; let nbox = ibuff.length / 2; let nBoxSelected = cells.length; let boxIdcs = []; @@ -295,7 +351,6 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let idxBuff = []; let vtxBuff = new Float32Array(nBoxSelected * 4 * 3); let protoIdcs = [0, 1, 2, 2, 3, 0]; - let rnr_data = this.obj3d.eve_el.render_data; for (let i = 0; i < nBoxSelected; ++i) { let BoxIdcs = boxIdcs[i]; for (let v = 0; v < 4; v++) { @@ -337,49 +392,85 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } let body = new RC.Geometry(); - body.indices = new RC.BufferAttribute(idxBuff, 1); - body.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); + body.indices = RC.Uint32Attribute(idxBuff, 1); + body.vertices = new RC.BufferAttribute(vtxBuff, 3); + body.computeVertexNormals(); + + let mesh = new RC.Mesh(body, null); + mesh._modelViewMatrix = this.invoke_obj._modelViewMatrix; + mesh._normalMatrix = this.invoke_obj._normalMatrix; - let mesh = new THREE.Mesh(body); res.geom.push(mesh); } - extractIndex(intersect) + extractIndex(instance) { - let idx = Math.floor(intersect.faceIndex/2); - return idx; + return Math.floor(instance / 4); } - elementSelectedSendMIR(idx, selectionId) + getTooltipText(idx) { - let calo = this.obj3d.eve_el; - let idxBuff = calo.render_data.idxBuff; - let scene = this.obj3d.scene; - let multi = this.event?.ctrlKey ? true : false; - let bin = idxBuff[idx*2 + 1]; - let slice = idxBuff[idx*2]; - // get sign for the case of RhoZ projection - if (calo.render_data.vtxBuff[idx*12 + 1] < 0) bin = -bin ; - - let fcall = "NewBinPicked(" + bin + ", " + slice + ", " + selectionId + ", " + multi + ")" - scene.mgr.SendMIR(fcall, calo.fElementId, "ROOT::Experimental::REveCalo2D"); - return true; + let eve_el = this.top_obj.eve_el; + let idxBuff = eve_el.render_data.idxBuff; + // let bin = idxBuff[idx*2 + 1]; + let val = eve_el.render_data.nrmBuff[idx]; + let caloData = this.top_obj.scene.mgr.GetElement(eve_el.dataId); + let slice = idxBuff[idx*2]; + let sname = caloData.sliceInfos[slice].name; + + let vbuff = eve_el.render_data.vtxBuff; + let p = idx*12; + let x = vbuff[p]; + let y = vbuff[p+1]; + // let z = vbuff[p+2]; + + if (eve_el.isRPhi) { + let phi = Math.acos(x/Math.sqrt(x*x+y*y)) * Math.sign(y); + return sname + " " + Math.floor(val*100)/100 + + " ("+ Math.floor(phi*100)/100 + ")"; + } + else + { + let cosTheta = x/Math.sqrt(x*x + y*y), eta = 0; + if (cosTheta*cosTheta < 1) + { + eta = -0.5* Math.log( (1.0-cosTheta)/(1.0+cosTheta) ); + } + + return sname + " " + Math.floor(val*100)/100 + + " ("+ Math.floor(eta*100)/100 + ")"; + } } - elementSelected(idx) + elementSelectedSendMIR(idx, selectionId, event) + { + let calo = this.top_obj.eve_el; + let idxBuff = calo.render_data.idxBuff; + let scene = this.top_obj.scene; + let multi = event?.ctrlKey ? true : false; + let bin = idxBuff[idx*2 + 1]; + let slice = idxBuff[idx*2]; + // get sign for the case of RhoZ projection + if (calo.render_data.vtxBuff[idx*12 + 1] < 0) bin = -bin ; + + let fcall = "NewBinPicked(" + bin + ", " + slice + ", " + selectionId + ", " + multi + ")" + scene.mgr.SendMIR(fcall, calo.fElementId, "ROOT::Experimental::REveCalo2D"); + return true; + } + + elementSelected(idx, event) { - return this.elementSelectedSendMIR(idx, this.obj3d.scene.mgr.global_selection_id); + return this.elementSelectedSendMIR(idx, this.top_obj.scene.mgr.global_selection_id, event); } - elementHighlighted(idx) + elementHighlighted(idx, event) { - return this.elementSelectedSendMIR(idx, this.obj3d.scene.mgr.global_highlight_id); + return this.elementSelectedSendMIR(idx, this.top_obj.scene.mgr.global_highlight_id, event); } } // class Calo2Control - //============================================================================== // EveElements //============================================================================== @@ -531,7 +622,9 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) RcPickable(el, obj3d, do_children = true, ctrl_class = EveElemControl) { if (el.fPickable) { - obj3d.get_ctrl = function(state) { return new ctrl_class(state); } + if (ctrl_class) { + obj3d.get_ctrl = function(iobj, tobj) { return new ctrl_class(iobj, tobj); } + } obj3d.pickable = true; if (do_children) { for (let i = 0; i < obj3d.children.length; ++i) @@ -888,16 +981,14 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } let body = new RC.Geometry(); - body.indices = new RC.BufferAttribute(idxBuff, 1); body.vertices = new RC.BufferAttribute(vBuff, 3); body.computeVertexNormals(); - // // set material and colors let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); - if (!boxset.fSingleColor) + if ( ! boxset.fSingleColor) { let ci = rnr_data.idxBuff; let off = 0 @@ -909,28 +1000,21 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let b = (ci[x] & 0x00FF0000) >> 16; for (let i = 0; i < 8; ++i) { - colBuff[off ] = r/256; - colBuff[off + 1] = g/256; - colBuff[off + 2] = b/256; + colBuff[off ] = r / 255; + colBuff[off + 1] = g / 255; + colBuff[off + 2] = b / 255; colBuff[off + 3] = 1.0; off += 4; } } body.vertColor = new RC.BufferAttribute(colBuff, 4); mat.useVertexColors = true; - } - else - { - let mcol = RcCol(boxset.fMainColor); - mat.color = mcol; + } else { + mat.color = RcCol(boxset.fMainColor); } let mesh = new RC.Mesh(body, mat); - - if (boxset.fSecondarySelect) - mesh.get_ctrl = function() { return new BoxSetControl(mesh); }; - else - mesh.get_ctrl = function() { return new EveElemControl(mesh); }; + this.RcPickable(boxset, mesh, false, boxset.fSecondarySelect ? BoxSetControl : EveElemControl); mesh.dispose = function() { this.geometry.dispose(); this.material.dispose(); }; @@ -951,8 +1035,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let idxBuff = new Uint32Array(nBox * protoSize); let p = 0; for (let i = 0; i < nBox; ++i) { + let off = i * 8; for (let c = 0; c < protoSize; c++) { - let off = i * 8; idxBuff[p++] = protoIdcs[c] + off; } } @@ -967,7 +1051,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) for (let x = 0; x < nBox; ++x) { let slice = ci[x * 2]; let sliceColor = calo3D.sliceColors[slice]; - let tc = new RC.Color(EVE.JSR.getColor(sliceColor)); + let tc = RcCol(sliceColor); for (let i = 0; i < 8; ++i) { colBuff[off] = tc.r; colBuff[off + 1] = tc.g; @@ -981,13 +1065,12 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); //let mat = this.RcFlatMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); - mat.useVertexColors = true; + let mesh = new RC.Mesh(body, mat); - this.RcPickable(calo3D, mesh); + this.RcPickable(calo3D, mesh, false, Calo3DControl); - mesh.get_ctrl = function () { return new Calo3DControl(mesh); }; mesh.dispose = function () { this.geometry.dispose(); this.material.dispose(); }; return mesh; @@ -1026,7 +1109,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) for (let x = 0; x < nSquares; ++x) { let slice = ci[x * 2]; let sliceColor = calo2D.sliceColors[slice]; - let tc = new THREE.Color(EVE.JSR.getColor(sliceColor)); + let tc = RcCol(sliceColor); console.log() for (let i = 0; i < 4; ++i) { colBuff[off] = tc.r; @@ -1044,8 +1127,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) mat.useVertexColors = true; let mesh = new RC.Mesh(body, mat); - this.RcPickable(calo2D, mesh); - //mesh.get_ctrl = function () { return new Calo2DControl(mesh); }; + this.RcPickable(calo2D, mesh, false, Calo2DControl); + mesh.dispose = function () { this.geometry.dispose(); this.material.dispose(); }; return mesh; @@ -1178,7 +1261,6 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let line = new RC.Line(geom, line_mat); line.renderingPrimitive = RC.LINES; - this.RcPickable(el, line); obj3d.add(line); @@ -1208,19 +1290,21 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) obj3d.add(marker); // For secondary selection, see EveElements.js - obj3d.eve_idx_buf = rnr_data.idxBuff; - - /* - let octrl; - if (el.fSecondarySelect) - octrl = new StraightLineSetControl(obj3d); - else - octrl = new EveElemControl(obj3d); - - line.get_ctrl = function() { return octrl; }; - marker.get_ctrl = function() { return octrl; }; - obj3d.get_ctrl = function() { return octrl; }; - */ + // obj3d.eve_idx_buf = rnr_data.idxBuff; + // if (el.fSecondarySelect) + // octrl = new StraightLineSetControl(obj3d); + // else + // octrl = new EveElemControl(obj3d); + + this.RcPickable(el, obj3d, true, null); + obj3d.get_ctrl = function(iobj, tobj) { + let octrl = new EveElemControl(iobj, tobj); + octrl.DrawForSelection = function(sec_idcs, res) { + res.geom.push(this.top_obj.children[0]); + res.geom.push(this.top_obj.children[1]); + }; + return octrl; + } return obj3d; } diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 6fb60f9ad6e42..992e0fa7af555 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -55,7 +55,9 @@ sap.ui.define([ this.creator = new EveElements(RC, this); // this.creator.useIndexAsIs = EVE.JSR.decodeUrl().has('useindx'); + RC.GLManager.sCheckFrameBuffer = false; RC.Object3D.sDefaultPickable = false; + RC.PickingShaderMaterial.DEFAULT_PICK_MODE = RC.PickingShaderMaterial.PICK_MODE.UINT; this.createRCoreRenderer(); this.controller.createScenes(); @@ -103,8 +105,6 @@ sap.ui.define([ this.renderer.addShaderLoaderUrls("rootui5sys/eve7/lib/RC/shaders"); this.renderer.addShaderLoaderUrls("rootui5sys/eve7/shaders"); this.renderer.pickObject3D = true; - RC.PickingShaderMaterial.DEFAULT_PICK_MODE = RC.PickingShaderMaterial.PICK_MODE.UINT; - RC.GLManager.sCheckFrameBuffer = false; this.scene = new RC.Scene(); @@ -448,7 +448,6 @@ sap.ui.define([ this.rqt.RP_GBuffer.obj_list.push(el_entry.instance_object); } - console.log("AAA", el_entry.instance_object, insta_map.get(el_entry.instance_object)); } else { for (let geo of el_entry.geom) { @@ -600,13 +599,14 @@ sap.ui.define([ return this.clearHighlight(); let c = pstate.ctrl; + let idx = c.extractIndex(pstate.instance); - c.elementHighlighted(c.extractIndex(pstate.instance), null); + c.elementHighlighted(idx, null); if (this.highlighted_top_object !== pstate.top_object) { if (pstate.object && pstate.eve_el) - this.ttip_text.innerHTML = c.getTooltipText(); + this.ttip_text.innerHTML = c.getTooltipText(idx); else this.ttip_text.innerHTML = ""; } diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index 3f51b6ee9bf32..8933bc2fa98ce 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -153,7 +153,7 @@ export class RendeQuTor pick_instance(state) { // RCRC Proto-proto-secondary-selection. Requires branch: // https://github.com/osschar/RenderCore/tree/img-tex-cache - if (state.object !== this.renderer.pickedObject3D || ! state.object.instanced) { + if (state.object !== this.renderer.pickedObject3D) { console.error("RendeQuTor::pick_instance state mismatch", state, this.renderer.pickedObject3D); } else { console.log("RenderQuTor::pick going for secondary select"); From 506266a78d824204cd373a723a295efd0416d088 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Tue, 20 Sep 2022 11:32:10 -0700 Subject: [PATCH 17/84] [REve] Use RCore dFdxy flat shading and new point-light model. --- tutorials/eve7/boxset.C | 18 +++++++++-------- tutorials/eve7/calorimeters.C | 9 ++++----- tutorials/eve7/event_demo.C | 1 + ui5/eve7/lib/EveElementsRCore.js | 31 +++++++++++++++++------------ ui5/eve7/lib/GlViewerRCore.js | 34 +++++++++++++++++--------------- ui5/eve7/lib/RendeQuTor.js | 8 -------- 6 files changed, 51 insertions(+), 50 deletions(-) diff --git a/tutorials/eve7/boxset.C b/tutorials/eve7/boxset.C index fda5793fa970c..48e424d098372 100644 --- a/tutorials/eve7/boxset.C +++ b/tutorials/eve7/boxset.C @@ -38,14 +38,16 @@ REveBoxSet* boxset(Int_t num=100) #define RND_BOX(x) (Float_t)r.Uniform(-(x), (x)) - Float_t verts[24]; - for (Int_t i=0; iSetMainTransparency(60); jet->SetLineColor(kRed); - jet->SetCylinder(129 - 10, 268.36 - 10); + jet->SetCylinder(kR_min - 10, kZ_d - 10); jet->AddEllipticCone(eta, phi, deta, dphi); jet->SetPickable(kTRUE); jet->SetHighlightFrame(kFALSE); @@ -75,11 +75,12 @@ void calorimeters() auto b1 = new REveGeoShape("Barrel 1"); b1->SetShape(new TGeoTube(kR_min, kR_max, kZ_d)); b1->SetMainColor(kCyan); + b1->SetNSegments(80); eveMng->GetGlobalScene()->AddElement(b1); auto calo3d = new REveCalo3D(data); - calo3d->SetBarrelRadius(kR_max); - calo3d->SetEndCapPos(kZ_d); + calo3d->SetBarrelRadius(kR_max + 1); + calo3d->SetEndCapPos(kZ_d + 1); calo3d->SetMaxTowerH(300); eveMng->GetEventScene()->AddElement(calo3d); @@ -91,5 +92,3 @@ void calorimeters() eveMng->Show(); } - - diff --git a/tutorials/eve7/event_demo.C b/tutorials/eve7/event_demo.C index 07d6683980857..a42c40a27583f 100644 --- a/tutorials/eve7/event_demo.C +++ b/tutorials/eve7/event_demo.C @@ -160,6 +160,7 @@ void makeGeometryScene() auto b1 = new REX::REveGeoShape("Barrel 1"); b1->SetShape(new TGeoTube(kR_min, kR_max, kZ_d)); b1->SetMainColor(kCyan); + b1->SetNSegments(80); eveMng->GetGlobalScene()->AddElement(b1); // Debug of surface fill in RPhi (index buffer screwed). diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 5a24fc2128777..88ebb819cca38 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -818,7 +818,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // idcs.push( 0, i, i + 1 ); } geo_body.indices = new RC.BufferAttribute(idcs, 1); - geo_body.computeVertexNormals(); + // geo_body.computeVertexNormals(); let geo_rim = new RC.Geometry(); geo_rim.vertices = pos_ba; @@ -840,6 +840,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let lcol = RcCol(jet.fLineColor); let mesh = new RC.Mesh(geo_body, this.RcFancyMaterial(mcol, 0.5, { side: RC.FRONT_AND_BACK_SIDE })); + mesh.material.normalFlat = true; let line1 = new RC.Line(geo_rim, this.RcLineMaterial(lcol, 0.8, 4)); line1.renderingPrimitive = RC.LINE_LOOP; @@ -877,7 +878,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) idcs[0] = 0; idcs[1] = 1; idcs[2] = 2; if (N > 3) { idcs[3] = 0; idcs[4] = 2; idcs[5] = 3; } geo_body.indices = new RC.BufferAttribute(idcs, 1); - geo_body.computeVertexNormals(); + // geo_body.computeVertexNormals(); let geo_rim = new RC.Geometry(); geo_rim.vertices = pos_ba; @@ -983,11 +984,12 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let body = new RC.Geometry(); body.indices = new RC.BufferAttribute(idxBuff, 1); body.vertices = new RC.BufferAttribute(vBuff, 3); - body.computeVertexNormals(); + // body.computeVertexNormals(); // set material and colors let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); + mat.normalFlat = true; if ( ! boxset.fSingleColor) { let ci = rnr_data.idxBuff; @@ -1043,7 +1045,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) body.indices = new RC.BufferAttribute(idxBuff, 1); body.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); - body.computeVertexNormals(); + // body.computeVertexNormals(); let ci = rnr_data.idxBuff; let off = 0 @@ -1066,6 +1068,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); //let mat = this.RcFlatMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); mat.useVertexColors = true; + mat.normalFlat = true; let mesh = new RC.Mesh(body, mat); @@ -1101,7 +1104,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) body.indices = new RC.BufferAttribute(idxBuff, 1); body.vertices = new RC.BufferAttribute(rnrData.vtxBuff, 3); - body.computeVertexNormals(); + // body.computeVertexNormals(); let ci = rnrData.idxBuff; let colBuff = new Float32Array(nSquares * 4 * 4); @@ -1138,7 +1141,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // makeEveGeometry / makeEveGeoShape //============================================================================== - makeEveGeometry(rnr_data) + makeEveGeometry(rnr_data, compute_normals) { let nVert = rnr_data.idxBuff[1] * 3; @@ -1149,7 +1152,9 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) geo.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); geo.indices = new RC.BufferAttribute(rnr_data.idxBuff, 1); geo.setDrawRange(2, nVert); - geo.computeVertexNormalsIdxRange(2, nVert); + if (compute_normals) { + geo.computeVertexNormalsIdxRange(2, nVert); + } // XXXX Fix this. It seems we could have flat shading with usage of simple shaders. // XXXX Also, we could do edge detect on the server for outlines. @@ -1165,16 +1170,16 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) makeEveGeoShape(egs, rnr_data) { - let geom = this.makeEveGeometry(rnr_data); + let geom = this.makeEveGeometry(rnr_data, false); let fcol = RcCol(egs.fFillColor); - let material = this.RcFancyMaterial(fcol, 0.2); - material.side = RC.FRONT_AND_BACK_SIDE; - material.specular = new RC.Color(1, 1, 1); - material.shininess = 50; + let mat = this.RcFancyMaterial(fcol, 0.2); + mat.side = RC.FRONT_AND_BACK_SIDE; + mat.shininess = 50; + mat.normalFlat = true; - let mesh = new RC.Mesh(geom, material); + let mesh = new RC.Mesh(geom, mat); this.RcPickable(egs, mesh); return mesh; } diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 992e0fa7af555..c770a188c79a1 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -126,10 +126,11 @@ sap.ui.define([ this.camera.isPerspectiveCamera = true; let l_int = 1.4; - this.lights.add(new light_class_3d(0xaa8888, l_int )); // R - this.lights.add(new light_class_3d(0x88aa88, l_int )); // G - this.lights.add(new light_class_3d(0x8888aa, l_int )); // B - this.lights.add(new light_class_3d(0x999999, l_int )); // gray + let l_att = { constant: 1, linear: 0, quadratic: 0 }; + this.lights.add(new light_class_3d(0xaa8888, l_int, 0, 1, l_att)); // R + this.lights.add(new light_class_3d(0x88aa88, l_int, 0, 1, l_att)); // G + this.lights.add(new light_class_3d(0x8888aa, l_int, 0, 1, l_att)); // B + this.lights.add(new light_class_3d(0x999999, l_int, 0, 1, l_att)); // gray // Lights are positioned in resetRenderer. @@ -157,14 +158,14 @@ sap.ui.define([ // Test objects if (this.controller.isEveCameraPerspective()) { - let c = new RC.Cube(40, new RC.Color(0.2,.4,.8)); - c.material = new RC.MeshPhongMaterial(); - c.material.transparent = true; - c.material.opacity = 0.8; - c.material.depthWrite = false; - this.scene.add(c); - - let ss = new RC.Stripe([0,0,0, 100,50,50, 100,200,200, 300,300,300]); + // let c = new RC.Cube(40, new RC.Color(0.2,.4,.8)); + // c.material = new RC.MeshPhongMaterial(); + // c.material.transparent = true; + // c.material.opacity = 0.8; + // c.material.depthWrite = false; + // this.scene.add(c); + + let ss = new RC.Stripe([0,0,0, 400,0,0, 400,400,0, 400,400,400]); ss.material.lineWidth = 20.0; ss.material.color = new RC.Color(0xff0000); ss.material.emissive = new RC.Color(0x008080); @@ -350,10 +351,11 @@ sap.ui.define([ this.controls.screenSpacePanning = true; let lc = this.lights.children; - lc[1].position.set( extR, extR, -extR); lc[1].decay = 0.5 * extR; lc[1].distance = 3 * extR; - lc[2].position.set(-extR, extR, extR); lc[2].decay = 0.5 * extR; lc[2].distance = 3 * extR; - lc[3].position.set( extR, extR, extR); lc[3].decay = 0.5 * extR; lc[3].distance = 3 * extR; - lc[4].position.set(-extR, extR, -extR); lc[4].decay = 0.5 * extR; lc[4].distance = 3 * extR; + // lights are const now -- no need to set decay and distance + lc[1].position.set( extR, extR, -extR); + lc[2].position.set(-extR, extR, extR); + lc[3].position.set( extR, extR, extR); + lc[4].position.set(-extR, extR, -extR); // console.log("resetRenderer 3D scene bbox ", sbbox, ", camera_pos ", posC, ", look_at ", this.rot_center); } diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index 8933bc2fa98ce..c8934f6f46687 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -41,14 +41,6 @@ export class RendeQuTor const nearPlane = 0.0625; // XXXX - pass to view_setup(vport, nfclip) const farPlane = 8192; // XXXX - // Why object.pickable === false in Initialize functions ??? - // How is outline supposed to work ??? - // Picking ??? - - this.OriginalMats = []; - this.MultiMats = []; - - // RenderQueue ... subclass or envelop? // For every pass, store object + resize behaviour } From 258bb4483f52f5d0b979ad9f94ae277f574b779e Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 26 Sep 2022 18:53:49 -0700 Subject: [PATCH 18/84] [REve] [RCore] Integration with new outline / blending / tone-mapping; proto ZLine (multiple instanceData textures). --- ui5/eve7/lib/EveElementsRCore.js | 54 +++++----- ui5/eve7/lib/EveManager.js | 4 +- ui5/eve7/lib/GlViewerRCore.js | 2 +- ui5/eve7/lib/RendeQuTor.js | 171 ++++++++++++++++++++++++------- 4 files changed, 165 insertions(+), 66 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 88ebb819cca38..e67d8c5b50ad0 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -113,6 +113,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let mesh = new RC.Mesh(body, null); mesh._modelViewMatrix = this.invoke_obj._modelViewMatrix; mesh._normalMatrix = this.invoke_obj._normalMatrix; + mesh._material = this.invoke_obj._material; res.geom.push(mesh); } @@ -237,6 +238,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let mesh = new RC.Mesh(body, null); mesh._modelViewMatrix = this.invoke_obj._modelViewMatrix; mesh._normalMatrix = this.invoke_obj._normalMatrix; + mesh._material = this.invoke_obj._material; res.geom.push(mesh); @@ -399,6 +401,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let mesh = new RC.Mesh(body, null); mesh._modelViewMatrix = this.invoke_obj._modelViewMatrix; mesh._normalMatrix = this.invoke_obj._normalMatrix; + mesh._material = this.invoke_obj._material; res.geom.push(mesh); } @@ -664,6 +667,23 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) ); } + GetRgbaTexture(name, callback) + { + let url = window.location.origin + '/rootui5sys/eve7/textures/' + name; + + this.tex_cache.deliver(url, + callback, + (image) => { + return new RC.Texture + (image, RC.Texture.ClampToEdgeWrapping, RC.Texture.ClampToEdgeWrapping, + RC.Texture.LinearFilter, RC.Texture.LinearFilter, + RC.Texture.RGBA, RC.Texture.RGBA, RC.Texture.UNSIGNED_BYTE, + image.width, image.height); + }, + () => { this.viewer.request_render() } + ); + } + AddMapToAllMaterials(o3d, tex) { if (o3d.material) o3d.material.addMap(tex); @@ -696,13 +716,13 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // sm.addMap(tex); // }); - sm.instanceData = new RC.Texture(rnr_data.vtxBuff, + sm.addInstanceData(new RC.Texture(rnr_data.vtxBuff, RC.Texture.ClampToEdgeWrapping, RC.Texture.ClampToEdgeWrapping, RC.Texture.NearestFilter, RC.Texture.NearestFilter, // RC.Texture.R32F, RC.Texture.R32F, RC.Texture.FLOAT, RC.Texture.RGBA32F, RC.Texture.RGBA, RC.Texture.FLOAT, - hit.fTexX, hit.fTexY); - sm.instanceData.flipy = false; + hit.fTexX, hit.fTexY)); + sm.instanceData[0].flipy = false; let s = new RC.ZSprite(null, sm); s.frustumCulled = false; // need a way to speciy bounding box/sphere !!! @@ -710,11 +730,10 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) s.instanceCount = hit.fSize; this.GetLumAlphaTexture("star5-32a.png", this.AddMapToAllMaterials.bind(this, s)); + // this.GetRgbaTexture("unicorn-a.png", this.AddMapToAllMaterials.bind(this, s)); this.RcPickable(hit, s); - s.dispose = () => { delete this; } // ??? RCRC instanceData texture ??? - return s; } @@ -791,7 +810,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) //line.hightlightWidthScale = 2; this.RcPickable(track, line); - line.dispose = function() { /*delete this.geometry; delete this.material;*/ }; + return line; } @@ -850,12 +869,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) mesh.add(line1); mesh.add(line2); - this.RcPickable(jet, mesh); - - mesh.dispose = function() { - //this.children.forEach(c => { delete c.geometry; delete c.material; }); - //delete this.geometry; delete this.material; - }; + this.RcPickable(jet, mesh, false); return mesh; } @@ -895,10 +909,9 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let fcol = RcCol(jet.fFillColor); let lcol = RcCol(jet.fLineColor); // Process transparency !!! - // console.log("cols", fcol, lcol); - // double-side material required for correct tracing of colors - otherwise points sequence should be changed let mesh = new RC.Mesh(geo_body, this.RcFlatMaterial(fcol, 0.5)); + mesh.material.normalFlat = true; let line1 = new RC.Line(geo_rim, this.RcLineMaterial(lcol, 0.8, 2)); @@ -907,13 +920,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) mesh.add(line1); mesh.add(line2); - this.RcPickable(jet, mesh); + this.RcPickable(jet, mesh, false); - mesh.dispose = function() { - //this.children.forEach(c => { delete c.geometry; delete c.material; }); - //delete this.geometry; delete this.material; - }; - return mesh; } @@ -1018,8 +1026,6 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let mesh = new RC.Mesh(body, mat); this.RcPickable(boxset, mesh, false, boxset.fSecondarySelect ? BoxSetControl : EveElemControl); - mesh.dispose = function() { this.geometry.dispose(); this.material.dispose(); }; - return mesh; } //============================================================================== @@ -1074,8 +1080,6 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) this.RcPickable(calo3D, mesh, false, Calo3DControl); - mesh.dispose = function () { this.geometry.dispose(); this.material.dispose(); }; - return mesh; } @@ -1132,8 +1136,6 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) this.RcPickable(calo2D, mesh, false, Calo2DControl); - mesh.dispose = function () { this.geometry.dispose(); this.material.dispose(); }; - return mesh; } diff --git a/ui5/eve7/lib/EveManager.js b/ui5/eve7/lib/EveManager.js index 8e3d4096d1213..58c367cc788d0 100644 --- a/ui5/eve7/lib/EveManager.js +++ b/ui5/eve7/lib/EveManager.js @@ -428,7 +428,9 @@ sap.ui.define([], function() { let lastoff = offset; - for (let n=1; n 0) { - for (let i = 0; i < object.children.length; i++) { - iterateSceneR(object.children[i], callback); - } - } - - callback(object); -} export class RendeQuTor { @@ -54,14 +35,20 @@ export class RendeQuTor this.SSAA_value = ssaa_val; this.make_RP_SSAA_Super(); - this.make_RP_SSAA_Down(); this.make_RP_GBuffer(); this.make_RP_Outline(); - this.make_RP_ToScreen(); - this.RP_ToScreen.input_texture = "color_outline"; - // this.RP_ToScreen.input_texture = "color_ssaa_super"; + this.make_RP_GaussHVandBlend(); + + // this.make_RP_ToScreen(); + // // this.RP_ToneMapToScreen.input_texture = "color_main"; + // this.RP_ToScreen.input_texture = "color_final"; + + this.make_RP_ToneMapToScreen(); + //this.RP_ToneMapToScreen.input_texture = "color_main"; + this.RP_ToneMapToScreen.input_texture = "color_final"; + //this.RP_ToneMapToScreen.input_texture = "depth_gbuff"; this.RP_GBuffer.obj_list = []; } @@ -178,7 +165,8 @@ export class RendeQuTor RenderPass.TEXTURE, null, "depth_picking", - [ { id: "color_picking", textureConfig: RenderPass.DEFAULT_R32UI_TEXTURE_CONFIG } ] + [ { id: "color_picking", textureConfig: RenderPass.DEFAULT_R32UI_TEXTURE_CONFIG, + clearColorArray: new Uint32Array([0xffffffff, 0, 0, 0]) } ] ); this.PRP_plain.view_setup = function (vport) { this.viewport = vport; }; @@ -201,7 +189,8 @@ export class RendeQuTor RenderPass.TEXTURE, null, null, - [ { id: "depthr32f_picking", textureConfig: RenderPass.FULL_FLOAT_R32F_TEXTURE_CONFIG } ] + [ { id: "depthr32f_picking", textureConfig: RenderPass.FULL_FLOAT_R32F_TEXTURE_CONFIG, + clearColorArray: new Float32Array([1, 0, 0, 0]) } ] ); this.PRP_depth2r.view_setup = function (vport) { this.viewport = vport; }; @@ -250,9 +239,9 @@ export class RendeQuTor // Viewport null, // Bind depth texture to this ID - "depthDefaultSuper", + "depth_main", // Outputs - [ { id: "color_ssaa_super", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG } ] + [ { id: "color_main", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG } ] ); this.RP_SSAA_Super.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; @@ -287,9 +276,9 @@ export class RendeQuTor // Bind depth texture to this ID null, - [ { id: "color_ssaa_down", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG } ] + [ { id: "color_main", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG } ] ); - this.RP_SSAA_Down.input_texture = "color_ssaa_super"; + this.RP_SSAA_Down.input_texture = "color_super"; this.RP_SSAA_Down.view_setup = function(vport) { this.viewport = vport; }; this.queue.pushRenderPass(this.RP_SSAA_Down); @@ -313,12 +302,38 @@ export class RendeQuTor RenderPass.SCREEN, null ); - this.RP_ToScreen.input_texture = "color_ssaa_down"; + this.RP_ToScreen.input_texture = "color_main"; this.RP_ToScreen.view_setup = function(vport) { this.viewport = vport; }; this.queue.pushRenderPass(this.RP_ToScreen); } + make_RP_ToneMapToScreen() + { + this.RP_ToneMapToScreen_mat = new CustomShaderMaterial("ToneMapping", + { MODE: 1.0, gamma: 1.0, exposure: 2.0 }); + // u_clearColor set from MeshRenderer + this.RP_ToneMapToScreen_mat.lights = false; + + let pthis = this; + + this.RP_ToneMapToScreen = new RenderPass( + RenderPass.POSTPROCESS, + function (textureMap, additionalData) {}, + function (textureMap, additionalData) { + return { material: pthis.RP_ToneMapToScreen_mat, + textures: [ textureMap[this.input_texture] ] }; + }, + function (textureMap, additionalData) {}, + RenderPass.SCREEN, + null + ); + this.RP_ToneMapToScreen.input_texture = "color_main"; + this.RP_ToneMapToScreen.view_setup = function(vport) { this.viewport = vport; }; + + this.queue.pushRenderPass(this.RP_ToneMapToScreen); + } + //============================================================================= make_RP_HighPassGaussBloom() @@ -411,7 +426,13 @@ export class RendeQuTor this.RP_GBuffer_mat.lights = false; this.RP_GBuffer_mat.side = FRONT_AND_BACK_SIDE; + this.RP_GBuffer_mat_flat = new CustomShaderMaterial("GBufferMini"); + this.RP_GBuffer_mat_flat.lights = false; + this.RP_GBuffer_mat_flat.side = FRONT_AND_BACK_SIDE; + this.RP_GBuffer_mat_flat.normalFlat = true; + let pthis = this; + let clear_arr = new Float32Array([0,0,0,0]); this.RP_GBuffer = new RenderPass( RenderPass.BASIC, @@ -420,7 +441,9 @@ export class RendeQuTor pthis.renderer._outlineEnabled = true; pthis.renderer._outlineArray = this.obj_list; pthis.renderer._defaultOutlineMat = pthis.RP_GBuffer_mat; + pthis.renderer._defaultOutlineMatFlat = pthis.RP_GBuffer_mat_flat; pthis.renderer._fillRequiredPrograms(pthis.RP_GBuffer_mat.requiredProgram(pthis.renderer)); + pthis.renderer._fillRequiredPrograms(pthis.RP_GBuffer_mat_flat.requiredProgram(pthis.renderer)); for (const o3d of this.obj_list) { if (o3d.outlineMaterial) pthis.renderer._fillRequiredPrograms(o3d.outlineMaterial.requiredProgram(pthis.renderer)); @@ -433,10 +456,12 @@ export class RendeQuTor }, RenderPass.TEXTURE, null, - "depthDefault", + "depth_gbuff", [ - {id: "normal", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG}, - {id: "viewDir", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} + {id: "normal", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG, + clearColorArray: clear_arr}, + {id: "viewDir", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG, + clearColorArray: clear_arr} ] ); this.RP_GBuffer.view_setup = function (vport) { this.viewport = vport; }; @@ -449,8 +474,8 @@ export class RendeQuTor make_RP_Outline() { this.RP_Outline_mat = new CustomShaderMaterial("outline", - { scale: 1.5*Math.E, // Math.E, - edgeColor: [0.7, 0.1, 0.5, 1.0], + { scale: 1.0, + edgeColor: [ 1.4, 0.0, 0.8, 1.0 ], _DepthThreshold: 6.0, _NormalThreshold: 0.6, // 0.4, _DepthNormalThreshold: 0.5, @@ -464,15 +489,15 @@ export class RendeQuTor function (textureMap, additionalData) {}, function (textureMap, additionalData) { return { material: pthis.RP_Outline_mat, - textures: [ textureMap["depthDefault"], textureMap["normal"], - textureMap["viewDir"], textureMap["color_ssaa_down"] ] }; + textures: [ textureMap["depth_gbuff"], textureMap["normal"], + textureMap["viewDir"] ] }; }, function (textureMap, additionalData) {}, RenderPass.TEXTURE, null, null, [ - {id: "color_outline", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} + {id: "color_outline", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} ] ); this.RP_Outline.view_setup = function (vport) { this.viewport = vport; }; @@ -482,4 +507,74 @@ export class RendeQuTor return this.RP_Outline; } + make_RP_GaussHVandBlend() + { + let pthis = this; + + this.RP_GaussH_mat = new CustomShaderMaterial("gaussBlur", {horizontal: true, power: 4.0}); + this.RP_GaussH_mat.lights = false; + + this.RP_GaussH = new RenderPass( + RenderPass.POSTPROCESS, + (textureMap, additionalData) => {}, + (textureMap, additionalData) => { + return {material: pthis.RP_GaussH_mat, textures: [textureMap["color_outline"]]}; + }, + (textureMap, additionalData) => {}, + RenderPass.TEXTURE, + null, + null, + [ + {id: "gauss_h", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} + ] + ); + this.RP_GaussH.view_setup = function (vport) { this.viewport = vport; }; + + this.RP_GaussV_mat = new CustomShaderMaterial("gaussBlur", {horizontal: false, power: 4.0}); + this.RP_GaussV_mat.lights = false; + + this.RP_GaussV = new RenderPass( + RenderPass.POSTPROCESS, + (textureMap, additionalData) => {}, + (textureMap, additionalData) => { + return {material: pthis.RP_GaussV_mat, textures: [textureMap["gauss_h"]]}; + }, + (textureMap, additionalData) => {}, + RenderPass.TEXTURE, + null, + null, + [ + {id: "gauss_hv", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} + ] + ); + this.RP_GaussV.view_setup = function (vport) { this.viewport = vport; }; + + this.RP_Blend_mat = new CustomShaderMaterial("blendingAdditive"); + this.RP_Blend_mat.lights = false; + + this.RP_Blend = new RenderPass( + RenderPass.POSTPROCESS, + (textureMap, additionalData) => {}, + (textureMap, additionalData) => { + return {material: pthis.RP_Blend_mat, + textures: [textureMap["gauss_hv"], + textureMap["color_main"]]}; + }, + (textureMap, additionalData) => {}, + // Target + RenderPass.TEXTURE, + null, + null, + [ + {id: "color_final", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} + ] + ); + this.RP_Blend.view_setup = function (vport) { this.viewport = vport; }; + + this.queue.pushRenderPass(this.RP_GaussH); + this.queue.pushRenderPass(this.RP_GaussV); + this.queue.pushRenderPass(this.RP_Blend); + + return this.RP_Blend; + } } From 3ebdf7f9a3db9417da7f4da24e34f55132e22cdf Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Thu, 29 Sep 2022 15:37:47 -0700 Subject: [PATCH 19/84] [REve] [RCore] Use reduced 32x32 vieport around mouse event for picking. --- tutorials/eve7/event_demo.C | 2 +- ui5/eve7/lib/EveElementsRCore.js | 6 +++- ui5/eve7/lib/GlViewerRCore.js | 14 +++++--- ui5/eve7/lib/RendeQuTor.js | 58 +++++++++++++++++--------------- 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/tutorials/eve7/event_demo.C b/tutorials/eve7/event_demo.C index a42c40a27583f..6d928bb34301b 100644 --- a/tutorials/eve7/event_demo.C +++ b/tutorials/eve7/event_demo.C @@ -61,7 +61,7 @@ REX::REvePointSet *getPointSet(int npoints = 2, float s=2, int color=28) ps->SetNextPoint(r.Uniform(-s,s), r.Uniform(-s,s), r.Uniform(-s,s)); ps->SetMarkerColor(color); - ps->SetMarkerSize(3+r.Uniform(1, 7)); + ps->SetMarkerSize(8 + r.Uniform(1, 8)); ps->SetMarkerStyle(4); return ps; } diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index e67d8c5b50ad0..83e69aaa4bbfa 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -704,7 +704,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) if (this.TestRnr("hit", hit, rnr_data)) return null; let col = RcCol(hit.fMarkerColor); - const msize = this.POINT_SIZE_FAC * hit.fMarkerSize; + const msize = hit.fMarkerSize; let sm = new RC.ZSpriteBasicMaterial( { SpriteMode: RC.SPRITE_SPACE_SCREEN, SpriteSize: [msize, msize], color: this.ColorBlack, @@ -729,6 +729,10 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) s.instanced = true; s.instanceCount = hit.fSize; + // Now that outline and picking shaders are setup with final pixel-size, + // scale up the main size to account for SSAA. + sm.setUniform("SpriteSize", [msize * this.POINT_SIZE_FAC, msize * this.POINT_SIZE_FAC]); + this.GetLumAlphaTexture("star5-32a.png", this.AddMapToAllMaterials.bind(this, s)); // this.GetRgbaTexture("unicorn-a.png", this.AddMapToAllMaterials.bind(this, s)); diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index b8850324293ce..d978727558c6e 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -99,7 +99,8 @@ sap.ui.define([ let gl = this.canvas.getContext("webgl2"); - this.renderer = new RC.MeshRenderer(this.canvas, RC.WEBGL2, {antialias: false, stencil: true}); + this.renderer = new RC.MeshRenderer(this.canvas, RC.WEBGL2, + { antialias: false, stencil: false }); this.renderer._logLevel = 1; this.renderer.clearColor = "#FFFFFF00"; // "#00000000"; this.renderer.addShaderLoaderUrls("rootui5sys/eve7/lib/RC/shaders"); @@ -489,9 +490,14 @@ sap.ui.define([ if (this.canvas.width <= 0 || this.canvas.height <= 0) return null; + this.rqt.pick_begin(x, y); + let state = this.rqt.pick(x, y, detect_depth); - if (state.object === null) return null; + if (state.object === null) { + this.rqt.pick_end(); + return null; + } let top_obj = state.object; while (top_obj.eve_el === undefined) @@ -503,6 +509,8 @@ sap.ui.define([ if (state.eve_el.fSecondarySelect) this.rqt.pick_instance(state); + this.rqt.pick_end(); + state.w = this.get_width();; state.h = this.get_height(); state.mouse = new RC.Vector2( ((x + 0.5) / state.w) * 2 - 1, @@ -554,8 +562,6 @@ sap.ui.define([ this.camera.aspect = w / h; - this.renderer.updateViewport(w, h); - this.rqt.updateViewport(w, h); this.controls.update(); diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index a3ff45a7cf477..a2bb366acb4bf 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -13,6 +13,10 @@ export class RendeQuTor this.camera = camera; this.queue = new RenderQueue(renderer); this.pqueue = new RenderQueue(renderer); + this.vp_w = 0; + this.vp_h = 0; + this.pick_radius = 32; + this.pick_center = 16; this.make_PRP_plain(); this.make_PRP_depth2r(); @@ -66,17 +70,15 @@ export class RendeQuTor updateViewport(w, h) { + this.vp_w = w; + this.vp_h = h; let vp = { width: w, height: h }; let rq = this.queue._renderQueue; for (let i = 0; i < rq.length; i++) { rq[i].view_setup(vp); } - rq = this.pqueue._renderQueue; - for (let i = 0; i < rq.length; i++) - { - rq[i].view_setup(vp); - } + // Picking render-passes stay constant. } render() @@ -84,9 +86,22 @@ export class RendeQuTor this.queue.render(); } + pick_begin(x, y) + { + this.camera.prePickStoreTBLR(); + this.camera.narrowProjectionForPicking(this.vp_w, this.vp_h, + this.pick_radius, this.pick_radius, + x, this.vp_h - 1 - y); + } + + pick_end() + { + this.camera.postPickRestoreTBLR(); + } + pick(x, y, detect_depth = false) { - this.renderer.pick_setup(x, y); + this.renderer.pick_setup(this.pick_center, this.pick_center); let state = this.pqueue.render(); state.x = x; @@ -95,23 +110,15 @@ export class RendeQuTor state.object = this.renderer.pickedObject3D; // console.log("RenderQuTor::pick", state); - if (detect_depth && this.renderer.pickedObject3D !== null) { - let glman = this.renderer.glManager; - let gl = this.renderer.gl; - let texref = this.pqueue._textureMap["depthr32f_picking"]; - let tex = glman.getTexture(texref); - - // console.log("Dumper:", glman, gl, texref, tex); - - const fb = gl.createFramebuffer(); - gl.bindFramebuffer(gl.FRAMEBUFFER, fb); - gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); - - let x = this.renderer._pickCoordinateX; - let y = this.renderer._canvas.height - this.renderer._pickCoordinateY; + if (detect_depth && this.renderer.pickedObject3D !== null) + { + let rdr = this.renderer; + let x = rdr._pickCoordinateX; + let y = rdr._canvas.height - rdr._pickCoordinateY; let d = new Float32Array(9); - gl.readPixels(x-1, y-1, 3, 3, gl.RED, gl.FLOAT, d); + rdr.gl.readBuffer(rdr.gl.COLOR_ATTACHMENT0); + rdr.gl.readPixels(this.pick_center - 1, this.pick_center - 1, 3, 3, gl.RED, gl.FLOAT, d); let near = this.camera.near; let far = this.camera.far; @@ -120,9 +127,6 @@ export class RendeQuTor console.log("Pick depth at", x, ",", y, ":", d); - gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); - gl.deleteFramebuffer(fb); - state.depth = d[4]; } @@ -163,12 +167,11 @@ export class RendeQuTor }, function (textureMap, additionalData) {}, RenderPass.TEXTURE, - null, + { width: this.pick_radius, height: this.pick_radius }, "depth_picking", [ { id: "color_picking", textureConfig: RenderPass.DEFAULT_R32UI_TEXTURE_CONFIG, clearColorArray: new Uint32Array([0xffffffff, 0, 0, 0]) } ] ); - this.PRP_plain.view_setup = function (vport) { this.viewport = vport; }; this.pqueue.pushRenderPass(this.PRP_plain); } @@ -187,12 +190,11 @@ export class RendeQuTor }, function (textureMap, additionalData) {}, RenderPass.TEXTURE, - null, + { width: this.pick_radius, height: this.pick_radius }, null, [ { id: "depthr32f_picking", textureConfig: RenderPass.FULL_FLOAT_R32F_TEXTURE_CONFIG, clearColorArray: new Float32Array([1, 0, 0, 0]) } ] ); - this.PRP_depth2r.view_setup = function (vport) { this.viewport = vport; }; this.pqueue.pushRenderPass(this.PRP_depth2r); } From 6f1b8ccb855a1e425acf7fb5bffd2e67b8e31411 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Fri, 30 Sep 2022 15:56:37 -0700 Subject: [PATCH 20/84] [REve] Fix gl access in pick with depthdetection. --- ui5/eve7/lib/RendeQuTor.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index a2bb366acb4bf..89454ef99f45c 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -113,12 +113,13 @@ export class RendeQuTor if (detect_depth && this.renderer.pickedObject3D !== null) { let rdr = this.renderer; + let gl = rdr.gl; let x = rdr._pickCoordinateX; let y = rdr._canvas.height - rdr._pickCoordinateY; let d = new Float32Array(9); - rdr.gl.readBuffer(rdr.gl.COLOR_ATTACHMENT0); - rdr.gl.readPixels(this.pick_center - 1, this.pick_center - 1, 3, 3, gl.RED, gl.FLOAT, d); + gl.readBuffer(rdr.gl.COLOR_ATTACHMENT0); + gl.readPixels(this.pick_center - 1, this.pick_center - 1, 3, 3, gl.RED, gl.FLOAT, d); let near = this.camera.near; let far = this.camera.far; From bd0e60e97a9e7dc943228c9a6d7ee6a5150f93a7 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 3 Oct 2022 11:36:52 -0700 Subject: [PATCH 21/84] [REve] RCore renderer unbinds the FBO when doing RTT. --- ui5/eve7/lib/RendeQuTor.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index 89454ef99f45c..86ac2d65caf95 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -114,13 +114,18 @@ export class RendeQuTor { let rdr = this.renderer; let gl = rdr.gl; + let fbm = rdr.glManager._fboManager; let x = rdr._pickCoordinateX; let y = rdr._canvas.height - rdr._pickCoordinateY; + fbm.bindFramebuffer(this.pqueue._renderTarget); + let d = new Float32Array(9); - gl.readBuffer(rdr.gl.COLOR_ATTACHMENT0); + gl.readBuffer(gl.COLOR_ATTACHMENT0); gl.readPixels(this.pick_center - 1, this.pick_center - 1, 3, 3, gl.RED, gl.FLOAT, d); + fbm.unbindFramebuffer(); + let near = this.camera.near; let far = this.camera.far; for (let i = 0; i < 9; ++i) From e99a1298ebd275f8b350ee7cade6ff3416d86c59 Mon Sep 17 00:00:00 2001 From: alja Date: Mon, 3 Oct 2022 12:19:19 -0700 Subject: [PATCH 22/84] Change algorithm for depth in pick function. --- ui5/eve7/lib/RendeQuTor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index 86ac2d65caf95..de59b7a58b0d8 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -129,7 +129,7 @@ export class RendeQuTor let near = this.camera.near; let far = this.camera.far; for (let i = 0; i < 9; ++i) - d[i] = (2.0 * near * far) / (far + near - d[i] * (far - near)); + d[i] = (near * far) / ((near - far) * d[i] + far); console.log("Pick depth at", x, ",", y, ":", d); From 8d7ca91e7d739afa9e620c23bfb2135684d75c0b Mon Sep 17 00:00:00 2001 From: alja Date: Mon, 3 Oct 2022 12:25:52 -0700 Subject: [PATCH 23/84] Rewrite camera control to use ROOT GL camBase and camTrans logic. Add control to set camera center --- ui5/eve7/lib/GlViewerRCore.js | 69 +- ui5/eve7/lib/REveCameraControls.js | 1527 +++++++++++++++------------- 2 files changed, 880 insertions(+), 716 deletions(-) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index d978727558c6e..a83af2ce6230d 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -122,8 +122,6 @@ sap.ui.define([ if (this.controller.isEveCameraPerspective()) { this.camera = new RC.PerspectiveCamera(75, w / h, 20, 4000); - this.camera.position = new RC.Vector3(-500, 0, 0); - this.camera.lookAt(new RC.Vector3(0, 0, 0), new RC.Vector3(0, 1, 0)); this.camera.isPerspectiveCamera = true; let l_int = 1.4; @@ -145,8 +143,6 @@ sap.ui.define([ else { this.camera = new RC.OrthographicCamera(-w/2, w/2, -h/2, h/2, 20, 2000); - this.camera.position = new RC.Vector3(0, 0, 50); - this.camera.lookAt(new RC.Vector3(0, 0, 0), new RC.Vector3(0, 1, 0)); this.camera.isOrthographicCamera = true; let l_int = 0.85; @@ -156,6 +152,10 @@ sap.ui.define([ // Lights are positioned in resetRenderer. } + // AMT, disable auto update in camera in order prevent reading quaternions in update of + // model view matrix in Obejct3D function updateMatrixWorld + this.camera.matrixAutoUpdate = false; + // Test objects if (this.controller.isEveCameraPerspective()) { @@ -170,6 +170,7 @@ sap.ui.define([ ss.material.lineWidth = 20.0; ss.material.color = new RC.Color(0xff0000); ss.material.emissive = new RC.Color(0x008080); + ss.pickable = true; this.scene.add(ss); } @@ -318,6 +319,25 @@ sap.ui.define([ this.controls = new RC.REveCameraControls(this.camera, this.get_view().getDomRef()); this.controls.addEventListener('change', this.render.bind(this)); + // camera center marker + let col = new RC.Color(0.5, 0, 0); + const msize = this.RQ_SSAA * 8; // marker size + let sm = new RC.ZSpriteBasicMaterial({ + SpriteMode: RC.SPRITE_SPACE_SCREEN, SpriteSize: [msize, msize], + color: this.ColorBlack, + emissive: col, + diffuse: col.clone().multiplyScalar(0.5) + } + ); + let vtx = new Float32Array(3); + vtx[0] = 0; vtx[1] = 0; vtx[2] = 0; + let s = new RC.ZSprite(null, sm); + s.instanced = false; + s.position.set(0, 0, 0); + s.visible = false; + this.scene.add(s); + this.controls.centerMarker = s; + // This will also call render(). this.resetRenderer(); } @@ -344,11 +364,7 @@ sap.ui.define([ if (this.camera.isPerspectiveCamera) { - let posC = new RC.Vector3(-0.7 * extR, 0.5 * extR, -0.7 * extR); - - this.camera.position.copy(posC); - this.camera.lookAt(new RC.Vector3(0,0,0), new RC.Vector3(0,1,0)); - + this.controls.setCamBaseMtx(new RC.Vector3(-1, 0, 0), new RC.Vector3(0, 1, 0)); //XOZ floor this.controls.screenSpacePanning = true; let lc = this.lights.children; @@ -358,14 +374,11 @@ sap.ui.define([ lc[3].position.set( extR, extR, extR); lc[4].position.set(-extR, extR, -extR); - // console.log("resetRenderer 3D scene bbox ", sbbox, ", camera_pos ", posC, ", look_at ", this.rot_center); + // console.log("resetRenderer 3D scene bbox ", sbbox, ", look_at ", this.rot_center); } else { - let posC = new RC.Vector3(0, 0, extR); - - this.camera.position.copy(posC); - + this.controls.setCamBaseMtx(new RC.Vector3(0, 0, 1), new RC.Vector3(0, 1, 0)); // XOY floor let ey = 1.02 * extV.y; let ex = ey / this.get_height() * this.get_width(); this.camera._left = -ex; @@ -386,7 +399,8 @@ sap.ui.define([ // console.log("resetRenderer 2D scene bbox ex ey", sbbox, ex, ey, ", camera_pos ", posC, ", look_at ", this.rot_center); } - this.controls.target.copy( this.rot_center ); + + this.controls.setFromBBox(sbbox); // this.composer.reset(); @@ -699,6 +713,9 @@ sap.ui.define([ if (pstate) { if (pstate.eve_el) menu.add("Browse to " + (pstate.eve_el.fName || "element"), pstate.eve_el.fElementId, this.controller.invokeBrowseOf.bind(this.controller)); + + let data = { "p": pstate, "v":this, "cctrl": this.controls}; + menu.add("Set Camera Center", data, this.setCameraCenter.bind(data)); } menu.add("Reset camera", this.resetRenderer); @@ -715,6 +732,28 @@ sap.ui.define([ menu.show(event); } + setCameraCenter(data) + { + let pthis = data.v; + + let fov_rad_half = pthis.camera.fov * 0.5 * (Math.PI/180); + let ftan = Math.tan(fov_rad_half); + let x = data.p.mouse.x * data.p.w / data.p.h * data.p.depth * ftan; + let y = data.p.mouse.y * data.p.depth * ftan; + let e = new RC.Vector4(-data.p.depth, x, y, 1); + + // console.log("picked point >>> ", x, y, data.p.depth); + // console.log("picked camera vector ", e); + // pthis.camera.testMtx.dump(); + + let mvMtx = pthis.camera.testMtx; + e.applyMatrix4(pthis.camera.testMtx); + // console.log("picked word view coordinates ", e); + + pthis.controls.setCameraCenter(e.x, e.y, e.z); + pthis.request_render(); + } + defaultContextMenuAction(arg) { console.log("GLC::defaultContextMenuAction", this, arg); diff --git a/ui5/eve7/lib/REveCameraControls.js b/ui5/eve7/lib/REveCameraControls.js index c4084dc5c85c0..e215d4c770ca4 100644 --- a/ui5/eve7/lib/REveCameraControls.js +++ b/ui5/eve7/lib/REveCameraControls.js @@ -22,1047 +22,1082 @@ // This should be further cleaned up and classed ... -import {EventDispatcher} from './RC/core/EventDispatcher.js'; -import {Vector3} from './RC/math/Vector3.js'; -import {Vector2} from './RC/math/Vector2.js'; -import {Quaternion} from './RC/math/Quaternion.js'; -import {Spherical} from './RC/math/Spherical.js'; +import { EventDispatcher } from './RC/core/EventDispatcher.js'; +import { Vector3 } from './RC/math/Vector3.js'; +import { Vector2 } from './RC/math/Vector2.js'; +import { Quaternion } from './RC/math/Quaternion.js'; +import { Spherical } from './RC/math/Spherical.js'; +import { Matrix4 } from './RC/math/Matrix4.js'; -export class REveCameraControls extends EventDispatcher -{ - constructor( object, domElement ) - { - var MOUSE = { ROTATE: 0, DOLLY: 1, PAN: 2 }; - var TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; - - super(EventDispatcher); - - this.object = object; - - this.domElement = ( domElement !== undefined ) ? domElement : document; - - // Set to false to disable this control - this.enabled = true; - // "target" sets the location of focus, where the object orbits around - this.target = new Vector3(); +export class REveCameraControls extends EventDispatcher { - // How far you can dolly in and out ( PerspectiveCamera only ) - this.minDistance = 0; - this.maxDistance = Infinity; + static matrixExtendDone = false; - // How far you can zoom in and out ( OrthographicCamera only ) - this.minZoom = 0; - this.maxZoom = Infinity; + constructor(object, domElement) { + var MOUSE = { ROTATE: 0, DOLLY: 1, PAN: 2 }; + var TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; - // How far you can orbit vertically, upper and lower limits. - // Range is 0 to Math.PI radians. - this.minPolarAngle = 0; // radians - this.maxPolarAngle = Math.PI; // radians + super(EventDispatcher); - // How far you can orbit horizontally, upper and lower limits. - // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. - this.minAzimuthAngle = - Infinity; // radians - this.maxAzimuthAngle = Infinity; // radians + if (!REveCameraControls.matrixExtendDone) { + ExtendRCMatrix(); + REveCameraControls.matrixExtendDone = true; + } - // Set to true to enable damping (inertia) - // If damping is enabled, you must call controls.update() in your animation loop - this.enableDamping = false; - this.dampingFactor = 0.05; + this.object = object; - // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. - // Set to false to disable zooming - this.enableZoom = true; - this.zoomSpeed = 1.0; + this.domElement = (domElement !== undefined) ? domElement : document; - // Set to false to disable rotating - this.enableRotate = true; - this.rotateSpeed = 1.0; + // Set to false to disable this control + this.enabled = true; + + // "target" sets the location of focus, where the object orbits around + this.target = new Vector3(); + this.cameraCenter = new Vector3(); - // Set to false to disable panning - this.enablePan = true; - this.panSpeed = 1.0; - this.screenSpacePanning = false; // if true, pan in screen-space - this.keyPanSpeed = 7.0; // pixels moved per arrow key push + // How far you can dolly in and out ( PerspectiveCamera only ) + this.minDistance = 0; + this.maxDistance = Infinity; + + // How far you can zoom in and out ( OrthographicCamera only ) + this.minZoom = 0; + this.maxZoom = Infinity; + + // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. + this.minPolarAngle = 0; // radians + this.maxPolarAngle = Math.PI; // radians + + // How far you can orbit horizontally, upper and lower limits. + // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. + this.minAzimuthAngle = - Infinity; // radians + this.maxAzimuthAngle = Infinity; // radians - // Set to true to automatically rotate around the target - // If auto-rotate is enabled, you must call controls.update() in your animation loop - this.autoRotate = false; - this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 + // Set to true to enable damping (inertia) + // If damping is enabled, you must call controls.update() in your animation loop + this.enableDamping = false; + this.dampingFactor = 0.05; - // Set to false to disable use of the keys - this.enableKeys = true; + // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. + // Set to false to disable zooming + this.enableZoom = true; + this.zoomSpeed = 1.0; - // The four arrow keys - this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; + // Set to false to disable rotating + this.enableRotate = true; + this.rotateSpeed = 1.0; - // Mouse buttons - this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN }; + // Set to false to disable panning + this.enablePan = true; + this.panSpeed = 1.0; + this.screenSpacePanning = false; // if true, pan in screen-space + this.keyPanSpeed = 7.0; // pixels moved per arrow key push - // Touch fingers - this.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN }; + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, you must call controls.update() in your animation loop + this.autoRotate = false; + this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 - // for reset - this.target0 = this.target.clone(); - this.position0 = this.object.position.clone(); - this.zoom0 = this.object.zoom; + // Set to false to disable use of the keys + this.enableKeys = true; - // - // public methods - // + // The four arrow keys + this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; - this.getPolarAngle = function () { + // Mouse buttons + this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN }; - return spherical.phi; + // Touch fingers + this.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN }; - }; + // for reset + this.target0 = this.target.clone(); + this.position0 = this.object.position.clone(); + this.zoom0 = this.object.zoom; - this.getAzimuthalAngle = function () { + // + // public methods + // + this.setCamBaseMtx = function(hAxis, vAxis) + { + camBase.identity(); - return spherical.theta; + camBase.setBaseVector(1, hAxis); + camBase.setBaseVector(3, vAxis); - }; + let y = new Vector3(); + y.crossVectors(vAxis, hAxis); + camBase.setBaseVector(2, y); + }; - this.saveState = function () { + this.setFromBBox = function (bbox) { + let bb_center = new Vector3(); + bbox.getCenter(bb_center); - scope.target0.copy( scope.target ); - scope.position0.copy( scope.object.position ); - scope.zoom0 = scope.object.zoom; + let bb_R = Math.max(bbox.min.length(), bbox.max.length()); - }; + camTrans.identity(); - this.reset = function () { + if (this.object.isPerspectiveCamera) { + let fovDefault = 30; + let fov = Math.min(fovDefault, this.object.aspect*fovDefault); + let dollyDefault = bb_R / (2.0 * Math.tan(fov * Math.PI * 0.8/ 180)); - scope.target.copy( scope.target0 ); - scope.object.position.copy( scope.position0 ); - scope.object.zoom = scope.zoom0; + camTrans.moveLF(1, dollyDefault); + } + else { + let dollyDefault = 1.25*0.5*Math.sqrt(3)*bb_R; + camTrans.moveLF(1, dollyDefault); + scope.object.updateProjectionMatrix(); + } + }; + + this.setCameraCenter = function (x, y, z) { + this.cameraCenter.set(x, y, z); + + let bt = new Matrix4(); + bt.multiplyMatrices(camBase, camTrans); + camBase.setBaseVector(4, this.cameraCenter); + let binv = camBase.clone(); + binv.getInverse(camBase); + camTrans.multiplyMatrices(binv, bt); + + if (this.centerMarker) { + this.centerMarker.position = this.cameraCenter; + this.centerMarker.visible = true; + this.centerMarker.updateMatrix(); + } + }; + + this.getPolarAngle = function () { + + return spherical.phi; + + }; + + this.getAzimuthalAngle = function () { + + return spherical.theta; + + }; + + this.saveState = function () { + + scope.target0.copy(scope.target); + scope.position0.copy(scope.object.position); + scope.zoom0 = scope.object.zoom; + + }; + + this.reset = function () { + + scope.target.copy(scope.target0); + scope.object.position.copy(scope.position0); + scope.object.zoom = scope.zoom0; + + scope.object.updateProjectionMatrix(); + scope.dispatchEvent(changeEvent); - scope.object.updateProjectionMatrix(); - scope.dispatchEvent( changeEvent ); + scope.update(); - scope.update(); + state = STATE.NONE; + + }; - state = STATE.NONE; + // osschar - need to reset internal panOffset + this.resetOrthoPanZoom = function () { + return function resetOrthoPan() { + panOffset.set(0, 0, 0); + scope.object.zoom = 0.78; // AMT default ortho camera zoom value in ROOT GL + scope.object.updateProjectionMatrix(); + zoomChanged = true; + } + }(); + + // osschar - fake mouse up event, needed for context menu on M3 down + this.resetMouseDown = function (event) { + return function resetMouseDown(event) { + onMouseUp(event); + } + }(); - }; - // osschar - need to reset internal panOffset - this.resetOrthoPanZoom = function () - { - return function resetOrthoPan() { - panOffset.set(0,0,0); - scope.object.zoom = 1; - scope.object.updateProjectionMatrix(); - zoomChanged = true; - } - }(); + this.testCameraMenu = function () { + console.log("camera test func"); + return function testCameraMenu() { + dollyIn(0.5); + } + }(); - // osschar - fake mouse up event, needed for context menu on M3 down - this.resetMouseDown = function (event) - { - return function resetMouseDown(event) { - onMouseUp(event); - } - }(); + ///////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////// + // AMT set camera matrix from two operations camBase and camTrans + this.update = function () { - // this method is exposed, but perhaps it would be better if we can make it private... - this.update = function () { + var lastPosition = new Vector3(); + var lastQuaternion = new Quaternion(); + return function update() { + // dolly scale + if (scale != 1.0) { + let b1 = camTrans.getBaseVector(1); + let b4 = camTrans.getBaseVector(4); + let orig_dot = b1.dot(b4); + let newMag = Math.sqrt(orig_dot) * scale; + b4.multiplyScalar(scale); + camTrans.setBaseVector(4, b4); + scale = 1.0; + } - var offset = new Vector3(); + // pan/ truck + if (panOffset.x || panOffset.y) { + camTrans.moveLF(2, panOffset.x); + camTrans.moveLF(3, panOffset.y); + panOffset.set(0, 0, 0); + } - // so camera.up is the orbit axis - var quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) ); - var quatInverse = quat.clone().inverse(); + let cam = new Matrix4(); + cam.multiplyMatrices(camBase, camTrans); - var lastPosition = new Vector3(); - var lastQuaternion = new Quaternion(); + // matrix needed to transform position from the picking + scope.object.testMtx = cam; - return function update() { + let eye = new Vector3(); eye.setFromMatrixPosition(cam); + let fwd = new Vector3(); fwd.setFromMatrixColumn(cam, 0); + let up = new Vector3(); up.setFromMatrixColumn(cam, 2); - var position = scope.object.position; + /* + console.log("cam", cam, camBase, camTrans); + console.log("up", up.x, up.y, up.z); + console.log("fwd", fwd.x, fwd.y, fwd.z); + console.log("eye", eye.x, eye.y, eye.z); + */ - offset.copy( position ).sub( scope.target ); + scope.object._matrix.lookAtMt(eye, fwd, up); + scope.object._matrix.setPosition(eye); - // rotate offset to "y-axis-is-up" space - offset.applyQuaternion( quat ); + // camera matrix auto update is disabled to prevent reading from quaternions + scope.object.matrixWorld.copy(scope.object.matrix); - // angle from z-axis around y-axis - spherical.setFromVector3( offset ); + // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation - if ( scope.autoRotate && state === STATE.NONE ) { + if (zoomChanged || + lastPosition.distanceToSquared(cam.getBaseVector(4)) > EPS || + 10 * (sphericalDelta.phi + sphericalDelta.theta) > EPS) { - rotateLeft( getAutoRotationAngle() ); + scope.dispatchEvent(changeEvent); - } + lastPosition.copy(cam.getBaseVector(4)); + lastQuaternion.copy(scope.object.quaternion); + zoomChanged = false; - if ( scope.enableDamping ) { + sphericalDelta.theta = 0; + sphericalDelta.phi = 0; - spherical.theta += sphericalDelta.theta * scope.dampingFactor; - spherical.phi += sphericalDelta.phi * scope.dampingFactor; + return true; + } + else { + let dp = lastPosition.distanceToSquared(cam.getBaseVector(4)); + } - } else { - spherical.theta += sphericalDelta.theta; - spherical.phi += sphericalDelta.phi; + //scope.dispatchEvent(changeEvent); - } + return true; + }; - // restrict theta to be between desired limits - spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) ); + }(); - // restrict phi to be between desired limits - spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) ); + this.dispose = function () { - spherical.makeSafe(); + scope.domElement.removeEventListener('contextmenu', onContextMenu, false); + scope.domElement.removeEventListener('mousedown', onMouseDown, false); + scope.domElement.removeEventListener('wheel', onMouseWheel, false); + scope.domElement.removeEventListener('touchstart', onTouchStart, false); + scope.domElement.removeEventListener('touchend', onTouchEnd, false); + scope.domElement.removeEventListener('touchmove', onTouchMove, false); - spherical.radius *= scale; + document.removeEventListener('mousemove', onMouseMove, false); + document.removeEventListener('mouseup', onMouseUp, false); - // restrict radius to be between desired limits - spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); + window.removeEventListener('keydown', onKeyDown, false); - // move target to panned location + //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? - if ( scope.enableDamping === true ) { + }; - scope.target.addScaledVector( panOffset, scope.dampingFactor ); + // + // internals + // - } else { + var scope = this; - scope.target.add( panOffset ); + var changeEvent = { type: 'change' }; + var startEvent = { type: 'start' }; + var endEvent = { type: 'end' }; - } + var STATE = { + NONE: - 1, + ROTATE: 0, + DOLLY: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_PAN: 4, + TOUCH_DOLLY_PAN: 5, + TOUCH_DOLLY_ROTATE: 6 + }; - offset.setFromSpherical( spherical ); + var state = STATE.NONE; - // rotate offset back to "camera-up-vector-is-up" space - offset.applyQuaternion( quatInverse ); + var EPS = 0.000001; - position.copy( scope.target ).add( offset ); + // current position in spherical coordinates + var spherical = new Spherical(); + var sphericalDelta = new Spherical(); - scope.object.lookAt( scope.target, scope.object.up ); + var camBase = new Matrix4(); + var camTrans = new Matrix4(); - if ( scope.enableDamping === true ) { + var scale = 1; + var panOffset = new Vector3(); + var zoomChanged = false; - sphericalDelta.theta *= ( 1 - scope.dampingFactor ); - sphericalDelta.phi *= ( 1 - scope.dampingFactor ); + var rotateStart = new Vector2(); + var rotateEnd = new Vector2(); + var rotateDelta = new Vector2(); - panOffset.multiplyScalar( 1 - scope.dampingFactor ); + var panStart = new Vector2(); + var panEnd = new Vector2(); + var panDelta = new Vector2(); - } else { + var dollyStart = new Vector2(); + var dollyEnd = new Vector2(); + var dollyDelta = new Vector2(); - sphericalDelta.set( 0, 0, 0 ); + function getAutoRotationAngle() { - panOffset.set( 0, 0, 0 ); + return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; - } + } - scale = 1; + function getZoomScale() { - // update condition is: - // min(camera displacement, camera rotation in radians)^2 > EPS - // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + return Math.pow(0.95, scope.zoomSpeed); - if ( zoomChanged || - lastPosition.distanceToSquared( scope.object.position ) > EPS || - 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { + } - scope.dispatchEvent( changeEvent ); + function rotateLeft(angle) { - lastPosition.copy( scope.object.position ); - lastQuaternion.copy( scope.object.quaternion ); - zoomChanged = false; + sphericalDelta.theta -= angle; - return true; + } - } + function rotateUp(angle) { - return false; + sphericalDelta.phi -= angle; - }; + } - }(); + function rotateRad(hRotate, vRotate) { - this.dispose = function () { + let fVAxisMinAngle = 0.01; + // console.log("rotate rad BEGIN hrotate = ", hRotate, ", vRotate = ", vRotate); - scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false ); - scope.domElement.removeEventListener( 'mousedown', onMouseDown, false ); - scope.domElement.removeEventListener( 'wheel', onMouseWheel, false ); + if (hRotate != 0.0) { + let fwd = camTrans.getBaseVector(1); + let lft = camTrans.getBaseVector(2); + let up = camTrans.getBaseVector(3); + let pos = camTrans.getTranslation(); - scope.domElement.removeEventListener( 'touchstart', onTouchStart, false ); - scope.domElement.removeEventListener( 'touchend', onTouchEnd, false ); - scope.domElement.removeEventListener( 'touchmove', onTouchMove, false ); + let deltaF = pos.dot(fwd); + let deltaU = pos.dot(up); - document.removeEventListener( 'mousemove', onMouseMove, false ); - document.removeEventListener( 'mouseup', onMouseUp, false ); + // up vector lock + let zdir = camBase.getBaseVector(3); + camBase.rotateIP(fwd); + let theta = Math.acos(fwd.dot(zdir)); + if (theta + hRotate < fVAxisMinAngle) + hRotate = fVAxisMinAngle - theta; + else if (theta + hRotate > Math.PI - fVAxisMinAngle) + hRotate = Math.PI - fVAxisMinAngle - theta; - window.removeEventListener( 'keydown', onKeyDown, false ); - //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? + camTrans.moveLF(1, -deltaF); + camTrans.moveLF(3, -deltaU); + camTrans.rotateLF(3, 1, hRotate); + camTrans.moveLF(3, deltaU); + camTrans.moveLF(1, deltaF); - }; + } + if (vRotate != 0.0) { + camTrans.rotatePF(1, 2, -vRotate); + } - // - // internals - // + sphericalDelta.phi = hRotate; + sphericalDelta.theta = vRotate; + } - var scope = this; + // deltaX and deltaY are in pixels; right and down are positive + var pan = function () { - var changeEvent = { type: 'change' }; - var startEvent = { type: 'start' }; - var endEvent = { type: 'end' }; + var offset = new Vector3(); - var STATE = { - NONE: - 1, - ROTATE: 0, - DOLLY: 1, - PAN: 2, - TOUCH_ROTATE: 3, - TOUCH_PAN: 4, - TOUCH_DOLLY_PAN: 5, - TOUCH_DOLLY_ROTATE: 6 - }; + return function pan(deltaX, deltaY) { + // amt, x seem to be negatd + deltaX = -deltaX; - var state = STATE.NONE; + var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - var EPS = 0.000001; + if (scope.object.isPerspectiveCamera) { - // current position in spherical coordinates - var spherical = new Spherical(); - var sphericalDelta = new Spherical(); + // perspective - var scale = 1; - var panOffset = new Vector3(); - var zoomChanged = false; + let targetDistance = 0.5 * (scope.object.far + scope.object.near) * Math.tan(0.5 * scope.object.fov * Math.PI / 180.0); - var rotateStart = new Vector2(); - var rotateEnd = new Vector2(); - var rotateDelta = new Vector2(); + // we use only clientHeight here so aspect ratio does not distort speed + let h = deltaY * targetDistance / element.clientHeight; + let w = deltaX * targetDistance / element.clientHeight; - var panStart = new Vector2(); - var panEnd = new Vector2(); - var panDelta = new Vector2(); - var dollyStart = new Vector2(); - var dollyEnd = new Vector2(); - var dollyDelta = new Vector2(); + panOffset.setX(w); + panOffset.setY(h); - function getAutoRotationAngle() { + } else if (scope.object.isOrthographicCamera) { - return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; + // orthographic + panOffset.setX(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth); + panOffset.setY(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight); + } else { - } + // camera neither orthographic nor perspective + console.warn('WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.'); + scope.enablePan = false; - function getZoomScale() { + } + scope.update(); + }; - return Math.pow( 0.95, scope.zoomSpeed ); + }(); - } + function dollyIn(dollyScale) { - function rotateLeft( angle ) { + if (scope.object.isPerspectiveCamera) { - sphericalDelta.theta -= angle; + scale /= dollyScale; - } + } else if (scope.object.isOrthographicCamera) { - function rotateUp( angle ) { + scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale)); + scope.object.updateProjectionMatrix(); + zoomChanged = true; - sphericalDelta.phi -= angle; + } else { - } + console.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.'); + scope.enableZoom = false; - var panLeft = function () { + } + scope.update(); + } - var v = new Vector3(); + function dollyOut(dollyScale) { - return function panLeft( distance, objectMatrix ) { + if (scope.object.isPerspectiveCamera) { - v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix - v.multiplyScalar( - distance ); + scale *= dollyScale; - panOffset.add( v ); + } else if (scope.object.isOrthographicCamera) { - }; + scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale)); + scope.object.updateProjectionMatrix(); + zoomChanged = true; - }(); + } else { - var panUp = function () { + console.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.'); + scope.enableZoom = false; - var v = new Vector3(); + } - return function panUp( distance, objectMatrix ) { + scope.update(); + } - if ( scope.screenSpacePanning === true ) { + // + // event callbacks - update the object state + // - v.setFromMatrixColumn( objectMatrix, 1 ); + function handleMouseDownRotate(event) { - } else { + rotateStart.set(event.clientX, event.clientY); - v.setFromMatrixColumn( objectMatrix, 0 ); - v.crossVectors( scope.object.up, v ); + } - } + function handleMouseDownDolly(event) { - v.multiplyScalar( distance ); + dollyStart.set(event.clientX, event.clientY); - panOffset.add( v ); + } - }; + function handleMouseDownPan(event) { - }(); + panStart.set(event.clientX, event.clientY); - // deltaX and deltaY are in pixels; right and down are positive - var pan = function () { + } - var offset = new Vector3(); + function handleMouseMoveRotate(event) { - return function pan( deltaX, deltaY ) { + rotateEnd.set(event.clientX, event.clientY); - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; + rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed); - if ( scope.object.isPerspectiveCamera ) { + var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - // perspective - var position = scope.object.position; - offset.copy( position ).sub( scope.target ); - var targetDistance = offset.length(); + rotateRad(-2 * Math.PI * rotateDelta.y / element.clientHeight, 2 * Math.PI * rotateDelta.x / element.clientWidth); - // half of the fov is center to top of screen - targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 ); + rotateStart.copy(rotateEnd); - // we use only clientHeight here so aspect ratio does not distort speed - panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); - panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); + scope.update(); - } else if ( scope.object.isOrthographicCamera ) { + } - // orthographic - panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix ); - panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix ); + function handleMouseMoveDolly(event) { - } else { + dollyEnd.set(event.clientX, event.clientY); - // camera neither orthographic nor perspective - console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); - scope.enablePan = false; + dollyDelta.subVectors(dollyEnd, dollyStart); - } + if (dollyDelta.y > 0) { - }; + dollyIn(getZoomScale()); - }(); + } else if (dollyDelta.y < 0) { - function dollyIn( dollyScale ) { + dollyOut(getZoomScale()); - if ( scope.object.isPerspectiveCamera ) { + } - scale /= dollyScale; + dollyStart.copy(dollyEnd); - } else if ( scope.object.isOrthographicCamera ) { + scope.update(); - scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) ); - scope.object.updateProjectionMatrix(); - zoomChanged = true; + } - } else { + function handleMouseMovePan(event) { - console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); - scope.enableZoom = false; + panEnd.set(event.clientX, event.clientY); - } + panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed); - } + pan(panDelta.x, panDelta.y); - function dollyOut( dollyScale ) { + panStart.copy(panEnd); - if ( scope.object.isPerspectiveCamera ) { + scope.update(); - scale *= dollyScale; + } - } else if ( scope.object.isOrthographicCamera ) { + function handleMouseUp( /*event*/) { - scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) ); - scope.object.updateProjectionMatrix(); - zoomChanged = true; + // no-op - } else { + } - console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); - scope.enableZoom = false; + function handleMouseWheel(event) { - } + if (event.deltaY < 0) { - } + dollyOut(getZoomScale()); - // - // event callbacks - update the object state - // + } else if (event.deltaY > 0) { - function handleMouseDownRotate( event ) { + dollyIn(getZoomScale()); - rotateStart.set( event.clientX, event.clientY ); + } - } + scope.update(); - function handleMouseDownDolly( event ) { + } - dollyStart.set( event.clientX, event.clientY ); + function handleKeyDown(event) { - } + var needsUpdate = false; - function handleMouseDownPan( event ) { + switch (event.keyCode) { - panStart.set( event.clientX, event.clientY ); + case scope.keys.UP: + pan(0, scope.keyPanSpeed); + needsUpdate = true; + break; - } + case scope.keys.BOTTOM: + pan(0, - scope.keyPanSpeed); + needsUpdate = true; + break; - function handleMouseMoveRotate( event ) { + case scope.keys.LEFT: + pan(scope.keyPanSpeed, 0); + needsUpdate = true; + break; - rotateEnd.set( event.clientX, event.clientY ); + case scope.keys.RIGHT: + pan(- scope.keyPanSpeed, 0); + needsUpdate = true; + break; - rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + } - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; + if (needsUpdate) { - rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + // prevent the browser from scrolling on cursor keys + event.preventDefault(); + // and prevent others from consuming the event + event.stopImmediatePropagation(); + scope.update(); - rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + } - rotateStart.copy( rotateEnd ); - scope.update(); + } - } + function handleTouchStartRotate(event) { - function handleMouseMoveDolly( event ) { + if (event.touches.length == 1) { - dollyEnd.set( event.clientX, event.clientY ); + rotateStart.set(event.touches[0].pageX, event.touches[0].pageY); - dollyDelta.subVectors( dollyEnd, dollyStart ); + } else { - if ( dollyDelta.y > 0 ) { + var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); + var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); - dollyIn( getZoomScale() ); + rotateStart.set(x, y); - } else if ( dollyDelta.y < 0 ) { + } - dollyOut( getZoomScale() ); + } - } + function handleTouchStartPan(event) { - dollyStart.copy( dollyEnd ); + if (event.touches.length == 1) { - scope.update(); + panStart.set(event.touches[0].pageX, event.touches[0].pageY); - } + } else { - function handleMouseMovePan( event ) { + var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); + var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); - panEnd.set( event.clientX, event.clientY ); + panStart.set(x, y); - panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + } - pan( panDelta.x, panDelta.y ); + } - panStart.copy( panEnd ); + function handleTouchStartDolly(event) { - scope.update(); + var dx = event.touches[0].pageX - event.touches[1].pageX; + var dy = event.touches[0].pageY - event.touches[1].pageY; - } + var distance = Math.sqrt(dx * dx + dy * dy); - function handleMouseUp( /*event*/ ) { + dollyStart.set(0, distance); - // no-op + } - } + function handleTouchStartDollyPan(event) { - function handleMouseWheel( event ) { + if (scope.enableZoom) handleTouchStartDolly(event); - if ( event.deltaY < 0 ) { + if (scope.enablePan) handleTouchStartPan(event); - dollyOut( getZoomScale() ); + } - } else if ( event.deltaY > 0 ) { + function handleTouchStartDollyRotate(event) { - dollyIn( getZoomScale() ); + if (scope.enableZoom) handleTouchStartDolly(event); - } + if (scope.enableRotate) handleTouchStartRotate(event); - scope.update(); + } - } + function handleTouchMoveRotate(event) { - function handleKeyDown( event ) { + if (event.touches.length == 1) { - var needsUpdate = false; + rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY); - switch ( event.keyCode ) { + } else { - case scope.keys.UP: - pan( 0, scope.keyPanSpeed ); - needsUpdate = true; - break; + var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); + var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); - case scope.keys.BOTTOM: - pan( 0, - scope.keyPanSpeed ); - needsUpdate = true; - break; + rotateEnd.set(x, y); - case scope.keys.LEFT: - pan( scope.keyPanSpeed, 0 ); - needsUpdate = true; - break; + } - case scope.keys.RIGHT: - pan( - scope.keyPanSpeed, 0 ); - needsUpdate = true; - break; + rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed); - } + var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - if ( needsUpdate ) { + rotateRad(-2 * Math.PI * rotateDelta.y / element.clientHeight, 2 * Math.PI * rotateDelta.x / element.clientWidth); - // prevent the browser from scrolling on cursor keys - event.preventDefault(); - // and prevent others from consuming the event - event.stopImmediatePropagation(); - scope.update(); + rotateStart.copy(rotateEnd); - } + } + function handleTouchMovePan(event) { - } + if (event.touches.length == 1) { - function handleTouchStartRotate( event ) { + panEnd.set(event.touches[0].pageX, event.touches[0].pageY); - if ( event.touches.length == 1 ) { + } else { - rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); + var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); - } else { + panEnd.set(x, y); - var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); - var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + } - rotateStart.set( x, y ); + panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed); - } + pan(panDelta.x, panDelta.y); - } + panStart.copy(panEnd); - function handleTouchStartPan( event ) { + } - if ( event.touches.length == 1 ) { + function handleTouchMoveDolly(event) { - panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + var dx = event.touches[0].pageX - event.touches[1].pageX; + var dy = event.touches[0].pageY - event.touches[1].pageY; - } else { + var distance = Math.sqrt(dx * dx + dy * dy); - var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); - var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + dollyEnd.set(0, distance); - panStart.set( x, y ); + dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed)); - } + dollyIn(dollyDelta.y); - } + dollyStart.copy(dollyEnd); - function handleTouchStartDolly( event ) { + } - var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; - var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + function handleTouchMoveDollyPan(event) { - var distance = Math.sqrt( dx * dx + dy * dy ); + if (scope.enableZoom) handleTouchMoveDolly(event); - dollyStart.set( 0, distance ); + if (scope.enablePan) handleTouchMovePan(event); - } + } - function handleTouchStartDollyPan( event ) { + function handleTouchMoveDollyRotate(event) { - if ( scope.enableZoom ) handleTouchStartDolly( event ); + if (scope.enableZoom) handleTouchMoveDolly(event); - if ( scope.enablePan ) handleTouchStartPan( event ); + if (scope.enableRotate) handleTouchMoveRotate(event); - } + } - function handleTouchStartDollyRotate( event ) { + function handleTouchEnd( /*event*/) { - if ( scope.enableZoom ) handleTouchStartDolly( event ); + // no-op - if ( scope.enableRotate ) handleTouchStartRotate( event ); + } - } + // + // event handlers - FSM: listen for events and reset state + // - function handleTouchMoveRotate( event ) { + function onMouseDown(event) { - if ( event.touches.length == 1 ) { + if (scope.enabled === false) return; - rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + // Prevent the browser from scrolling. - } else { + event.preventDefault(); - var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); - var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + // Manually set the focus since calling preventDefault above + // prevents the browser from setting it automatically. - rotateEnd.set( x, y ); + scope.domElement.focus ? scope.domElement.focus() : window.focus(); - } + switch (event.button) { - rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + case 0: - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; + switch (scope.mouseButtons.LEFT) { - rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + case MOUSE.ROTATE: - rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + if (event.ctrlKey || event.metaKey || event.shiftKey) { - rotateStart.copy( rotateEnd ); + if (scope.enablePan === false) return; - } + handleMouseDownPan(event); - function handleTouchMovePan( event ) { + state = STATE.PAN; - if ( event.touches.length == 1 ) { + } else { - panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + if (scope.enableRotate === false) return; - } else { + handleMouseDownRotate(event); - var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); - var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + state = STATE.ROTATE; - panEnd.set( x, y ); + } - } + break; - panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + case MOUSE.PAN: - pan( panDelta.x, panDelta.y ); + if (event.ctrlKey || event.metaKey || event.shiftKey) { - panStart.copy( panEnd ); + if (scope.enableRotate === false) return; - } + handleMouseDownRotate(event); - function handleTouchMoveDolly( event ) { + state = STATE.ROTATE; - var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; - var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + } else { - var distance = Math.sqrt( dx * dx + dy * dy ); + if (scope.enablePan === false) return; - dollyEnd.set( 0, distance ); + handleMouseDownPan(event); - dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) ); + state = STATE.PAN; - dollyIn( dollyDelta.y ); + } - dollyStart.copy( dollyEnd ); + break; - } + default: - function handleTouchMoveDollyPan( event ) { + state = STATE.NONE; - if ( scope.enableZoom ) handleTouchMoveDolly( event ); + } - if ( scope.enablePan ) handleTouchMovePan( event ); + break; - } - function handleTouchMoveDollyRotate( event ) { + case 1: - if ( scope.enableZoom ) handleTouchMoveDolly( event ); + switch (scope.mouseButtons.MIDDLE) { - if ( scope.enableRotate ) handleTouchMoveRotate( event ); + case MOUSE.DOLLY: - } + if (scope.enableZoom === false) return; - function handleTouchEnd( /*event*/ ) { + handleMouseDownDolly(event); - // no-op + state = STATE.DOLLY; - } + break; - // - // event handlers - FSM: listen for events and reset state - // - function onMouseDown( event ) { + default: - if ( scope.enabled === false ) return; + state = STATE.NONE; - // Prevent the browser from scrolling. + } - event.preventDefault(); + break; - // Manually set the focus since calling preventDefault above - // prevents the browser from setting it automatically. + case 2: - scope.domElement.focus ? scope.domElement.focus() : window.focus(); + switch (scope.mouseButtons.RIGHT) { - switch ( event.button ) { + case MOUSE.ROTATE: - case 0: + if (scope.enableRotate === false) return; - switch ( scope.mouseButtons.LEFT ) { + handleMouseDownRotate(event); - case MOUSE.ROTATE: + state = STATE.ROTATE; - if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + break; - if ( scope.enablePan === false ) return; + case MOUSE.PAN: - handleMouseDownPan( event ); + if (scope.enablePan === false) return; - state = STATE.PAN; + handleMouseDownPan(event); - } else { + state = STATE.PAN; - if ( scope.enableRotate === false ) return; + break; - handleMouseDownRotate( event ); + default: - state = STATE.ROTATE; + state = STATE.NONE; } break; - case MOUSE.PAN: + } - if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + if (state !== STATE.NONE) { - if ( scope.enableRotate === false ) return; + document.addEventListener('mousemove', onMouseMove, false); + document.addEventListener('mouseup', onMouseUp, false); - handleMouseDownRotate( event ); + scope.dispatchEvent(startEvent); - state = STATE.ROTATE; + } - } else { + } - if ( scope.enablePan === false ) return; + function onMouseMove(event) { - handleMouseDownPan( event ); + if (scope.enabled === false) return; - state = STATE.PAN; + event.preventDefault(); - } - - break; - - default: - - state = STATE.NONE; - - } - - break; - - - case 1: - - switch ( scope.mouseButtons.MIDDLE ) { + switch (state) { - case MOUSE.DOLLY: + case STATE.ROTATE: - if ( scope.enableZoom === false ) return; + if (scope.enableRotate === false) return; - handleMouseDownDolly( event ); - - state = STATE.DOLLY; + handleMouseMoveRotate(event); break; + case STATE.DOLLY: - default: - - state = STATE.NONE; - - } - - break; - - case 2: - - switch ( scope.mouseButtons.RIGHT ) { - - case MOUSE.ROTATE: - - if ( scope.enableRotate === false ) return; - - handleMouseDownRotate( event ); + if (scope.enableZoom === false) return; - state = STATE.ROTATE; + handleMouseMoveDolly(event); break; - case MOUSE.PAN: + case STATE.PAN: - if ( scope.enablePan === false ) return; + if (scope.enablePan === false) return; - handleMouseDownPan( event ); - - state = STATE.PAN; + handleMouseMovePan(event); break; - default: - - state = STATE.NONE; - - } - - break; - - } - - if ( state !== STATE.NONE ) { - - document.addEventListener( 'mousemove', onMouseMove, false ); - document.addEventListener( 'mouseup', onMouseUp, false ); - - scope.dispatchEvent( startEvent ); - - } - - } - - function onMouseMove( event ) { - - if ( scope.enabled === false ) return; - - event.preventDefault(); - - switch ( state ) { - - case STATE.ROTATE: - - if ( scope.enableRotate === false ) return; - - handleMouseMoveRotate( event ); - - break; - - case STATE.DOLLY: - - if ( scope.enableZoom === false ) return; - - handleMouseMoveDolly( event ); - - break; + } - case STATE.PAN: + } - if ( scope.enablePan === false ) return; + function onMouseUp(event) { - handleMouseMovePan( event ); + if (scope.enabled === false) return; - break; + handleMouseUp(event); - } + document.removeEventListener('mousemove', onMouseMove, false); + document.removeEventListener('mouseup', onMouseUp, false); - } + scope.dispatchEvent(endEvent); - function onMouseUp( event ) { + state = STATE.NONE; - if ( scope.enabled === false ) return; + } - handleMouseUp( event ); + function onMouseWheel(event) { - document.removeEventListener( 'mousemove', onMouseMove, false ); - document.removeEventListener( 'mouseup', onMouseUp, false ); + if (scope.enabled === false || scope.enableZoom === false || (state !== STATE.NONE && state !== STATE.ROTATE)) return; - scope.dispatchEvent( endEvent ); + event.preventDefault(); + event.stopPropagation(); - state = STATE.NONE; + scope.dispatchEvent(startEvent); - } + handleMouseWheel(event); - function onMouseWheel( event ) { + scope.dispatchEvent(endEvent); - if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return; + } - event.preventDefault(); - event.stopPropagation(); + function onKeyDown(event) { - scope.dispatchEvent( startEvent ); + if (scope.enabled === false || scope.enableKeys === false || scope.enablePan === false) return; - handleMouseWheel( event ); + handleKeyDown(event); - scope.dispatchEvent( endEvent ); + } - } + function onTouchStart(event) { - function onKeyDown( event ) { + if (scope.enabled === false) return; - if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return; + event.preventDefault(); - handleKeyDown( event ); + switch (event.touches.length) { - } + case 1: - function onTouchStart( event ) { + switch (scope.touches.ONE) { - if ( scope.enabled === false ) return; + case TOUCH.ROTATE: - event.preventDefault(); + if (scope.enableRotate === false) return; - switch ( event.touches.length ) { + handleTouchStartRotate(event); - case 1: + state = STATE.TOUCH_ROTATE; - switch ( scope.touches.ONE ) { + break; - case TOUCH.ROTATE: + case TOUCH.PAN: - if ( scope.enableRotate === false ) return; + if (scope.enablePan === false) return; - handleTouchStartRotate( event ); + handleTouchStartPan(event); - state = STATE.TOUCH_ROTATE; + state = STATE.TOUCH_PAN; - break; - - case TOUCH.PAN: + break; - if ( scope.enablePan === false ) return; + default: - handleTouchStartPan( event ); + state = STATE.NONE; - state = STATE.TOUCH_PAN; + } break; - default: + case 2: - state = STATE.NONE; + switch (scope.touches.TWO) { - } + case TOUCH.DOLLY_PAN: - break; + if (scope.enableZoom === false && scope.enablePan === false) return; - case 2: + handleTouchStartDollyPan(event); - switch ( scope.touches.TWO ) { + state = STATE.TOUCH_DOLLY_PAN; - case TOUCH.DOLLY_PAN: + break; - if ( scope.enableZoom === false && scope.enablePan === false ) return; + case TOUCH.DOLLY_ROTATE: - handleTouchStartDollyPan( event ); + if (scope.enableZoom === false && scope.enableRotate === false) return; - state = STATE.TOUCH_DOLLY_PAN; + handleTouchStartDollyRotate(event); - break; + state = STATE.TOUCH_DOLLY_ROTATE; - case TOUCH.DOLLY_ROTATE: + break; - if ( scope.enableZoom === false && scope.enableRotate === false ) return; + default: - handleTouchStartDollyRotate( event ); + state = STATE.NONE; - state = STATE.TOUCH_DOLLY_ROTATE; + } break; @@ -1070,122 +1105,212 @@ export class REveCameraControls extends EventDispatcher state = STATE.NONE; - } + } - break; + if (state !== STATE.NONE) { - default: + scope.dispatchEvent(startEvent); - state = STATE.NONE; + } - } + } - if ( state !== STATE.NONE ) { + function onTouchMove(event) { - scope.dispatchEvent( startEvent ); + if (scope.enabled === false) return; - } + event.preventDefault(); + event.stopPropagation(); - } + switch (state) { - function onTouchMove( event ) { + case STATE.TOUCH_ROTATE: - if ( scope.enabled === false ) return; + if (scope.enableRotate === false) return; - event.preventDefault(); - event.stopPropagation(); + handleTouchMoveRotate(event); - switch ( state ) { + scope.update(); - case STATE.TOUCH_ROTATE: + break; - if ( scope.enableRotate === false ) return; + case STATE.TOUCH_PAN: - handleTouchMoveRotate( event ); + if (scope.enablePan === false) return; - scope.update(); + handleTouchMovePan(event); - break; + scope.update(); - case STATE.TOUCH_PAN: + break; - if ( scope.enablePan === false ) return; + case STATE.TOUCH_DOLLY_PAN: - handleTouchMovePan( event ); + if (scope.enableZoom === false && scope.enablePan === false) return; - scope.update(); + handleTouchMoveDollyPan(event); - break; + scope.update(); - case STATE.TOUCH_DOLLY_PAN: + break; - if ( scope.enableZoom === false && scope.enablePan === false ) return; + case STATE.TOUCH_DOLLY_ROTATE: - handleTouchMoveDollyPan( event ); + if (scope.enableZoom === false && scope.enableRotate === false) return; - scope.update(); + handleTouchMoveDollyRotate(event); - break; + scope.update(); - case STATE.TOUCH_DOLLY_ROTATE: + break; - if ( scope.enableZoom === false && scope.enableRotate === false ) return; + default: - handleTouchMoveDollyRotate( event ); + state = STATE.NONE; - scope.update(); + } - break; + } - default: + function onTouchEnd(event) { - state = STATE.NONE; + if (scope.enabled === false) return; - } + handleTouchEnd(event); - } + scope.dispatchEvent(endEvent); - function onTouchEnd( event ) { + state = STATE.NONE; - if ( scope.enabled === false ) return; + } - handleTouchEnd( event ); + function onContextMenu(event) { - scope.dispatchEvent( endEvent ); + if (scope.enabled === false) return; - state = STATE.NONE; + event.preventDefault(); - } + } - function onContextMenu( event ) { + function ExtendRCMatrix() { + Matrix4.prototype.lookAtMt = function ( eye, fwd, up ) { + var _x = new Vector3(); + var _y = new Vector3(); + var _z = new Vector3(); + var te = this.elements; - if ( scope.enabled === false ) return; + _z.copy(fwd); + // _z.negate(); + _z.normalize(); + _x.crossVectors( up, _z ); + _x.normalize(); + _y.crossVectors( _z, _x ); - event.preventDefault(); + te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x; + te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y; + te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z; + + return this; + }; - } + Matrix4.prototype.getBaseVector = function (idx) { + let off = 4 * --idx; + let C = this.elements; + return new Vector3(C[off + 0], C[off + 1], C[off + 2]); + }; - // + Matrix4.prototype.getTranslation = function () { + let C = this.elements; + return new Vector3(C[12], C[13], C[14]); + }; - scope.domElement.addEventListener( 'contextmenu', onContextMenu, false ); + Matrix4.prototype.setBaseVector = function (idx, x, y, z) { + let off = 4 * --idx; + let C = this.elements; + if (x.isVector3) { + C[off + 0] = x.x; C[off + 1] = x.y; C[off + 2] = x.z; + } + else { + C[off + 0] = x; C[off + 1] = y; C[off + 2] = z; + } + }; + + Matrix4.prototype.rotateIP = function (v) { + let M = this.elements; + let r = v.clone(); + v.x = M[0] * r.x + M[4] * r.y + M[8] * r.z; + v.y = M[1] * r.x + M[5] * r.y + M[9] * r.z; + v.z = M[2] * r.x + M[6] * r.y + M[10] * r.z; + }; + + Matrix4.prototype.rotateLF = function (i1, i2, amount) { + if (i1 == i2) return; + + let cos = Math.cos(amount); let sin = Math.sin(amount); + let b1; let b2; + let C = this.elements; + i1 = (i1 - 1) * 4; + i2 = (i2 - 1) * 4; // column major + let off = 0; + for (let r = 0; r < 4; ++r, ++off) { + b1 = cos * C[i1 + off] + sin * C[i2 + off]; + b2 = cos * C[i2 + off] - sin * C[i1 + off]; + C[i1 + off] = b1; C[i2 + off] = b2; + } + }; + + Matrix4.prototype.rotatePF = function (i1, i2, amount) { + if (i1 == i2) return; + + let cos = Math.cos(amount); let sin = Math.sin(amount); + let b1; let b2; + let C = this.elements; + --i1; --i2; + for (let c = 0; c < 4; ++c) { + let off = c * 4; + b1 = cos * C[i1 + off] - sin * C[i2 + off]; + b2 = cos * C[i2 + off] + sin * C[i1 + off]; + C[i1 + off] = b1; C[i2 + off] = b2; + } + }; + + Matrix4.prototype.moveLF = function (ai, amount) { + let C = this.elements; let off = 4 * (ai - 1); + C[12] += amount * C[off]; + C[13] += amount * C[off + 1]; + C[14] += amount * C[off + 2]; + }; + + Matrix4.prototype.dump = function () { + for (let x = 0; x < 4; x++) { + let row = "[ "; + for (let y = 0; y < 4; y++) { + let val = this.elements[y * 4 + x].toFixed(2); + row += val; row += " "; + } + console.log(row + "]"); + } + } + } - scope.domElement.addEventListener( 'mousedown', onMouseDown, false ); - scope.domElement.addEventListener( 'wheel', onMouseWheel, false ); + scope.domElement.addEventListener('contextmenu', onContextMenu, false); - scope.domElement.addEventListener( 'touchstart', onTouchStart, false ); - scope.domElement.addEventListener( 'touchend', onTouchEnd, false ); - scope.domElement.addEventListener( 'touchmove', onTouchMove, false ); + scope.domElement.addEventListener('mousedown', onMouseDown, false); + scope.domElement.addEventListener('wheel', onMouseWheel, false); - scope.domElement.addEventListener( 'mouseenter', function (event) { - window.addEventListener( 'keydown', onKeyDown ); - }); - scope.domElement.addEventListener( 'mouseleave', function (event) { - window.removeEventListener( 'keydown', onKeyDown ); - }); + scope.domElement.addEventListener('touchstart', onTouchStart, false); + scope.domElement.addEventListener('touchend', onTouchEnd, false); + scope.domElement.addEventListener('touchmove', onTouchMove, false); - // force an update at start + scope.domElement.addEventListener('mouseenter', function (event) { + window.addEventListener('keydown', onKeyDown); + }); + scope.domElement.addEventListener('mouseleave', function (event) { + window.removeEventListener('keydown', onKeyDown); + }); - this.update(); + // force an update at start - } + this.update(); + } }; From 858c7d0b25ee9c9738b334773c23d4ca1b47518e Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Tue, 4 Oct 2022 15:29:57 -0700 Subject: [PATCH 24/84] [REve] Proper selection / highlight outlines, optimize buffer usage. * RendeQuTor, GlViewerRCore - deep control of rendering passes, reuse intermediate 16F buffers. - outline selection and highlight properly. - pre-download picking, gbuffer, outline shaders. * Cleanup console logs. --- ui5/eve7/lib/EveElementsRCore.js | 11 +- ui5/eve7/lib/GlViewerRCore.js | 96 ++++---- ui5/eve7/lib/RendeQuTor.js | 386 +++++++++++++++++++++---------- 3 files changed, 315 insertions(+), 178 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 83e69aaa4bbfa..9244b0be3b358 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -507,8 +507,10 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) class EveElements { - constructor(rc, viewer) { - console.log("EveElements -- RCore"); + constructor(rc, viewer) + { + if (viewer._logLevel >= 2) + console.log("EveElements -- RCore instantiated."); RC = rc; this.viewer = viewer; @@ -545,6 +547,11 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) p.drawCircles = m.drawCircles; } + RcCol(root_col) + { + return RcCol(root_col); + } + RcPointMaterial(color, opacity, point_size, props) { let mat = new RC.PointBasicMaterial; diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index a83af2ce6230d..0a5fb14aad573 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -43,7 +43,8 @@ sap.ui.define([ // import("https://desire.physics.ucsd.edu/matevz/alja.github.io/rootui5/eve7/rnr_core/RenderCore.js").then((module) => { import(window.location.origin + '/rootui5sys/eve7/lib/REveRenderCore.js').then((module) => { - console.log("GlViewerRCore.onInit - RenderCore.js loaded"); + if (this._logLevel >= 2) + console.log("GlViewerRCore.onInit - RenderCore.js loaded"); RC = module; pthis.bootstrap(); @@ -166,12 +167,11 @@ sap.ui.define([ // c.material.depthWrite = false; // this.scene.add(c); - let ss = new RC.Stripe([0,0,0, 400,0,0, 400,400,0, 400,400,400]); - ss.material.lineWidth = 20.0; - ss.material.color = new RC.Color(0xff0000); - ss.material.emissive = new RC.Color(0x008080); - ss.pickable = true; - this.scene.add(ss); + // let ss = new RC.Stripe([0,0,0, 400,0,0, 400,400,0, 400,400,400]); + // ss.material.lineWidth = 20.0; + // ss.material.color = new RC.Color(0xff0000); + // ss.material.emissive = new RC.Color(0x008080); + // this.scene.add(ss); } this.rot_center = new RC.Vector3(0,0,0); @@ -360,7 +360,8 @@ sap.ui.define([ let extV = new RC.Vector3; extV = negV; extV.negate(); extV.max(posV); let extR = extV.length(); - console.log("GlViewerRenderCore.resetRenderer", sbbox, posV, negV, extV, extR); + if (this._logLevel >= 2) + console.log("GlViewerRenderCore.resetRenderer", sbbox, posV, negV, extV, extR); if (this.camera.isPerspectiveCamera) { @@ -402,8 +403,6 @@ sap.ui.define([ this.controls.setFromBBox(sbbox); - // this.composer.reset(); - this.controls.update(); } @@ -426,24 +425,16 @@ sap.ui.define([ if (this.canvas.width <= 0 || this.canvas.height <= 0) return; - // Workaround to merge secondary-indices from multiple selections. See comments below. - let insta_map = new Map(); // Keep track of instanced-based secondary-seectables + this.rqt.render_begin(true); + + // Render outlines for active selections. for (let sel_id of this._selection_list) { let sel_entry = this._selection_map[ sel_id ]; - // Extract edge color (note, root colors), width from selection object. - // let sel_object = this.get_manager().GetElement(sel_id); - // console.log("selection", sel_object.fVisibleEdgeColor, sel_object.fHiddenEdgeColor); - - // TODO: for now we do single outline pass, merging all objects together into - // a single list. This needs to be split into actuall separate outline passes. - // Problem: an object that uses instanced rendering and secondary selection can - // be in several selections. And we use the same object with the same - // outlineMaterial (where indicies are defined as vertex-atttrib with divisor 1) for - // all of them. So the buffer needs to be set for every pass (if needed). - // In this case, we have to merge the lists (not caring if certain index appears multiple times). + let obj_list = this.rqt.RP_GBuffer.obj_list; + // let instance_list = []; for (let el_idx in sel_entry) { @@ -453,42 +444,42 @@ sap.ui.define([ // or setup secondary indices for sub-instance drawing if (el_entry.instance_object) { - if (insta_map.has(el_entry.instance_object)) - { - insta_map.get(el_entry.instance_object).push(...el_entry.instance_sec_idcs); - } - else - { - let arr = []; - arr.push(...el_entry.instance_sec_idcs); - insta_map.set(el_entry.instance_object, arr); - - this.rqt.RP_GBuffer.obj_list.push(el_entry.instance_object); - } + // instance_list.push(el_entry.instance_object); + obj_list.push(el_entry.instance_object); + el_entry.instance_object.outlineMaterial.outline_instances_setup( el_entry.instance_sec_idcs ); } else { for (let geo of el_entry.geom) { - this.rqt.RP_GBuffer.obj_list.push(geo); + obj_list.push(geo); } } } - } - // This would then be done per outline pass, if needed. Same for loop below render call. - for (const [obj, arr] of insta_map) { - obj.outlineMaterial.outline_instances_setup(arr); + if (obj_list.length == 0) + continue; + + // Extract edge color (note, root colors), width from selection object. + let sel_object = this.get_manager().GetElement(sel_id); + let c = this.creator.RcCol(sel_object.fVisibleEdgeColor); + this.rqt.RP_Outline_mat.setUniform("edgeColor", [ 2*c.r, 2*c.g, 2*c.b, 1 ]); + this.rqt.render_outline(); + + // for (const obj of instance_list) { + // obj.outlineMaterial.outline_instances_reset(); + // } + + this.rqt.RP_GBuffer.obj_list = []; } - this.rqt.render(); + this.rqt.render_main_and_blend_outline(); - for (const [obj, arr] of insta_map) { - obj.outlineMaterial.outline_instances_reset(); + if (this.rqt.queue.used_fail_count == 0) { + this.rqt.render_tone_map_to_screen(); } - this.rqt.RP_GBuffer.obj_list = []; + this.rqt.render_end(); - if (this.renderer.used == false) { - // RCRC Ideally there would be an onShadersLoaded callback. + if (this.rqt.queue.used_fail_count > 0) { if (this._logLevel >= 2) console.log("GlViewerRCore render: not all programs compiled -- setting up render timer"); setTimeout(this.render.bind(this), 200); @@ -500,7 +491,7 @@ sap.ui.define([ render_for_picking(x, y, detect_depth) { - console.log("RENDER FOR PICKING", this.scene, this.camera, this.canvas, this.renderer); + // console.log("RENDER FOR PICKING", this.scene, this.camera, this.canvas, this.renderer); if (this.canvas.width <= 0 || this.canvas.height <= 0) return null; @@ -536,7 +527,7 @@ sap.ui.define([ state.ctrl = ctrl_obj.get_ctrl(ctrl_obj, top_obj); - console.log("pick result", state); + // console.log("pick result", state); return state; } @@ -561,14 +552,15 @@ sap.ui.define([ onResizeTimeout() { - let w = this.get_width(); - let h = this.get_height(); - if ( ! this.canvas) { - console.log("GlViewerRCore onResizeTimeout", w, h, "canvas IS NOT SET, STOP CALLING ME!"); + if (this._logLevel >= 2) + console.log("GlViewerRCore onResizeTimeout -- canvas is not set yet."); return; } + let w = this.get_width(); + let h = this.get_height(); + //console.log("GlViewerRCore onResizeTimeout", w, h, "canvas=", this.canvas, this.canvas.width, this.canvas.height); this.canvas.width = w; diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index de59b7a58b0d8..8caaa95241de8 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -20,13 +20,17 @@ export class RendeQuTor this.make_PRP_plain(); this.make_PRP_depth2r(); + this.renderer.preDownloadPrograms( + [ this.PRP_depth2r_mat.requiredProgram(this.renderer) + ]); - this.SSAA_value = 1; + this.SSAA_value = 1; - const nearPlane = 0.0625; // XXXX - pass to view_setup(vport, nfclip) - const farPlane = 8192; // XXXX + this.clear_zero_f32arr = new Float32Array([0,0,0,0]); - // For every pass, store object + resize behaviour + this.std_textures = []; + this.std_tex_cnt = 0; + this.std_tex_used = new Set(); } initDirectToScreen() @@ -46,15 +50,17 @@ export class RendeQuTor this.make_RP_GaussHVandBlend(); // this.make_RP_ToScreen(); - // // this.RP_ToneMapToScreen.input_texture = "color_main"; - // this.RP_ToScreen.input_texture = "color_final"; - this.make_RP_ToneMapToScreen(); - //this.RP_ToneMapToScreen.input_texture = "color_main"; - this.RP_ToneMapToScreen.input_texture = "color_final"; - //this.RP_ToneMapToScreen.input_texture = "depth_gbuff"; this.RP_GBuffer.obj_list = []; + + this.renderer.preDownloadPrograms( + [ this.RP_GBuffer_mat.requiredProgram(this.renderer), + this.RP_Outline_mat.requiredProgram(this.renderer), + this.RP_GaussH_mat.requiredProgram(this.renderer), + this.RP_Blend_mat.requiredProgram(this.renderer), + this.RP_ToneMapToScreen_mat.requiredProgram(this.renderer) + ]); } initFull(ssaa_val) @@ -81,11 +87,138 @@ export class RendeQuTor // Picking render-passes stay constant. } + //============================================================================= + + pop_std_texture() { + let tex; + if (this.std_textures.length == 0) { + tex = "std_tex_" + this.std_tex_cnt++; + } else { + tex = this.std_textures.pop(); + } + this.std_tex_used.add(tex); + return tex; + } + + push_std_texture(tex) { + this.std_tex_used.delete(tex); + this.std_textures.push(tex); + } + + release_std_textures() { + if (this.std_tex_used.size > 0) { + // console.log("RendeQuTor releasing std textures", this.std_tex_used.size); + for (const tex of this.std_tex_used) + this.std_textures.push(tex); + this.std_tex_used.clear(); + } + } + + // ---------- + + render_outline() + { + let tex_normal = this.pop_std_texture(); + let tex_view_dir = this.pop_std_texture(); + this.RP_GBuffer.outTextures[0].id = tex_normal; + this.RP_GBuffer.outTextures[1].id = tex_view_dir; + + this.queue.render_pass(this.RP_GBuffer, "GBuffer"); + + this.RP_Outline.intex_normal = tex_normal; + this.RP_Outline.intex_view_dir = tex_view_dir; + if ( ! this.tex_outline) { + // First outline, get the texture to accumulate all outlines + this.tex_outline = this.pop_std_texture(); + } else { + // Additional outlines, do not clear the accumulatortexture. + this.RP_Outline.outTextures[0].clearColorArray = null; + } + this.RP_Outline.outTextures[0].id = this.tex_outline; + + this.queue.render_pass(this.RP_Outline, "Outline"); + + this.push_std_texture(tex_normal); + this.push_std_texture(tex_view_dir); + } + + render_main_and_blend_outline() + { + let main_is_std = (this.SSAA_value == 1); + let tex_main = main_is_std ? this.pop_std_texture() : "color_main"; + + this.RP_SSAA_Super.outTextures[0].id = tex_main; + this.queue.render_pass(this.RP_SSAA_Super, "SSAA Super"); + + if (this.tex_outline) { + let tA = this.tex_outline; + let tB = this.pop_std_texture(); + + this.RP_GaussH.intex = tA; + this.RP_GaussH.outTextures[0].id = tB; + this.queue.render_pass(this.RP_GaussH, "GaussH"); + + this.RP_GaussV.intex = tB; + this.RP_GaussV.outTextures[0].id = tA; + this.queue.render_pass(this.RP_GaussV, "GaussV"); + + this.RP_Blend.intex_outline_blurred = tA; + this.RP_Blend.intex_main = tex_main; + this.RP_Blend.outTextures[0].id = tB; + this.queue.render_pass(this.RP_Blend, "Blend"); + + if (main_is_std) this.push_std_texture(tex_main); + + this.push_std_texture(this.tex_outline); + this.RP_Outline.outTextures[0].clearColorArray = this.clear_zero_f32arr; + this.tex_outline = null; + + this.tex_final = tB; + this.tex_final_push = true; + } else { + this.tex_final = tex_main; + this.tex_final_push = main_is_std; + } + } + + render_tone_map_to_screen() + { + this.RP_ToneMapToScreen.input_texture = this.tex_final; + + this.queue.render_pass(this.RP_ToneMapToScreen, "Tone Map To Screen"); + + if (this.tex_final_push) { + this.push_std_texture(this.tex_final); + this.tex_final = null; + this.tex_final_push = null; + } + } + + render_begin(used_check) + { + this.tex_outline = null; + + this.queue.render_begin(used_check); + } + + render_end() + { + this.queue.render_end(); + this.release_std_textures(); + } + + // ---------- + render() { + // This can work for setups without outline passes -- once they are + // brought back to life. + this.queue.render(); } + //============================================================================= + pick_begin(x, y) { this.camera.prePickStoreTBLR(); @@ -131,7 +264,7 @@ export class RendeQuTor for (let i = 0; i < 9; ++i) d[i] = (near * far) / ((near - far) * d[i] + far); - console.log("Pick depth at", x, ",", y, ":", d); + // console.log("Pick depth at", x, ",", y, ":", d); state.depth = d[4]; } @@ -145,7 +278,7 @@ export class RendeQuTor if (state.object !== this.renderer.pickedObject3D) { console.error("RendeQuTor::pick_instance state mismatch", state, this.renderer.pickedObject3D); } else { - console.log("RenderQuTor::pick going for secondary select"); + // console.log("RenderQuTor::pick_instance going for secondary select"); this.renderer._pickSecondaryEnabled = true; this.pqueue.render(); @@ -162,13 +295,12 @@ export class RendeQuTor make_PRP_plain() { - var pthis = this; + let pthis = this; this.PRP_plain = new RenderPass( RenderPass.BASIC, function (textureMap, additionalData) {}, function (textureMap, additionalData) { - // pthis.renderer._specialRenderFoo = "Choopacabra"; return { scene: pthis.scene, camera: pthis.camera }; }, function (textureMap, additionalData) {}, @@ -186,7 +318,7 @@ export class RendeQuTor { this.PRP_depth2r_mat = new CustomShaderMaterial("copyDepth2RReve"); this.PRP_depth2r_mat.lights = false; - var pthis = this; + let pthis = this; this.PRP_depth2r = new RenderPass( RenderPass.POSTPROCESS, @@ -212,7 +344,7 @@ export class RendeQuTor make_RP_DirectToScreen() { - var pthis = this; + let pthis = this; this.RP_DirectToScreen = new RenderPass( RenderPass.BASIC, @@ -231,7 +363,7 @@ export class RendeQuTor make_RP_SSAA_Super() { - var pthis = this; + let pthis = this; this.RP_SSAA_Super = new RenderPass( // Rendering pass type @@ -344,90 +476,6 @@ export class RendeQuTor //============================================================================= - make_RP_HighPassGaussBloom() - { - var pthis = this; - // let hp = new CustomShaderMaterial("highPass", {MODE: HIGHPASS_MODE_BRIGHTNESS, targetColor: [0.2126, 0.7152, 0.0722], threshold: 0.75}); - let hp = new CustomShaderMaterial("highPass", { MODE: HIGHPASS_MODE_DIFFERENCE, - targetColor: [0x0/255, 0x0/255, 0xff/255], threshold: 0.1}); - console.log("XXXXXXXX", hp); - // let hp = new CustomShaderMaterial("highPassReve"); - this.RP_HighPass_mat = hp; - this.RP_HighPass_mat.lights = false; - - this.RP_HighPass = new RenderPass( - RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_HighPass_mat, textures: [textureMap["color_ssaa_super"]] }; - }, - function (textureMap, additionalData) {}, - RenderPass.TEXTURE, - null, - // XXXXXX MT: this was "dt", why not null ???? - null, // "dt", - [ {id: "color_high_pass", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] - ); - this.RP_HighPass.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; - this.queue.pushRenderPass(this.RP_HighPass); - - this.RP_Gauss1_mat = new CustomShaderMaterial("gaussBlur", {horizontal: true, power: 1.0}); - this.RP_Gauss1_mat.lights = false; - - this.RP_Gauss1 = new RenderPass( - RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_Gauss1_mat, textures: [textureMap["color_high_pass"]] }; - }, - function (textureMap, additionalData) {}, - RenderPass.TEXTURE, - null, - null, - [ {id: "color_gauss_half", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] - ); - this.RP_Gauss1.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; - this.queue.pushRenderPass(this.RP_Gauss1); - - this.RP_Gauss2_mat = new CustomShaderMaterial("gaussBlur", {horizontal: false, power: 1.0}); - this.RP_Gauss2_mat.lights = false; - - this.RP_Gauss2 = new RenderPass( - RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_Gauss2_mat, textures: [textureMap["color_gauss_half"]] }; - }, - function (textureMap, additionalData) {}, - RenderPass.TEXTURE, - null, - null, - [ {id: "color_gauss_full", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] - ); - this.RP_Gauss2.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; - this.queue.pushRenderPass(this.RP_Gauss2); - - this.RP_Bloom_mat = new CustomShaderMaterial("bloom"); - this.RP_Bloom_mat.lights = false; - - this.RP_Bloom = new RenderPass( - RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_Bloom_mat, textures: [textureMap["color_gauss_full"], textureMap["color_ssaa_super"]] }; - }, - function (textureMap, additionalData) {}, - RenderPass.TEXTURE, - null, - null, - [ {id: "color_bloom", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] - ); - this.RP_Bloom.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; - this.queue.pushRenderPass(this.RP_Bloom); - } - - //============================================================================= - make_RP_GBuffer() { this.RP_GBuffer_mat = new CustomShaderMaterial("GBufferMini"); @@ -440,7 +488,6 @@ export class RendeQuTor this.RP_GBuffer_mat_flat.normalFlat = true; let pthis = this; - let clear_arr = new Float32Array([0,0,0,0]); this.RP_GBuffer = new RenderPass( RenderPass.BASIC, @@ -467,16 +514,15 @@ export class RendeQuTor "depth_gbuff", [ {id: "normal", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG, - clearColorArray: clear_arr}, - {id: "viewDir", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG, - clearColorArray: clear_arr} + clearColorArray: this.clear_zero_f32arr}, + {id: "view_dir", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG, + clearColorArray: this.clear_zero_f32arr} ] ); this.RP_GBuffer.view_setup = function (vport) { this.viewport = vport; }; // TODO: No push, GBuffer/Outline passes should be handled separately as there can be more of them. this.queue.pushRenderPass(this.RP_GBuffer); - return this.RP_GBuffer; } make_RP_Outline() @@ -488,6 +534,7 @@ export class RendeQuTor _NormalThreshold: 0.6, // 0.4, _DepthNormalThreshold: 0.5, _DepthNormalThresholdScale: 7.0 }); + this.RP_Outline_mat.addSBFlag("DISCARD_NON_EDGE"); this.RP_Outline_mat.lights = false; let pthis = this; @@ -497,22 +544,25 @@ export class RendeQuTor function (textureMap, additionalData) {}, function (textureMap, additionalData) { return { material: pthis.RP_Outline_mat, - textures: [ textureMap["depth_gbuff"], textureMap["normal"], - textureMap["viewDir"] ] }; + textures: [ textureMap["depth_gbuff"], + textureMap[this.intex_normal], + textureMap[this.intex_view_dir] ] }; }, function (textureMap, additionalData) {}, RenderPass.TEXTURE, null, null, [ - {id: "color_outline", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} + {id: "color_outline", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG, + clearColorArray: this.clear_zero_f32arr} ] ); + this.RP_Outline.intex_normal = "normal"; + this.RP_Outline.intex_view_dir = "view_dir"; this.RP_Outline.view_setup = function (vport) { this.viewport = vport; }; // TODO: No push, GBuffer/Outline passes should be handled separately as there can be more of them. this.queue.pushRenderPass(this.RP_Outline); - return this.RP_Outline; } make_RP_GaussHVandBlend() @@ -524,11 +574,11 @@ export class RendeQuTor this.RP_GaussH = new RenderPass( RenderPass.POSTPROCESS, - (textureMap, additionalData) => {}, - (textureMap, additionalData) => { - return {material: pthis.RP_GaussH_mat, textures: [textureMap["color_outline"]]}; + function(textureMap, additionalData) {}, + function(textureMap, additionalData) { + return {material: pthis.RP_GaussH_mat, textures: [textureMap[this.intex]]}; }, - (textureMap, additionalData) => {}, + function(textureMap, additionalData) {}, RenderPass.TEXTURE, null, null, @@ -536,6 +586,7 @@ export class RendeQuTor {id: "gauss_h", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} ] ); + this.RP_GaussH.intex = "color_outline"; this.RP_GaussH.view_setup = function (vport) { this.viewport = vport; }; this.RP_GaussV_mat = new CustomShaderMaterial("gaussBlur", {horizontal: false, power: 4.0}); @@ -543,11 +594,11 @@ export class RendeQuTor this.RP_GaussV = new RenderPass( RenderPass.POSTPROCESS, - (textureMap, additionalData) => {}, - (textureMap, additionalData) => { - return {material: pthis.RP_GaussV_mat, textures: [textureMap["gauss_h"]]}; + function(textureMap, additionalData) {}, + function(textureMap, additionalData) { + return {material: pthis.RP_GaussV_mat, textures: [textureMap[this.intex]]}; }, - (textureMap, additionalData) => {}, + function(textureMap, additionalData) {}, RenderPass.TEXTURE, null, null, @@ -555,6 +606,7 @@ export class RendeQuTor {id: "gauss_hv", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} ] ); + this.RP_GaussV.intex = "gauss_h"; this.RP_GaussV.view_setup = function (vport) { this.viewport = vport; }; this.RP_Blend_mat = new CustomShaderMaterial("blendingAdditive"); @@ -562,13 +614,13 @@ export class RendeQuTor this.RP_Blend = new RenderPass( RenderPass.POSTPROCESS, - (textureMap, additionalData) => {}, - (textureMap, additionalData) => { + function(textureMap, additionalData) {}, + function(textureMap, additionalData) { return {material: pthis.RP_Blend_mat, - textures: [textureMap["gauss_hv"], - textureMap["color_main"]]}; + textures: [textureMap[this.intex_outline_blurred], + textureMap[this.intex_main]]}; }, - (textureMap, additionalData) => {}, + function(textureMap, additionalData) {}, // Target RenderPass.TEXTURE, null, @@ -577,12 +629,98 @@ export class RendeQuTor {id: "color_final", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} ] ); + this.RP_Blend.intex_outline_blurred = "gauss_hv"; + this.RP_Blend.intex_main = "color_main"; this.RP_Blend.view_setup = function (vport) { this.viewport = vport; }; this.queue.pushRenderPass(this.RP_GaussH); this.queue.pushRenderPass(this.RP_GaussV); this.queue.pushRenderPass(this.RP_Blend); + } - return this.RP_Blend; + //============================================================================= + // HighPass and Bloom + //============================================================================= + + make_RP_HighPassGaussBloom() + { + let pthis = this; + // let hp = new CustomShaderMaterial("highPass", {MODE: HIGHPASS_MODE_BRIGHTNESS, targetColor: [0.2126, 0.7152, 0.0722], threshold: 0.75}); + let hp = new CustomShaderMaterial("highPass", { MODE: HIGHPASS_MODE_DIFFERENCE, + targetColor: [0x0/255, 0x0/255, 0xff/255], threshold: 0.1}); + console.log("XXXXXXXX", hp); + // let hp = new CustomShaderMaterial("highPassReve"); + this.RP_HighPass_mat = hp; + this.RP_HighPass_mat.lights = false; + + this.RP_HighPass = new RenderPass( + RenderPass.POSTPROCESS, + function (textureMap, additionalData) {}, + function (textureMap, additionalData) { + return { material: pthis.RP_HighPass_mat, textures: [textureMap["color_ssaa_super"]] }; + }, + function (textureMap, additionalData) {}, + RenderPass.TEXTURE, + null, + // XXXXXX MT: this was "dt", why not null ???? + null, // "dt", + [ {id: "color_high_pass", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] + ); + this.RP_HighPass.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; + this.queue.pushRenderPass(this.RP_HighPass); + + this.RP_Gauss1_mat = new CustomShaderMaterial("gaussBlur", {horizontal: true, power: 1.0}); + this.RP_Gauss1_mat.lights = false; + + this.RP_Gauss1 = new RenderPass( + RenderPass.POSTPROCESS, + function (textureMap, additionalData) {}, + function (textureMap, additionalData) { + return { material: pthis.RP_Gauss1_mat, textures: [textureMap["color_high_pass"]] }; + }, + function (textureMap, additionalData) {}, + RenderPass.TEXTURE, + null, + null, + [ {id: "color_gauss_half", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] + ); + this.RP_Gauss1.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; + this.queue.pushRenderPass(this.RP_Gauss1); + + this.RP_Gauss2_mat = new CustomShaderMaterial("gaussBlur", {horizontal: false, power: 1.0}); + this.RP_Gauss2_mat.lights = false; + + this.RP_Gauss2 = new RenderPass( + RenderPass.POSTPROCESS, + function (textureMap, additionalData) {}, + function (textureMap, additionalData) { + return { material: pthis.RP_Gauss2_mat, textures: [textureMap["color_gauss_half"]] }; + }, + function (textureMap, additionalData) {}, + RenderPass.TEXTURE, + null, + null, + [ {id: "color_gauss_full", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] + ); + this.RP_Gauss2.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; + this.queue.pushRenderPass(this.RP_Gauss2); + + this.RP_Bloom_mat = new CustomShaderMaterial("bloom"); + this.RP_Bloom_mat.lights = false; + + this.RP_Bloom = new RenderPass( + RenderPass.POSTPROCESS, + function (textureMap, additionalData) {}, + function (textureMap, additionalData) { + return { material: pthis.RP_Bloom_mat, textures: [textureMap["color_gauss_full"], textureMap["color_ssaa_super"]] }; + }, + function (textureMap, additionalData) {}, + RenderPass.TEXTURE, + null, + null, + [ {id: "color_bloom", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] + ); + this.RP_Bloom.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; + this.queue.pushRenderPass(this.RP_Bloom); } } From eb24df5163a0cd3e512a60e1f62debfcca337ead Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Fri, 7 Oct 2022 13:35:08 -0700 Subject: [PATCH 25/84] Fix picking in projected polygon set. (from Matevz) --- ui5/eve7/lib/EveElementsRCore.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 9244b0be3b358..0211358cfcd66 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -1253,7 +1253,18 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } } - this.RcPickable(psp, psp_ro); + + if (psp.fPickable) { + for (let m of meshes) m.pickable = true; + } + psp_ro.get_ctrl = function (iobj, tobj) { + let octrl = new EveElemControl(iobj, tobj); + octrl.DrawForSelection = function (sec_idcs, res) { + res.geom.push(...meshes); + //res.geom.push(...tobj.children); + } + return octrl; + } return psp_ro; } From 8c5c49ecacc73c90b307a9a929747c21ef5954ea Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Fri, 7 Oct 2022 13:41:27 -0700 Subject: [PATCH 26/84] replace RC.Line with RC.Stripes in projected jets, line segments, and tracks --- ui5/eve7/lib/EveElementsRCore.js | 115 ++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 34 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 0211358cfcd66..3ce0ed77500e8 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -615,8 +615,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // let mat = new RC.MeshBasicMaterial; mat._color = color; - mat._specular = this.ColorWhite; - mat._shininess = 32; + mat._specular = new RC.Color(0.3, 0.8, 0.0); // this.ColorWhite; + mat._shininess = 64; if (opacity !== undefined && opacity < 1.0) { mat._opacity = opacity; @@ -795,30 +795,26 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) pos += 6; } - let style = (track.fLineStyle > 1) ? EVE.JSR.getSvgLineStyle(track.fLineStyle) : "", - dash = style ? style.split(",") : [], - lineMaterial; - - if (dash && (dash.length > 1)) - { - lineMaterial = this.RcLineMaterial(track_color, 1.0, track_width, { dashSize: parseInt(dash[0]), gapSize: parseInt(dash[1]) }); - } else - { - lineMaterial = this.RcLineMaterial(track_color, 1.0, track_width); - } - - let geom = new RC.Geometry(); - geom.vertices = new RC.BufferAttribute(buf, 3); - - let line = new RC.Line(geom, lineMaterial); - line.renderingPrimitive = RC.LINES; - line.lineWidth = track_width; - - // required for the dashed material - //if (dash && (dash.length > 1)) - // line.computeLineDistances(); - - //line.hightlightWidthScale = 2; + const geom = new RC.Geometry(); + geom.vertices = new RC.Float32Attribute(buf, 3); + + let line = new RC.Stripes( + { + geometry: new RC.StripesGeometry( + { + baseGeometry: geom + } + ), + material: new RC.StripesBasicMaterial( + { + baseGeometry: geom, + lineWidth: track_width, + mode: RC.STRIPE_SPACE_SCREEN, + color: track_color + } + ) + } + ); this.RcPickable(track, line); @@ -924,10 +920,41 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let mesh = new RC.Mesh(geo_body, this.RcFlatMaterial(fcol, 0.5)); mesh.material.normalFlat = true; - let line1 = new RC.Line(geo_rim, this.RcLineMaterial(lcol, 0.8, 2)); + let line1 = new RC.Stripes( + { + geometry: new RC.StripesGeometry( + { + baseGeometry: geo_rim + } + ), + material: new RC.StripesBasicMaterial( + { + baseGeometry: geo_rim, + lineWidth: 2, + mode: RC.STRIPE_SPACE_SCREEN, + color: lcol + } + ) + } + ); - let line2 = new RC.Line(geo_rays, this.RcLineMaterial(lcol, 0.8, 0.5)); - line2.renderingPrimitive = RC.LINES; + let line2 = new RC.Stripes( + { + geometry: new RC.StripesGeometry( + { + baseGeometry: geo_rays + } + ), + material: new RC.StripesBasicMaterial( + { + baseGeometry: geo_rays, + lineWidth: 1, + mode: RC.STRIPE_SPACE_SCREEN, + color: lcol + } + ) + } + ); mesh.add(line1); mesh.add(line2); @@ -1217,6 +1244,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let line_mat = this.RcLineMaterial(fcol); + let meshes = []; for (let ib_pos = 0; ib_pos < ib_len;) { if (rnr_data.idxBuff[ib_pos] == GL.TRIANGLES) @@ -1230,6 +1258,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let mesh = new RC.Mesh(geo, material); this.RcPickable(psp, mesh); psp_ro.add(mesh); + meshes.push(mesh); ib_pos += 2 + 3 * rnr_data.idxBuff[ib_pos + 1]; } @@ -1253,7 +1282,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } } - + // this.RcPickable(psp, psp_ro); + // this.RcPickable(el, psp_ro, false, null); if (psp.fPickable) { for (let m of meshes) m.pickable = true; } @@ -1283,13 +1313,30 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) buf[i] = rnr_data.vtxBuff[i]; } - let line_mat = this.RcLineMaterial(RcCol(el.fMainColor)); - let geom = new RC.Geometry(); geom.vertices = new RC.BufferAttribute(buf, 3); - let line = new RC.Line(geom, line_mat); - line.renderingPrimitive = RC.LINES; + let line_color = RcCol(el.fMainColor); + + const line = new RC.Stripes( + { + geometry: new RC.StripesGeometry( + { + baseGeometry: geom + } + ), + material: new RC.StripesBasicMaterial( + { + baseGeometry: geom, + lineWidth: el.fLineWidth, + mode: RC.STRIPE_SPACE_SCREEN, + color: line_color + } + ) + } + ); + + this.RcPickable(el, line); obj3d.add(line); From 45c1ebc7cf242c18e3d86724c26e12464620ee8d Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Fri, 7 Oct 2022 13:44:59 -0700 Subject: [PATCH 27/84] [REve] Proper setting of object matrices, comment/log cleanups. --- tutorials/eve7/event_demo.C | 13 +++++-------- ui5/eve7/lib/EveScene.js | 10 +++++++--- ui5/eve7/lib/RendeQuTor.js | 11 +++-------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/tutorials/eve7/event_demo.C b/tutorials/eve7/event_demo.C index 6d928bb34301b..a7128b05ab5eb 100644 --- a/tutorials/eve7/event_demo.C +++ b/tutorials/eve7/event_demo.C @@ -209,12 +209,14 @@ void projectScenes(bool geomp, bool eventp) } if (eventp) { + int depth = 50; for (auto &ie : eveMng->GetEventScene()->RefChildren()) { - mngRhoPhi->SetCurrentDepth(10); + mngRhoPhi->SetCurrentDepth(depth); mngRhoPhi->ImportElements(ie, rPhiEventScene); - mngRhoZ ->SetCurrentDepth(10); + mngRhoZ ->SetCurrentDepth(depth); mngRhoZ ->ImportElements(ie, rhoZEventScene); + depth -= 10; } } @@ -258,12 +260,7 @@ public: auto scene = eveMng->GetEventScene(); scene->DestroyElements(); makeEventScene(); - for (auto &ie : scene->RefChildren()) { - if (mngRhoPhi) - mngRhoPhi->ImportElements(ie, rPhiEventScene); - if (mngRhoZ) - mngRhoZ->ImportElements(ie, rhoZEventScene); - } + projectScenes(false, true); // if (++fCount % 10 == 0) printf("At event %d\n", fCount); } diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index 8cfc50410bdae..1f704325abf51 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -57,10 +57,14 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { obj3d.geo_object = elem.fMasterId || elem.fElementId; obj3d.geo_name = elem.fName; // used for highlight + obj3d.matrixAutoUpdate = false; if (elem.render_data.matrix) { - obj3d.matrixAutoUpdate = false; - obj3d.matrix.fromArray(elem.render_data.matrix); - obj3d.updateMatrixWorld(true); + if (this.mgr.is_rcore) { + obj3d.setMatrixFromArray(arr); + } else { + obj3d.matrix.fromArray(elem.render_data.matrix); + obj3d.updateMatrixWorld(true); + } } return obj3d; diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js index 8caaa95241de8..66f05a275f2c1 100644 --- a/ui5/eve7/lib/RendeQuTor.js +++ b/ui5/eve7/lib/RendeQuTor.js @@ -248,8 +248,6 @@ export class RendeQuTor let rdr = this.renderer; let gl = rdr.gl; let fbm = rdr.glManager._fboManager; - let x = rdr._pickCoordinateX; - let y = rdr._canvas.height - rdr._pickCoordinateY; fbm.bindFramebuffer(this.pqueue._renderTarget); @@ -263,18 +261,15 @@ export class RendeQuTor let far = this.camera.far; for (let i = 0; i < 9; ++i) d[i] = (near * far) / ((near - far) * d[i] + far); - - // console.log("Pick depth at", x, ",", y, ":", d); - state.depth = d[4]; + // console.log(" pick depth at", x, ",", y, ":", d); } return state; } - pick_instance(state) { - // RCRC Proto-proto-secondary-selection. Requires branch: - // https://github.com/osschar/RenderCore/tree/img-tex-cache + pick_instance(state) + { if (state.object !== this.renderer.pickedObject3D) { console.error("RendeQuTor::pick_instance state mismatch", state, this.renderer.pickedObject3D); } else { From 527f891dadf6bb2504b2a2e0f8ef355c9fe2a2c3 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Fri, 7 Oct 2022 13:53:22 -0700 Subject: [PATCH 28/84] [REve] typo fix. --- ui5/eve7/lib/EveScene.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index 1f704325abf51..f6d74db1d6070 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -60,7 +60,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { obj3d.matrixAutoUpdate = false; if (elem.render_data.matrix) { if (this.mgr.is_rcore) { - obj3d.setMatrixFromArray(arr); + obj3d.setMatrixFromArray(elem.render_data.matrix); } else { obj3d.matrix.fromArray(elem.render_data.matrix); obj3d.updateMatrixWorld(true); From 67142a69cac7adad92e0957dfd782fe42b070c9c Mon Sep 17 00:00:00 2001 From: alja Date: Mon, 10 Oct 2022 09:41:20 -0700 Subject: [PATCH 29/84] Add parameter for projection depth in the collection --- graf3d/eve7/inc/ROOT/REveDataCollection.hxx | 8 ++++++-- graf3d/eve7/inc/ROOT/REveDataProxyBuilderBase.hxx | 1 - graf3d/eve7/src/REveDataProxyBuilderBase.cxx | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/graf3d/eve7/inc/ROOT/REveDataCollection.hxx b/graf3d/eve7/inc/ROOT/REveDataCollection.hxx index ca5776243045d..20c808c490f34 100644 --- a/graf3d/eve7/inc/ROOT/REveDataCollection.hxx +++ b/graf3d/eve7/inc/ROOT/REveDataCollection.hxx @@ -116,6 +116,7 @@ class REveDataCollection : public REveElement { private: REveDataItemList* fItemList{nullptr}; + int fLayer{0}; public: typedef std::vector Ids_t; @@ -138,8 +139,11 @@ public: TClass *GetItemClass() const { return fItemClass; } - void SetItemClass(TClass *cls) { fItemClass = cls; - } + void SetItemClass(TClass *cls) { fItemClass = cls;} + + int GetLayer() const { return fLayer; } + void SetLayer(int i) { fLayer = i; } + REveDataItemList* GetItemList() {return fItemList;} void SetFilterExpr(const char* filter); diff --git a/graf3d/eve7/inc/ROOT/REveDataProxyBuilderBase.hxx b/graf3d/eve7/inc/ROOT/REveDataProxyBuilderBase.hxx index 641e0b54c8cca..3bb6ccde993d7 100644 --- a/graf3d/eve7/inc/ROOT/REveDataProxyBuilderBase.hxx +++ b/graf3d/eve7/inc/ROOT/REveDataProxyBuilderBase.hxx @@ -93,7 +93,6 @@ protected: private: REveDataCollection *m_collection{nullptr}; - float m_layer{0.}; bool m_haveWindow{false}; bool m_modelsChanged{false}; }; diff --git a/graf3d/eve7/src/REveDataProxyBuilderBase.cxx b/graf3d/eve7/src/REveDataProxyBuilderBase.cxx index 875db7cd2bb58..8f7958f27f5b8 100644 --- a/graf3d/eve7/src/REveDataProxyBuilderBase.cxx +++ b/graf3d/eve7/src/REveDataProxyBuilderBase.cxx @@ -105,7 +105,7 @@ void REveDataProxyBuilderBase::Build() { REveProjectionManager *pmgr = projectedProduct->GetManager(); Float_t oldDepth = pmgr->GetCurrentDepth(); - pmgr->SetCurrentDepth(m_layer); + pmgr->SetCurrentDepth(m_collection->GetLayer()); Int_t cnt = 0; REveElement *projectedProductAsElement = projectedProduct->GetProjectedAsElement(); // printf("projectedProduct children %d, product children %d\n", projectedProductAsElement->NumChildren(), product->NumChildren()); From 4e41fd00080a37cc2c1446235be17dd1f4cba0b6 Mon Sep 17 00:00:00 2001 From: alja Date: Mon, 10 Oct 2022 11:16:44 -0700 Subject: [PATCH 30/84] Add datGUI to set backgroundcolor --- ui5/eve7/eve.mjs | 1 + ui5/eve7/lib/GlViewerRCore.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/ui5/eve7/eve.mjs b/ui5/eve7/eve.mjs index 046bf47e27379..80da8aae61ce3 100644 --- a/ui5/eve7/eve.mjs +++ b/ui5/eve7/eve.mjs @@ -14,6 +14,7 @@ function initEVE(source_dir) { import(mpath+'base/colors.mjs'), import(mpath+'base/base3d.mjs'), import(mpath+'geom/geobase.mjs'), + import(mpath+'gui/dat.gui.mjs'), import(mpath+'geom/TGeoPainter.mjs')]) .then(arr => { globalThis.THREE = Object.assign({}, arr.shift()); diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 0a5fb14aad573..157939a1b854f 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -6,6 +6,7 @@ sap.ui.define([ "use strict"; let RC, RP, RendeQuTor; + let datGUI; class GlViewerRCore extends GlViewer { @@ -49,6 +50,10 @@ sap.ui.define([ RC = module; pthis.bootstrap(); }); + + if (!datGUI) { + datGUI = new EVE.JSR.gui.GUI(); + } } bootstrap() @@ -108,6 +113,19 @@ sap.ui.define([ this.renderer.addShaderLoaderUrls("rootui5sys/eve7/shaders"); this.renderer.pickObject3D = true; + // add dat GUI option to set background + let vd = this.controller.getView().getViewData(); + let name = vd.mgr.GetElement(vd.eveViewerId).fName; + name = name.substring(0,3); + let parName = name + "_WhiteBG"; + let conf = {}; conf[parName] = true; + let pr = this; + datGUI.add(conf, parName).onChange(function (wbg) { + conf[parName] = wbg; + pr.renderer.clearColor = wbg ? "#FFFFFF00" : "#00000000"; + pr.request_render(); + }); + this.scene = new RC.Scene(); this.lights = new RC.Group; From 6bff89736e71f686f35d66b746b25a5afc9e3fa0 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 10 Oct 2022 11:55:41 -0700 Subject: [PATCH 31/84] [REve] RCore Add picking and outline materials for Stripes. --- ui5/eve7/lib/EveElementsRCore.js | 115 +++++++++++-------------------- ui5/eve7/lib/GlViewerRCore.js | 2 +- 2 files changed, 42 insertions(+), 75 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 3ce0ed77500e8..0cc02b1eade34 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -629,6 +629,39 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return mat; } + RcMakeStripes(geom, line_width, line_color) + { + return new RC.Stripes( + { geometry: new RC.StripesGeometry({ baseGeometry: geom }), + material: new RC.StripesBasicMaterial({ + baseGeometry: geom, mode: RC.STRIPE_SPACE_SCREEN, + lineWidth: line_width, color: line_color}) + } + ); + } + + RcApplyStripesMaterials(eve_el, stripes) + { + if (eve_el.fPickable) { + let m = stripes.material; + stripes.pickingMaterial = new RC.StripesBasicMaterial( + { lineWidth: m.lineWidth, mode: m.mode, color: m.color }); + let pm = stripes.pickingMaterial; + pm.addSBFlag("PICK_MODE_UINT"); + pm.prevVertex = m.prevVertex; + pm.nextVertex = m.nextVertex; + pm.deltaOffset = m.deltaOffset; + + stripes.outlineMaterial = new RC.StripesBasicMaterial( + { lineWidth: m.lineWidth, mode: m.mode, color: m.color }); + let om = stripes.outlineMaterial; + om.programName = "custom_GBufferMini_stripes"; + om.prevVertex = m.prevVertex; + om.nextVertex = m.nextVertex; + om.deltaOffset = m.deltaOffset; + } + } + RcPickable(el, obj3d, do_children = true, ctrl_class = EveElemControl) { if (el.fPickable) { @@ -785,7 +818,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) buf[pos + 3] = rnr_data.vtxBuff[k * 3]; buf[pos + 4] = rnr_data.vtxBuff[k * 3 + 1]; buf[pos + 5] = rnr_data.vtxBuff[k * 3 + 2]; - } else + } + else { buf[pos + 3] = rnr_data.vtxBuff[k * 3 + 3]; buf[pos + 4] = rnr_data.vtxBuff[k * 3 + 4]; @@ -798,24 +832,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) const geom = new RC.Geometry(); geom.vertices = new RC.Float32Attribute(buf, 3); - let line = new RC.Stripes( - { - geometry: new RC.StripesGeometry( - { - baseGeometry: geom - } - ), - material: new RC.StripesBasicMaterial( - { - baseGeometry: geom, - lineWidth: track_width, - mode: RC.STRIPE_SPACE_SCREEN, - color: track_color - } - ) - } - ); - + const line = this.RcMakeStripes(geom, track_width, track_color); + this.RcApplyStripesMaterials(track, line); this.RcPickable(track, line); return line; @@ -920,42 +938,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let mesh = new RC.Mesh(geo_body, this.RcFlatMaterial(fcol, 0.5)); mesh.material.normalFlat = true; - let line1 = new RC.Stripes( - { - geometry: new RC.StripesGeometry( - { - baseGeometry: geo_rim - } - ), - material: new RC.StripesBasicMaterial( - { - baseGeometry: geo_rim, - lineWidth: 2, - mode: RC.STRIPE_SPACE_SCREEN, - color: lcol - } - ) - } - ); - - let line2 = new RC.Stripes( - { - geometry: new RC.StripesGeometry( - { - baseGeometry: geo_rays - } - ), - material: new RC.StripesBasicMaterial( - { - baseGeometry: geo_rays, - lineWidth: 1, - mode: RC.STRIPE_SPACE_SCREEN, - color: lcol - } - ) - } - ); - + let line1 = this.RcMakeStripes(geo_rim, 2, lcol); + let line2 = this.RcMakeStripes(geo_rays, 1, lcol); mesh.add(line1); mesh.add(line2); this.RcPickable(jet, mesh, false); @@ -1318,25 +1302,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let line_color = RcCol(el.fMainColor); - const line = new RC.Stripes( - { - geometry: new RC.StripesGeometry( - { - baseGeometry: geom - } - ), - material: new RC.StripesBasicMaterial( - { - baseGeometry: geom, - lineWidth: el.fLineWidth, - mode: RC.STRIPE_SPACE_SCREEN, - color: line_color - } - ) - } - ); - - + const line = this.Rc.MakeStripes(geom, el.fLineWidth, line_color); + this.RcApplyStripesMaterials(el, line); this.RcPickable(el, line); obj3d.add(line); diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 157939a1b854f..0ec3b3fe58ffa 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -107,7 +107,7 @@ sap.ui.define([ this.renderer = new RC.MeshRenderer(this.canvas, RC.WEBGL2, { antialias: false, stencil: false }); - this.renderer._logLevel = 1; + this.renderer._logLevel = 0; this.renderer.clearColor = "#FFFFFF00"; // "#00000000"; this.renderer.addShaderLoaderUrls("rootui5sys/eve7/lib/RC/shaders"); this.renderer.addShaderLoaderUrls("rootui5sys/eve7/shaders"); From fc8d7226120b51a59579ff02ce4872a7a51ee080 Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Mon, 10 Oct 2022 16:03:58 -0700 Subject: [PATCH 32/84] Comment debug prints. Make calo2D opaque. --- ui5/eve7/lib/EveElementsRCore.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 0cc02b1eade34..dd412d0b752ae 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -635,7 +635,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) { geometry: new RC.StripesGeometry({ baseGeometry: geom }), material: new RC.StripesBasicMaterial({ baseGeometry: geom, mode: RC.STRIPE_SPACE_SCREEN, - lineWidth: line_width, color: line_color}) + lineWidth: line_width * this.LINE_WIDTH_FAC, + color: line_color}) } ); } @@ -1139,7 +1140,6 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let slice = ci[x * 2]; let sliceColor = calo2D.sliceColors[slice]; let tc = RcCol(sliceColor); - console.log() for (let i = 0; i < 4; ++i) { colBuff[off] = tc.r; colBuff[off + 1] = tc.g; @@ -1152,7 +1152,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } - let mat = this.RcFlatMaterial(this.ColorBlack,0.5); + let mat = this.RcFlatMaterial(this.ColorBlack, 1); mat.useVertexColors = true; let mesh = new RC.Mesh(body, mat); @@ -1287,7 +1287,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) makeStraightLineSet(el, rnr_data) { - console.log("makeStraightLineSet ..."); + // console.log("makeStraightLineSet ..."); let obj3d = new RC.Group(); @@ -1302,7 +1302,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let line_color = RcCol(el.fMainColor); - const line = this.Rc.MakeStripes(geom, el.fLineWidth, line_color); + const line = this.RcMakeStripes(geom, el.fLineWidth, line_color); this.RcApplyStripesMaterials(el, line); this.RcPickable(el, line); obj3d.add(line); From edd115ddc76c96fb60f12ae99fca7cf3d11cdc24 Mon Sep 17 00:00:00 2001 From: alja Date: Tue, 11 Oct 2022 20:46:03 +0200 Subject: [PATCH 33/84] Use EVE.JSR.source_dir instead of window.location for the RC import path. This is needed in case of client versioning and virtual hosts --- ui5/eve7/lib/GlViewerRCore.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 0ec3b3fe58ffa..b3ec52ce2cfc9 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -43,7 +43,10 @@ sap.ui.define([ // // console.log(window.location.pathname); // where are we loading from? // import("https://desire.physics.ucsd.edu/matevz/alja.github.io/rootui5/eve7/rnr_core/RenderCore.js").then((module) => { - import(window.location.origin + '/rootui5sys/eve7/lib/REveRenderCore.js').then((module) => { + let sp = EVE.JSR.source_dir; + let rp = sp.substring(0, sp.length - 10); // take out 'jsrootsys' to replace it with 'rootui5sys' + rp += 'rootui5sys/eve7/lib/REveRenderCore.js'; + import(rp).then((module) => { if (this._logLevel >= 2) console.log("GlViewerRCore.onInit - RenderCore.js loaded"); From 23af483768da9e803d6989d39f0688edae90669d Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Thu, 13 Oct 2022 15:49:49 -0700 Subject: [PATCH 34/84] [REve] RCore Stripes picker is now in GBuffer_mini shader. --- ui5/eve7/lib/EveElementsRCore.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index dd412d0b752ae..ed0a0154c2349 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -648,6 +648,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) stripes.pickingMaterial = new RC.StripesBasicMaterial( { lineWidth: m.lineWidth, mode: m.mode, color: m.color }); let pm = stripes.pickingMaterial; + pm.programName = "custom_GBufferMini_stripes"; pm.addSBFlag("PICK_MODE_UINT"); pm.prevVertex = m.prevVertex; pm.nextVertex = m.nextVertex; From 5a53ce25cca6759dc46cd01980a94d43f4d32754 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Wed, 19 Oct 2022 13:17:43 -0700 Subject: [PATCH 35/84] [REve RCore] Use emissive color for Stripes / tracks. --- ui5/eve7/lib/EveElementsRCore.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index ed0a0154c2349..f6a7364067115 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -631,14 +631,18 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) RcMakeStripes(geom, line_width, line_color) { - return new RC.Stripes( + let s = new RC.Stripes( { geometry: new RC.StripesGeometry({ baseGeometry: geom }), material: new RC.StripesBasicMaterial({ baseGeometry: geom, mode: RC.STRIPE_SPACE_SCREEN, lineWidth: line_width * this.LINE_WIDTH_FAC, - color: line_color}) + color: this.ColorBlack, + emissive: line_color + }) } ); + s.lights = false; + return s; } RcApplyStripesMaterials(eve_el, stripes) From f7409c9eef66846fca60bc1cfb866f44d456a752 Mon Sep 17 00:00:00 2001 From: alja Date: Wed, 19 Oct 2022 11:57:29 -0700 Subject: [PATCH 36/84] Add initialization for empty 3D and 2D calorimters --- ui5/eve7/lib/EveElementsRCore.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index f6a7364067115..9bfb4e900253d 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -1098,9 +1098,14 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } body.vertColor = new RC.BufferAttribute(colBuff, 4); } + else + { + body.indices = new RC.BufferAttribute(new Uint32Array(0), 1); + body.vertices = new RC.BufferAttribute(new Float32Array(0), 3); + body.vertColor = new RC.BufferAttribute(new Float32Array, 4); + } let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); - //let mat = this.RcFlatMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); mat.useVertexColors = true; mat.normalFlat = true; @@ -1155,7 +1160,12 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } body.vertColor = new RC.BufferAttribute(colBuff, 4); } - + else + { + body.indices = new RC.BufferAttribute(new Uint32Array(0), 1); + body.vertices = new RC.BufferAttribute(new Float32Array(0), 3); + body.vertColor = new RC.BufferAttribute(new Float32Array, 4); + } let mat = this.RcFlatMaterial(this.ColorBlack, 1); mat.useVertexColors = true; @@ -1179,8 +1189,11 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let geo = new RC.Geometry(); geo.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); - geo.indices = new RC.BufferAttribute(rnr_data.idxBuff, 1); - geo.setDrawRange(2, nVert); + let ib = rnr_data.idxBuff; + geo.indices = new RC.BufferAttribute( + new Uint32Array(ib.buffer, ib.byteOffset + 8, nVert), + 1); + if (compute_normals) { geo.computeVertexNormalsIdxRange(2, nVert); } From 70c984cb6afc49470d3994f85294ae3f3065dbe6 Mon Sep 17 00:00:00 2001 From: alja Date: Thu, 20 Oct 2022 12:54:56 -0700 Subject: [PATCH 37/84] Reposition dat GUI --- ui5/eve7/css/eve.css | 7 ++++++- ui5/eve7/lib/GlViewerRCore.js | 8 ++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ui5/eve7/css/eve.css b/ui5/eve7/css/eve.css index 9d06f2881673d..b12df129e2562 100644 --- a/ui5/eve7/css/eve.css +++ b/ui5/eve7/css/eve.css @@ -82,7 +82,12 @@ white-space: pre; } +#posDatGUI +{ + position: relative; + float: right; +} .eveNoSelectionCheckBox .sapMLIBSelectM { display: none; -} \ No newline at end of file +} diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index b3ec52ce2cfc9..cfe149ad69876 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -55,7 +55,11 @@ sap.ui.define([ }); if (!datGUI) { - datGUI = new EVE.JSR.gui.GUI(); + datGUI = new EVE.JSR.gui.GUI({ autoPlace: false, width: 220 }); + datGUI.domElement.id = 'posDatGUI'; + pthis.datGUIFolder = datGUI.addFolder("background") + let dome = this.controller.getView().getParent().getParent(); + dome.getDomRef().appendChild(datGUI.domElement); } } @@ -123,7 +127,7 @@ sap.ui.define([ let parName = name + "_WhiteBG"; let conf = {}; conf[parName] = true; let pr = this; - datGUI.add(conf, parName).onChange(function (wbg) { + datGUI.__folders.background.add(conf, parName).onChange(function (wbg) { conf[parName] = wbg; pr.renderer.clearColor = wbg ? "#FFFFFF00" : "#00000000"; pr.request_render(); From 729bdc267c8b60ed7c3551e0cd5ceaa9fb1fdcad Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Thu, 20 Oct 2022 14:51:08 -0700 Subject: [PATCH 38/84] Print missing dispose function warnings only for three.js implementation --- ui5/eve7/lib/EveScene.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index f6d74db1d6070..5184dcd717219 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -261,10 +261,12 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { this.id2obj_map.delete(elId); - if (typeof obj3d.dispose !== 'function') - console.log("EveScene.elementsRemoved no dispose function for " + this.mgr.GetElement(elId)._typename, ", rnr obj ", obj3d._typename, obj3d); - else - obj3d.dispose(); + if (!this.mgr.is_rcore) { + if (typeof obj3d.dispose !== 'function') + console.log("EveScene.elementsRemoved no dispose function for " + this.mgr.GetElement(elId)._typename, ", rnr obj ", obj3d._typename, obj3d); + else + obj3d.dispose(); + } } } From 7eb2fb3715e1d874ea0adf5210182d1b3cf32309 Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Fri, 21 Oct 2022 10:33:55 -0700 Subject: [PATCH 39/84] Ajust near camera clip to camera look at distance --- ui5/eve7/lib/REveCameraControls.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui5/eve7/lib/REveCameraControls.js b/ui5/eve7/lib/REveCameraControls.js index e215d4c770ca4..1139ef74cb8c8 100644 --- a/ui5/eve7/lib/REveCameraControls.js +++ b/ui5/eve7/lib/REveCameraControls.js @@ -244,10 +244,13 @@ export class REveCameraControls extends EventDispatcher { let b1 = camTrans.getBaseVector(1); let b4 = camTrans.getBaseVector(4); let orig_dot = b1.dot(b4); - let newMag = Math.sqrt(orig_dot) * scale; + let lookAtDist = Math.sqrt(orig_dot); + let newMag = Math.sqrt(lookAtDist) * scale; b4.multiplyScalar(scale); camTrans.setBaseVector(4, b4); scale = 1.0; + + scope.object.near = Math.min(lookAtDist*0.1, 20); } // pan/ truck From 602e7366e8af14724d8a270b68ca0bfab2dbe239 Mon Sep 17 00:00:00 2001 From: alja Date: Wed, 26 Oct 2022 13:24:49 -0700 Subject: [PATCH 40/84] Remove wrap attribute from FlexBox --- ui5/eve7/view/Summary.view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui5/eve7/view/Summary.view.xml b/ui5/eve7/view/Summary.view.xml index f20c20e4bb628..4905b11a369ec 100644 --- a/ui5/eve7/view/Summary.view.xml +++ b/ui5/eve7/view/Summary.view.xml @@ -4,7 +4,7 @@ xmlns:l="sap.ui.layout" xmlns="sap.m" class="sapUiSizeCompact"> - + From 7813da589720a6199e0915a550ed406e59d79a01 Mon Sep 17 00:00:00 2001 From: alja Date: Wed, 26 Oct 2022 13:28:01 -0700 Subject: [PATCH 41/84] Use zsprite for straight line markers --- graf3d/eve7/src/REveStraightLineSet.cxx | 8 ++ ui5/eve7/lib/EveElementsRCore.js | 109 ++++++++++++------------ 2 files changed, 63 insertions(+), 54 deletions(-) diff --git a/graf3d/eve7/src/REveStraightLineSet.cxx b/graf3d/eve7/src/REveStraightLineSet.cxx index dac4393604e8b..8556a6901156c 100644 --- a/graf3d/eve7/src/REveStraightLineSet.cxx +++ b/graf3d/eve7/src/REveStraightLineSet.cxx @@ -11,6 +11,7 @@ #include #include +#include #include #include "TClass.h" @@ -170,6 +171,13 @@ Int_t REveStraightLineSet::WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) j["fMarkerStyle"] = fMarkerStyle; j["fSecondarySelect"] = fAlwaysSecSelect; + if (fMarkerSize && gEve->IsRCore()) { + int x, y; + int ms = fMarkerPlex.Size(); + REveRenderData::CalcTextureSize(ms, 1, x, y); + j["fTexX"] = x; + j["fTexY"] = y; + } return ret; } diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 9bfb4e900253d..6eb93061806da 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -629,6 +629,38 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return mat; } + RcMakeZSprite(colIdx, sSize, nInstance, vbuff, instX, instY, textureName) + { + let col = RcCol(colIdx); + let sm = new RC.ZSpriteBasicMaterial( { + SpriteMode: RC.SPRITE_SPACE_SCREEN, SpriteSize: [sSize, sSize], + color: this.ColorBlack, + emissive: col, + diffuse: col.clone().multiplyScalar(0.5) } ); + sm.transparent = true; + + sm.addInstanceData(new RC.Texture(vbuff, + RC.Texture.ClampToEdgeWrapping, RC.Texture.ClampToEdgeWrapping, + RC.Texture.NearestFilter, RC.Texture.NearestFilter, + // RC.Texture.R32F, RC.Texture.R32F, RC.Texture.FLOAT, + RC.Texture.RGBA32F, RC.Texture.RGBA, RC.Texture.FLOAT, + instX, instY)); + sm.instanceData[0].flipy = false; + + let s = new RC.ZSprite(null, sm); + s.frustumCulled = false; // need a way to speciy bounding box/sphere !!! + s.instanced = true; + s.instanceCount = nInstance; + + // Now that outline and picking shaders are setup with final pixel-size, + // scale up the main size to account for SSAA. + sm.setUniform("SpriteSize", [sSize * this.POINT_SIZE_FAC, sSize * this.POINT_SIZE_FAC]); + + this.GetLumAlphaTexture(textureName, this.AddMapToAllMaterials.bind(this, s)); + + return s; + } + RcMakeStripes(geom, line_width, line_color) { let s = new RC.Stripes( @@ -749,38 +781,9 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) { if (this.TestRnr("hit", hit, rnr_data)) return null; - let col = RcCol(hit.fMarkerColor); - const msize = hit.fMarkerSize; - let sm = new RC.ZSpriteBasicMaterial( { - SpriteMode: RC.SPRITE_SPACE_SCREEN, SpriteSize: [msize, msize], - color: this.ColorBlack, - emissive: col, - diffuse: col.clone().multiplyScalar(0.5) } ); - sm.transparent = true; - // sm.depthWrite = false; - // this.GetLumAlphaTexture("star5-32a.png", (tex) => { - // sm.addMap(tex); - // }); - - sm.addInstanceData(new RC.Texture(rnr_data.vtxBuff, - RC.Texture.ClampToEdgeWrapping, RC.Texture.ClampToEdgeWrapping, - RC.Texture.NearestFilter, RC.Texture.NearestFilter, - // RC.Texture.R32F, RC.Texture.R32F, RC.Texture.FLOAT, - RC.Texture.RGBA32F, RC.Texture.RGBA, RC.Texture.FLOAT, - hit.fTexX, hit.fTexY)); - sm.instanceData[0].flipy = false; - - let s = new RC.ZSprite(null, sm); - s.frustumCulled = false; // need a way to speciy bounding box/sphere !!! - s.instanced = true; - s.instanceCount = hit.fSize; - - // Now that outline and picking shaders are setup with final pixel-size, - // scale up the main size to account for SSAA. - sm.setUniform("SpriteSize", [msize * this.POINT_SIZE_FAC, msize * this.POINT_SIZE_FAC]); - - this.GetLumAlphaTexture("star5-32a.png", this.AddMapToAllMaterials.bind(this, s)); - // this.GetRgbaTexture("unicorn-a.png", this.AddMapToAllMaterials.bind(this, s)); + let s = this.RcMakeZSprite(hit.fMarkerColor, hit.fMarkerSize, hit.fSize, + rnr_data.vtxBuff, hit.fTexX, hit.fTexY, + "star5-32a.png"); this.RcPickable(hit, s); @@ -1327,29 +1330,27 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // ---------------- DUH, could share buffer attribute. XXXXX - let msize = el.fMarkerPlexSize; - - let p_buf = new Float32Array(msize * 3); - - let startIdx = el.fLinePlexSize * 6; - let endIdx = startIdx + msize * 3; - for (let i = startIdx; i < endIdx; ++i) - { - p_buf[i] = rnr_data.vtxBuff[i]; + if (el.fMarkerPlexSize) { + let nPnts = el.fMarkerPlexSize; + let off = el.fLinePlexSize * 6; + let p_buf = new Float32Array(el.fTexX*el.fTexY*4); + for (let i = 0; i < nPnts; ++i) { + let j = i*3; + let k = i*4; + p_buf[k] = rnr_data.vtxBuff[j+off]; + p_buf[k+1] = rnr_data.vtxBuff[j+off+1]; + p_buf[k+2] = rnr_data.vtxBuff[j+off+2]; + p_buf[k+3] = 0; + } + + console.log("straight line set = ",p_buf ); + console.log("eve el = ", el.fTexX, el.fTexY); + + let marker = this.RcMakeZSprite(el.fMainColor, el.fMarkerSize, nPnts, + p_buf, el.fTexX, el.fTexY, + "star5-32a.png"); + obj3d.add(marker); } - - let p_geom = new RC.Geometry(); - p_geom.vertices = new RC.BufferAttribute(p_buf, 3); - - let p_mat = this.RcPointMaterial(RcCol(el.fMarkerColor), 1, el.fMarkerSize); - p_mat.pointsScale = false; - p_mat.drawCircles = true; - - let marker = new RC.Point({ geometry: p_geom, material: p_mat }); - this.UpdatePointPickingMaterial(marker); - this.RcPickable(el, marker); - obj3d.add(marker); - // For secondary selection, see EveElements.js // obj3d.eve_idx_buf = rnr_data.idxBuff; // if (el.fSecondarySelect) From 21c0322dccd2bd0562c823bc486c40fb501e292c Mon Sep 17 00:00:00 2001 From: alja Date: Thu, 3 Nov 2022 22:19:19 -0700 Subject: [PATCH 42/84] Stream interpreter errors and show them in client log --- graf3d/eve7/inc/ROOT/REveManager.hxx | 3 +++ graf3d/eve7/src/REveManager.cxx | 29 ++++++++++++++++++++++++---- ui5/eve7/lib/EveManager.js | 11 +++++++++-- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/graf3d/eve7/inc/ROOT/REveManager.hxx b/graf3d/eve7/inc/ROOT/REveManager.hxx index ddd28fb636455..e0b35de7bf996 100644 --- a/graf3d/eve7/inc/ROOT/REveManager.hxx +++ b/graf3d/eve7/inc/ROOT/REveManager.hxx @@ -254,6 +254,9 @@ public: static void ExecuteInMainThread(std::function func); static void QuitRoot(); + static void ErrorHandler(Int_t level, Bool_t abort, const char *location, + const char *msg); + // Access to internals, needed for low-level control in advanced // applications. diff --git a/graf3d/eve7/src/REveManager.cxx b/graf3d/eve7/src/REveManager.cxx index db5b01bcc1b7a..fa3cccc02c6f9 100644 --- a/graf3d/eve7/src/REveManager.cxx +++ b/graf3d/eve7/src/REveManager.cxx @@ -163,6 +163,10 @@ REveManager::REveManager() fWebWindow->SetMaxQueueLength(30); // number of allowed entries in the window queue fMIRExecThread = std::thread{[this] { MIRExecThread(); }}; + + // activate interpreter error report + gInterpreter->ReportDiagnosticsToErrorHandler(); + SetErrorHandler(ErrorHandler); } //////////////////////////////////////////////////////////////////////////////// @@ -944,20 +948,25 @@ void REveManager::PublishChanges() jobj["content"] = "EndChanges"; if (!gEveLogEntries.empty()) { - constexpr static int numLevels = static_cast(ELogLevel::kDebug) + 1; constexpr static std::array sTag{ - {"{unset-error-level please report}", "FATAL", "Error", "Warning", "Info", "Debug"}}; + {"{unset-error-level please report}", "FATAL", "Error", "Warning", "Info", "Debug"}}; + jobj["log"] = nlohmann::json::array(); std::stringstream strm; for (auto entry : gEveLogEntries) { + nlohmann::json item = {}; + item["lvl"] = entry.fLevel; int cappedLevel = std::min(static_cast(entry.fLevel), numLevels - 1); - strm << sTag[cappedLevel]; + strm << "Server " << sTag[cappedLevel] << ":"; + if (!entry.fLocation.fFuncName.empty()) strm << " " << entry.fLocation.fFuncName; strm << " " << entry.fMessage; + item["msg"] = strm.str(); + jobj["log"].push_back(item); + strm.clear(); } - jobj["log"] = strm.str(); gEveLogEntries.clear(); } @@ -1117,6 +1126,18 @@ REveManager::ChangeGuard::~ChangeGuard() gEve->EndChange(); } +// Error handler streams error-level messages to client log +void REveManager::ErrorHandler(Int_t level, Bool_t abort, const char * location, const char *msg) +{ + if (level >= kError) + { + RLogEntry entry(ELogLevel::kError, REveLog()); + entry.fMessage = msg; + gEveLogEntries.emplace_back(entry); + } + ::DefaultErrorHandler(level, abort, location, msg); +} + /** \class REveManager::RExceptionHandler \ingroup REve Exception handler for Eve exceptions. diff --git a/ui5/eve7/lib/EveManager.js b/ui5/eve7/lib/EveManager.js index 58c367cc788d0..c39b6ee263e5b 100644 --- a/ui5/eve7/lib/EveManager.js +++ b/ui5/eve7/lib/EveManager.js @@ -147,8 +147,15 @@ sap.ui.define([], function() { } else if (resp.content == "EndChanges") { this.ServerEndRedrawCallback(); - if (resp.log) - console.log(resp.log); + if (resp.log) { + resp.log.forEach((item) => { + // use console error above warning serverity + if (item.lvl < 3) + console.error(item.msg); + else + console.log(item.msg); + }); + } } else if (resp.content == "BrowseElement") { this.BrowseElement(resp.id); From bb423ce00901ec12b6972db4078921d26b1821fd Mon Sep 17 00:00:00 2001 From: alja Date: Thu, 3 Nov 2022 22:22:02 -0700 Subject: [PATCH 43/84] Remove obsolete hyper link --- ui5/eve7/controller/ClientLog.controller.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ui5/eve7/controller/ClientLog.controller.js b/ui5/eve7/controller/ClientLog.controller.js index f1b2e10987f7f..7dd58c8e70a9d 100644 --- a/ui5/eve7/controller/ClientLog.controller.js +++ b/ui5/eve7/controller/ClientLog.controller.js @@ -14,11 +14,6 @@ sap.ui.define([ return Controller.extend("rootui5.eve7.controller.ClientLog", { onInit: function () { // create any data and a model and set it to the view - let oLink = new Link({ - text: "Show more information", - href: "http://sap.com", - target: "_blank" - }); let oMessageTemplate = new MessageItem({ type: '{type}', @@ -26,8 +21,7 @@ sap.ui.define([ activeTitle: "{active}", description: '{description}', subtitle: '{subtitle}', - counter: '{counter}', - link: oLink + counter: '{counter}' }); this.oMessageView = new MessageView({ From 1f8a4bcd94aff3d2165f1ae9ea8681c15baed13c Mon Sep 17 00:00:00 2001 From: alja Date: Tue, 15 Nov 2022 11:01:03 -0800 Subject: [PATCH 44/84] Clear textures and buffers with idle time above given idle time --- ui5/eve7/lib/EveManager.js | 21 ++++++++++++++++++++- ui5/eve7/lib/GlViewerRCore.js | 21 +++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/ui5/eve7/lib/EveManager.js b/ui5/eve7/lib/EveManager.js index c39b6ee263e5b..8c75f3023148f 100644 --- a/ui5/eve7/lib/EveManager.js +++ b/ui5/eve7/lib/EveManager.js @@ -696,14 +696,25 @@ sap.ui.define([], function() { { // console.log("ServerEndRedrawCallback ", this.listScenesToRedraw); let recs = new Set(); + let viewers = new Set(); for ( let i =0; i < this.listScenesToRedraw.length; i++) { let scene = this.listScenesToRedraw[i]; if (scene.$receivers) { for (let r=0; r < scene.$receivers.length; r++) { - recs.add( scene.$receivers[r]); + let sr = scene.$receivers[r]; + recs.add(sr); + if (sr.glctrl) { viewers.add(sr.glctrl.viewer)}; } } } + + if (this.is_rcore) + { + for (let v of viewers ) { + v.timeStampAttributesAndTextures(); + } + } + for (let item of recs) { try { item.endChanges(); @@ -716,6 +727,14 @@ sap.ui.define([], function() { } } + if (this.is_rcore) + { + for (let v of viewers ) { + v.clearAttributesAndTextures(); + } + } + + if (this.handle.kind != "file") this.handle.send("__REveDoneChanges"); this.busyProcessingChanges = false; diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index cfe149ad69876..350994eb85133 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -791,6 +791,27 @@ sap.ui.define([ } } + timeStampAttributesAndTextures() { + try { + this.renderer.glManager._textureManager.incrementTime(); + this.renderer.glManager._attributeManager.incrementTime(); + } + catch (e) { + console.error("Exception cought in timeStampAttributesAndTextures", e); + } + } + + clearAttributesAndTextures() { + try { + let delta = 10; + this.renderer.glManager._textureManager.deleteTextures(true, delta); + this.renderer.glManager._attributeManager.deleteBuffers(true, delta); + } + catch (e) { + console.error("Exception cought in clearAttributesAndTextures", e); + } + } + } // class GlViewerRCore return GlViewerRCore; From 01e16b634ae2ac0d39f74640058f9aa71dc402ea Mon Sep 17 00:00:00 2001 From: alja Date: Fri, 18 Nov 2022 00:54:33 +0100 Subject: [PATCH 45/84] Correction in texture sources for the case of the web service --- ui5/eve7/lib/EveElementsRCore.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 6eb93061806da..f6b5fdeefda0f 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -730,7 +730,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) GetLumAlphaTexture(name, callback) { - let url = window.location.origin + '/rootui5sys/eve7/textures/' + name; + let sp = EVE.JSR.source_dir; let rp = sp.substring(0, sp.length - 10); + let url = rp + '/rootui5sys/eve7/textures/' + name; this.tex_cache.deliver(url, callback, From c038d91078c1a6ea8d146f5ffe1bbab64a3f79a4 Mon Sep 17 00:00:00 2001 From: alja Date: Mon, 21 Nov 2022 21:57:52 +0100 Subject: [PATCH 46/84] Correction in straight lineset selection: handle case where no marker is created --- ui5/eve7/lib/EveElementsRCore.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index f6b5fdeefda0f..92d6469262ea7 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -1363,8 +1363,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) obj3d.get_ctrl = function(iobj, tobj) { let octrl = new EveElemControl(iobj, tobj); octrl.DrawForSelection = function(sec_idcs, res) { - res.geom.push(this.top_obj.children[0]); - res.geom.push(this.top_obj.children[1]); + res.geom.push(...this.top_obj.children); }; return octrl; } From 92861dac75712f412255bdc1e396c6fc54d29cc5 Mon Sep 17 00:00:00 2001 From: alja Date: Mon, 21 Nov 2022 22:05:27 +0100 Subject: [PATCH 47/84] Remove useage of error MessageBox popup during client update. --- ui5/eve7/controller/Main.controller.js | 14 -------------- ui5/eve7/lib/EveManager.js | 7 +------ 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/ui5/eve7/controller/Main.controller.js b/ui5/eve7/controller/Main.controller.js index 9a842b2989696..b28922b0ce3fa 100644 --- a/ui5/eve7/controller/Main.controller.js +++ b/ui5/eve7/controller/Main.controller.js @@ -92,20 +92,6 @@ sap.ui.define(['sap/ui/core/Component', let toolbar = pthis.byId("otb1"); toolbar.addContentRight(logCtrl.getButton()); }); - consoleObj.alert = true; - EVE.alert = function (oText) - { - if (consoleObj.alert) - { - MessageBox.error(oText, { - actions: ["Stop Alerts", MessageBox.Action.CLOSE], - onClose: function (sAction) - { - if (sAction == "Stop Alerts") { consoleObj.alert = false; } - } - }); - } - }; }, UpdateCommandsButtons: function(cmds) { diff --git a/ui5/eve7/lib/EveManager.js b/ui5/eve7/lib/EveManager.js index 8c75f3023148f..f0c9bd08d61ff 100644 --- a/ui5/eve7/lib/EveManager.js +++ b/ui5/eve7/lib/EveManager.js @@ -44,10 +44,8 @@ sap.ui.define([], function() { globExceptionHandler(msg, url, lineNo, columnNo, error) { // NOTE: currently NOT connected, see onWebsocketOpened() below. - console.log("EveManager got global error", msg, url, lineNo, columnNo, error); + console.error("EveManager got global error", msg, url, lineNo, columnNo, error); - EVE.alert("Global Exception handler: " + msg + "\n" + url + - " line:" + lineNo + " col:" + columnNo); let suppress_alert = false; return suppress_alert; } @@ -719,10 +717,7 @@ sap.ui.define([], function() { try { item.endChanges(); } catch (e) { - EVE.alert("EveManager: Exception caught during update processing: " + e + "\n" + - "You might want to reload the page in browser and / or check error consoles."); console.error("EveManager: Exception caught during update processing", e); - // XXXX We might want to send e.name, e.message, e.stack back to the server. } } From adec1a55328af9b9b5571f5a917f924199ed64f1 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 21 Nov 2022 14:27:42 -0800 Subject: [PATCH 48/84] [REve] Package RenderCore as builtin, cleanup ui5/eve7/ accordingly. --- builtins/rendercore/RenderCore.tar.gz | Bin 0 -> 95908 bytes cmake/modules/SearchInstalledSoftware.cmake | 11 + ui5/eve7/lib/EveElementsRCore.js | 5 +- ui5/eve7/lib/GlViewerRCore.js | 109 +- ui5/eve7/lib/REveCameraControls.js | 1319 ------------------ ui5/eve7/lib/REveRenderCore.js | 4 - ui5/eve7/lib/RendeQuTor.js | 721 ---------- ui5/eve7/lib/RenderCore.js | 9 + ui5/eve7/shaders/custom/copyDepth2RReve.frag | 28 - ui5/eve7/shaders/custom/copyDepth2RReve.vert | 20 - ui5/eve7/shaders/custom/highPassReve.frag | 37 - ui5/eve7/shaders/custom/highPassReve.vert | 23 - ui5/eve7/shaders/custom/lowPassReve.frag | 37 - ui5/eve7/shaders/custom/lowPassReve.vert | 23 - ui5/eve7/shaders/programs.json | 24 - 15 files changed, 95 insertions(+), 2275 deletions(-) create mode 100644 builtins/rendercore/RenderCore.tar.gz delete mode 100644 ui5/eve7/lib/REveCameraControls.js delete mode 100644 ui5/eve7/lib/REveRenderCore.js delete mode 100644 ui5/eve7/lib/RendeQuTor.js create mode 100644 ui5/eve7/lib/RenderCore.js delete mode 100644 ui5/eve7/shaders/custom/copyDepth2RReve.frag delete mode 100644 ui5/eve7/shaders/custom/copyDepth2RReve.vert delete mode 100644 ui5/eve7/shaders/custom/highPassReve.frag delete mode 100644 ui5/eve7/shaders/custom/highPassReve.vert delete mode 100644 ui5/eve7/shaders/custom/lowPassReve.frag delete mode 100644 ui5/eve7/shaders/custom/lowPassReve.vert delete mode 100644 ui5/eve7/shaders/programs.json diff --git a/builtins/rendercore/RenderCore.tar.gz b/builtins/rendercore/RenderCore.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..7d2d0ee8032be437f19fc8674b10272528c89160 GIT binary patch literal 95908 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𝔞A(J=OGE5H4*z1i;F5Q_=f z`^5T=V07<2Nwy;7^XsYH0GgzD#Ikhc@?3Eki2hfWPG)jeDN_6E$k9^6&5pGR`8 zP{tOob_zj#AffTa{)2~)SHbS<3aBcU$}z!d^DmG+)*T7-JV+#Of>74QlcaaGy9bbV zsq21ZB6`JBM?H%3pBpjCo(UHpI)8Kq1fZv2FwF^E=VS#sbuq+-T5c@${m7gRu(KmD zN!GP8sn8?Qi!m*4?jh*02|MLIfV@2ZMvE>$J65k{HR3jmkks_!e<;pRn$pilKhu03 zT0zMGU3k=)G&+@Mi{c=uiR!GfpyX{3m=!7-Q|N+L{DzcfVS@g3>i)uO4hIbpkg>+} zJb}X%(8F$SC3eZJ(%AR=zG#tt-=YvkM@@uMg8+b8#9#rm227t7FkwXHdwk~w`iQW6 zJN5h{cdH1EcMLO@sBmaNC$;Y%$?(6$x7)iB9Y-k= zLR309o9~c_`o+Y=^NlEWD!*DU3gSX;rGNyi6=+KZfO~qF!#hHR9Ty4I)TRi%?A1&0 zF}f5y%Z*##Jy#^H2XeNOcGZ7N%T!*8t>43$?;CROoR?ZNv%M&d4==&&N@yzkxRi=@ z$r%nU%iGdaRh{?j8$ms@-3o46;taxu+^QATRN0+JP{a4-4i@s0LehtvXi3vRv*vlx zb5rFa+*syskD=g{z&X-r3Z1q7%O0R`nTgYgp50(Vs-4mZ3Qe$b0n3^EGQ#qH?Mxvt~Yh!9CKo-_{ig6Y({BRHZUjYm~Yq5B%0Dhu;lZs*#%0 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 { - let sp = EVE.JSR.source_dir; - let rp = sp.substring(0, sp.length - 10); // take out 'jsrootsys' to replace it with 'rootui5sys' - rp += 'rootui5sys/eve7/lib/REveRenderCore.js'; - import(rp).then((module) => { - if (this._logLevel >= 2) - console.log("GlViewerRCore.onInit - RenderCore.js loaded"); - - RC = module; - pthis.bootstrap(); - }); - - if (!datGUI) { - datGUI = new EVE.JSR.gui.GUI({ autoPlace: false, width: 220 }); - datGUI.domElement.id = 'posDatGUI'; - pthis.datGUIFolder = datGUI.addFolder("background") - let dome = this.controller.getView().getParent().getParent(); - dome.getDomRef().appendChild(datGUI.domElement); + if (!RC) { + import(this.eve_path + 'lib/RenderCore.js').then((module) => { + if (this._logLevel >= 2) + console.log("GlViewerRCore.onInit - RenderCore.js loaded"); + RC = module; + pthis.bootstrap(); + }); + } else { + this.bootstrap(); } } @@ -116,8 +120,7 @@ sap.ui.define([ { antialias: false, stencil: false }); this.renderer._logLevel = 0; this.renderer.clearColor = "#FFFFFF00"; // "#00000000"; - this.renderer.addShaderLoaderUrls("rootui5sys/eve7/lib/RC/shaders"); - this.renderer.addShaderLoaderUrls("rootui5sys/eve7/shaders"); + this.renderer.addShaderLoaderUrls(this.eve_path + RC.REveShaderPath); this.renderer.pickObject3D = true; // add dat GUI option to set background @@ -737,14 +740,11 @@ sap.ui.define([ menu.add("Reset camera", this.resetRenderer); - menu.add("separator"); - - let fff = this.defaultContextMenuAction; - // menu.add("sub:Sub Test"); - // menu.add("Foo", 'foo', fff); - // menu.add("Bar", 'bar', fff); - // menu.add("Baz", 'baz', fff); - // menu.add("endsub:"); + if (RC.REveDevelMode) { + menu.add("separator"); + menu.add("Show program names", 'names', this.showShaderJson); + menu.add("Show programs", 'progs', this.showShaderJson); + } menu.show(event); } @@ -771,11 +771,6 @@ sap.ui.define([ pthis.request_render(); } - defaultContextMenuAction(arg) - { - console.log("GLC::defaultContextMenuAction", this, arg); - } - handleMouseSelect(event) { let pstate = this.render_for_picking(event.offsetX, event.offsetY, false); @@ -797,21 +792,63 @@ sap.ui.define([ this.renderer.glManager._attributeManager.incrementTime(); } catch (e) { - console.error("Exception cought in timeStampAttributesAndTextures", e); + console.error("Exception caught in timeStampAttributesAndTextures.", e); } } clearAttributesAndTextures() { try { - let delta = 10; + let delta = 2; this.renderer.glManager._textureManager.deleteTextures(true, delta); this.renderer.glManager._attributeManager.deleteBuffers(true, delta); } catch (e) { - console.error("Exception cought in clearAttributesAndTextures", e); + console.error("Exception caught in clearAttributesAndTextures.", e); } } + static showShaderCount = 0; + showShaderJson(arg) + { + let progs = RC.ShaderLoader.sAllPrograms; + let json; + if (arg == "names") { + let names = []; + for (const p of progs) names.push(p); + json = JSON.stringify(names, null, 2); + } else if (arg == "progs") { + let shdrs = this.rqt.renderer._shaderLoader.resolvePrograms( progs ); + json = JSON.stringify(shdrs, null, 2); + } else { + json = "bad option '" + arg + "' to GlViewerRCore.showShaderJson"; + } + + let count = GlViewerRCore.showShaderCount++; + let extra = count ? ("-" + count) : ""; + + const win = window.open("", "rcore.programs.json"); + win.document.open(); + win.document.write(` + + programs.json + + + +
+ + +
+
 ${json} 
+ + `); + win.document.close(); + } } // class GlViewerRCore return GlViewerRCore; diff --git a/ui5/eve7/lib/REveCameraControls.js b/ui5/eve7/lib/REveCameraControls.js deleted file mode 100644 index 1139ef74cb8c8..0000000000000 --- a/ui5/eve7/lib/REveCameraControls.js +++ /dev/null @@ -1,1319 +0,0 @@ -/** Taken from THREE OrbitCameraControls - * @author qiao / https://github.com/qiao - * @author mrdoob / http://mrdoob.com - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author erich666 / http://erichaines.com - * @author ScieCode / http://github.com/sciecode - * @author osschar - */ - -// This set of controls performs orbiting, dollying (zooming), and panning. -// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). -// -// Orbit - left mouse / touch: one-finger move -// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish -// Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move - -// Requires the following to be set on Camera passed. -// this.camera.isPerspectiveCamera = true; -// or -// this.camera.isOrthographicCamera = true; - -// This should be further cleaned up and classed ... - -import { EventDispatcher } from './RC/core/EventDispatcher.js'; -import { Vector3 } from './RC/math/Vector3.js'; -import { Vector2 } from './RC/math/Vector2.js'; -import { Quaternion } from './RC/math/Quaternion.js'; -import { Spherical } from './RC/math/Spherical.js'; -import { Matrix4 } from './RC/math/Matrix4.js'; - - - -export class REveCameraControls extends EventDispatcher { - - static matrixExtendDone = false; - - constructor(object, domElement) { - var MOUSE = { ROTATE: 0, DOLLY: 1, PAN: 2 }; - var TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; - - super(EventDispatcher); - - if (!REveCameraControls.matrixExtendDone) { - ExtendRCMatrix(); - REveCameraControls.matrixExtendDone = true; - } - - this.object = object; - - this.domElement = (domElement !== undefined) ? domElement : document; - - // Set to false to disable this control - this.enabled = true; - - // "target" sets the location of focus, where the object orbits around - this.target = new Vector3(); - this.cameraCenter = new Vector3(); - - // How far you can dolly in and out ( PerspectiveCamera only ) - this.minDistance = 0; - this.maxDistance = Infinity; - - // How far you can zoom in and out ( OrthographicCamera only ) - this.minZoom = 0; - this.maxZoom = Infinity; - - // How far you can orbit vertically, upper and lower limits. - // Range is 0 to Math.PI radians. - this.minPolarAngle = 0; // radians - this.maxPolarAngle = Math.PI; // radians - - // How far you can orbit horizontally, upper and lower limits. - // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. - this.minAzimuthAngle = - Infinity; // radians - this.maxAzimuthAngle = Infinity; // radians - - // Set to true to enable damping (inertia) - // If damping is enabled, you must call controls.update() in your animation loop - this.enableDamping = false; - this.dampingFactor = 0.05; - - // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. - // Set to false to disable zooming - this.enableZoom = true; - this.zoomSpeed = 1.0; - - // Set to false to disable rotating - this.enableRotate = true; - this.rotateSpeed = 1.0; - - // Set to false to disable panning - this.enablePan = true; - this.panSpeed = 1.0; - this.screenSpacePanning = false; // if true, pan in screen-space - this.keyPanSpeed = 7.0; // pixels moved per arrow key push - - // Set to true to automatically rotate around the target - // If auto-rotate is enabled, you must call controls.update() in your animation loop - this.autoRotate = false; - this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 - - // Set to false to disable use of the keys - this.enableKeys = true; - - // The four arrow keys - this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; - - // Mouse buttons - this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN }; - - // Touch fingers - this.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN }; - - // for reset - this.target0 = this.target.clone(); - this.position0 = this.object.position.clone(); - this.zoom0 = this.object.zoom; - - // - // public methods - // - this.setCamBaseMtx = function(hAxis, vAxis) - { - camBase.identity(); - - camBase.setBaseVector(1, hAxis); - camBase.setBaseVector(3, vAxis); - - let y = new Vector3(); - y.crossVectors(vAxis, hAxis); - camBase.setBaseVector(2, y); - }; - - this.setFromBBox = function (bbox) { - let bb_center = new Vector3(); - bbox.getCenter(bb_center); - - let bb_R = Math.max(bbox.min.length(), bbox.max.length()); - - camTrans.identity(); - - if (this.object.isPerspectiveCamera) { - let fovDefault = 30; - let fov = Math.min(fovDefault, this.object.aspect*fovDefault); - let dollyDefault = bb_R / (2.0 * Math.tan(fov * Math.PI * 0.8/ 180)); - - camTrans.moveLF(1, dollyDefault); - } - else { - let dollyDefault = 1.25*0.5*Math.sqrt(3)*bb_R; - camTrans.moveLF(1, dollyDefault); - scope.object.updateProjectionMatrix(); - } - }; - - this.setCameraCenter = function (x, y, z) { - this.cameraCenter.set(x, y, z); - - let bt = new Matrix4(); - bt.multiplyMatrices(camBase, camTrans); - camBase.setBaseVector(4, this.cameraCenter); - let binv = camBase.clone(); - binv.getInverse(camBase); - camTrans.multiplyMatrices(binv, bt); - - if (this.centerMarker) { - this.centerMarker.position = this.cameraCenter; - this.centerMarker.visible = true; - this.centerMarker.updateMatrix(); - } - }; - - this.getPolarAngle = function () { - - return spherical.phi; - - }; - - this.getAzimuthalAngle = function () { - - return spherical.theta; - - }; - - this.saveState = function () { - - scope.target0.copy(scope.target); - scope.position0.copy(scope.object.position); - scope.zoom0 = scope.object.zoom; - - }; - - this.reset = function () { - - scope.target.copy(scope.target0); - scope.object.position.copy(scope.position0); - scope.object.zoom = scope.zoom0; - - scope.object.updateProjectionMatrix(); - scope.dispatchEvent(changeEvent); - - scope.update(); - - state = STATE.NONE; - - }; - - // osschar - need to reset internal panOffset - this.resetOrthoPanZoom = function () { - return function resetOrthoPan() { - panOffset.set(0, 0, 0); - scope.object.zoom = 0.78; // AMT default ortho camera zoom value in ROOT GL - scope.object.updateProjectionMatrix(); - zoomChanged = true; - } - }(); - - // osschar - fake mouse up event, needed for context menu on M3 down - this.resetMouseDown = function (event) { - return function resetMouseDown(event) { - onMouseUp(event); - } - }(); - - - this.testCameraMenu = function () { - console.log("camera test func"); - return function testCameraMenu() { - dollyIn(0.5); - } - }(); - - ///////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// - // AMT set camera matrix from two operations camBase and camTrans - this.update = function () { - - var lastPosition = new Vector3(); - var lastQuaternion = new Quaternion(); - return function update() { - // dolly scale - if (scale != 1.0) { - let b1 = camTrans.getBaseVector(1); - let b4 = camTrans.getBaseVector(4); - let orig_dot = b1.dot(b4); - let lookAtDist = Math.sqrt(orig_dot); - let newMag = Math.sqrt(lookAtDist) * scale; - b4.multiplyScalar(scale); - camTrans.setBaseVector(4, b4); - scale = 1.0; - - scope.object.near = Math.min(lookAtDist*0.1, 20); - } - - // pan/ truck - if (panOffset.x || panOffset.y) { - camTrans.moveLF(2, panOffset.x); - camTrans.moveLF(3, panOffset.y); - panOffset.set(0, 0, 0); - } - - let cam = new Matrix4(); - cam.multiplyMatrices(camBase, camTrans); - - // matrix needed to transform position from the picking - scope.object.testMtx = cam; - - let eye = new Vector3(); eye.setFromMatrixPosition(cam); - let fwd = new Vector3(); fwd.setFromMatrixColumn(cam, 0); - let up = new Vector3(); up.setFromMatrixColumn(cam, 2); - - /* - console.log("cam", cam, camBase, camTrans); - console.log("up", up.x, up.y, up.z); - console.log("fwd", fwd.x, fwd.y, fwd.z); - console.log("eye", eye.x, eye.y, eye.z); - */ - - scope.object._matrix.lookAtMt(eye, fwd, up); - scope.object._matrix.setPosition(eye); - - // camera matrix auto update is disabled to prevent reading from quaternions - scope.object.matrixWorld.copy(scope.object.matrix); - - // update condition is: - // min(camera displacement, camera rotation in radians)^2 > EPS - // using small-angle approximation - - if (zoomChanged || - lastPosition.distanceToSquared(cam.getBaseVector(4)) > EPS || - 10 * (sphericalDelta.phi + sphericalDelta.theta) > EPS) { - - scope.dispatchEvent(changeEvent); - - lastPosition.copy(cam.getBaseVector(4)); - lastQuaternion.copy(scope.object.quaternion); - zoomChanged = false; - - sphericalDelta.theta = 0; - sphericalDelta.phi = 0; - - return true; - } - else { - let dp = lastPosition.distanceToSquared(cam.getBaseVector(4)); - } - - - //scope.dispatchEvent(changeEvent); - - return true; - }; - - }(); - - this.dispose = function () { - - scope.domElement.removeEventListener('contextmenu', onContextMenu, false); - scope.domElement.removeEventListener('mousedown', onMouseDown, false); - scope.domElement.removeEventListener('wheel', onMouseWheel, false); - - scope.domElement.removeEventListener('touchstart', onTouchStart, false); - scope.domElement.removeEventListener('touchend', onTouchEnd, false); - scope.domElement.removeEventListener('touchmove', onTouchMove, false); - - document.removeEventListener('mousemove', onMouseMove, false); - document.removeEventListener('mouseup', onMouseUp, false); - - window.removeEventListener('keydown', onKeyDown, false); - - //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? - - }; - - // - // internals - // - - var scope = this; - - var changeEvent = { type: 'change' }; - var startEvent = { type: 'start' }; - var endEvent = { type: 'end' }; - - var STATE = { - NONE: - 1, - ROTATE: 0, - DOLLY: 1, - PAN: 2, - TOUCH_ROTATE: 3, - TOUCH_PAN: 4, - TOUCH_DOLLY_PAN: 5, - TOUCH_DOLLY_ROTATE: 6 - }; - - var state = STATE.NONE; - - var EPS = 0.000001; - - // current position in spherical coordinates - var spherical = new Spherical(); - var sphericalDelta = new Spherical(); - - var camBase = new Matrix4(); - var camTrans = new Matrix4(); - - var scale = 1; - var panOffset = new Vector3(); - var zoomChanged = false; - - var rotateStart = new Vector2(); - var rotateEnd = new Vector2(); - var rotateDelta = new Vector2(); - - var panStart = new Vector2(); - var panEnd = new Vector2(); - var panDelta = new Vector2(); - - var dollyStart = new Vector2(); - var dollyEnd = new Vector2(); - var dollyDelta = new Vector2(); - - function getAutoRotationAngle() { - - return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; - - } - - function getZoomScale() { - - return Math.pow(0.95, scope.zoomSpeed); - - } - - function rotateLeft(angle) { - - sphericalDelta.theta -= angle; - - } - - function rotateUp(angle) { - - sphericalDelta.phi -= angle; - - } - - function rotateRad(hRotate, vRotate) { - - let fVAxisMinAngle = 0.01; - // console.log("rotate rad BEGIN hrotate = ", hRotate, ", vRotate = ", vRotate); - - if (hRotate != 0.0) { - let fwd = camTrans.getBaseVector(1); - let lft = camTrans.getBaseVector(2); - let up = camTrans.getBaseVector(3); - let pos = camTrans.getTranslation(); - - let deltaF = pos.dot(fwd); - let deltaU = pos.dot(up); - - // up vector lock - let zdir = camBase.getBaseVector(3); - camBase.rotateIP(fwd); - let theta = Math.acos(fwd.dot(zdir)); - if (theta + hRotate < fVAxisMinAngle) - hRotate = fVAxisMinAngle - theta; - else if (theta + hRotate > Math.PI - fVAxisMinAngle) - hRotate = Math.PI - fVAxisMinAngle - theta; - - - camTrans.moveLF(1, -deltaF); - camTrans.moveLF(3, -deltaU); - camTrans.rotateLF(3, 1, hRotate); - camTrans.moveLF(3, deltaU); - camTrans.moveLF(1, deltaF); - - } - if (vRotate != 0.0) { - camTrans.rotatePF(1, 2, -vRotate); - } - - sphericalDelta.phi = hRotate; - sphericalDelta.theta = vRotate; - } - - // deltaX and deltaY are in pixels; right and down are positive - var pan = function () { - - var offset = new Vector3(); - - return function pan(deltaX, deltaY) { - // amt, x seem to be negatd - deltaX = -deltaX; - - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - - if (scope.object.isPerspectiveCamera) { - - // perspective - - let targetDistance = 0.5 * (scope.object.far + scope.object.near) * Math.tan(0.5 * scope.object.fov * Math.PI / 180.0); - - // we use only clientHeight here so aspect ratio does not distort speed - let h = deltaY * targetDistance / element.clientHeight; - let w = deltaX * targetDistance / element.clientHeight; - - - panOffset.setX(w); - panOffset.setY(h); - - } else if (scope.object.isOrthographicCamera) { - - // orthographic - panOffset.setX(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth); - panOffset.setY(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight); - } else { - - // camera neither orthographic nor perspective - console.warn('WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.'); - scope.enablePan = false; - - } - scope.update(); - }; - - }(); - - function dollyIn(dollyScale) { - - if (scope.object.isPerspectiveCamera) { - - scale /= dollyScale; - - } else if (scope.object.isOrthographicCamera) { - - scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale)); - scope.object.updateProjectionMatrix(); - zoomChanged = true; - - } else { - - console.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.'); - scope.enableZoom = false; - - } - scope.update(); - } - - function dollyOut(dollyScale) { - - if (scope.object.isPerspectiveCamera) { - - scale *= dollyScale; - - } else if (scope.object.isOrthographicCamera) { - - scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale)); - scope.object.updateProjectionMatrix(); - zoomChanged = true; - - } else { - - console.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.'); - scope.enableZoom = false; - - } - - scope.update(); - } - - // - // event callbacks - update the object state - // - - function handleMouseDownRotate(event) { - - rotateStart.set(event.clientX, event.clientY); - - } - - function handleMouseDownDolly(event) { - - dollyStart.set(event.clientX, event.clientY); - - } - - function handleMouseDownPan(event) { - - panStart.set(event.clientX, event.clientY); - - } - - function handleMouseMoveRotate(event) { - - rotateEnd.set(event.clientX, event.clientY); - - rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed); - - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - - rotateRad(-2 * Math.PI * rotateDelta.y / element.clientHeight, 2 * Math.PI * rotateDelta.x / element.clientWidth); - - rotateStart.copy(rotateEnd); - - scope.update(); - - } - - function handleMouseMoveDolly(event) { - - dollyEnd.set(event.clientX, event.clientY); - - dollyDelta.subVectors(dollyEnd, dollyStart); - - if (dollyDelta.y > 0) { - - dollyIn(getZoomScale()); - - } else if (dollyDelta.y < 0) { - - dollyOut(getZoomScale()); - - } - - dollyStart.copy(dollyEnd); - - scope.update(); - - } - - function handleMouseMovePan(event) { - - panEnd.set(event.clientX, event.clientY); - - panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed); - - pan(panDelta.x, panDelta.y); - - panStart.copy(panEnd); - - scope.update(); - - } - - function handleMouseUp( /*event*/) { - - // no-op - - } - - function handleMouseWheel(event) { - - if (event.deltaY < 0) { - - dollyOut(getZoomScale()); - - } else if (event.deltaY > 0) { - - dollyIn(getZoomScale()); - - } - - scope.update(); - - } - - function handleKeyDown(event) { - - var needsUpdate = false; - - switch (event.keyCode) { - - case scope.keys.UP: - pan(0, scope.keyPanSpeed); - needsUpdate = true; - break; - - case scope.keys.BOTTOM: - pan(0, - scope.keyPanSpeed); - needsUpdate = true; - break; - - case scope.keys.LEFT: - pan(scope.keyPanSpeed, 0); - needsUpdate = true; - break; - - case scope.keys.RIGHT: - pan(- scope.keyPanSpeed, 0); - needsUpdate = true; - break; - - } - - if (needsUpdate) { - - // prevent the browser from scrolling on cursor keys - event.preventDefault(); - // and prevent others from consuming the event - event.stopImmediatePropagation(); - scope.update(); - - } - - - } - - function handleTouchStartRotate(event) { - - if (event.touches.length == 1) { - - rotateStart.set(event.touches[0].pageX, event.touches[0].pageY); - - } else { - - var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); - var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); - - rotateStart.set(x, y); - - } - - } - - function handleTouchStartPan(event) { - - if (event.touches.length == 1) { - - panStart.set(event.touches[0].pageX, event.touches[0].pageY); - - } else { - - var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); - var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); - - panStart.set(x, y); - - } - - } - - function handleTouchStartDolly(event) { - - var dx = event.touches[0].pageX - event.touches[1].pageX; - var dy = event.touches[0].pageY - event.touches[1].pageY; - - var distance = Math.sqrt(dx * dx + dy * dy); - - dollyStart.set(0, distance); - - } - - function handleTouchStartDollyPan(event) { - - if (scope.enableZoom) handleTouchStartDolly(event); - - if (scope.enablePan) handleTouchStartPan(event); - - } - - function handleTouchStartDollyRotate(event) { - - if (scope.enableZoom) handleTouchStartDolly(event); - - if (scope.enableRotate) handleTouchStartRotate(event); - - } - - function handleTouchMoveRotate(event) { - - if (event.touches.length == 1) { - - rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY); - - } else { - - var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); - var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); - - rotateEnd.set(x, y); - - } - - rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed); - - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - - rotateRad(-2 * Math.PI * rotateDelta.y / element.clientHeight, 2 * Math.PI * rotateDelta.x / element.clientWidth); - - rotateStart.copy(rotateEnd); - - } - - function handleTouchMovePan(event) { - - if (event.touches.length == 1) { - - panEnd.set(event.touches[0].pageX, event.touches[0].pageY); - - } else { - - var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); - var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); - - panEnd.set(x, y); - - } - - panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed); - - pan(panDelta.x, panDelta.y); - - panStart.copy(panEnd); - - } - - function handleTouchMoveDolly(event) { - - var dx = event.touches[0].pageX - event.touches[1].pageX; - var dy = event.touches[0].pageY - event.touches[1].pageY; - - var distance = Math.sqrt(dx * dx + dy * dy); - - dollyEnd.set(0, distance); - - dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed)); - - dollyIn(dollyDelta.y); - - dollyStart.copy(dollyEnd); - - } - - function handleTouchMoveDollyPan(event) { - - if (scope.enableZoom) handleTouchMoveDolly(event); - - if (scope.enablePan) handleTouchMovePan(event); - - } - - function handleTouchMoveDollyRotate(event) { - - if (scope.enableZoom) handleTouchMoveDolly(event); - - if (scope.enableRotate) handleTouchMoveRotate(event); - - } - - function handleTouchEnd( /*event*/) { - - // no-op - - } - - // - // event handlers - FSM: listen for events and reset state - // - - function onMouseDown(event) { - - if (scope.enabled === false) return; - - // Prevent the browser from scrolling. - - event.preventDefault(); - - // Manually set the focus since calling preventDefault above - // prevents the browser from setting it automatically. - - scope.domElement.focus ? scope.domElement.focus() : window.focus(); - - switch (event.button) { - - case 0: - - switch (scope.mouseButtons.LEFT) { - - case MOUSE.ROTATE: - - if (event.ctrlKey || event.metaKey || event.shiftKey) { - - if (scope.enablePan === false) return; - - handleMouseDownPan(event); - - state = STATE.PAN; - - } else { - - if (scope.enableRotate === false) return; - - handleMouseDownRotate(event); - - state = STATE.ROTATE; - - } - - break; - - case MOUSE.PAN: - - if (event.ctrlKey || event.metaKey || event.shiftKey) { - - if (scope.enableRotate === false) return; - - handleMouseDownRotate(event); - - state = STATE.ROTATE; - - } else { - - if (scope.enablePan === false) return; - - handleMouseDownPan(event); - - state = STATE.PAN; - - } - - break; - - default: - - state = STATE.NONE; - - } - - break; - - - case 1: - - switch (scope.mouseButtons.MIDDLE) { - - case MOUSE.DOLLY: - - if (scope.enableZoom === false) return; - - handleMouseDownDolly(event); - - state = STATE.DOLLY; - - break; - - - default: - - state = STATE.NONE; - - } - - break; - - case 2: - - switch (scope.mouseButtons.RIGHT) { - - case MOUSE.ROTATE: - - if (scope.enableRotate === false) return; - - handleMouseDownRotate(event); - - state = STATE.ROTATE; - - break; - - case MOUSE.PAN: - - if (scope.enablePan === false) return; - - handleMouseDownPan(event); - - state = STATE.PAN; - - break; - - default: - - state = STATE.NONE; - - } - - break; - - } - - if (state !== STATE.NONE) { - - document.addEventListener('mousemove', onMouseMove, false); - document.addEventListener('mouseup', onMouseUp, false); - - scope.dispatchEvent(startEvent); - - } - - } - - function onMouseMove(event) { - - if (scope.enabled === false) return; - - event.preventDefault(); - - switch (state) { - - case STATE.ROTATE: - - if (scope.enableRotate === false) return; - - handleMouseMoveRotate(event); - - break; - - case STATE.DOLLY: - - if (scope.enableZoom === false) return; - - handleMouseMoveDolly(event); - - break; - - case STATE.PAN: - - if (scope.enablePan === false) return; - - handleMouseMovePan(event); - - break; - - } - - } - - function onMouseUp(event) { - - if (scope.enabled === false) return; - - handleMouseUp(event); - - document.removeEventListener('mousemove', onMouseMove, false); - document.removeEventListener('mouseup', onMouseUp, false); - - scope.dispatchEvent(endEvent); - - state = STATE.NONE; - - } - - function onMouseWheel(event) { - - if (scope.enabled === false || scope.enableZoom === false || (state !== STATE.NONE && state !== STATE.ROTATE)) return; - - event.preventDefault(); - event.stopPropagation(); - - scope.dispatchEvent(startEvent); - - handleMouseWheel(event); - - scope.dispatchEvent(endEvent); - - } - - function onKeyDown(event) { - - if (scope.enabled === false || scope.enableKeys === false || scope.enablePan === false) return; - - handleKeyDown(event); - - } - - function onTouchStart(event) { - - if (scope.enabled === false) return; - - event.preventDefault(); - - switch (event.touches.length) { - - case 1: - - switch (scope.touches.ONE) { - - case TOUCH.ROTATE: - - if (scope.enableRotate === false) return; - - handleTouchStartRotate(event); - - state = STATE.TOUCH_ROTATE; - - break; - - case TOUCH.PAN: - - if (scope.enablePan === false) return; - - handleTouchStartPan(event); - - state = STATE.TOUCH_PAN; - - break; - - default: - - state = STATE.NONE; - - } - - break; - - case 2: - - switch (scope.touches.TWO) { - - case TOUCH.DOLLY_PAN: - - if (scope.enableZoom === false && scope.enablePan === false) return; - - handleTouchStartDollyPan(event); - - state = STATE.TOUCH_DOLLY_PAN; - - break; - - case TOUCH.DOLLY_ROTATE: - - if (scope.enableZoom === false && scope.enableRotate === false) return; - - handleTouchStartDollyRotate(event); - - state = STATE.TOUCH_DOLLY_ROTATE; - - break; - - default: - - state = STATE.NONE; - - } - - break; - - default: - - state = STATE.NONE; - - } - - if (state !== STATE.NONE) { - - scope.dispatchEvent(startEvent); - - } - - } - - function onTouchMove(event) { - - if (scope.enabled === false) return; - - event.preventDefault(); - event.stopPropagation(); - - switch (state) { - - case STATE.TOUCH_ROTATE: - - if (scope.enableRotate === false) return; - - handleTouchMoveRotate(event); - - scope.update(); - - break; - - case STATE.TOUCH_PAN: - - if (scope.enablePan === false) return; - - handleTouchMovePan(event); - - scope.update(); - - break; - - case STATE.TOUCH_DOLLY_PAN: - - if (scope.enableZoom === false && scope.enablePan === false) return; - - handleTouchMoveDollyPan(event); - - scope.update(); - - break; - - case STATE.TOUCH_DOLLY_ROTATE: - - if (scope.enableZoom === false && scope.enableRotate === false) return; - - handleTouchMoveDollyRotate(event); - - scope.update(); - - break; - - default: - - state = STATE.NONE; - - } - - } - - function onTouchEnd(event) { - - if (scope.enabled === false) return; - - handleTouchEnd(event); - - scope.dispatchEvent(endEvent); - - state = STATE.NONE; - - } - - function onContextMenu(event) { - - if (scope.enabled === false) return; - - event.preventDefault(); - - } - - function ExtendRCMatrix() { - Matrix4.prototype.lookAtMt = function ( eye, fwd, up ) { - var _x = new Vector3(); - var _y = new Vector3(); - var _z = new Vector3(); - var te = this.elements; - - _z.copy(fwd); - // _z.negate(); - _z.normalize(); - _x.crossVectors( up, _z ); - _x.normalize(); - _y.crossVectors( _z, _x ); - - te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x; - te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y; - te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z; - - return this; - }; - - Matrix4.prototype.getBaseVector = function (idx) { - let off = 4 * --idx; - let C = this.elements; - return new Vector3(C[off + 0], C[off + 1], C[off + 2]); - }; - - Matrix4.prototype.getTranslation = function () { - let C = this.elements; - return new Vector3(C[12], C[13], C[14]); - }; - - Matrix4.prototype.setBaseVector = function (idx, x, y, z) { - let off = 4 * --idx; - let C = this.elements; - if (x.isVector3) { - C[off + 0] = x.x; C[off + 1] = x.y; C[off + 2] = x.z; - } - else { - C[off + 0] = x; C[off + 1] = y; C[off + 2] = z; - } - }; - - Matrix4.prototype.rotateIP = function (v) { - let M = this.elements; - let r = v.clone(); - v.x = M[0] * r.x + M[4] * r.y + M[8] * r.z; - v.y = M[1] * r.x + M[5] * r.y + M[9] * r.z; - v.z = M[2] * r.x + M[6] * r.y + M[10] * r.z; - }; - - Matrix4.prototype.rotateLF = function (i1, i2, amount) { - if (i1 == i2) return; - - let cos = Math.cos(amount); let sin = Math.sin(amount); - let b1; let b2; - let C = this.elements; - i1 = (i1 - 1) * 4; - i2 = (i2 - 1) * 4; // column major - let off = 0; - for (let r = 0; r < 4; ++r, ++off) { - b1 = cos * C[i1 + off] + sin * C[i2 + off]; - b2 = cos * C[i2 + off] - sin * C[i1 + off]; - C[i1 + off] = b1; C[i2 + off] = b2; - } - }; - - Matrix4.prototype.rotatePF = function (i1, i2, amount) { - if (i1 == i2) return; - - let cos = Math.cos(amount); let sin = Math.sin(amount); - let b1; let b2; - let C = this.elements; - --i1; --i2; - for (let c = 0; c < 4; ++c) { - let off = c * 4; - b1 = cos * C[i1 + off] - sin * C[i2 + off]; - b2 = cos * C[i2 + off] + sin * C[i1 + off]; - C[i1 + off] = b1; C[i2 + off] = b2; - } - }; - - Matrix4.prototype.moveLF = function (ai, amount) { - let C = this.elements; let off = 4 * (ai - 1); - C[12] += amount * C[off]; - C[13] += amount * C[off + 1]; - C[14] += amount * C[off + 2]; - }; - - Matrix4.prototype.dump = function () { - for (let x = 0; x < 4; x++) { - let row = "[ "; - for (let y = 0; y < 4; y++) { - let val = this.elements[y * 4 + x].toFixed(2); - row += val; row += " "; - } - console.log(row + "]"); - } - } - } - - scope.domElement.addEventListener('contextmenu', onContextMenu, false); - - scope.domElement.addEventListener('mousedown', onMouseDown, false); - scope.domElement.addEventListener('wheel', onMouseWheel, false); - - scope.domElement.addEventListener('touchstart', onTouchStart, false); - scope.domElement.addEventListener('touchend', onTouchEnd, false); - scope.domElement.addEventListener('touchmove', onTouchMove, false); - - scope.domElement.addEventListener('mouseenter', function (event) { - window.addEventListener('keydown', onKeyDown); - }); - scope.domElement.addEventListener('mouseleave', function (event) { - window.removeEventListener('keydown', onKeyDown); - }); - - // force an update at start - - this.update(); - } -}; diff --git a/ui5/eve7/lib/REveRenderCore.js b/ui5/eve7/lib/REveRenderCore.js deleted file mode 100644 index 23a9cbe35c90a..0000000000000 --- a/ui5/eve7/lib/REveRenderCore.js +++ /dev/null @@ -1,4 +0,0 @@ -export * from './RC/RenderCore.js'; - -export {RendeQuTor} from './RendeQuTor.js'; -export {REveCameraControls} from './REveCameraControls.js'; \ No newline at end of file diff --git a/ui5/eve7/lib/RendeQuTor.js b/ui5/eve7/lib/RendeQuTor.js deleted file mode 100644 index 66f05a275f2c1..0000000000000 --- a/ui5/eve7/lib/RendeQuTor.js +++ /dev/null @@ -1,721 +0,0 @@ -import {RenderQueue} from './RC/renderers/RenderQueue.js'; -import {RenderPass} from './RC/renderers/RenderPass.js'; -import {CustomShaderMaterial} from './RC/materials/CustomShaderMaterial.js'; -import {FRONT_AND_BACK_SIDE, HIGHPASS_MODE_BRIGHTNESS, HIGHPASS_MODE_DIFFERENCE} - from './RC/constants.js'; - -export class RendeQuTor -{ - constructor(renderer, scene, camera) - { - this.renderer = renderer; - this.scene = scene; - this.camera = camera; - this.queue = new RenderQueue(renderer); - this.pqueue = new RenderQueue(renderer); - this.vp_w = 0; - this.vp_h = 0; - this.pick_radius = 32; - this.pick_center = 16; - - this.make_PRP_plain(); - this.make_PRP_depth2r(); - this.renderer.preDownloadPrograms( - [ this.PRP_depth2r_mat.requiredProgram(this.renderer) - ]); - - this.SSAA_value = 1; - - this.clear_zero_f32arr = new Float32Array([0,0,0,0]); - - this.std_textures = []; - this.std_tex_cnt = 0; - this.std_tex_used = new Set(); - } - - initDirectToScreen() - { - this.make_RP_DirectToScreen(); - } - - initSimple(ssaa_val) - { - this.SSAA_value = ssaa_val; - - this.make_RP_SSAA_Super(); - - this.make_RP_GBuffer(); - this.make_RP_Outline(); - - this.make_RP_GaussHVandBlend(); - - // this.make_RP_ToScreen(); - this.make_RP_ToneMapToScreen(); - - this.RP_GBuffer.obj_list = []; - - this.renderer.preDownloadPrograms( - [ this.RP_GBuffer_mat.requiredProgram(this.renderer), - this.RP_Outline_mat.requiredProgram(this.renderer), - this.RP_GaussH_mat.requiredProgram(this.renderer), - this.RP_Blend_mat.requiredProgram(this.renderer), - this.RP_ToneMapToScreen_mat.requiredProgram(this.renderer) - ]); - } - - initFull(ssaa_val) - { - this.SSAA_value = ssaa_val; - - this.make_RP_SSAA_Super(); - this.make_RP_HighPassGaussBloom(); - // this.make_RP_SSAA_Down(); this.RP_SSAA_Down.input_texture = "color_bloom"; - this.make_RP_ToScreen(); - this.RP_ToScreen.input_texture = "color_bloom"; - } - - updateViewport(w, h) - { - this.vp_w = w; - this.vp_h = h; - let vp = { width: w, height: h }; - let rq = this.queue._renderQueue; - for (let i = 0; i < rq.length; i++) - { - rq[i].view_setup(vp); - } - // Picking render-passes stay constant. - } - - //============================================================================= - - pop_std_texture() { - let tex; - if (this.std_textures.length == 0) { - tex = "std_tex_" + this.std_tex_cnt++; - } else { - tex = this.std_textures.pop(); - } - this.std_tex_used.add(tex); - return tex; - } - - push_std_texture(tex) { - this.std_tex_used.delete(tex); - this.std_textures.push(tex); - } - - release_std_textures() { - if (this.std_tex_used.size > 0) { - // console.log("RendeQuTor releasing std textures", this.std_tex_used.size); - for (const tex of this.std_tex_used) - this.std_textures.push(tex); - this.std_tex_used.clear(); - } - } - - // ---------- - - render_outline() - { - let tex_normal = this.pop_std_texture(); - let tex_view_dir = this.pop_std_texture(); - this.RP_GBuffer.outTextures[0].id = tex_normal; - this.RP_GBuffer.outTextures[1].id = tex_view_dir; - - this.queue.render_pass(this.RP_GBuffer, "GBuffer"); - - this.RP_Outline.intex_normal = tex_normal; - this.RP_Outline.intex_view_dir = tex_view_dir; - if ( ! this.tex_outline) { - // First outline, get the texture to accumulate all outlines - this.tex_outline = this.pop_std_texture(); - } else { - // Additional outlines, do not clear the accumulatortexture. - this.RP_Outline.outTextures[0].clearColorArray = null; - } - this.RP_Outline.outTextures[0].id = this.tex_outline; - - this.queue.render_pass(this.RP_Outline, "Outline"); - - this.push_std_texture(tex_normal); - this.push_std_texture(tex_view_dir); - } - - render_main_and_blend_outline() - { - let main_is_std = (this.SSAA_value == 1); - let tex_main = main_is_std ? this.pop_std_texture() : "color_main"; - - this.RP_SSAA_Super.outTextures[0].id = tex_main; - this.queue.render_pass(this.RP_SSAA_Super, "SSAA Super"); - - if (this.tex_outline) { - let tA = this.tex_outline; - let tB = this.pop_std_texture(); - - this.RP_GaussH.intex = tA; - this.RP_GaussH.outTextures[0].id = tB; - this.queue.render_pass(this.RP_GaussH, "GaussH"); - - this.RP_GaussV.intex = tB; - this.RP_GaussV.outTextures[0].id = tA; - this.queue.render_pass(this.RP_GaussV, "GaussV"); - - this.RP_Blend.intex_outline_blurred = tA; - this.RP_Blend.intex_main = tex_main; - this.RP_Blend.outTextures[0].id = tB; - this.queue.render_pass(this.RP_Blend, "Blend"); - - if (main_is_std) this.push_std_texture(tex_main); - - this.push_std_texture(this.tex_outline); - this.RP_Outline.outTextures[0].clearColorArray = this.clear_zero_f32arr; - this.tex_outline = null; - - this.tex_final = tB; - this.tex_final_push = true; - } else { - this.tex_final = tex_main; - this.tex_final_push = main_is_std; - } - } - - render_tone_map_to_screen() - { - this.RP_ToneMapToScreen.input_texture = this.tex_final; - - this.queue.render_pass(this.RP_ToneMapToScreen, "Tone Map To Screen"); - - if (this.tex_final_push) { - this.push_std_texture(this.tex_final); - this.tex_final = null; - this.tex_final_push = null; - } - } - - render_begin(used_check) - { - this.tex_outline = null; - - this.queue.render_begin(used_check); - } - - render_end() - { - this.queue.render_end(); - this.release_std_textures(); - } - - // ---------- - - render() - { - // This can work for setups without outline passes -- once they are - // brought back to life. - - this.queue.render(); - } - - //============================================================================= - - pick_begin(x, y) - { - this.camera.prePickStoreTBLR(); - this.camera.narrowProjectionForPicking(this.vp_w, this.vp_h, - this.pick_radius, this.pick_radius, - x, this.vp_h - 1 - y); - } - - pick_end() - { - this.camera.postPickRestoreTBLR(); - } - - pick(x, y, detect_depth = false) - { - this.renderer.pick_setup(this.pick_center, this.pick_center); - - let state = this.pqueue.render(); - state.x = x; - state.y = y; - state.depth = -1.0; - state.object = this.renderer.pickedObject3D; - // console.log("RenderQuTor::pick", state); - - if (detect_depth && this.renderer.pickedObject3D !== null) - { - let rdr = this.renderer; - let gl = rdr.gl; - let fbm = rdr.glManager._fboManager; - - fbm.bindFramebuffer(this.pqueue._renderTarget); - - let d = new Float32Array(9); - gl.readBuffer(gl.COLOR_ATTACHMENT0); - gl.readPixels(this.pick_center - 1, this.pick_center - 1, 3, 3, gl.RED, gl.FLOAT, d); - - fbm.unbindFramebuffer(); - - let near = this.camera.near; - let far = this.camera.far; - for (let i = 0; i < 9; ++i) - d[i] = (near * far) / ((near - far) * d[i] + far); - state.depth = d[4]; - // console.log(" pick depth at", x, ",", y, ":", d); - } - - return state; - } - - pick_instance(state) - { - if (state.object !== this.renderer.pickedObject3D) { - console.error("RendeQuTor::pick_instance state mismatch", state, this.renderer.pickedObject3D); - } else { - // console.log("RenderQuTor::pick_instance going for secondary select"); - - this.renderer._pickSecondaryEnabled = true; - this.pqueue.render(); - - state.instance = this.renderer._pickedID; - } - return state; - } - - - //============================================================================= - // Picking RenderPasses - //============================================================================= - - make_PRP_plain() - { - let pthis = this; - - this.PRP_plain = new RenderPass( - RenderPass.BASIC, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { scene: pthis.scene, camera: pthis.camera }; - }, - function (textureMap, additionalData) {}, - RenderPass.TEXTURE, - { width: this.pick_radius, height: this.pick_radius }, - "depth_picking", - [ { id: "color_picking", textureConfig: RenderPass.DEFAULT_R32UI_TEXTURE_CONFIG, - clearColorArray: new Uint32Array([0xffffffff, 0, 0, 0]) } ] - ); - - this.pqueue.pushRenderPass(this.PRP_plain); - } - - make_PRP_depth2r() - { - this.PRP_depth2r_mat = new CustomShaderMaterial("copyDepth2RReve"); - this.PRP_depth2r_mat.lights = false; - let pthis = this; - - this.PRP_depth2r = new RenderPass( - RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.PRP_depth2r_mat, textures: [ textureMap["depth_picking"] ] }; - }, - function (textureMap, additionalData) {}, - RenderPass.TEXTURE, - { width: this.pick_radius, height: this.pick_radius }, - null, - [ { id: "depthr32f_picking", textureConfig: RenderPass.FULL_FLOAT_R32F_TEXTURE_CONFIG, - clearColorArray: new Float32Array([1, 0, 0, 0]) } ] - ); - - this.pqueue.pushRenderPass(this.PRP_depth2r); - } - - - //============================================================================= - // Regular RenderPasses - //============================================================================= - - make_RP_DirectToScreen() - { - let pthis = this; - - this.RP_DirectToScreen = new RenderPass( - RenderPass.BASIC, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { return { scene: pthis.scene, camera: pthis.camera }; }, - function (textureMap, additionalData) {}, - RenderPass.SCREEN, - null - ); - this.RP_DirectToScreen.view_setup = function (vport) { this.viewport = vport; }; - - this.queue.pushRenderPass(this.RP_DirectToScreen); - } - - //============================================================================= - - make_RP_SSAA_Super() - { - let pthis = this; - - this.RP_SSAA_Super = new RenderPass( - // Rendering pass type - RenderPass.BASIC, - // Initialize function - function (textureMap, additionalData) {}, - // Preprocess function - function (textureMap, additionalData) { return { scene: pthis.scene, camera: pthis.camera }; }, - // Postprocess - function (textureMap, additionalData) {}, - // Target - RenderPass.TEXTURE, - // Viewport - null, - // Bind depth texture to this ID - "depth_main", - // Outputs - [ { id: "color_main", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG } ] - ); - this.RP_SSAA_Super.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; - - this.queue.pushRenderPass(this.RP_SSAA_Super); - } - - make_RP_SSAA_Down() - { - this.RP_SSAA_Down_mat = new CustomShaderMaterial("copyTexture"); - this.RP_SSAA_Down_mat.lights = false; - let pthis = this; - - this.RP_SSAA_Down = new RenderPass( - // Rendering pass type - RenderPass.POSTPROCESS, - - // Initialize function - function (textureMap, additionalData) {}, - // Preprocess function - function (textureMap, additionalData) { - return { material: pthis.RP_SSAA_Down_mat, textures: [textureMap[this.input_texture]] }; - }, - // Postprocess function - function (textureMap, additionalData) {}, - - // Target - RenderPass.TEXTURE, - - // Viewport - null, - - // Bind depth texture to this ID - null, - - [ { id: "color_main", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG } ] - ); - this.RP_SSAA_Down.input_texture = "color_super"; - this.RP_SSAA_Down.view_setup = function(vport) { this.viewport = vport; }; - - this.queue.pushRenderPass(this.RP_SSAA_Down); - } - - //============================================================================= - - make_RP_ToScreen() - { - this.RP_ToScreen_mat = new CustomShaderMaterial("copyTexture"); - this.RP_ToScreen_mat.lights = false; - let pthis = this; - - this.RP_ToScreen = new RenderPass( - RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_ToScreen_mat, textures: [ textureMap[this.input_texture] ] }; - }, - function (textureMap, additionalData) {}, - RenderPass.SCREEN, - null - ); - this.RP_ToScreen.input_texture = "color_main"; - this.RP_ToScreen.view_setup = function(vport) { this.viewport = vport; }; - - this.queue.pushRenderPass(this.RP_ToScreen); - } - - make_RP_ToneMapToScreen() - { - this.RP_ToneMapToScreen_mat = new CustomShaderMaterial("ToneMapping", - { MODE: 1.0, gamma: 1.0, exposure: 2.0 }); - // u_clearColor set from MeshRenderer - this.RP_ToneMapToScreen_mat.lights = false; - - let pthis = this; - - this.RP_ToneMapToScreen = new RenderPass( - RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_ToneMapToScreen_mat, - textures: [ textureMap[this.input_texture] ] }; - }, - function (textureMap, additionalData) {}, - RenderPass.SCREEN, - null - ); - this.RP_ToneMapToScreen.input_texture = "color_main"; - this.RP_ToneMapToScreen.view_setup = function(vport) { this.viewport = vport; }; - - this.queue.pushRenderPass(this.RP_ToneMapToScreen); - } - - //============================================================================= - - make_RP_GBuffer() - { - this.RP_GBuffer_mat = new CustomShaderMaterial("GBufferMini"); - this.RP_GBuffer_mat.lights = false; - this.RP_GBuffer_mat.side = FRONT_AND_BACK_SIDE; - - this.RP_GBuffer_mat_flat = new CustomShaderMaterial("GBufferMini"); - this.RP_GBuffer_mat_flat.lights = false; - this.RP_GBuffer_mat_flat.side = FRONT_AND_BACK_SIDE; - this.RP_GBuffer_mat_flat.normalFlat = true; - - let pthis = this; - - this.RP_GBuffer = new RenderPass( - RenderPass.BASIC, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - pthis.renderer._outlineEnabled = true; - pthis.renderer._outlineArray = this.obj_list; - pthis.renderer._defaultOutlineMat = pthis.RP_GBuffer_mat; - pthis.renderer._defaultOutlineMatFlat = pthis.RP_GBuffer_mat_flat; - pthis.renderer._fillRequiredPrograms(pthis.RP_GBuffer_mat.requiredProgram(pthis.renderer)); - pthis.renderer._fillRequiredPrograms(pthis.RP_GBuffer_mat_flat.requiredProgram(pthis.renderer)); - for (const o3d of this.obj_list) { - if (o3d.outlineMaterial) - pthis.renderer._fillRequiredPrograms(o3d.outlineMaterial.requiredProgram(pthis.renderer)); - } - return { scene: pthis.scene, camera: pthis.camera }; - }, - function (textureMap, additionalData) { - pthis.renderer._outlineEnabled = false; // can remain true if not all progs are loaded - pthis.renderer._outlineArray = null; - }, - RenderPass.TEXTURE, - null, - "depth_gbuff", - [ - {id: "normal", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG, - clearColorArray: this.clear_zero_f32arr}, - {id: "view_dir", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG, - clearColorArray: this.clear_zero_f32arr} - ] - ); - this.RP_GBuffer.view_setup = function (vport) { this.viewport = vport; }; - - // TODO: No push, GBuffer/Outline passes should be handled separately as there can be more of them. - this.queue.pushRenderPass(this.RP_GBuffer); - } - - make_RP_Outline() - { - this.RP_Outline_mat = new CustomShaderMaterial("outline", - { scale: 1.0, - edgeColor: [ 1.4, 0.0, 0.8, 1.0 ], - _DepthThreshold: 6.0, - _NormalThreshold: 0.6, // 0.4, - _DepthNormalThreshold: 0.5, - _DepthNormalThresholdScale: 7.0 }); - this.RP_Outline_mat.addSBFlag("DISCARD_NON_EDGE"); - this.RP_Outline_mat.lights = false; - - let pthis = this; - - this.RP_Outline = new RenderPass( - RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_Outline_mat, - textures: [ textureMap["depth_gbuff"], - textureMap[this.intex_normal], - textureMap[this.intex_view_dir] ] }; - }, - function (textureMap, additionalData) {}, - RenderPass.TEXTURE, - null, - null, - [ - {id: "color_outline", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG, - clearColorArray: this.clear_zero_f32arr} - ] - ); - this.RP_Outline.intex_normal = "normal"; - this.RP_Outline.intex_view_dir = "view_dir"; - this.RP_Outline.view_setup = function (vport) { this.viewport = vport; }; - - // TODO: No push, GBuffer/Outline passes should be handled separately as there can be more of them. - this.queue.pushRenderPass(this.RP_Outline); - } - - make_RP_GaussHVandBlend() - { - let pthis = this; - - this.RP_GaussH_mat = new CustomShaderMaterial("gaussBlur", {horizontal: true, power: 4.0}); - this.RP_GaussH_mat.lights = false; - - this.RP_GaussH = new RenderPass( - RenderPass.POSTPROCESS, - function(textureMap, additionalData) {}, - function(textureMap, additionalData) { - return {material: pthis.RP_GaussH_mat, textures: [textureMap[this.intex]]}; - }, - function(textureMap, additionalData) {}, - RenderPass.TEXTURE, - null, - null, - [ - {id: "gauss_h", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} - ] - ); - this.RP_GaussH.intex = "color_outline"; - this.RP_GaussH.view_setup = function (vport) { this.viewport = vport; }; - - this.RP_GaussV_mat = new CustomShaderMaterial("gaussBlur", {horizontal: false, power: 4.0}); - this.RP_GaussV_mat.lights = false; - - this.RP_GaussV = new RenderPass( - RenderPass.POSTPROCESS, - function(textureMap, additionalData) {}, - function(textureMap, additionalData) { - return {material: pthis.RP_GaussV_mat, textures: [textureMap[this.intex]]}; - }, - function(textureMap, additionalData) {}, - RenderPass.TEXTURE, - null, - null, - [ - {id: "gauss_hv", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} - ] - ); - this.RP_GaussV.intex = "gauss_h"; - this.RP_GaussV.view_setup = function (vport) { this.viewport = vport; }; - - this.RP_Blend_mat = new CustomShaderMaterial("blendingAdditive"); - this.RP_Blend_mat.lights = false; - - this.RP_Blend = new RenderPass( - RenderPass.POSTPROCESS, - function(textureMap, additionalData) {}, - function(textureMap, additionalData) { - return {material: pthis.RP_Blend_mat, - textures: [textureMap[this.intex_outline_blurred], - textureMap[this.intex_main]]}; - }, - function(textureMap, additionalData) {}, - // Target - RenderPass.TEXTURE, - null, - null, - [ - {id: "color_final", textureConfig: RenderPass.DEFAULT_RGBA16F_TEXTURE_CONFIG} - ] - ); - this.RP_Blend.intex_outline_blurred = "gauss_hv"; - this.RP_Blend.intex_main = "color_main"; - this.RP_Blend.view_setup = function (vport) { this.viewport = vport; }; - - this.queue.pushRenderPass(this.RP_GaussH); - this.queue.pushRenderPass(this.RP_GaussV); - this.queue.pushRenderPass(this.RP_Blend); - } - - //============================================================================= - // HighPass and Bloom - //============================================================================= - - make_RP_HighPassGaussBloom() - { - let pthis = this; - // let hp = new CustomShaderMaterial("highPass", {MODE: HIGHPASS_MODE_BRIGHTNESS, targetColor: [0.2126, 0.7152, 0.0722], threshold: 0.75}); - let hp = new CustomShaderMaterial("highPass", { MODE: HIGHPASS_MODE_DIFFERENCE, - targetColor: [0x0/255, 0x0/255, 0xff/255], threshold: 0.1}); - console.log("XXXXXXXX", hp); - // let hp = new CustomShaderMaterial("highPassReve"); - this.RP_HighPass_mat = hp; - this.RP_HighPass_mat.lights = false; - - this.RP_HighPass = new RenderPass( - RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_HighPass_mat, textures: [textureMap["color_ssaa_super"]] }; - }, - function (textureMap, additionalData) {}, - RenderPass.TEXTURE, - null, - // XXXXXX MT: this was "dt", why not null ???? - null, // "dt", - [ {id: "color_high_pass", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] - ); - this.RP_HighPass.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; - this.queue.pushRenderPass(this.RP_HighPass); - - this.RP_Gauss1_mat = new CustomShaderMaterial("gaussBlur", {horizontal: true, power: 1.0}); - this.RP_Gauss1_mat.lights = false; - - this.RP_Gauss1 = new RenderPass( - RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_Gauss1_mat, textures: [textureMap["color_high_pass"]] }; - }, - function (textureMap, additionalData) {}, - RenderPass.TEXTURE, - null, - null, - [ {id: "color_gauss_half", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] - ); - this.RP_Gauss1.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; - this.queue.pushRenderPass(this.RP_Gauss1); - - this.RP_Gauss2_mat = new CustomShaderMaterial("gaussBlur", {horizontal: false, power: 1.0}); - this.RP_Gauss2_mat.lights = false; - - this.RP_Gauss2 = new RenderPass( - RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_Gauss2_mat, textures: [textureMap["color_gauss_half"]] }; - }, - function (textureMap, additionalData) {}, - RenderPass.TEXTURE, - null, - null, - [ {id: "color_gauss_full", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] - ); - this.RP_Gauss2.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; - this.queue.pushRenderPass(this.RP_Gauss2); - - this.RP_Bloom_mat = new CustomShaderMaterial("bloom"); - this.RP_Bloom_mat.lights = false; - - this.RP_Bloom = new RenderPass( - RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_Bloom_mat, textures: [textureMap["color_gauss_full"], textureMap["color_ssaa_super"]] }; - }, - function (textureMap, additionalData) {}, - RenderPass.TEXTURE, - null, - null, - [ {id: "color_bloom", textureConfig: RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} ] - ); - this.RP_Bloom.view_setup = function (vport) { this.viewport = { width: vport.width*pthis.SSAA_value, height: vport.height*pthis.SSAA_value }; }; - this.queue.pushRenderPass(this.RP_Bloom); - } -} diff --git a/ui5/eve7/lib/RenderCore.js b/ui5/eve7/lib/RenderCore.js new file mode 100644 index 0000000000000..36b45492c3b5d --- /dev/null +++ b/ui5/eve7/lib/RenderCore.js @@ -0,0 +1,9 @@ +// Standard import from ROOT build +// export * from '../rcore/REveRenderCore-min.mjs'; +// export const REveShaderPath = "rcore/shaders/"; +// export const REveDevelMode = false; + +// Development import from a RenderCore checkout in RC directory +export * from '../RC/src/contrib/REveRenderCore.js'; +export const REveShaderPath = "RC/src/shaders/"; +export const REveDevelMode = true; diff --git a/ui5/eve7/shaders/custom/copyDepth2RReve.frag b/ui5/eve7/shaders/custom/copyDepth2RReve.frag deleted file mode 100644 index 17f60b2ea2258..0000000000000 --- a/ui5/eve7/shaders/custom/copyDepth2RReve.frag +++ /dev/null @@ -1,28 +0,0 @@ -#version 300 es -precision highp float; -precision highp sampler2D; - -struct Material { - #if (TEXTURE) - sampler2D texture0; - #fi -}; - -uniform Material material; - -#if (TEXTURE) - in vec2 fragUV; -#fi - -out float color; - - -void main() { - #if (TEXTURE) - // TEST, write known numbers into result - // color.r = 0.5370; - // color.r = fragUV.x; - - color = texture(material.texture0, fragUV).r; - #fi -} diff --git a/ui5/eve7/shaders/custom/copyDepth2RReve.vert b/ui5/eve7/shaders/custom/copyDepth2RReve.vert deleted file mode 100644 index 0ff3e68b0dc71..0000000000000 --- a/ui5/eve7/shaders/custom/copyDepth2RReve.vert +++ /dev/null @@ -1,20 +0,0 @@ -#version 300 es -precision highp float; - -in vec3 VPos; // Vertex position - -#if (TEXTURE) - in vec2 uv; // Texture coordinate -#fi - -// Output quad texture coordinates -out vec2 fragUV; - -void main() { - gl_Position = vec4(VPos, 1.0); - - #if (TEXTURE) - // Pass-through texture coordinate - fragUV = uv; - #fi -} \ No newline at end of file diff --git a/ui5/eve7/shaders/custom/highPassReve.frag b/ui5/eve7/shaders/custom/highPassReve.frag deleted file mode 100644 index 2bbecb46cef67..0000000000000 --- a/ui5/eve7/shaders/custom/highPassReve.frag +++ /dev/null @@ -1,37 +0,0 @@ -#version 300 es -precision mediump float; - - -struct Material { - #if (TEXTURE) - sampler2D texture0; - #fi -}; - - -uniform Material material; - -#if (TEXTURE) - in vec2 fragUV; -#fi - -//out vec4 color[2]; -out vec4 color; - - -void main() { - // check whether fragment output is higher than threshold, if so output as brightness color - float brightness = dot(texture(material.texture0, fragUV).rgb, vec3(0.2126, 0.7152, 0.0722)); - - if(brightness > 0.75) { - //color[0] = texture(material.texture0, fragUV); //texture(material.texture##I_TEX, fragUV) - color = texture(material.texture0, fragUV); //texture(material.texture##I_TEX, fragUV) - }else{ - //color[0] = vec4(0.0, 0.0, 0.0, 1.0); - color = vec4(0.0, 0.0, 0.0, 1.0); - } - - - //COPY - //color[1] = texture(material.texture0, fragUV); -} \ No newline at end of file diff --git a/ui5/eve7/shaders/custom/highPassReve.vert b/ui5/eve7/shaders/custom/highPassReve.vert deleted file mode 100644 index 0356489792427..0000000000000 --- a/ui5/eve7/shaders/custom/highPassReve.vert +++ /dev/null @@ -1,23 +0,0 @@ -#version 300 es -precision mediump float; - - -in vec3 VPos; // Vertex position - -#if (TEXTURE) - in vec2 uv; // Texture coordinate -#fi - -// Output quad texture coordinates -out vec2 fragUV; - - -void main() { - gl_Position = vec4(VPos, 1.0); - - - #if (TEXTURE) - // Pass-through texture coordinate - fragUV = uv; - #fi -} diff --git a/ui5/eve7/shaders/custom/lowPassReve.frag b/ui5/eve7/shaders/custom/lowPassReve.frag deleted file mode 100644 index 69887883b2210..0000000000000 --- a/ui5/eve7/shaders/custom/lowPassReve.frag +++ /dev/null @@ -1,37 +0,0 @@ -#version 300 es -precision mediump float; - - -struct Material { - #if (TEXTURE) - sampler2D texture0; - #fi -}; - - -uniform Material material; - -#if (TEXTURE) - in vec2 fragUV; -#fi - -//out vec4 color[2]; -out vec4 color; - - -void main() { - // check whether fragment output is higher than threshold, if so output as brightness color - float brightness = dot(texture(material.texture0, fragUV).rgb, vec3(0.2126, 0.7152, 0.0722)); - - if(brightness > 0.75){ - //color[0] = texture(material.texture0, fragUV); //texture(material.texture##I_TEX, fragUV) - color = texture(material.texture0, fragUV); //texture(material.texture##I_TEX, fragUV) - }else{ - //color[0] = vec4(0.0, 0.0, 0.0, 1.0); - color = vec4(0.0, 0.0, 0.0, 1.0); - } - - - //COPY - //color[1] = texture(material.texture0, fragUV); -} diff --git a/ui5/eve7/shaders/custom/lowPassReve.vert b/ui5/eve7/shaders/custom/lowPassReve.vert deleted file mode 100644 index 0356489792427..0000000000000 --- a/ui5/eve7/shaders/custom/lowPassReve.vert +++ /dev/null @@ -1,23 +0,0 @@ -#version 300 es -precision mediump float; - - -in vec3 VPos; // Vertex position - -#if (TEXTURE) - in vec2 uv; // Texture coordinate -#fi - -// Output quad texture coordinates -out vec2 fragUV; - - -void main() { - gl_Position = vec4(VPos, 1.0); - - - #if (TEXTURE) - // Pass-through texture coordinate - fragUV = uv; - #fi -} diff --git a/ui5/eve7/shaders/programs.json b/ui5/eve7/shaders/programs.json deleted file mode 100644 index eef8be861b9b1..0000000000000 --- a/ui5/eve7/shaders/programs.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "custom_highPassReve": { - "description": "High Pass Filter fo REve.", - "shaders": { - "vertex": "custom/highPassReve.vert", - "fragment": "custom/highPassReve.frag" - } - }, - "custom_lowPassReve": { - "description": "Low Pass Filter fo REve.", - "shaders": { - "vertex": "custom/post_process/lowPassReve.vert", - "fragment": "custom/post_process/lowPassReve.frag" - } - }, - - "custom_copyDepth2RReve" : { - "description": "Copy depth buffer values to R component (R32F) for picking depth extraction.", - "shaders": { - "vertex": "custom/copyDepth2RReve.vert", - "fragment": "custom/copyDepth2RReve.frag" - } - } -} From f333d58cfad486d30c4bd8c9d13550b3c846f3a8 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 21 Nov 2022 14:29:42 -0800 Subject: [PATCH 49/84] [REve] Load RenderCore from root build dir. --- ui5/eve7/lib/RenderCore.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ui5/eve7/lib/RenderCore.js b/ui5/eve7/lib/RenderCore.js index 36b45492c3b5d..815c299388a7a 100644 --- a/ui5/eve7/lib/RenderCore.js +++ b/ui5/eve7/lib/RenderCore.js @@ -1,9 +1,9 @@ // Standard import from ROOT build -// export * from '../rcore/REveRenderCore-min.mjs'; -// export const REveShaderPath = "rcore/shaders/"; -// export const REveDevelMode = false; +export * from '../rcore/REveRenderCore-min.mjs'; +export const REveShaderPath = "rcore/shaders/"; +export const REveDevelMode = false; // Development import from a RenderCore checkout in RC directory -export * from '../RC/src/contrib/REveRenderCore.js'; -export const REveShaderPath = "RC/src/shaders/"; -export const REveDevelMode = true; +// export * from '../RC/src/contrib/REveRenderCore.js'; +// export const REveShaderPath = "RC/src/shaders/"; +// export const REveDevelMode = true; From 8b242dfb5d75180dac0aed95c7e0752e057b5e35 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 21 Nov 2022 15:40:46 -0800 Subject: [PATCH 50/84] [REve] update RenderCore.tar.gz --- builtins/rendercore/RenderCore.tar.gz | Bin 95908 -> 95882 bytes cmake/modules/SearchInstalledSoftware.cmake | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/builtins/rendercore/RenderCore.tar.gz b/builtins/rendercore/RenderCore.tar.gz index 7d2d0ee8032be437f19fc8674b10272528c89160..14abaa7f3ba4a051ab494ea7760bb16baf38a8fb 100644 GIT binary patch delta 89601 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
aeSW-LH6rt3oYycut4Cu8{B{9GPoKn= z`l4_yTiQ~0N;|65=bzcUf$c)Po^)tXiWr|ONu>s6CkCS#e%AAX1b@5jwEUEwxjGhG zfs?yV@x1WPS97jcLQiWs{ffU`&)ti8yZtHWR6QTg-RoN&i|Kpah>Uk5^Y~Tj#@}CbiSYf-7A= z35mvy*RJKiSif2E`prD+H@j$g#=)9Bn5Gu6W-W?ku>PuO>VNXdFAf&c8#ajuzM@th zHK-P<9dV}y|Y*t$ssUe_;7A877cppe#*BZ6tynW%L zSEnh*p4fkWFE$e$^#R&IL?r8v7P-d2^Km_7HY5O`!6uJ%=CRn#UCXn@_$xGP4zCSM z7%k%U*~gM=#DDTm!Yct`F@qdOVG<<6@x99LD>nE!$*6&?-ug zf+Mi23P#a9ZQu+B=A}}Qbu(u`Xa?10ugL_jCUZC0OM;v_oy~w-GxLxod>$+n#*@VW z30r1{>3{laPX{1a}D+Ur!rPlKbf*9OQUyxdNnULk`iaZJ(*@{P_ z<`=mh>;6EQDcbH2wD$u|DRwQc>8Wj08JT!Fru!w6S0oZIp#@dzKDnhyMc{L)wU$Gw zY=MxQ`BjsxJQ2;47fHuRNZv{IgJMJKeW{ty34cijG^df_BsH;W`7=(zw6xi6eGV<3 zCl?Kz*4zje7CKtD(kH#KW(og$9*o%MVKkLbX#fp~L6)7*O}u6?f)~viOyx)^?uy!N*vR#9x zr+;&tOwwe$HZ_!(G6ErpTqZg)pO^{hE`3aq}v|v)}93@EpVN zQi$9mAp#(>V!2;y;Y74Itx9Y)mc_(Iu<1E{T}X5de)DE65L2U35?7K}KG_u?Fjf}~ zgo-SQlP_-8#(ImxH4yvOz~9wmg*A|#$A4mePH;8E7mSr7R`m(8_z4!ATr|W)tGei5t78xluS61(L*jzamZNS)$+jwwv8)U5K9q?op> z1&N50bq?cCACM7CbM=T(p=nS%kMvMPP01#VMlX|b8Hhc2(j_19Oyv^{G6U4z*pIqWJMs)ldbT6$hixIRRRw_)>aqR@4S+?qK&@6K(a*lGjH zJTPk;=O7pE_!_)xZJBSx-Q;;Y6@R4y-I~YjRQik+2dc>lYVjS@LI{~_v-7p({s(Ty zEC6`C!F6WCC3agI2Wbr-(oV0%&XA2`ar|rzaE!_(<$dLROlDH-dqQ z!IX<_Mk?{&895|YD*d-3$8{(UzSeuW^mj%Y4~D-Tc@%5b+w<>)D1_HfW)SmZUO3ho3{sk<9no8{^&Vaw7iyo6|j8A`L=|v%*tmQ89*TQJpYIiqg?_MBN_CmjW|skxGCOSHy*C@c9Ch6nxp0v#>MI5X zPWFNXl=9CVS@Zd=t#f?JdII^}tjZb4-1@biS1xXRIfhla@t>=Fy<>17UD&N1TN7I| zv29Om+qR94GZWjkZDS_3&53O%U!M2V`Elx0-Cet?tE;>ApYFZ;Uh7)y-4JW#>mH!D z%me+;DR}^vxnc45@QCBb^Nw8;^ez946UMT$Ve&$4)M?Y7h25pwD}zh%evkY)V!N@v z1Mg>ufihQ3W1hvC=PQ$^@>`zkOUC(b2A3WsIHX|U3IR9~8FTL2CQ%7o=sj@a|Oy=xZ zP|T2~_c?RiR(yIZL0g?GFE#b+?SXPjswFCW@oc9t_(Zq)&Jhw*vqWe*wTYlqRn>yz z3S*MPvRmE{<4hiDPbSL=9ADEiSN-wpuLi@m+3DQ2(G1RQ=Goie)a7~4*0YZX`*u_3M2pMsWdEnt6;r_9(wYI1<|11pzp3l7(*NBe6(wfrYdf4Z z91-r=N9rUnSipD~9Af%|uJ#ZjZFQ>(AM^}*8l>n5l=a_=TDwMjuN2mG8R158_NkGC znJk7Fw4M6D#62A!Q-1$Z>JyY0Ah%^41JMFxPE=m6;j6ir*;SZn%?Dc&AEX*3Te$~#Ybp{<~UDI>Sx(1 zYXR;1Cz44kQHLHt6?H=kmWTM|WGeL(bY{kUAO}Qq=(7GV&c47DuvyQrJ3#c*bt}O0 zp?mm1aOPn+yf(M{;m0-9V^c(G`;ylp7R{8bWjft|?gOb&$vqnChO^#ICu$7HgQS%R z{IajKIfAk`XRtjjwDwAF%v!zFS;5fmk+DOovNamMwdZ)3tB2ZlwLUG~`Mr6T2-`3O zE_U@QBDt>c4XVl}pPKc1!1SJaDzD;xv`l@GhNS=>%6^KfO$ev1e}lA1=BoL zm_5?Lrxxb`XOnmG0OW5ot#7W*tny2;jM;`GJ+^pKD&rDo%5Cq2cpFi~6mMQFP7 zF00l)PQTaigmWg!x;`$js(-Ba9ZT?x^Nndo6mW;8aIdtRcaj(NvF_y;NL9!GD2lT; z?aS{)nDpPkT;Erk7p@VTT04sBn6+|Ln7lX+Q|Zib^NFKQ1wt6eW)S*^S3t@wr_kPO zXZ%DiJne=l2K&&7t~>}=nRjm<_qU7Re)ar(?AA$1fc;gYMvkwrk^%nyN7@;T@~wb) zRTWI#$bJVS&;WdTGfaf^%dPHE0Y@YwKFwm<=8YpOUN5}7DzFX>d2jH)dWBLKlbGE4 zfFDwF17Ji)!ifx_XNsa!7{1FC+NF2BXK_^nLEjxrwW9%R35svqp*b;f$o%-{mx#fQ z0ni`68l%m+Z(W&d5(oSZerbi;ig6?JkJWC zn2&?A|By9^d?8Nm>t)g?IlQ_;YJad-;L}$%J2ycZL$Zr>GeDIk&?C}s;>ClB4xg&59X4%&JV;Z z%Oh3<1x5rb08?LmcaM(hW1layyo)aMh=mKO;^-R1HF z@U5e{la#{_qmx5SE^#`y17jv|np7&3p{#BO1X^#ZTLnz!sL6pZP*!G?TSJzWCD*Lh zYyb)Y8bTg=^RGLju}K2>V&-s}_CD@O9rmix@%@KZ7ZEr)M#Xyqwo0XEHsH5W>Pr)e zr&kfqMCbMZ;d3urwInFV&X3IS%lNl`(}LDv;3h*ccair@VM!y0QZ{;miGPKv5zTMt z3S*f1pB~~|W+x-4Y*BNAt84d(B#r^9NF^O3LBgE@uCa$)VXDjb$#M{_pH zImJ=+<0c&vYILU~Wi!&=?|^|3%j95T11YCLllU~ELF~r|V@AYkDmhrUE>IVrOI=pB`WB$3p{v~1$BbeuOA@r&7ox+Q~O1i~@)KuFv&KZDc-CV1#(%CdO zY!6iL4pcKnB$8*?TgSxaXcd5f$8km?onN4TpBow=s<(j(TR>UICN{VFtIQN#;LT|g z;=+*CqM*`Zr*M@>Tbrchb~!i0pM8F^+nW{6mGkYCGcM>!1O|@HV~RTYgH@a7&vVCY zEK3C}_ISUg?|#@j!7m^~q~;<0$H}Nrb3^PF_)ieS#Z{?6!ty=97!;%$xqx##C@v zznRj)7IzoqS=JB+M@Csw@b`il$nbWr@3Me)-?u(TydXc(Ssfti9acdhF^}s5ik6Dj z#EQl`*38&~L_@p66}MeC9p_1lZx+80!*pk&d)OZw&G0uvtmJ6DbY7Bpe_41a5q~|@ zk)b)0|2DH6Gm(E8n@>zh>cAT7jMFiF18bpjqV;MgR!1;28OD+p9uNLSCKwTbo|4ic zBDf&e(bLr3b`3~$=j_T2r15XTq7FRA03Kn>TI%-z7q8@P*^oCy_D>WI*_~#{6*m%y z$X`eo&n^ll%VmL)C2hV^Gj4w#sN$O8eT^lrdC{DR8fO1)j5?Fg+9(WaWBs*=p{J%5 zNnL~dPOEK+_mkWjBA}hER+hoqHMC|%DeKyaPlrkE(GbA!WY-d7cNmTjpv_Ko71zC9 zO4vhfb`Zg|{Q4Tx?@}q!SmtVoBq@KV`%uksMG|tR8!^Ld! zIHU@KkOfSwIezz<$)k`Ko??754xH4&zRBl({j$4!2#`(4j!ZC?yVKRR~J%gq<1!Q$I^H@@iCC8f66h4i#w5w9|C6*4U*#2j-gdOD+Jli6O zvwPYqA^kBzVRWli5R8}uQ3;L(*pU26)$JW`2TIt5^|7uv*NMLgBoZG#V{^N^Fk0Eh zOU#uXO2*rzK}6ospx`zixy8EX6e*)VKENn))!D$CnnS=Ch_&>qDM6ao?oLU406N8z zBQWpnUA>RY4)-UzPCdsB$66WVS&NK74E;a4Mu;4|#|70P@5!it+>`kTwtfZVNw~-t zbLFz#>^HAjA)>c-Kqt6T%-+ zrEDV$qS?8|Is}M}>SKnFiz>5LX)-#kYdRrMvedVRHdz~2>Y<$(M*ayKRI~C(H|-~+ z&izqgzrC0*ut8yYSG^lD2_2I#nNA7(SO(W5sft4#SWCY+4o79?X>`5Wtrfz$3@8m? zDoR5`{dx8?kwe1vFm7fRC*v#jdM3W+ov>~^HCS{{sGoX>nx*wfYx|GZPQNmem4OZukNScAzN?YziBE1R;fHcj1w;c|o>Bjk)I&4W#W;xzKSS^<}>G%%T_|r2V%kPgeh)rq7Sp!~=PRA7A`h=aqjT;;Px4R^32)m#c#sfnZdW?$?6w{Sg5oJ4nUL2@76iY$9Y+ORJGj=ad- zk}>UgQEiid`z-Vo#z3dULlV?pP&AzMv0D4D9?nNQqvv~)L$f!{4sR3n%y<*LyX~2r zb5f?~Wffw=Pogc9`_emR(VSs%L&O>_W8tSe~rez0Rm>ywSpX&@MB13ovE62 zy6`qE;e>D54}io!)+ncAnvw`Pql|6~j}L}u|AxBnopCB9!f7qxZgN<8RJ-Du(ZQE+)1{PMOp{+ALPGQqXdZj7jHH4 z6lCY`WHL&vL@(HH>X}ctprMuKqAiz#0-WVgeCcWd-E!0NJ(=0(0Q#x<=h4~rd!L^s ze95CF=H@(-*bZw%bv`4NPH9)Qji~JTd%=4`7E7JapFm&WVNZ_A`bp3WnR7gIP<_Rg z_-UZOc(DareHq|e!K#AIKR@@;{DbWlA{e>k=H18VA^(92CAnYpT7GVQKlU*xxo?(Y zEniL1TDB$dE%M=zS$Gz-0LokJ9`j%0EtS1=di){1QxqiSGG&AO0RvlW-;+)uIKXFw5d z(gT62c;{SlXYN~nK19gC6*u$~zfx`=Wovf%Iy>(BViV>|igt0F6S{baixjHWB+1x!D^=8%u#eAMd* zr5BW#QV_t^S69)DWS(Im&+ZPL4O95NjeA~}E1byP5BE(4?8ewZ{k06PQypqE1@fv} z#lNM=a{Ij#WOE8*yDQ%K`=7X*53xDw_w#1&|G9$tuBBp;uJ_dwv@@roH(}4wtJ&EJ zYW!#@tLJP$PEhB?!~9X;0V9SsA*;6;8hbVd=vzXWNBUD26STvSx0?u`n(&vlV?!3Y z<`J5r#60LdXYwKD;o%Xkd72u#J0_mB;=I5c!?FARvP61kRok883DQDs?HDUp!*lQW z!JFPs)xCSj)>G~@V{=iS#?}J~%yPdiM;N< zpKNYU_chvaapGB73I2X+{Ia?{mjp)<;9}25rb>7#C-OzyFH&s57)3_7TRsE{t+byv zDbcR<+RR&w;MjzFDK5i?wuPc*kWPG%A}zD z6;^HC1k#JIOg>#c|1rF_(McKr zYe@$M^iXa$rKJOdOqe9=KrF8*91a`i#)W{b`i#b>+v$rq*K;1_PcvFW@y zr`h8+{xduK2Y(q5I2&5k^Qi=Y?TwLQE9u`j!$#&{^~FkmA*)}-OQ6k7pYVIf(pX0? zD(Gm7pUGk6s9B`6i1TEv=rOHw@1NH&3FHfVJ+x+H;cYsL|O*RRps}*G0X_=iQ@| zyTry9L{>YJl>V2)6)1+~{z>PkYVM}kFqPZEv+EMw!ZY!ax?Lvq!b`2RIQKv@^pc2O zYLL@Q-UChu(|N&TVA5OLy|->5`WcE47FVgUrO-P7q2^?%Fx_FI&ReFi+_A3q-=IrP z;}&SQo_;`Mhl*~D=Ja)a@20viQvN&lq&fdPDGQ)0otY5)N z?!?Y&+3@Dz!_CR_q%m0hGj3JW1udDfu(`3PGy1>uc;?xLi*nS}Ie@^-_-=ooEz23Q<*%Q=wzVklwU0G^v$|97u2h>K!Z69te;Gh?zou z5GOz^dIxu6Sp=~@A$34+P^O=CQ73dYteafk_pF#a=G--Ba~^joc%M_q`U#9*^pDJH zTh+S|vS@}M2!G;@hulw4JA>L0&W8kX*FPp~eUyL3o|IK4CC4+%@e2EVW zE$^`6-H2-Ve|2>&mRV;KZ`0TWep()KvEqEFZfsIvjyr9jbWjsB>KA%LJpXYbzM{q5 z0BCR1JpkWdo$abX9dCm!v^zWOqlonG_3yO)e%`0fx0eCoqtmXC$bwIeLB;MTwbA;x zhD7?zqnwbM^}?CSQm_Y!6uSH4$ysq4-*bsPx z`ZHyv<}-3K*>8kKBR6_^r6!tgkhor`(U7IzuhL;=N$;*-t0`K#tf5r8{A8Mv5#`r@Qd)^)k$6DBXZWT zfHcLdrTR{*wzO3qaJl5ywKdeFfBEQezVu0<|5^piS@+!Ad!4s@$kx2GW9q-Uu1eRf zR|#lb*pE87D!@Gkmc zK$n1R8QU64)ttM;3USC(BmJ;8BC21mce8jBqt~h=u>YwRyIGfb+BfSTKYOCu<{S)C zllr!bXgxtwE{=C%f54efF{sMTdGvi9myn=RJfva%ogBKQzGO`ei>2;{;ZRdUpk}1^ zx(U7xz7*z>95)dxyp$^l*r1J|l4hV)|A!Qz7~cp^I}^$yiPF6*vPmTjqFJb8?e|m= z{M)LHFl<^LGd{ETA7Zp~Z*nT~a)x;-3K5d&IH*6pww(LW&Q;1|Z+8>4`<++mjj6-P zh5;uOG{Z|$(IHnPMw;jDi=vty+`>&dB{ZkKzsRqor@fC3Fh0CCcqre$ZJjq+T* zpJ!$aMtBo4flaDPcfQ#*t-43S9n#D|s`^W1lVkP!p*+*7W|VPkgot^7%LXy%c!_x9 z_3oR_q9HRzRnKBDLa)zLd-Z95s3Q>qJv)ZS!OOEc&hAOb$k?EykGA%T z02gQu@@0?(YP28%AZ=ib__y-iK_lU)QB99U3OxI%8FyGyf93PohB1=Dk(rnw9NfvE zcm

ckA7S^5JU}-H^3GL>!#&NXKv4=E1%u|7jMT1~$f!yOEHlPto1t-^~S zi?T?0=b0UBcg{kSwp5rCpjB-5mw;km$%1iecLVm1{T|605EfexKi>p)b$=Rvy+c63 z(1A61^-T7RGtbxGsmx?HU||H^jk0c`&an$xar4cgYk*OW3)QA;W4li8_bBG!D0+^k zwjd)8+G2Gf)GC(u+|MW-xJ1an?-ThmHwsPR8Pw)4M>)D@%ngmxNj1O0piZ|qs(yqz zDJ^_Q_)?@60DKS1nX@}@%(T{&W$V+`{)M>GKaJZ-T<$h;Mb*`BRp!$a*E_vR2M|-f z6Ot|-ak^q69VQ6UR%!0V2^x4EO?SqG#y1U;tgE2@x|{h`>YwjDs$OFcFmByVXZ$x;dPgjtk+JW&d-4adkMF}0!yeAp(er*&EcBxw;Uu%>3CdVwT6`?!=)bX z)0e-J)3rS{H5(W~tx8$SXiBg}C)Z*^e|sPP`z7bg%fBwLW^Zx15v^`wB-4bzHRl#J zQ_UXLfE&z<(TJ>H$$9IDbC(+9zz`2D4ks(-mjl2b{!Own->W4zfpqKyc_!#ODrUPP z_CzbZ5OPmMXLDPg|TCdMnu zH%FKdH)?Ue`Zi9_Pmo0)fKj1>R?;~p=^@ew&CK*8{&PXhp)$}}v>n0fs{N!RCpTc3(>m& zq18#|5#Oc6Duj`Oeu*`*Au6~j!h5ghQxvdm_%lYZvWmxI2`u18;=l#Y8C>-0^{uGw zp^_l#;fo_LyyL`XSks!L4m?S$BVuva^@dzy@qhv+Jh7J?9}UWYpk6f|ANU#L@AyHb z@Uv^)Sq&w6NQbuf9J07`KR*hy`N`|;r@7<4l|KCkXaON!_&c8Z#MEMt_t1VVk_#Xi zB88r!uSls>!|Lo~MM)<_5uy9H#bM+NGnn29jK{HnZm%|Hj#N>1@Avzn&l9B_T^>u; z&sgyPzcBU%ITpe__rHBB44iTBPQ@k)x=VS9X#NWeO25$lqSZo%t3uATR1KDt;-a+^c0==mjG8q3~Jdx zQxydYSWO(@1QmSQSw3%@YG;k1FpQgzg&;@Zao>ELD2<5*s58+7TuA`YR-!#msUCG) z?oFG-5gq(9jCxJc8ON_T%`pN}feNY7YqLQw5t3@G(Uf0WLs%`%@HumEL0NO$G%4NM zr?W#Tl6tJApp0c4ChWKFc>K_Hxbv4uxASDc#HoYAfMr@H)B-SGVU(oV4bV#t<^!9)T&Gcbp@89hpBwm zT*G_8M$mvxL36F9Jnp#5G)xsgP(;48Ok0n;Za2eD45#hhD{--t1O0T^oJVqHwCV^n z;groYIU1Q7An3a+!_?o(Kec!=2Arzc$?#Yrc17)&&}N|8S-l6QFIVnPus< zl>ho1nuN%qjoMLf{bHV{wi=wbc{%S8=ATxQyN$fL|ARgU75@>)oDdLl`)(k1kRA<7 zJ!iK1kZHrbvOtCiN3$yDSwj)w^_>T(($qew>HVjnr=kZ_Mz>EpxFM?TY>aZj0WW%5 z+=%9EYD(p3F0-4gjgCvel%{_aKl{E>ni6c3RYv50D^f66L- z`r7M~kP3P93pwae>Veb&t(#`KV>TM@9p?!BvOZn6?Xk>7 zbLnG2$Q-W9WA#G(+Io;*A2v0~p?wy7a`dcUvK4#R3nF~XVl!8#Q|)hWL?6UQR(Ioccqyq{*Rx-{2%iFUVSebOJ{ zjM#T;ki=vl)J0KTQFLC0w|wE4AoEnXGq#aMKSFzIC|8ZJ(oaUWu3Dh8lF8E*;V;x7 z)Qr4Q5guR=#T6;=nhx}V_lA&YNP>I&k(lQ9PoKhYC8<&O&bH~a>dwGH3ML&H#Y<^} zt}4zLns^WXIqTT7WN&ZNOKDXcEKcFsn4{|W|3bgrLV6<=3-w&!^rDx&N$BlCR2Tr3 z{KPZ$853b{@v_e9ciqBC%H8@m)YpUG2LV#i{j4B-<#ODWz67IeG70mF*=shqk?y}!!FtB|l^9f!S*4}}`d$D%d z-A$DTOwX=7#E<+NKXOX0*WG>gYW3??o=Afqd0g9R?JT311-aRm7GuF^NQWL(B2LdV z>EMZFQOemx`y+G_PFst{F1#KWgQ&E33@!F2#bbE11K`y=pYi-7;wRJ}Y|P+Gm}{&# z`vtw2V#!n&ii-8I9^^%1OhMGDNABR-d8gcBFh4?AH9h?{xqk1?&s+-fs<+9oiO|ik zw9UiPZ!pHPdIJ)QXQ(cclI1aNi3{cds_ARt<1bVU+u>1ZE!t+* z-VSZ)X!b;AGN3rsB!SHqfvKPHEny}{acoiHNE|CV-JhE=_Of9Nb7gkmAQHeKqA$J- za?4YN{|1d{T}6+p!+jgeEGjIA#UqA{iE;{P+H#* zo3lFWZlg$Vy#i?A8Zen38O*HQ-A0K6=z4)>N{ATsVVu33g!ZM6mdu3UtFT@F zEVGqbZXdU0h85qY>vF%>OnWa9Pm;?!x4y|3$Af>~N+SNUVZqN4KBEDaYAUn!H3=9l z{@u!w&-GQ5+#@fwlmrcL$sm(;ydrkM(Alw=WY0<($!F`KO0#dM(7pg1XB6yh6W5+n z@&SEbFR&TK$7Hs7J%&W0L2FP6C3o_6NZItGvKx0wmp46z;$;)I@I^yz91+*TOY5L} zb2^>ps+woGoHjFJCGObMVA9d!f0-4di*yZ@>b8W3Ec0k8mg-b_2^5S`{hD4a-P8+_ zVCk}o?SqfJpc%xDFTeq#-k|*mFSU$1iYgkgtR!1wIyw%ZKVC*_LA|h(^k5UFT2P)7 zy{T@5-iq^16YOX-^n1(i#U#jmD^L^zKm2f`zjX2AZ1^vuv4&PIjT;A@6t`HgO+!d&$ zM{q+6HMLKUQj;2v)5}iz1h$vloOx7(+E!J`UF8B)JwAfCu|YS#w%<_)jLAOXL+atg z_LM;6_T@BbJ;>T2zKwbnTrAz?menbU^qgt(x+g5Dgi*iVR7-~acokO8a&cNp^%!|+ zWbxh1=VjPjT+md?0pFLL#P9pyJQtX={LIKU2*_79FG|TA^ob;GP8B?soLBcfv-e$C zYu^UAob{b6ASZs`Tp>9lFl>}kdDO8NbsV)l;h^=lQKB&PRq%$HS{Q>JE=bO~uQt`+ zmVCSRR^O%39ZZ6)*@sHXq-{N8>f zuWes{*#{eJLLn1Z+SxUvPDm5n;&iryqe=@LNVD2XO0cR7IpXfH2>yc4&7o&J5&Rn$ zzCx$ZQ(iJ#buVVkuj+QL37##~KEYO~{dNRO=pDEv6J0C5lp6wxXS!I~i*Za&&U7QC zLC$O`OTOZfbRVk6R^^IoatnVk@AAtjjMB{^UkC!JT}d%Md-Go?;a;-K5mTez5C2)< zdoJi)*m`5&5`+&a{WN=xrZQYTSPfxmr(yOt@L8h4H0$wFD0i>2c|S&s`WjNN0t9J&@zgUu$onm<&kVr+L#Fww!Ko( zIF1%O;)=Je_K1wn5%h;xne$EHib61xOUdyvBww8H=te}$Uol|M!2s|#d)7iFmAKVnTKNBqK& zRB$L8I|pRO=j__`cIeB{pDsYugAg=FKN+n3Zq1IcOZncngKPg*Aq3=~Y$mA&X3J82 za~S-;l!WYb&JArGVZPgVhi zcJ)h5oE&kh(TGE;(uIShnaQ$mF0mhg&M14_l)5i{T=itXR^NQj_b&kvCJs!PZ?L5d zk=*KU8VId?^nFFp1PB75ICJ4baF?1c=~GoEx+ zMzsGgd47=59Jhw}zv66wc0V>IcL?)GZf+(as=j8{h|b499dX3e1mw@;p3dL^;ubC+ zkCImr4|RK9QBxakYgd2yG4r!vsE+gITl58ijM>c{wv~1Hgfe5~tfu5_XAs2gb02N_ zV*%~h?vDnWIY4jdq-O#)yY3U=%B{Pq@Mkec&D7~nkm2T8{~&NZQBu5Qe{4|_I|2qetU0o!g-ozPc_w^&GtW!X&==& ziV0+EoTd;}6GS{nA*FG0imfR`m+Rh+?RFwoJaF3=-@GdQa!5e4E9!7$V0!W?!(t%N zWB4xcP7E&#q zXrs>Oc-jN^P48-3e-V^tB0mt)4Z2&4Bxj5dI}FYuyUn2=uEmB?#hp#! zSNwc?NO^sB9p}8J?h=Xy+&9`E9-0oX`KEXfOemR1rb#&|%uoU6e`N)-G%i!}7gV!V zE@_lbfRimQSAE@mLTINjoEFvN=qg-eLT%A}Z^` z__PI|Vj3sLhl*w=|MnMkcCgeJyM~fwD73X`ZtDhFJBsBu@8S?$+RNhGdUexkdtc8) zkYeE8zj+oM`znSRv(`oTF7bW+gig}#9#NSVP2lF@4;_vweVPh=ni@Th3hi_H&;RVB z6cs$_f(JIKw%XRMh(??|@=Z;D@25*rO3GIZZ}Ch^0s=tZnikk)@R1sVvFq%F$V$^yFzaH%{1yJQlOEbM1Jlctu&le1?Ve zfcoOYKlp-n&QJ0yc5D+}yQ$qNYDINn-TATC=)cY1J;?~|>yQ}K;A*uI4QiNs{n-3Z z`Tcv+?wUX3V>cIb6uoG0@8F8sD^)BDx}>&WlBBARNFBvoqV9Ru23_@%Fx>X0{a984Ml559kbQA{PM#z~6?jlLV9+%2p3n zC6dUixE3gu?6sP0tHaS=4M0_Pm89dRdgH)C*{x$29U59^(^vtd`vgw&?&87(zoQc{+ZDce z?N2l?uCRqXbHwH@C>CEr6bnk?s3|D1w{1Nu$Qa0vM280u(mUQ&=Jr)mGksR%Se8q@ zeU_W&2>eL>D!>#L>X4CH=@LK~#AgS}3i-U*YWxPCzE2(wH1vIuAdp{6>d|Id;QsVN-T@;dkuSn2q$eV6 z8wy*y8a$?^3}1SRJ2D0DuA|DZCgNsO)N#3m7#0K&RM{L>F8VlH`AQ^Kz6RL1=KTzk3q5j3YUHF)w4P z2Z%%mY18%ada+RfW>2L_qBFMFbE zjR9G=YymjMkkp5sXkznBm)5KsH&xto=>1%TP#h_S@n!ze}1Q+=~l(AQIa2h6*QX zXo^8J4}9*Y9mNvL#hp>WO680BbTn7;e?(Vi!-% z!33ATgqJl0-XwyO2?y!RbnPgXyg z#HRtct6JKOOfVRGYF2_hr-Zu#hu>reHYQ2lQ~BzzQztGz1&_D&b+WyaeG4L2v@>h{ zCl1|^KgCQujEm@g)zLzY=mC*&OsR`bDGaQM;J5xX7?h+hg*?05c zzOujV#;=q2OsnKC2f7%-RG2W5-hHH1K!yM%TL%e{2D04G5qd3$K$+4ZW~?O?u}VTfnFZ1p>C#u zfBDiZ#tt@J#3YCH8oT?rXMhF?1Ee9699ioPp{5A&gAt`VxB24>8|U z);)4`@u#f^;E4Lv&7^^AK~$Uf4spqUMrAogFU#jQ;*#?47}(aMoTtXf!K(847?X*a z!(2h+qaN12X^*@fo6c5-z^eAWafh3io0Ef04y5c_!;d#95>8#l3#MriD^DceWJbYi zN=}G$s1hSE-lo3qumws%XCALlm=y%BIgVqro7m570RC6c`My1*wQ7r|E%c547tXe8 zJMnDV5G18(hjy+dMsg{x28|ig^D1*&v8dXB)lzy?rE75&qbNQtF#hM}HA%f~y`!_* z(9lp;Q2?{}R}f@|t)Deh)`ab#48f37q`a;GdGy2J^}l1y9922RgG7{-lJXz!7QdGB z^3;9G!!wmdG+uL>>|`tZ**TqLC%q|qdeALz@Z*}M70Jwg-aJ})1gyBU*3-C-(zw#6 z%Z1o^hE%sCZ5qv=0dVhsE%voF^@DL4Gs}O1Z>496Ps=W82fDOR#?Lo6R7wcK_mEi( zJJ`_jic-jOl`T+lyDo~yYNJ@%2|X=}XtfgtzD*Zb(p2Q(OcD#Ex8)1w5eo#iIq4D& z>lvO3`Q>)X9tu`tHAc^Q32mKn`bCXGFz(YR^r2Ua!QrJr0(Z4cnlk9oGRASj-(%4h z_TQUJ?-<5ki`b99+1T9wcf|dFqs(6Gx}ASo45{(!HxnCy_{ekd*t&NK=4L>>L&)|X zvGS#eJ(znkv?z7=gjvSXRkFCX9YI+~H=fGMgxU_P!eG1(-E?(Kp}6bE|2qJy^6T{7 z`&rWNX*?iY^88IHw;ugYuyO27yEWst76&_Zs=J7>jGgl$3sHLC#uO zVa29xE1Ag%kVs5sHV1#gQbPPOQ4u=7DXuP5FKVdZ!1a0$uUub`2>?U_&GAMyex^+s zF<+A!+l~aCKADlDN>aH52N({IqIg0@Irl?(f}kU~(AF8CPvk|-r-8GM4_2y<+?49b z!H1;={&KKi{-;9p6w>P-Lu>XU^*VjavbL5M)et9%ED7mR8^yKM74cIC46J4*1Nk6? zj+L-S%$aoa*jm!}$2(B1()Icz_Ze3+S3MQ*eK zS?Qt1hlyGl4hY~B)T8d*SFm|qs%>S`bV5C9ZPT%9t-a+#h40e;UDiwWJrko0Au)6} zDM6X_E*!1y-h_jc;UK&kG-EX8rnK?_)bx<%bWQ5Fhmdbbt@4(0?F%_K=a)EE3#B=`xad76o<-rn^qw){x^g#WP@32 z$4FkUMPmtSp<-I6N6YyXBYmxOdflw)pqZNWu^f(RZDIA)C#9W zt~@|el4NvGD10K?{b<20ijMXq5h0HG_@ExkpQM~YHNGMR0?(ik)$UYFN~-WUz->HN1}w3gg`fpS7eDdP`fg0Z8a@jD_kf(k%27CJN6sT&J2 zwIF$V!AEKm@%c~wkU8}Sw;tjvcCBqqgW9Rr1lxDdfd~rq8S7g~_Z?axy>N`BqjnI3 z`iix_rR)!2Sk%yc7;tI&Q)*XmmY6}4uEv0ip25ooca*t=AHp?UjdGZ%kS`^)AZMv+ zum_3JQH0T9YWskhudPtmgR;`kzJ!%8ow7%=f+LVVK4LtQ$(#MZ4*a3bgu*2;Bret8 zkBv(&a02g`L}E`>UsA8H5aeD``v6BT$hTJISF}nPlB(dVvE8Q_9SZBIMvKL4Q^+d5 zIVUaeRoRUchK%xUHk{$;zR{9;MdLnX$Ld7L+uHeG4WP+#KpY5?-caD_X5 zn@d1Yfar#kc_OPuDgIS?*^1{1OYd>MJH^#X0YU}GR!Ot*ICYkOHV$%fM#ws&@5ajk zM@S{Qmfz>1?P|A%HluL|LKsv~eE5_94Uso+sdb&+uaP<2 zmh>ok5FS@{jE|`q*4s>=r_W`?jT_?MLtIL$_Hlw{pc`Zjoy&glT3;uB6FAXl4fFN}4Pz$;LNVl;z|{i-j`AM?t5*%#)2k9l3b?91}U zyehALz53g@7g_L1+V9b${7SX-Wwg0>EPW7N=*Oh+dUe4g=*riRy>Dec+FRay6olz6 z+ynG-=8d-XXfJ2ln7175c9t`~Nj@4dxl?WkZezQBDOr(sh94v}cLmTqkI#dc-Gfg1u4b(>9oelTT}bAi|gT^C4`whbDJZD(jO zGnVo*k1XLI*#?$>hd%TE`_L?>9q^EN61Ku55nN>Dd<7KUnr*DsRxY+{pQpb}<6CU3 zh6Uu@hTIhv+z9$;AF3qZP^au?oyz8zhV6O|X^_st-07a%NZLFqbjdfIgn>Aw&C+^x z%JR5;rd1D$EZblTUAIw`9FQGNv5W^Gq#H>0IY{?8NcRPQknSx=itKsPDYqPUpNqnQ zs61Ov%Pm4rtRU}e^Nb(r)M|9kaxf1tERZ?9Sw+pEO_oFpA$(wMmHYe`4z27=ml^bJ zIkJy(- zq>nzruM@omX9o0EM!yxWy7Ee>8LT3Y-!@2;B!1|y%tZ<3+BhMrbHtpXlS4?zfl z--eNg%Q5nB2}T|+$H>FyW#sA#_FyDv8eK*3zUH?e=vv21(M}OX^W}T~WE0ybN7GIb zO*>wHnlARzRzy^H5qKR%J)NwnkF1~zg^LC_0^sje!O`z5Pj!smtEy~Um%VQ~1-nZE z?&Zpt0PkB^lmlL`it)x0KsU>}%40Ih#zKL+Tt;Wy%;*#^ovbS`$c_Xy{CI zk^PMeWtX`vyTrw^i`(NdNfUFAR5ErX4k$D5S0`6_TD}=CfMgX%*=3p|flL`d%7CY^ zK`2aNwHS0g2wY7ZmL2ZG#SdSac;_C{VXf%pr@WRAZKdjmB&y`8&6s_3q%X8icMDv9 z5<0FPU41LSUnxw@46Y$UR}B?YtVnj@n8yP0~lHTYK3WB+=oi4 zEz5ad8L^eGKZ^JcchcG{%M@y~1PO;hRLOBq&Ltxd3_k|fB4ZAUH#9k`9qv-7uJc-Jy(#~z zU0~Md;w-qie;1@$eK%$I^M5(mJN&#|brcTv7)9G917H=zr%;_nPVHEsK@yHRsNy#B zWpT*8ipnerrs*t5gtRC<54xr{*W)bZYe*CoV-iiTkCW&|OfHPsba-&Ie@YvFr-e#d zw+|-Z%M@03x82`*jb{bqQ)^LEI?WH|_RwDSytH3th11M*>)@=ywrwYE3R{9O%e ze-=Ly+0)YEs#A$NLO6wg%eIVv9bk@BK7N@yS!;SlHoeqj>NG9?mhG|*Mb2DaTvzoj za;C7irag5{ktI;7P`3ajf6bDK>N2hjed#VcU)!p^_G0oo^NDJpF}13WAC>1=DS)Tr zmj}FPmN@v801kK!;O3h*z8ElKx(#3m6eXcvWe zcOc8K^8Cw%EHAFzNb`>kk*IK~5GAo)6k%}`U0uyns;YihYoAu?a1u|$fuO@c8aX>| zWC4(GAn9J#5PVySz}^8P;po(j4u9<*1S-wLwo=&7@AAP*br4T9oTUD5Ta-~|lC+R; z1`C!C*6Ab>&BXaX)c22n_MvGIp%6O^_kt|YT!|+(sqX2!_mkkdzH)r9`yT_)jSfB^ z9G$J;fr`(x`2ZX)97q6Sw!P@^6BQecc%Fe=`^RWJVKhE{J_8BXHw>SMydMOzQ#BkZ z9}h>D9;h0;@IlVUG&+?Q$K+0bv%l5b=x@S04gUy?yi{Q1f4SIy$IQ%~X1UkSowAte zyewOs>8%>9<1$+{_>kS{z0q^F~MEr57$eGvS zrw?a4AMn`-ud-cRG1jj)vx(?Nx*H6~p^Wz}@EYR_fB)C- z|N8R$KVM$FtiRp<>&sQ~^RM4uU_#^NU&Zh5ubH+t6=ax%1z^5!y@bLhbo5C$nh!%= zW)wJS0t|ucRm@ z4Oo3g=fOoQix1=5Fxd^#kX>l8nu(`oB5Hy;<2n4`&j+Mk+c-$i+W=8W=UjyoU#ppb}aL_8AT8Nvk6V|K}rE0li{uO`#k?A5eX+Q#H z`Bjr|!)h3*X%-|Y0;tPiQMF$MgT_rHZ0KS%ytdJ+#RgVuEBklDaE6bGe7WjlWKhllXEH-r%J@431zWB4>G0%KNh#J%E++ z4*erLlC-`ClL$A?hBk7}PgW&%34(}(5lssaw0=dw3%jsgOAtCrHQ?Z@oJc{iFRovQ_fs?;d_S#r%$&FDIkk>;5mnXj?D;@qY=4 z3jRb__#rv~f3G63xeA%W!C@-6}2vOYxuW*9XBl?#2%$WmrMhf*MZ4#mMM3y;Fv)A=RJ zG3-HSF%M`7cApusD_>YnM5i2odlH(?FX2tTIH~lE*ivN?IO0pSc}93-4ZTa))pQM@ zfS4q~WG;xJQ(?O}zfgihUIw(POI0NdKoZ~9R^A08v1fw@LF@`cRdPi$eorrQoX;g= zmYX;}Hr5L7!lCqvOU?ArBa0FBycpsruUMO7zRS=U_4XW|8fWKS{I_?1VRp2I;2pDQ zm!_jo&PR4CU?%}tb4A8nWFi~ORRL<71yZ|SsY*NGS*TeW!%& zKRGq@U|3J4?K0=yD&Vom$U>m>A zF?qk|m24qEfW2$t&EX<3yn4ee2)x<&@zEKi0VWn2WoBf+iU0SntNK=bnbC-g?cIoz ztTlb9uCDH`uCA`G5|aqtPXRHLSl%oFT$6>~AAkG!L%r^*3amA&$V1I({RH7R-bxps z2@-uEhd0ybl=@il^8~p}?!glxFH`7qU?}SU??@@W%65J(ffq0k0`-LkTgn}El~OKQ zND;EHJsMf!i=NsB>E#AXH`u65hvi4>$XtCr#0$vEa8=;|prApsYPL+JJ`m_T*A z6%;$UXKvjGIaL4oj|oAhKl7GGj!$K>Jrv1y43X4Opo(edfD&_0Ni48@qJXx^CYP5i z#pkd3`;`y(JO}Xc#$IzwBq0?p4sQO2im}s^lj_=xIVym!d?+KMJye2{8rBPIQhxyQ zFAU`IArRhnN)?y1ieR1B>`BNjmL6-`@PFZV5?u2qIHtK*;MCPBe3Q5S#hd!tQ2IOU zT+YwG6tna9g*j9fR^lBgQ?Qkqa<vJ9ppDSXseeX28fp3ThX*MGp3R~SNbA$tVKAejAQg&&qN$F< zkxETM@vO#j?>`tPA^#vb2Qi<-!_K4}M&ZFusPH5p*ji#Ksy=&DCaijfdwZDlKkf{Z zY?4Oi0kDebt2;dXNXwW;>>TlCIMtOC;V+fZuGp+cP*-NpXnw$jzD=+GZGWng%8{<& zDyL3t*ePEm^FeJ^dpSBqQC`{L+;eV={cxQh81yeZiWGR|(L$p}@WDVvE}Of4v4 zkO=OzamD%!xu|qjNU!3%-jv_3XU@@FUN3r&VyMF*vu)a5 z>#(0D^f-NyCf7i4Wp4wy@$Xb&IfF$vIv==_I8gyzeX59Pkt5yBh zcoc2O4dl|kdo6JhC@z%LN)!7ml9^?boJO#^V$36Axq#+nM-XKzotnYa1NJp*29pW*ImF88rC>69*IxRc>6>x|1is(cI4DN!708N!5-prc~IC zG%z62PCPrr00Rtth8~+PDJZ9z$m*u2T$E*8Yz2O#@I&F&86gwLeZj;rYns}SCsEZ) z%M<{dc(v+;wR8QtoPU(ip|q~;^yyN@UUKt8?6G=2w4?)f99=1j{RR# zXn7KK|E6+Luz$>7oE506h2atnWY80D)U;XCu*o@!07bOhBPP-^ls>!e2SRBM-i>lt z2X732tP^f#Zsc*IvwER6#4?d=8kq*N+K>xu2rh>TRri8G)PK;WNiTfmNw%(Ibgw0Wpm2vHEax)qxtp30<=k+va8s#zu z_O5+$+Wvd5`+xJ+Zuqn1ZxNi#crWv6HMxskR;T*aDyIVOq~!l zf^ClAk+LPy^JuBq?(9oR7T$+633aZ7Vn!Pr` z)swLYrGIV`^^grPhVkg5oNr-M?M!vj4BHe$>amo`Xi-vfzjOH49*7xdU6l1|Bf3j# zIGxc&vY%X94KCQGy~N5^5Fz*_I)A$#hy~jW{&xh16)%DjzZ6vFx{I8m0Vm9BUMT0c z^jODi4y#CNnw8=@B?W)tM5yb}5kyAPTicP|5`VX>eas|A*tEAmUGvP?Hyt8|O-t}u zX%zD%@YcEMQhsl%v(Jukr$@o|S!aJ&&?GoMIeL4tbs%k<18+y%H*owxQ6f4)7i7Wo ziU?)5c1}C*+P$sQ)058j*=f65m(k`>XpTkTF~eS+0^jO`+Z>K008Z5fd6uJRvqY7| zGJpF?KSTv7E1Mx#;1%SH5eb|7A>*&KumJ32+-4o7{Z)WZIXY}Yv6Y~|dhgmhEjMY6 zB)#45iPUv==H@V7gO|9o!*1v8VS5*{`MrgxK{M6ob(zqi`&!uLZ%Ls_>W4~7m}mW*5S_gG!BHUDEC)`?ZRGo~KceRwT9LQ=uuu}l$Tnm(^p4yDqp~p zCo-4iOywX4aaJ@Jxt`FnsLctpGty21rcuP2V= z+&1Fh!s{DgpkGJPht`HFAQlG;S%0H$e%eNf5jRRS%J8>Y;#pL{+p`oG;tf+nxGdY$ zSlknXXATB%))6jw%$G*Fe)Cfpl8Sl{<(o!`j=qiUMLtZ=8*-`W5+YCSD>>}$dSAi2 z68#`NejghA)f`0KEnN!OYlz#B#1fuur+T5{!)*wl&WdF`;)`m<;oABsA%8z4^Y&IR zKGjCNZxs+)k?#{<-=m>>v}0UC`Y3>V;v*;$(OaQO2V8s~?_#9&3+4kF~Ew zk2Q-P@ZZ)`P-XoQsIvaGsIu;*3jBBN(P?wAbt-1etXLj|Y=^uRQw5k+^aQxAKLoe+ zC&7(L&yT@*GJ;PU=Yp7YQVkNy& zb`Yv#As#klxHX;z(E!g*+AE;p1l5?*40wyNW{E1qw*%ylPp_S`?SJ++=`1wNq=Vxp z?(!hI2q(k*wZ}ch;@RO}508F1r0ykLugIp3-?d1!Zo1_ag5ly<7U6dsUA%gO>w<`? zsjbTdOU=)dwSs|OHtZZ79C!BHRK4$W#6bZ`HGeD|y(}&gdq96dII2sqH(@%eEuzMs z7keFeYt}=}y-34LaKN+J2&SW~-B#!5Qe~iS6Mc^t9Q}Gk zoib7D9Ih!TyYVZ82(5`r9P^_31bxMOE~u%gqBaw`9LfuAiG}!96%-QT=u?={i*3B- zw!nakd>*cfHSl;X!QC3X=Lv4W{rydvz)$qdqOL0-mw(^z2w2?oN5Zo1;Vt4x z>>V2N1+kxm_9Z+|qM;&sY4op2oEq2gP#)Z#DtK@Mj~@Api+FDHNg4fq6#UbGD<~Ma z(=fe^a?27WoaD(4#OE~bak6NL#*AvjWhHGtF^S>or-#0UrQ@Hov(7HHQssW@I=c)l zUng_{6;exBfPaM_qb}n_(I~r0awCp%rjk1&?0l4EW`PJ7Uo>z4Xg?V$2OQlVaQ|8{ z_ELf2aS{GDi6%Ncv5SM)6i%WGMx{}o7WK3y{MX6|gFoyH!|QQ0P!7;}`A>0lGfvW6 zs#9-|L~Mx_RBqmxpEvO!zj|$~qb8;eU z5H!T=6=9D;ZF+YYLr+7{-#=Sr?9gP~+N%*d(_|Ys7LGH#c@0MjP@o_!q601M7O^RU zTA-qpJG$g2>tB*|IFNH5o*~M#&WN#O?(J0ktQq;N3cXI(<|@D}=z^)qa8bs+w&Y2A z{U`v0VShnJ4VD%Ef4yjZ$?!KtD?q8e@3S;k+^gu*5d204x<<3vTr^zp`{3L)arGy)PK1L#KJ;+!Sm6r`Ir)YOPphTwdcV) z>1{<8rmEJZiHYu7AbBQqY40#xO4nms!G=SRYsD^WaK_HG*5k zv5Ylp+%v`)ekAC@KTB_dYjFz34sw}Wb`TwyECtuf+9Z|$O^6eIb2)^6Uc3ng@?6b{ zDPbZpg-?_L3@n&_2*EPwDd1QJq})LI-kw^?#bP z4qUN+)T=e?S{A6Ah^yJl_ha}HbiYE{zd%l@$KnODzC`@SQ`AM1$tmIc+(;J>m|wim zuNlYugB;rxAt#iO@McsDT5JqjuQGL=<$KxSeQ4;Z1j}?F41v|Tkq@z)698Nqb>+hM zG-xsOVahtgz(snEm*IwcEwH_@q<>FxG{@1efjM$rK;kZ7bJLcVCql5y#pWXAxpwnl zfWVt4aR!ZpTa$E`>oziY;q9mZ5%IVZ*3qCU(g4stel|@T=mu}p>=ri)l!V>nGQH%U z4(hfEUI-`1AWs4SD{UStpI=v2oOjuFq&S#{{ z7hG#fi~2>@^_#>$mZ=88b$?Fm?Sbiu2d}9bLN#lsr?&FQzOzgZc->rAqKC^#A)DB1 z8Ak}m^D+_H{YQ$Zt~CaVF8qM3M4q(y8Mcd?1`o2FVq95$oYU*h#%E`8j*BnWr?cY1 z%6X&za74YDP18zQ_FQr<($W-c46&@I(%9gpp zifo$3`NthU!avjlLaFR78*W;@d|q4*Y1tjFdy}B=6b%hZ5h?a(sHss-B`?vF!S5%3 z4d7|#i}Zyn<(l%iFxoS-HXrtcimq7?stAz8{&Yv>H8FLp9Q~1fnW_n`t6L zbj|0|Ca2n7AY|+h zEA%RmPcXA2%Hgc!%as++4WN!Qwl1R)TQ^06G`tZ~r{M^95RLOIF$W9}13(YN*thG- z1tZFFgnb2h4vBzBn)8N1lgIEO7;r~(C?X~H?;2IelQn-m5gQIpWwH`?^pf!yf4{Jt zaXh+I#ZIdgJDFbWIv(xC!yGJWWYI$=j7M3{lX;==a(W?rt2GLT;HWXob;;fK@#)V! zuoXHwWV~vvwbu~p>9S&22G+1Hfrj0fo?$3lT>A|FTJcz;PKzy77z8;0aziSkOtnmt z2Gf!~bSUh+)#s_RIlbO>SMwCEe*&{vaUyH_YYs);Nbz=@Dkjq)HNkyzAGHyy`czZB zz6v-8qphoXj~=vHp#~CBn%P*mb^UzUw;LUM;>2jZmVC)LQp%7-aP%wt^eDC??M^-G zIId`H-zd~S+&GQKY0~GH-Z71Om}I%mQPO-al{A@$U4|-t>?FsDgZ4Zle*%?dNTmln zhgN5V7(L^W{RaBw8xipY+HqJ@?ypAI(Eas$#F4qAh9-o!iq0n3Q&pFVKj!F?pJqCZ zYr6W%>s+IT)-rjk$ZQgLC?5FZ4#fkqW8(-#zPadg)KlcA$1G1q$0%>iQd*vjjak8% zy%cMyp)^j$QiZC^sd0%4e{?mZEEyFKJ(y&t*L<_PbJA`fdTdX5oW9oqJlBPrP6l*5 z5we8b*WreS@Q?f|%!Pec23h>1{mi)jGFGCAvzix=jx>)YEQOK#VNKWsjdc|d>`+&n zbwrZO612Csx}6=abt9?rAal?@dE4fS6Owy;)IB{uIofG=!Fx@Mf8pd-Wf^N;kkSSm z3N%{{4+-DEYjX;6x4pM@wtw0?`Jtzv93Ad;-g0$dCE2Z#wOT}}x7)vEI=$WYQ3+EYXPtq5<~L2BEkA*_9+g6e?X8n` z_w?&i%03)dI6r?&TCKj^`z_BVhJM9u?dPriy`EGf+>1IwaCjmzRnpn~25Bi5;%|YL zkGXcAcxJxc{*A9(>_AoSc25#*{pM-3^+ZHctMXeB>5;d|e@~SkPjBn}h>V z3Vzn~b#AM+e+0G(U@Sn=RxuDVPdkXRtL-q0`_ihcW>`Gf%``94NtREpcP7K3b@4)r z%Ga^j#8H}Gfhq9#D(>?Pjurk-{Av|7iroeS(3&5ix;Yx!xE8}rP-9(bNE>;qXG`oM zgo$q!<(5q?FW~^m8peQQy<@ABd&D(WZSp?-<2-%2n!&QNigM+8@SEd3|B(>>Zu-UwjSNrU%bf zvyc3te~`penRrSPPh{eWNF*ELsHr|=rrrx7p7N!UX>Wt0rkT=E4u?hd1x@Dr z;RwyOM3QCQp~gckC+>2m$gV?DK=s<_kkJ7be^-s3#3^vwuQ!eT8fLzkVgwK^nJZDf z;hVH#3m3O#;>jVIz!|aHM_WgXA!euf%DoQwg9f*_4lm5{?VU%LjQFmJQx<-T2E9*X z$7jSMku#bUNYD>)uf2)cHaZdRBN){`MQ|w@u#!#gJi=<=jV0Nb#-Ez6O)^%#e--sV zla2OCe}`L<`*}lz@+BAdv$p93aTK<^m>4yE_tAK)=txso)jLZA7^6UifC#R_i~-{D#)uIEzbAi2gBV8z44hva*X=oL zJu!)u{|B|B#7*&%1b&KFBy|r5VZg-WU_q^hf1&{m6djdsFe-kIBMwG0HtO38Etm8L zKF`WGywX8C8+{xlHzTpY?7`y=s0ZeyJ$yjtxKEg<36>0on|M14rGGIP_6&7OB5PI1 zCnbEAt1mjw*%2nW=1inrV*$9R_RO5yO!xeg7Apj^RO5$OeGg$FOmjjIzlX)-^oJW^L)t z&xiG~hE=Vqg7ds0B&9Jd({IkE3v>a+>W105=Qm}VGxyKGV-Q9P|6wu;F&3O%FtSBL z?Gs54Hp`XAY*S8DQmB#4J<$a(UigGae-SX3%75&?KC{fC$!3bZrj|jan&(fItmdSZ zZcI=q^BYAPf%Ou>AvI)&26bQ9{f`8b|(2ff14oi zurw2F-lrbU{jXcCN3Hs~xQCXTjkPR!>Cs3KSH5^*zg#z&q6~?I`CFf8vP>W8U7W&-R%K%x>krlE718>(b~t`4su^c;jg? zWbfdz&AU22T4o1k6;+*q0Lx~#8WrtuL$L2O~#~p;Wi^ElZ++9!@D3lGNyI5 zb5kT(mkp8w<1T$1Sj3T<4<4!}w8!JfRUx(EpVxs7@_4~0%|J#0c;$&Qe-N~hg>j9M zZ(2q6tTHe}naZ77ScYh#dDL2~-_`xjSW{X$kdbGUnPw@rE~lyWI*BXwtXsj^p2>TZ^Pv> zrMzBIaHnT2UzP+yqXMYEe`mmgvmzTbPu-``Nm6yJ`^1TiZw7!$U5tz({xtmcQ$6P; z4#h&`7S7~?XxjIm&|XK}*~h!{I({`xvtU%*pZ zVK{(nGWIz9X9x0se{w;cd+}B)3xj2m)iu6~Qf2ai9|k3a`GqL3$G^Ob*YxS{vI!4? zm8(4AqA6sbY+PQm$-un=tOOtMSWCR+y@ovxeR_gZJoN>R@8E-aZ2HXYPYizpYlhbl z9xqjUz2NVu$%xNtZ;5Amjt#zaUa`H&5~4|kEJwl@PNYJ#9NdAaB~dN<@`cVOr)NJRU3tMWC>yXqo)lKE1n5496jQnp-u|UFp=L|zn={>ueq10 zJNyI>tmudIpL})kG7Ybre-Bdtw_AH@A|mkB{4JKSil*KRsA&}TM(#nv8Ow^LY%;(I zZY^A_t79GNM)&!qG^MWP@uk26>R*VmvCPG8&G1&ce`No`jfRuB;io2P+p!PaW*4P@Vw{05SHQd3d$6_tn>ojfw+ z^~&9^yS9+706!y<9FP@plX5ur4?DP8?t7ejIglJy`o-pY6z=0!x-GaThdpV}`Rkm& zehvOAwZwjIW*pSCCqoc>xJe-d#5LUn;_NO#UhYq*0T2{xpBah?b;79zDkPe*19OaF5C`9<={8 z!N{n@%jenQPH$^>*Wx2s8jPd65u*b{$52__6INmW_-E>u_UN$PJLnvqb$bQ5!(t$B@tNa^j^`D z5k!9h^*n}%g0?gf<@}nMhvHndrl=&4_R#Bp!%_BbLmCV5_ZpXA>|mXE<#o7zvGHuB z@Lnyn?$rVjB2`?57(){(doeT=s~5bzpi|-?8E^|ts(x*Pj+O5VjHsEmEqh(HE?2)| z<=$@hpn65Ax#d-li>i8RN+mDWe9JevgHnIQea&}v{wkV=mUY+bP2sppCt-@Pe2bcK z*5&$XqlioeLp*tg8CXSRGL#v?ql@9*FwD(DI$Z~k8VMF?%q~8;^up5y+cd_meYR!M5uM9q4 z6LCW5@raiQb#M+|CRU;0bgzWHo^VaOD5Xq@!j2Z~$pvGrP~KIqa0qy07MAtWYJ8Lg zSVcjT?~@=^30KZ~Cn3U|9*BS_n!q9yK-^S?z?UVy;nVhPjD|-y5FK_LrTN`qc+DV% zD%N7MY1@?*8Qj+rZvUeZQb2#MHVYQ`$XwvrO`P|yg4zgd$1g<6kMG=qj;Yl;jqiYBN0$h!3 zvJ)omeu~-QqVBPjdymoL)UbYd9Y|cb85UbB14g+(qAK45oU?QC$IX8Q-MvFLNqPUQ zzH!bqd)EMoR#>_RS#g#U3M}AR=_eV^svV#C)SdkTemvbn|;9{ zyxICT`NaEW^=a~H*3N%SKFN->9@de`r`dXNz*w&yo4(l($i!OxDn03APoR$M%j!$3 zGyT~*1F&Xh7@+VOqH2Wq%j#3E^Jndv0laA9&Dcc(akidb4tr9d>g-}qRr)(NnWI~g zN-7F*^fi_7(E7r7;GS5o-Y{@a@*eim4_e9t;c*((M1YJJGSj4M2#tdAMJQ; zA^<|v6g8w^#^ZiBdp&$(!e?v>c1a-HlF=PCk71FqVdcL>=wI86q$wY%@Xi|mCOxRw z8GYhV)Mo)GVS;~B2JzsX!U=yOq_}yV45A^t+;VX;svoM_hq^MCKdSWRKvn0zW$W6C zrm$s=_d88X*Ziiu?{YwBkB{x~sAT%%kW7TM7LC|sJuVz{yPy1>HWPgDxfLQC+Ln2y zL6IzL(nI27!b7~mW}XPkT&H=o^O2={HvlOchyCc`h!lT8o`O4a+sWl!<}J_ zPS1{q;fTK)_U9n@tbAI62fNO$oS6JejG*|?*fs3RQh_9Di%(HqX8!ckPr-_(?Jyg| z;S=lf-+X2p(H?{gpJgiugyAmBfU3eoAY4@*AiocMup55R!3PiUJid-NVEBbVVNUGA z^+z2xse^xbIE*ti4#|83(;iwR&2)oylVP$DN~^pIWG*>v53;4cZu^QC;62E$VLa>aj1-c%s@!ZUWFOaoG_8Y z;wJI?^aHXs6vaaJRi|huS4e-slAM>+Q2f;2O2#k&FDm6`bRB0|{3%+*ru;c#Lz4;i zoG*Yph%YWCnFp}S5ODjxg;W3(*wADcrY=;SBf!dps*tbZQOtO9<^ipd3X(Ib zZaP%@!cBTTWAQ4DD zkWI!oU&xoQ&?m87=|SdiXaS2_;B{W&7o2tTWy_Ehf z#k}ARURCL%sxVs**JOi|%_t{Sz8kNrf*Y@ifeHnGg?eoJ;2FQ42qY&{k-UOSXEqWm z07$bop&ta%Zk!dNJ1juAXP_(IWEWuC6PWgO2wxir z_qDge0;I16($|GZQ;&xOj(E!?F}gz#7rJm&atsf5Z1Fd4;(H!A;$w^YQ=SRsx69p{ za8>kw3(AsMReg%8>bu?uC?cjnT`#zr?VDn^L05xTHBcKZn#ECj!xcA7dSU;F^(@y` z-$;|2nh7HMAPSW3MjR5p5(`JU316ocwjhh(s3{^5J7Lgy8AK0<J(3*I9v#X_BUWFF5flcv$^}q3~$h||2DqLMh(gkY<#y#{RReb!C z#(7kP3W?Fi%~JMGj@U75>u|TXy|we#UbnN`R@clvbEzHl*}b*X2C`BRqGqkopiI}a zEKVoGq4_cnFsW;3?nGT1SD+W{zohjHH9-UT$BMX** zYQL+{Ei6?GWNZJItzV~)6fZ_yMHH_+GQSK z`9bz+^O3DAFvXdZRf)X3Ef6Wd!gX}tZ?7mJT18^0l11|_8Lx3P@7ADv6Xgdxq5GqlBR2Sc* z_3QA~Q%xqyYW!PCsg+j*3Zf;JwTollS_q5Q0)o@4AoH$*%(n_cm0&Fbvoujj`@tCn zEXY)!?Jf}u4v#on){;@eZi-|Uwq-2G%vp}1XF1Apj3eV=(yXmh1pt{~H9Uy=;hj~L zC&_y7Wv~9sUHzG}`ojvVKl87D{;cZir>C^g-~i%0Y?0Yz0a*bH2ptxX6|sP{BMBWSaR8uLWUGx0qrm9&gPFrTvLkw7B z)|F|ZCjTTY{%aBrQZU^%tC3_;Q>Dz#^1!)90mnn#QRd@#NfE~bXqw@Fjl2wRYMc1bs(QBP?wyKY)02;U>j896%XWGL za>oA&W$jrWLyee!NYMzuV!nYlHnjp_*i3`xK@SkbuS@eX)+mqYj(Es!D@JftD~r_YYhkukDP`bLqfJRd)O^*i1-H9>QDV?vqx=`df;<(8wfu zmGW{#TJ;u`$As57Dfw@a0|x<2h9BS8GNtXX1N3WuCeZ#Mnh_G(YvgDAH_zcx7^L%G zJXJ|okfA;V8yNeoGCh`^_6qIkqh_@VxI}fODyzEZKXTruJp(|Mwqa2hRR25+aGPZa zSAA&IQUJl?!%M5>y|IcnH;O424hFQ8d>r*)u9@6}YbMjVCX;4{*cr(+6Zk0Qn!R$a z*(>LNn!RGK+4FPFo>p=Zbl4YU&AiDL3PD`3L=N0@IdGRrk(>deLF4d|IPl|gR<1)4 zVKDni1|$*s5X>hU5~GlzIjJCMdG#3IwMh1ae7z#C9L~m=7Bz)m=$#414;Eo_ z&yIJuPTRfhqqD=^E>~&d>%((+wi=Hvxzl;mA3f(MdEK0ikt+i`@X;k>!}3#&;fphW zQ1%HA_q44#i7Lf4ZPI{DxZtz>f)lr}1+LToP68WyysGELPSRt7i}EFF#~k{eTu4T? zn;_tl#Ptg}LXwY;7qzP%kDnS&bO&Ck-J)xy8zJ zr4ocZvdf99`?~N8$$2})x>f~aKf;lA{rDF^|57)N?|(xxg}Wjw?j!fqH?^O|U8L}& z7eCcJhfjnpGIz|$gpWm(&4cu*jt-8I7)YJhfg}??`^L!*Y5bQc{&;ia2}u2@v^Fua zDL687&8g@{B^Pu?cKzCaVBSb<&YWMHyqd#WLZjlaPZ$_2l40}Pol(8SF_K~n|VYsjeuRkN0`7+G@#z1<3Uh- zHFt*L_4qVt4=$r$(h#4ZE>_GuWY|Snz84SCSJjkcuC9RaB1ebp?7Y_6E6mdwd;3RQ zr~HUa1AU;amLQN1r4!tSX}Hz^OR_#u0uguT=r^e5S$Pt_dcmURQiJlZ9m~L9@ZLC1^E=q?;=1_) z_dFgAOhU0l$zxl)99Y!67{=o}9n#G;~Z8K&g9?|FS;J^~nTDyMeE9hJamLL8OaW!%U z|7#6}tzd$77KN&jR~Q_cv5lIWU& zRW+z)eR)A5!)_nMV{jQ_EM_y$2m9e%V1Lz)E;Ehu;Fv(OJqq=OyXF9yzj78=G?4}sm!}qjd}O0ac*!}RCN~H|GHya-@e& zrGV?=E|ba}8O)x(XZGB`b84LXL^^rY3G_&S-3j#A82|cI82{s`FfIlB7_wz;Kqs3c zIzG>)B85z&cUK4hJVpT{y3AdsD(TkKhC5qYT!J{^W^$*=4VkG7ilue zA7`c(b|dV6q#>&BKb@X#7CqVId8#?{gj40|W{7uUJjRJqwrNBst#+8voVws>NZ!jw z#;r{xF7@cau<$g7Pj>a0-hWI~Y~7db(-PMeipJ6PyFrs+B~az2fMBJm4u7!9@H3*P zT>rMVd$RRQZ|`L5puK&zx7R-DZFdeKR(YMD)~D3w=5IUu?X8pEyRH4Rw&^tuW(>WL zAnpNGgQeFSboyQBWYJT)SUeDY=6Rk|2k0^`hf3+ZVy#TDGvro(nQ~w6gRE~pm4POI z?y{onIDJN(HZ9dCoPMpo^MAXa6_5I7`p`uMeFpnNaNe+r|83!a*FK0D%cEVp+I;^K z;H7IuOD2RIwNQ%Ftaw_nG0#3auY{g*)VH4+t*Lq`Q$8FYhXk$;aD!K!d!Ky^aG zBuaSXjEJvIdC_z7!)p>2Tbrx?p#3zeqU~LO+4ioturzlqswDG0mEUe}`D?KZZ}Fni zZea|B?JbTuZiW4`gU;dB;ZECIN#&MQ>=n0Zm2rVsS9M+>R+*_lTI*H7wAQBrT5Ii9 zfy9b=2W|D`UeUO*EPrp6q853UeZy*G!(&T0)t>O$|hro?!tZxmZa{MiS37q8Dgzl_0Gl8N>Arf z#tpc)Ux!S5X?Hzye;=PZmekzuK;1_riMYQnC5dcS6UEfQe}6Yb@wLg090%dJG6KDW z&M`my6yRfkor;_VwFp-Zrz)x(%2Z4#(27*_;Q37_n!bjqARa{HD9oi5OTkWl+}`p~ z%3}rNt-rIsb#UA}J?gc0-+Fe@gBZ-sqCo{r4mu|%M<7@blpcxFK(i@yw)&yStuM8v zlUqFp+Wz&_FMn?sC0uIJ_e8zcdhdsFAhJ{mpzhB{C#U65ut+&BQ_*m%7uE6>Mtdc1 zam;Zm{Jgcl*DJ22vmbL7aT_Z#i-OuDW7Q=5x;v|^@fNd6z3oC9&c97gleF|b7lPwf zq-bv_Z5Gvo2=T4nJH#U4U-(pvJ{G{oV>S8!a9mahOMiSC_ing9GWmH$KJf`=8V=$K zT!OE)2xQ1%DCUSX1gyp6>+oaLJ3cw?jfY`8QkVTI8BL{IsmhQYZ;sPwH@O)NlTf>u z6Z!yB51ul51J)}*bs5$UQ@h=*Er~up@F3m$9HmL`VyzXX^2Nm-Yn;3kU7-&| zHOMSC?0-n#OTTg=z1K&-b1PQrB*V9|&`cL%iOLgaoO4fPrwR8lSR<1HiN^YFm(X>) z@%4BZ8HTS$kE4bO2{XI+3a4&mz1>zetw#FMBnOWa)Yes12`5?h^Sf{~*d8+KJ5^7U z5d@~vh>LvPS~EHSXKxs1xgeyy9Li>ehEict=zo?)e`cz~J33Ppq{vJ)ENWGo>3S;c zO@_lqnFv3}msenTj-B2fCdsvL?0thO)A(a7xkxY^5I&7K2VjfTe(9ZvNJ+F*GMEB= zj6oSyWW2_pJWIUBP^L%7`lNwAa=jvFiAV(KZG2m^8fhnCAMnzlu zXSN7l5TqVFWhL1rO~J}Hx9Y9110D>N#e-s`JAWn@DIFRuTrb7IhdfvCl83{5sNvZ! zXIZYI-WfuohIjImuAMS0{kQ|%W5ffpxPJFxg!(s9E38rQtoW_GVC4vMb3lhnD6H?9UpjJBLwkV!F$_YwA6;s%QoR5q)#KtsQ z9m#Tw;@2XTeB3qAD9Fjx6vsBMnc&i6n;PR+z{5SWNjb(?RqI@HTh4)ENm`d_ynmMb z5E@#flT34EFM-mj6wv?}QQ#xM4@wtv^lOoy@MY`8*cACRb0(q4^bYgXUhvAW1n|dV z-39$lwVOBWoU$c4rO|h?(RWs(xSfk7C8)%v$0SW7iviGrFur8iRBi!PrZWeu&QQdE z0mE3`k2sS$En5rrh0T~zZ2w7Kdr}Y3=Zu+YXFlYs<0i#ZA zuH!sGF>lO%2yaSMxOOEjM{F@$nL2|kaBQ3)1s<6Nr%AvQ?UhLISBA~SqlKmG9x`(3 z77_+c1`OJqN0(qkMd(pDTty@8BB}tsM(;+f$w8RjnQqKXwV7HRXaXitusfqXJL&V6tpro}i;LZ2#B#p%a| zh*vLp-xoKDC_%Yn2Y-*-2%p~w^yCtJ@wPF|Rf5A1odY__G(08<*AJ$%1mbiB^X~sT zo;%4f1((;AUBX%J7Wj0BlZDO-*nu$846Ycn@dwP6wwA1c(?>F6~a}JnX7Js6A?&Fo0;jf;7ZQ~0;Ri@G}} z?e?LvhxK=bsPR~@G(Z^`2*oy`gcQElpk*R}`l#+SW6_>!S4-)x3;xFVKVLV3jiVmJ z$HRF>bx$m-FMsz+ecqTVlG%oqlS6O{@p^>GJTcYWaPQuNVaSIiRv}8P>C;4`>zg8Q zwPBq}ReGiEL7dPRZ30OEl{N=j>FezdHmaWO;l1|kCeMo>?zKtq+3NE8r=6wHv!bgI z^n|zQtMF6|OSNE4MBl|DNxttiG_J8K&caIj&tp$Qiht-6%)x?PYT8wqV5uJBJlO;( z*vp(t+%gr~)Y&4+kGa&37=uf#*G&9@-o#k zQ_Vs9YtFcGWoOC6Gb=vb{4?6IrlB%VFs2_d04SYyqTE3|iWglg1bhCN*A1i$c-Lkn z_D+rtPk(z`hr7LP@EFnU?6$oydl$pm@bWi{U`+f9OO;_*2A$s}?s0sdIWY}AH=&Oy zuo7j8P(hn&8BYP@7D8H)m?eebmblR1K?qW-_gvvtT1yZm_0i32&>zBcnxTq@Ami`O z43m#x8Q@Lp3O-g>@RD}$^d?cA<{mcx=YOW-;(yedj)(7nlKKuPX@vvI^a-?DI)S7I z-zo>4OHjsICmp_W9wtBfl?46^Hjb)pUtaKkT?`CqR~kJ$)y^Q`TRXy$aWC&N?<(cI zViqha@4DeIQi8|eGTPx$wcZD-&2?1EG=FFWtHB2>(Bo>kE4F1{B||m}FM0AI&IOX* ze1A#GySW?1xm}LXD@*dB)@u-mXq$1T%i7{@r@OOtvfDd6Iz$ua#eymog`^{W5BSxD zBZ6kJrVtlkL(53o4CaHCDwoAm92nKy`DQDwzz|3=qv^&#gm3ulbDnA`3;4EhXB(21 zD$TStX6XvQB#l2Oqa3E3h=1BPPHy0h#=5o2h`py@?85x7x;!*WB}WF9 z__*^OY1q4ZWbKG$Ib^RYyW9ijqO$9G;A~l)I$PdNnJw?W{%m>ojb_WIr_Qu27@?{KN&hNZS!4pn8XrabtWjB$|r(t)Mjs|pcZ(Ft$!5F zlpcA$l-uf&Sz2baSEvr*WuHvcMV42uT=ZStwi_%cjc8ljuFulnyYouZoZ@A1B|w=< zy`MX8e?H#ocF}EqZ?^+ZE!u}WZ9d*;hoj_de)%aS?3_r++`qMqvI1rz!-UDae;0p? z#7ze2lvv4;Kc{eo%0gdtky6Zj!hf&0Gswb_UmQHaLWBWCbH>HT3Q$4%^_#e=lgQdT z&+21JnyWt9VRee^u=@37ht=|_sAkI(%tXPT!{NnaPDS3U-^4`ZsM@%<9#e$%PQ%ue zY1sPu)38-O4fRxcvUzyHavyyjwthSFuw@8VOhl+4A;T*_`}u^Z>7QPh{eP9kVu8@K z$#sFV*lZ z1U}@Uk=s~qHyK4z)k$C9Z-c<79&>RokE-h@N2gn-OmyYD_U_UC{;yIke7toiuA&?I zg{oN|i>&IZJzj?-$ntB#{(lfG&3RZvt5a+oT?#av{z1$&5g8g{b>|8AF<=66@^LFa z$c+)FP6yOm09bPGBB0A!O}M(Zl0r90nVm;N^p}>=Yn@Prt%mr4Tp<~M#+PGhv!5pH z%z}V2aN-tXs!=F23x&#ie*p2w@gnY)Veo$a0|tP@-#?&1JO91P%YWR#?+soCfB(qK z;O`bM^I5`u$;*Al`YXKP=Y~4|uyJxp%+4;`VHR;beJe{In%3FMSX!cw>U>nA6wcqT zfENnx;ZOZ);jelbLZ@js%7!7JK{4_@u$YEJ^nSI4N`Tch{?B?z(^(-c_?&|=EFene zMJR8^Vg{^Xr z8ZgL97;7w*3HV5c(+*V;xr|`qf7r5)4_g}SKWyto2F8F~y^o>$@SY{X&lEoeJ0mHq zt%Q^pQ7TpSH_%O0mN5n%MzWli#|AC=3ZS%vH!+G6D^_e!F|(-{`l-0I#K12t#nZ?m z8^hK{g3=Kmt$&pL4BzMQ^ase1;b)AWeDqS1!v2$y^1NML{S8ElQDxr*SG>TNQmS1i zpRD;u#5m~?!dhpNi_{`LTVh~Z!3*#k%BDOIFb)h%CrNf114GlvoEH?Xkiq17>|v;i z+A*hg%&8rN4~c&pvv=`*uvj`mk*;Gt(~}*3kK@JAjDJ5g^JFi+jRv)rSRo&)cC5kve@Zt+zmq&~f%eapE zJP;YSJ^b-0>H=LsgS>6qk*ctyE~4M=&J_&6J%JlEN5Y)v_uIun&bt7WN;P z&LsgFU3}!gAkOWadsS~*%+RiOHM2OZm3`;Yi#zetuO{pD~4D} zMwjv?0XYF-mn4hj3d;%P~YfS2wN zIDl?KwvZxSA~wfYu~koOKH+d`-TW%bLu0hVPf=I!YP;4*@++KoMMEz}ZB`OTtyMsyZ%zSEtJC< zWzw8g`}<6daS?trU={x{TYHesYW+%@ljq_RiilbrQL93Y$(WTtB(2=UBSwE$e+_n2 z5;WhHvEU`o7HYhI>)`W?{i|?v87*obn>3TtljmJoc|b6pGm$xmc=}o57bR0~T=?ne z=xpa_eS1REu+Tb5AU7`?PO^mXlB1-zWFDD!HClSfgYTlJ-tkq$cxgBUHaqYoUc2o0 z(oGV3#)Z56$pw9CWVImc)=huvx=C#}Y0FJIag#o|NjGlNv7Ll2R0U%Q4lF?tH^Fgo zQ)_}Nm629ENFSZL>XD=3Lya@&lyR2;C6b5)78dOIc3MlQP3`nG=~fALt5g;scO`6R zLIEKZTUv@=nE-d~0e7u#2Cx$D@}ZOhLeSxc0tVy8FHp(XTv`ey&a8;+Qv^RozsjcWwR z#!9E2e3bV7jy@al=dZPx2i?^@!4tw|8Z!F#byq~i$mj!xnFOa^G6ADQvS!U=gGS>Q zxaAi!K(wD55c6bA;fdglB@lVXxF}+I>R#*?Y-Y0^^<=I9DAcd5RQV$=;H_u zCBpMP>?aJ1G0R~>3hI!Xi)!;Ww3DmG$qT2a!MIewhiP+V94x;9S+ z=7v5bjHI&JKFU1@ZB69^=bd(x`N%{bB*Wp|GNM#SYpG=R5S!Bab9Guj|EjcJ{{7K< zN74F}Yt_VZ{5yY|FyYT%-CBF9R(pn8XQoFVAE8It0Ix;Nek-z>Z|uFtH+T;EuY)VcQf>|{XO@xUDnIDj*8ra(2@rs zu6OZZ;VJy9qkaKR35r0#_P8V<)gHNviiY6$ae6>SCNE;o=i5GoEAICMt4NbZ#bHsYEw!!Ov(&#Y!A=?}om%mN8^;M=BSV7(Zi+ViDZL^=J!@owT zLyVf&>|mrmva9$aXI~16>iZkgcP6>k#W{LY7TbSA%`4YY9B&=U^e;T{Z5cFvW$pmn zApm(N6io5&c^ZWuF|L;GE~ru-wXd^dH@(NR(9hRb8b%B(cZ|ClU5VB~@~ny)fRZ(J zxOD(xDGUTOSv)-e8PD#*r(%Ijb_@YaBsrZNBE&ng~SI)Ch6{FOy;b1U}mbRd{qoQ@L4W*l$FE*EVE&-Qgzfh##7)Z12(ZlZ{ z+2%O%o3BiK;o)1y{Ng&xlkstyFv(7+vKtmRM=r*G~~H zKh~mZ(u=odCYf)5Q4!AKFOs0SN*1$iNRnn};S!Ap{^{1mKu(5~aqrkry zOJl-X^VOMl|0tK`W|gx3S_;mcvFdu7o+RAkSq1B*f-{|Kx-_L$so9cSyvSy$O0^Pu zrGgr+u~HQppt>o8@Wrv$LHX6Jk0^% z*7bReFyQpK5NJ=z?DszV*za^t;dgS|;{SkE5_eU)mFH=EKFQ&&{7%RQ0sn=yKK>)v~}A5W24gBW}IQ)N^<~W>OqII8k%OcVt0k6s;-_o%=XH|gS9;!{ooFO~2!`DqCu%x$ z$7!5L>VJnlb$BXaG+nlk#*zBrl*iOe|0*azAcFsx)~-z@BUMs~QEuz-?LIOU`MbBb zbx1!YZvk%E+EqUY3VM4Jza)n{Wd-0768j0U`AlvnqV-uRKR5|H!|-|>4UBZ$-K7}7 z64qjcfR<{##N>Mz5^nk_$N8!PPZ)y4+=yZUNl1^#VqynKb};_nZu>uYN-U%h;_ z_J4By4=byyt&P?nf{m|1fC-!*g5VF}2PfY%N;P}5>UoRT}muqXQ*7(1A^=kbO!ODF6pZxDn@WdOGM{6r9 zL6j|w*})n2(EzSMz`x4{oGdpN78aJ5nSUh6{`>r!{4M-x5M4m<4Oi|CR+=mRY%aS6 zt1N%vPoU849ClB)*hzA?zQFz7sk55AQ;Yg*L3ABw89VxL?cVY-PaVV;7n4jRW=y0S zMrms|kO8oF!#rG3HBPUh;363glN<2!(N8ABK~T%C;NJ$5Rl?!$t{$96VExQQw0|I! zvRQBw=U1#LCd?!$`Xfbfi2TvnDV$a7G7*&2E*`y@$x8hwQ>gsuBF3KxL%2q)OH&}0 z%i6&R(F{Vc668s6cy<8as)*TN;e+u{f5J+e8W1}$@pf2yUp5!uA2wUgI!E7b&P+xz z>)tiEKU@zE-m$UX1d1FagJ>AMi+|N?G_&9_mV<)Y;N33BW<)EH{vkJ2GAOYx5mrw$W`MAK;6LyK}UEbkgO+#w)G|?@&?3Mi4}9O z)j9ljO9ow4fqQ@Xh7s3+^ncxf(b1wHN#o0SgcC`k-<0fg9VayHmmVQ&UT~`CLEPDe z=ZC|dJ-o$3D{njtM%65cg|UsIp`~+4Vig2=h8_wz!-G{@lM}aTaDA{dXx@^UgsUm< z2jEi?e%GM&{}13b5Rqm0S=SYiY_Q~cbJ1`w%KKM^t>t}aQCDXplz&BRFBxVDseW{E z0q#J;bC`Qq$qle}@Fq5j;>&Y3f^1*H!r6iXWR4t|Lj%tYo+E-ahF|mc?sEh7Q_=dL zz^<}lb+$`40{tHX1m->GOcyoHJHaI0-R$|u{+srFE6XO=Q2chS=lHELWdopzDDNNnJvf@U zmQ#?+LpBNZqU{gku^c;rp}m;>-LYzuZZL!ylvWcQLKxiuQ-68sU-`KOpm{?&Df_6| z2;B@NhXU8gpZL~^ZlhtSVLwA_Nq)-Fdy3j40d=yA;!G@-m1H}UPppk39mFHJ7oO74 z8H6~JTdmoEcX!1Rp&Ki_2R26mR-q4`!zJC_2%HhJZHO$!CB6{Jh6^Ih;569@;c1<4 z=;b0n*;mn?=6^?>jXVeM>x0@N;Lf^8DA4-^(3UZ4V6cRnu-P(K?cMwQpK*n_KL5is ze!BDjtCiL(=lsu-=I8(K?fl<8JvrMs{e~(4U=X|ea8uk>2l!pQH&U`H%K8I+|1Xch zD149ASw)@o`<(lW11mp@SS=h^X<-U{!dZp?A&Hnsjeq*#o#4Ve1zq!p;$fml1IaZs zpn=$tf{TCEg)+s4p~CQ}I=-@s;JeWecn+qV6enAUOmaGD!{%e2@x$TxDrCh_047P` z(x$m0hQgY$5`vhr1Ng0heYrEm_4}DPP1Yl7uh; z_UV_TpoPx|0YOs9qvlY$8%8WXkHKQ+v~zUW{l@H3j4_xvcI9vjGKItbR-Q+r2{%qP ziPtb#Ov7d`4U2ne<$##`8Zci07vPl@|9t^+=6~u16Y^zcp0vUfYbsS2kOvz-bc~hL zM2-oK(9Z|7h5r!_n;6~zS<;5V;AAo3D&mwt{z8_ET7KdzvBL&r0s>ZsN|iC##PH6E zBMewxqFNaAfOr2L>iRa2aFZ-d;te`J)9P{=0Mvsmba&8EdQ1>mVc2Ms}M6=-$@u(WUL^KvdJ*d zOb#P0r-$~Gu1*xN1_6_#`MbqRT-+r>o7z5 zVLGtYP;_mwMTpa7pjM`LP0B)VG!{h209#6s0VqRkx;d&WjeWA2L^^%0!;F1?C^I{zluYbuf zprQ;_`z|jJqVvfmFDO!s=3uXKN~9>EldCNvbDN4*Z+KX`k!xlR<|z@ zmzRx8d%WEDUHI$c^fOYsvSk20Q-4pj4seiU+?uzbFsXR!@9Oha#Y2Y5rd^SXM`B+h z_^t(q3g1I6LJ3^WqT*x$2KUE?63f(jBzUK2SO|O@!vx|}^M7RsmqvO; zC=u$JbIs+fZs%rm-M)<0H>`dGfFg4RR3vMd0_4FI$X+}SDxySL;1t;WT-1yTf5r)B z13~5fL$C7Ji*E4Uy@O62!oKA!@-q=a6(8>h@9k_Os^#G89im#)ViD>Iz=3b}=X9sx zH|q1V(tq9g?}7LJ)y{vbYa1)h`EPY&b$HZP`8_|Hs_tA%_-E}7zGLy zH*=Gdxyi}gD?`7RXg&ce0_97Wl|BI^e`Uqg0DjL_W8ctd?E5zyZf({OB* zv&@%P1rreeF_-g~Z(tzzeVN7Cw?g067EWQ)t&UB%0ycVk&%O`Cyx*GTf7~>!4z7ic zA!Yb3cb2R(r+HbrhH;D2=wir(h+3y%1G5f{b!%7S3;IZ1=Xc-U6AC9R6 zB9KkPO2{@iX14f#-+?aFmlcn=t37K3C%;!y$x8m8p7#Cc%k>r4|I^z1{^vWp|M|x5 zpC0W0>0$n!icDZi{Xl&qf6q(bT%}*8(=StT8>)WSNY7CBlarvM@_%&ox8C`r@{GzPb)`naI*E%mBY*axiT>x1p0OsU>`QjKE!64536j+1nLq2DBee``=g@J~*|o(ik9 z!oaS;PbKZ+)1Ni1JwRFn$RHv>fF6D6Fb1ct_9~^Ow4Nc8+?lAqgZq~G8@S(wIz!oI z8V9?QqdPh4-SepT;GOa@4sjX@doQA-! zc;JGbCEO($bZeX@f1lz(#5hFGP!FQPWyF|B&Us!#LWwdCh8>B}<5a?gxM7HMK>`~H z_MA0KY=>!AK*7G@D3d;oY}Y~SHJ4M{>LRQ;@YO8f;XVL9cB^z;kqi8C*xO^niaNFC zXTPU0pV_A!L)TEE*%~mz#I#5%kbiQ6lo(0@!LeK}6#=Fhe_@;6@aS%D52gn%vh%~l zS_$GT2!l`Td_E9bZwG>xULMevv|@lTJLcH!R)b_%s5>y^{t1@@n$g(n^1uG2VDA#Pvnevo`+>m=N(x=@fHe7 z=+`}FTUX)m0wOqJ6l)t1*k(7$D^i}y2OYDjKGl@PAiN&W+f->ICU}}@tpMW*ABl&Q zrmn(%Kw0(iBz-tJ{n2E7q2QIIN)~R7jJG@Yc`#Y}e^~Nc9|hT>aId!GiyDkRdQNrN zOr5%&eb;IKf_Z`9A%^9G@!m`yrY31x>>#)BS zhL`NTr&G`!ZLqc76FEN5u#ALciZ^e8mgr>E6d8R$;JV2~cgdm|k;tXLTc@!Xl^e6h zW67d4e`)ObvPspd*xLXpb;+A;1(z|j?Gh9>eR>@e19iRDPm?UG`4Ht^oXw{2F`YI1 zNLkzJMI7EvlLL0_#QNimHcha3PI+DPZnMBPjDV88usF9#BLwOm0E;W${aOxcBWkJGuGvz@~fBr{S{_-+Mz~p%vm)bB&$AR_%4c^RI zU*HxcO7Y2Pd^u_aSwD@U5icSprkTiRQN1cRr7o+v#8Hi%7T2r7Pm61N7%I8PF6520 zkm1~1a8$F^=I7wg(jd~L0?R>D$+`{00cuzS$n^ov(wCgJUO0_x7C>`|a~uouGJt zgU3&WBmU>=Bkm!Epq!UTesUt^Y%G?Y6h=9_6ICc@fhnS#;0(rEmi;k7loQ?fD3>Xw zEmHr$z>ryJ&a_Bp95N3@W*RaZ)khyPfB)j0Wyp+m;^%)}qR+5S{PPNk?x$}thq19( zc2e%iVJt9}ILw#F*^OW;cNkPXc=iT2d1pxK^$HW)JEv_9^f2c0+>iHETHk9|d&vIs z+)u_*M4yVO`B710?XZjcFtviQH(@`Fi#_*aJ9X?GVbSFQMPq-zmH!B1PmkjMe{QSc za~4DW-xvhP=z`+pmTtj3tH@)Fp$aOgO`L^e zVqobh$64*)nxM~|3qREKzUBCUQl>LFTYe?8fg(t3!GSx2RZxmzQu zHNvdm=L-#-4!WtI<61-m#B+zWIkNsu9WJKYhr47Dr@pJsM z$n|tOsZdMzo4oSSeYlRYEXsn(SXh(6o6K~a4AHvt*|TSU(MoI4ZPAM6%r08dJ}A+O zD6h>X4AF`-yzHb%(TZaCf85`lDWa8)p^cG^F%hi{4DA%>>ckYSrejD%7)LEXldMI1 zSa>~DAZrz04H<||QELnJa>-4QN2e_+6=CdGWs6ESs&irRD+z-o(%}5o@xix_{Bq9% z<(dBFw}~FXW15JjsZ-c`(|F*04n zrxVuJNc!-Vl>p8zC{cM-Re*E*Ka(~je3Opkj=&bGQ)nu>OJn3V-77E$_$d> z=XjKWm$&$zk$&j~e|9q;)AKm^90qChIUM~nV#m(Fgz%)NPu{}!e+Jcfe%~iij^`H{ z#a_JyE8f`YPRw|Qj$(lOVbMlRH{pUR{tcLJz6BKvHeR}0F+}z1qFBSuvFxVaz~cB! z;|s)DusBSzd@*2)Zmf*U7wpYV@6A>lX41{(g1xutJ=v;heG zm2S0Nlf{7Tq-8&2v#4f@6AoA*hu|@O!DB;z2NT}Ze^2^WudBg?ha6IJ0>5r6{QvbT zX7o$t-~iOB3vQth=$!}X?7a{@XskY7FII|rQO0*2Mp;hkQm(sH3d|+6VpwHWOd?S} z%}}Tn+``nAmE2>Z<0r?0Kh_d|Zv?-*E*Ywa^eT4SH)HgshemFiC2G@sA~wwwt!aix zO|yq#e|r27N>#!q%|jDC{QWl*w=dK1I&1zjOGb~}#udJ=?{!vT{{H)G`~lBi z>@y-H*S&r+zT1t)`PFH15)Bq#3(L*LL6r5=cnm9$B`)r;VoY9P<%07GJnjL15fgAG zo&+c0Qgob*fa%mu)>?aY^l&nc`yWBK!D}&Te;1rVGH}gB?$cyZOheTsOXA!T8sz9L z57O}FG!dQ|mrZ2RMS%du>Pp5}wKkMrRD1rH1|iDZZS3PgJcXu3p;#tkDjnyHt#Vu(~q)jS(0LE54^QX ze=xrcCt0>VoTSBr1tsEe6hNu__dqo?V;^+Al3tv%{grLwms^7Y+xR{e55#VC5l)6V z+hIX9f-F3kWb8x%(=Ly)oB^4skFw?EP&7Tgdv2AIo}Dt@aKK#^eZ5W@13)mCap-7G zUl+$$$yezWwzG`?t-=eu#eMjr_m{7Le}7@Dc|ZPzp$WbCOYgOX{rE>0^Oe8OL6Bdi z$>j1%x((Y5vdI|K09gS3n3zNwgrh+qyk`a12?IELM;)iS)jI6;#q005aNF~h2hi&* zXnMb#YSp&jsh#}FTd_dremk+OT+($AoT9XMdeYfCe7oQ7mI!4-A!o79tKt>;e+kxF zw%aOWDFrpA_k^D>t965yy-y!R&8i&`#VzdrE6$bb{D+&w)3gDHyjL3=Mdv^Gv(A65 zwU--z2sY;Dzpp(09wFh$&;KtsU~X9Pe_8(g{6CNX`)Kihi$dFy(6e^9TTI}A8;@1w zM(vCp7EW?=9gcYh_Yxdtc^A_&f0B9?rUN6D8{IJBWIGPcr0|v}Jy|qj<%QdhICog8fK`|9!Ae{fnW(A9o! z!#wm=yNX~&s%paDAtrYF;V|++`!5P?tp}g2jVS&Usmc5WLzx6&nud1}Oen#7SiOkw zl!$Gz!ga3+u09O2jrs+#gx=voG ze+Pk8enX+m3j)17b+mW3wD;2FTHdvbi*HYybZG3EX3O9&NPh0^Z=G7P)gelm$MY&! zDUi(sBVdy~0={j|?~5-}8V~%NL?~ZgevBC9GsfZh9fUVg4tr7Pe|x_Mb*xou&;STK zzzB;-w+d_5sXlh9m#tu@dgfHO*71TPz?l8fQ{_{Svmi+m`R2jjHM^D$3sG9Fh$0wc zXlnD*Nds`Qsc^cUZe-KDVUgAo9f?-bevEk!o5*sK7|<`Qfe zhk%BC0BBeTqq;h2fB9lPGiHAgEC)6G_XX_Js~5!7lP9h4#F|Rg1+;0b54s4@4Tmvk zgnmAttpyVBnc)qPRji&Df-ELnMVu1IG|0PJk1AF>pNV{@uI-X=?G4H`#m6Tem_@}z zT3)Ui7rjo7WZvRV%yVsBzZ=70%Qzb2@oNv>aD=xt2#F-of0VHKD~k&Pr7MnJ6mbz9 zmE$5qr7qba*{zu%&v1Ka?RHa>C>fOacn1zPij0R-Sr7)+)gEUA;R ze$pW2S5Z~@mnJD@k-DUc)<=?uXH&M7GK6N?U>vqJ-(cn&j2L-xQm28mjf1d#qL&Oq zp6L0ve>~CiFLI(+Yhm;0wlzp2NI%9d=Y#n4qP(}&M-uG4M0x}{-v&FA)UP?YCG;N` z2>m)FvPb40o0(IN0Hr&@vF5whLEzhL1b%$x`@no3_`U4|kG>5&#V+vJC!b(8&j0NX zLS>uD6CH~xlIXiSBo&cqwj)#5(dl=`i97&xfB!2FK$3@Kj1Z(->=cP^KztjX_YT6? zW1?{u56SHhx4dI5^H0a@j@JU$&?AQA9WY6BCRO8TcgVRC+${4E|PS$V~Njf17yAgyy{x7xX~!UfZR-(mAXd+zRh zf6JY3x$`Y|er}(i+vn%@-|e~GmPeFz>8@)g$#+ElAf={^alsZB(WZe23$6C*^l4OO zt2^bVHcHV3n*ED@JL69gn<}5;L8O72IC00h1$YXt_C>kc4{x4^qYPWlli>YIWA#Ij zf|N#{&!x#f`3O7Bai`lW%?&iV+)zL-eSCZXr`M1#gpTgTu2X~+CyIvw#Iuv ztRqn%EqzwR=wC(skHHO-Pp+cWXayuX@UR?@#4|us0>C8gnv^&4liBUyFKD~^e;W2F zJ)17#TUkBqkCf|NctHrhQYOQYIC18!oyQ@JFPP5iam?~48p|5dV8QTEFKWQ{$!cxD zK?qP;3cRLNd@EhqFa#0;f{&Vbxi}q`D9+zLs&zyOX9?}(^(1jU>ZkD%N6aF%L1|Bf zspaJ?xsa`AZWAjs5VSm+L__U>e=*>$gll3VceUb;OlHH4Ia{|iFw+3fze}r|>|Z7T zvwvT_xV8MN%93}YN+%Wr}o)zFFwr3MeY*Ygi?dZ5T)OaXCPf2wimt*$vc z+j1@@DK7r}DjWqDY=axan-=2xl`;<2Clv!)IBs?4kXh$eM796Ve+)7UNK>odd8^-5 zt^V0t{jUH{o;8+qW5O*rnJh|e0=|{xsrk#whIO#XA;bLl;1?rNN*OZD)^=1 zW>ZEqAGLv>CR`VyUuKDIf7N=?rOwZV{s9<9Ao75<7H^Qcmlb%jB>vQl?`BYzZ+L7? zs^u`-cIxj0EM7ICbJ*3y3K`zP{wAJN@U2}E54Zbfa1t$PDdaq4n^-+m{Djgqe#pjvCie#OW& z1-AOox}!7vNW|I4lW-7E^Z>KTEFT-O+&)_wkX>FA$Ld8;GumI~tDp|LwblmgeGnQ! zWGd0k+eq~$tkra{f5wCa5(5b~**|}lGzKXow&j&aU`cQo^t%a&Kk!#uqTh;lY3lnq zjbOT?K?3}9%#SRas~^lLqg6N&akf8w!q$lpv`VE&pA3VPs|nK91t*zJo>{hs`$6)J z-Nm28g!Ri6R#6+1*`x{2gGjiHs3c5upGKJAG?}Xh=IVjpf2Vq2ez2b(?0=sJ`%yAl znjh}(dAJwWbJTg3WG%!)7Q$I=F%H86%Y|t;9EP`Ceyf?+`IbqY@&gC1jL{*qsjcL# zi1oPS-f1Z3UFMC38Ltj*Lqvl-MxFfl42(@QK`t~%*T|inAdqSXuJ$!^R!miOU^KZt zXY-5gL3}eBe};E#w~>bildLITfsmG2mEmoK`n=0`dYum=OWc)o1e zzZ4)Y=?ycl_-^QFX-Os~tZwe`fjHFW z1U9sFNO#IibE<- zZC2)4J-NkY=_WN^@8)OBBN&5|Y*LvW_V?x=a3Kl&7ABkqkn%SPc zZK_H9$<*!`l~AkL(FWTOVXu58&XcL8REpZUru*Z08Sw(MUbr9R zecJ>&i~`PUEy$YT^3+mm^3;?sQZk>Ci0m@AQ>Kkh_1ua!Y;7Bij#>P{IP_z+-^$6K z8|JJRKYtkBA$}j<=s0KnPD9Gs!`l`)m!X@RGqs3(bNgJYC{? zz}I#hA6&88{;4?L#k}A)#u}%Vw@cdL+MXst4@nmzfLlfwebaI+<`UDq@7GPpr!;q| zswBtlkFaJBLa95&`TIqB4oY$Jv%0qxZw51x#k2sAAg=mv(&w?@o=E2J_1y%PlQ`oQ1;U1*t*KGg9zJqY6zo@|`L^@PnTtL9H17w#H0@*AP% zpaYzrA9+^)1M+$htT?4DULA2@(3u{BJ3k1|=nHMFgCnrcyx8Lt)Y<<`NHV)BY2e6^ z&2|%hSSPgQPxQ#4R7V*CMv`Qkav70RQI(wWo9$?TC^Rfd)8Vf2=tB3`H@^W_&_)}s z#bz<->NwRF&tLs7)|g?OXvo;!bzl|HY9gJ-$ZcpnsPRkc_a**srOGJ-jYJWTN_1;S z3CW!VF*?PdYel=!+=ZPxaaN=JDpOuO2|0e1fc)!A=W7{pMDHvZFw$L834TpUySjs* zf_c^8u`R;*`Zzc1I&m{fc!gOQez!-#DchzIpMz&PmMKKk`9%S;+5(INQ3pfEwxC^a z#`WV8k@&iU2}1PiZ{Uoc*~n%mL=u^{$~4pvk#rFh-lcs5?(OYy#DLWm9oa(wJP&c) zC@^AdhD2WFLtIq4?D_76Zj$d;dLF@DCoK}lj9ple7^Y;}lxv9(S?%6?vbn8L{Bkdv zFCc7K)+t$~S}L|j$D}shyFBn$jyJiPd4#u>=TIuEoTZQ{PJ9g6+>jP?5uRVXw0m?9ukKt9nsnCPCum#ueF*`%+xUxIg zXhpEZ+y|R>*e2DKl%QmsGSKY5#AwJB68Bij z*ol&I<`(=r1Z_qhw@!kRJwks()ai20&qft-#=63tC=6Ui#M&bLJe?Bs;m&Pc^#5!!P2 z56#)%XF+M~|5UtwFzldc^ff2JGXF`0iYt1OpY_e}f%Zb%BEbtH#v51CU8ybXg2g8E1J6_&^nSDy%j8?v7|ch9KY`n>Fb=&SlyRO%UR5{ zK^K7^92QBnviUgw5;6LjaGxBHq7Uctt1FF5#%eB!}7ZBa%Y`# zh8+9Owa9k9r@hUSPD3PGD@EqvvyH@$_DjR`V~hn!PqnRwXFvC1_89 z0M6hVNleVQ{`jdiZEgSJ6@4iP$@;=~F+ab@`;#0Mq!T|_6TgFnd{$XOy@ADzbww10&EfoHm ziVgyMpJ%(dh9s9@B^%M^i5ws5YkHn|14dOJ4K0E5c;KN(7rR(__eT6)KXZ1a)aln^ zpk)>RsO?q_%O}E`KYvN4Y$*3lK6_#wqfQVSM7FRz3$muktdb`W#|s<%6vMW3_By!m zd!KlKi1L}wpYM{NTxJG%unxuiKclc;(WNvV3cX&_PVX82!yZX0CnV@3NceG(TM!7U zZU5-DHO5NMS@Nq)G0N(+?VZ8rZr^W^$?`;39ckm|P#f(-rX&qV;@yg3l-wf4RcTDp zIlZB9m{RaR?GPTs%Ql$GS$C`OXfTE<`J58V_jY=xcOY`mwJ+LEA&O-t%9g~F{za;M zQ`lO!YP6{fsov^??CB!&nBVk)>}$YigG}sSitWoS;S<7gVm_ktEE?5Vy#biU(OmBf zjCXu=dPLca`F`C~1kZX^36w*Ag?ixP)%rf~dx`GAY@rmWdyi`O|Gy(2JXWkU?5DQ= z&hO7U+d(Ni_vuW6%sr{R(ly!`c(YfEQT1jzkG@oPF736^+5UEz6cU(l=ZxP|tFZ9E zEVm#z^vc}RCSy0V#cXga?Gfau3d$fc8VWAynxjmPXGsY>^NHfx$R{06&sPy}aJx5vw z#%pr9KilWC3g*?tLI9o6ird=sy(?M9O5ZduO*z_JZ!tqfFB~vAU^>*4tzeE8Shw|q z>wuu9@Hg#4fEtXiHtWdV2RpeD;I*CqWkALoMAe}btv9-e4Winm0wQviSDAKxDb)xH zj40Ba7if_TQ6J&(tE`U=vi%^RgfFTkzuCY&{LKHm)^!_LVX{h)4rAQ=*RZ8 zzDCMv8ap%?RqGj5OFx()+yd5NmuWZk(7QwgQJDLu_2#%vp0B6dQpki^yL_F%<_KA0 zgATBp$m1|Vu(XRs>S4+VvMTl9w7JQStncsC`^3mm&Y;PCGGy`0cVq1$Tn~6~v$pYa zL3jId=?>Ve!=R~Md2U^4QYTom=Iswb!c%^?jOC}%!neKUX_WhI18?!fI5iCo?GD^Y zd>W*XTFa)FIs==*_T$UOoCm}h(!)CPIyfP3VsEJNBRaX3J9ULq-k&}!SNne&CByHC zsb9+i;lr_#7zj%kgXHN)zq(tQLU`rbjt`Z;HXuS%dfw#ICeZm+G1OeAD}9mV355`Z z9Qi=Xm1_B+(zUP7_}by)ZUMm;OK_FN)I46IG?$4D{wz5!RN@-)bg;f=Wlu+h^gY+Z zI;{2xQKR9z=Bo>^3Ky2U5-woZ~k3mF{5+c_>l%i1i9}iWH z!N$5b04Vw>MBu=i?)$M@LJ=@42$Z@wg?S>0vf-;BhX>*~8ZS z70b1?vWoLdL<;ObZmAj~;2miJ^w{Qq0cWICdi?kjEX5(5+jAAqEV~^rE7k6e3%z&# zS=-*GmQona2;0+<^IefSvCmV~*7SQB(B6jc)JkdXs?fq9Zk&j=h`_K}dt z3}dsIFBgM6zBE)pyStP^tm9%WL-0Prn^~@V7(2mOB)=w$w;UUGr?=c^=hu!5RuASe zuJ3~eH2p{6eI0>iFaQFmql)j-k$>%`$gh-Zl!D@N` zvd+f~uLM&In=Zz{ZqmQnO8=f}^aF-D_K%W-q&M&^ZzB0I=~cdkt*uN94SiRBWJzW( zai8SWz(c=LzIwcAoQS!w(Djrbp1Of-4B4{z6srQV{LiY2jp%`k_Y7jBW;_d`m$x63 zG&}J+o#Dzzpj8qzW(#(S9zcYE@BLW>&l{@`E*J-Mjj88+7Uj;qF-n5kuvxYyD3X2)z&H2a=md;M_~IKRGjp zEF(hMqV)vS7g!CJ(ps0k%q~Yns4Xuh{il}Gf}s6rzq#v!U-mrwbX`HxO3wb&X;vWj2f9|=Kf{0ToG@eed_RQ>5x$=| zIcTas*LQC4nGuzM7NzZ>@UgQ`l$dT%16?eIbKl%$4-p6l=6|*FVyy1^V!kxpaCZwc zy3|^?5@CjQwoQz58VA1QK1qR}-E^e-Q*sBD_(i5BhGUr5+0ZslS@eW!1{`-MV=RI? zm>KZx+i=O&>v8wN0FyOzw6W25o@tz!&CA7${bo9@!xZt%F_TDE_AsUsO9*=LG*p(9 z-lSi=K~?kO%{)J^X7}WsL!yl!ZQ;{`5=+4_RF8^Pr9VdOJk6OJNg*4LtqU-6mrRTE z?7Eb#oT6th3U;2b&EdtUWD3aUE4pR>=_>^!xt*i4nqB->tW9zfo6mX_Lo6JyIO^oA ze7hDB=-MmNeye(jaCaPgckL<5x45FJ3fYdnN9ELTW}p3$rG&$yTj;3~@Zqs-|{Bz{8U|J6tT z8y^kr{trI#-#8XHeD627D;cn0&P^AFxz+D&`0BCF^aU}|$CI0~kG}!XB;dDX@zdn< z=YtyR#o1r`>XOi^mnzkD3bHXvBHe@eUpg6H!7#McJ=cp&2s0a$5$Nc0wgsY73^{HC z62ut}1I{|M0Rs;)KB@HlGf{bLvRQ!Ro%3;agXnl~`k05*vbIA&wdo=K{g8(gx$3h3_L40ng|Ez8aDA)1VRtV7%Qnud(&DOK4yr2382SP77eN9UC#B1 zpy@Ki0hsy>>fN|iBGD;nRY0z;Q48jI1w%YA|E#qts)UTY>PJ{~ zM63Ad8v=3D8fVsJgP$bw3Hm-h8hT61gU%!P7K7!jb#fN8Vmc>In_ACniCD_?y&i@g6UlXZ@t&(TSN9PZYhHk^7FVfT5v{ zNTsEnXDU?>P1bp@&=#9Xw>aI8Dojdkj@a_~aTRbFx?U~LP3C+c{$NtQ^;Hg>_?iF%1cGbJye zmeVssPQOR=d~(Zb{zZ%fUi~6ROc(j%bJ>p9mn+dr%f|70$*Sa?;bwT2pwBU-i`J}1 z2;$P_UzycGJCh+ig?h*vzu`;4ikM#Z7v1E2a*dq;NYY6H-i@uVc)Tp0*#6ka z4M7b-1#AMmkVuas@W;WEb;eG86Ffp)nP*FHiP7L6ZN`XhwcFQ=Mpqpgk8UF4l|(-+ zkscq`*l*W-Zt-fGTCVI}kUFD#5v}8IGT;>@vG*PV0rr1YIicNUd8@hM&KkV*`qB1k zI+rn*M7REOw@p}=hQZy_`>~xBmebqVzK*Eu1-u(w^_e#m^`FAmhZORK-pQ%RdS1&- z(_ZaRW}3V_@p9kw=TQ*f$v`!tH};!#AE56ou9o3=%0a~XRY}n4?)rq`&hsTH1GD7M zuEG*reIKi|ow{0Dqb#+cH8%EUJ4-C)Ml{DJqvYZ4ri`cAsOo}y*Y0!@P;HUl-d&|P zcEC|146P)#SvTTge`tF7g{Wg$D34JSAMw(%k~dCxPdf59y4~g; z{M5{Q4c;IIfu*UW`kX09!}b>savf#ATs)Ikmuhqm{TTdyIi{mh5v$ZmHjcf;w76J< z=|alF1|p)^;kY)JdK}EnR@g+CvS~Woz(U-@yZpYybVcElm6%qL6`M>WOxMVAsUWkPl_}DPg&_)>V$Lt{AO8RA2l9iF`A7wJ0c)9Kt0I z;}JxG{KsGOg}y#jo^dP(IV}thxPe>m8<{=GxRjbp#|30xE4FvN`Dy~kJaQ~7j~KNw zEwW%9jP69G^{n3kjyO=>O@VDD=57~K93CL(frvi@heVfBAjt|wc&0Na?hI?7oP<-0q<99|0WK8e44G~zY^I4`;12X2I})$^7fR6N?~J{nRoHm z2>$&bjw|YK%tbPKNoAP%p z3aZcRT*4xp&)-L2yWTfiXIHJx1j{7Oa@GktPr_(3*Gfuh9ySJ(i-13M-8L8z>XoBq zylsx{g!-}w9_puGQ48K}f3SmVimn`99a6uuNmeh$wZ^Wh470FSYjmUSA(SOE?8BNC z5@3`ez{Sz%XUSl4w8$a*&Lh5h6#Z3Bq#>4@fM}px)}IvQb+PF9mze>t?Mn}hhd>S{y2(uHYtFnu@w1pAJqFQM^ycc zEy3>hQ(r}|5y0#T_|Q(mQH8s@B!XZdqqq`l`@OsTa3D61^n0dT{2=_O!e|$cj}Zv4 zLCC0j3kh_VJaG5tfm7>ud$34^t^zn~WDe~InK?w$!0j`jv*;suEHQ=H+@e5W?&D7py~pEDF%0-DU{j&Oi}?gWLC= zQ1FE*IJj`wvP=90&B0`BOxSWK*M04smy0xZX}agDO=`6+#JP0 zq?(h*s@1?tktBkexOaL6KtxYq#J8Cg{3B;~pb1w<{}@VmV9XM5F{-el&90Ic-{C$Z zc?j72&UbhKdE)}7ZoqPVLeSi)a^x1g?gKk{?*adHIIdmYp9sEVHGw+UzGLcTM5_dB zY5zuWLB;KkcNoCP{L;eSS2S5$G0xB}KU0GYlads*Ft?h*BvcklnC}upy>9cm#eXg6 z^n8DgJLLk1r+?620V%5wZpJ99x6VKlBnU|WJFQia*I#_^r&&{P9jwzVyiuvsT)j~V S3G~5x5OtaWgrg|qp!`2;rth5q diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index 660e0f5562f78..ec904e0c00bc2 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -2148,7 +2148,7 @@ if(webgui) ExternalProject_Add( RENDERCORE URL ${CMAKE_SOURCE_DIR}/builtins/rendercore/RenderCore.tar.gz - URL_HASH SHA256=6fd36b7993ff5588e3110485a9286bf503f59b32a52db6c2cc777c556cb8659c + URL_HASH SHA256=17fa2e093cf4315ace5c784ed370f00478d248797fef1aeaec281c42e0b5d5d3 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From f4c70f4afa7747b38decd243a5111c1b923ff1a0 Mon Sep 17 00:00:00 2001 From: alja Date: Wed, 23 Nov 2022 10:04:41 -0800 Subject: [PATCH 51/84] In render() print warning when eve element selection controller pushes null object. --- ui5/eve7/lib/GlViewerRCore.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index bbde078076a3d..f5c64c83ae273 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -476,9 +476,11 @@ sap.ui.define([ obj_list.push(el_entry.instance_object); el_entry.instance_object.outlineMaterial.outline_instances_setup( el_entry.instance_sec_idcs ); } else { - for (let geo of el_entry.geom) - { - obj_list.push(geo); + for (let geo of el_entry.geom) { + if (geo === undefined) + console.warning("Processing viewer selection, undefined object for element", this.mgr.GetElement(el_idx)); + else + obj_list.push(geo); } } } From e02788cb19f93e698014a73c01ca5f33ab6a4934 Mon Sep 17 00:00:00 2001 From: alja Date: Wed, 23 Nov 2022 10:06:12 -0800 Subject: [PATCH 52/84] Check change bits in ImportSceneBinary when scene changes are streamed --- ui5/eve7/lib/EveManager.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ui5/eve7/lib/EveManager.js b/ui5/eve7/lib/EveManager.js index f0c9bd08d61ff..6561e9b08ab12 100644 --- a/ui5/eve7/lib/EveManager.js +++ b/ui5/eve7/lib/EveManager.js @@ -440,6 +440,14 @@ sap.ui.define([], function() { if (!elem.render_data) continue; + // in the scene change update check change bits are kCBElementAdded or kCBObjProps + // see REveScene::StreamRepresentationChanges binary stream + if (this.scene_changes) { + if (!(elem.changeBit & this.EChangeBits.kCBObjProps + || elem.changeBit & this.EChangeBits.kCBAdded)) + continue; + } + let rd = elem.render_data, off = offset + rd.rnr_offset, obj = this.GetElement(elem.fElementId); From f86b1bbb076abbb6fe443f674874a9b236e85553 Mon Sep 17 00:00:00 2001 From: alja Date: Wed, 23 Nov 2022 10:09:21 -0800 Subject: [PATCH 53/84] Check view data is present when filling datGUI --- ui5/eve7/lib/GlViewerRCore.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index f5c64c83ae273..59df4374cbc6a 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -125,16 +125,18 @@ sap.ui.define([ // add dat GUI option to set background let vd = this.controller.getView().getViewData(); - let name = vd.mgr.GetElement(vd.eveViewerId).fName; - name = name.substring(0,3); - let parName = name + "_WhiteBG"; - let conf = {}; conf[parName] = true; - let pr = this; - datGUI.__folders.background.add(conf, parName).onChange(function (wbg) { - conf[parName] = wbg; - pr.renderer.clearColor = wbg ? "#FFFFFF00" : "#00000000"; - pr.request_render(); - }); + if (vd) { + let name = vd.mgr.GetElement(vd.eveViewerId).fName; + name = name.substring(0, 3); + let parName = name + "_WhiteBG"; + let conf = {}; conf[parName] = true; + let pr = this; + datGUI.__folders.background.add(conf, parName).onChange(function (wbg) { + conf[parName] = wbg; + pr.renderer.clearColor = wbg ? "#FFFFFF00" : "#00000000"; + pr.request_render(); + }); + } this.scene = new RC.Scene(); From 3447de55ffa04ef78dab4d011b303f6d0ab8e784 Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Wed, 23 Nov 2022 19:39:55 -0800 Subject: [PATCH 54/84] Fix projections of RPhi cell towers --- graf3d/eve7/src/REveCalo.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/graf3d/eve7/src/REveCalo.cxx b/graf3d/eve7/src/REveCalo.cxx index 9aadc7ba8c4f1..c3d04be414481 100644 --- a/graf3d/eve7/src/REveCalo.cxx +++ b/graf3d/eve7/src/REveCalo.cxx @@ -1393,13 +1393,12 @@ void REveCalo2D::MakeRPhiCell(Float_t phiMin, Float_t phiMax, pnts[4] = r2*Cos(phiMax); pnts[5] = r2*Sin(phiMax); pnts[6] = r1*Cos(phiMax); pnts[7] = r1*Sin(phiMax); - Float_t x, y, z; for (Int_t i = 0; i < 4; ++i) { pntsOut[i*3] = pnts[2*i]; pntsOut[i*3+1] = pnts[2*i+1]; pntsOut[i*3+2] = 0.f; - fManager->GetProjection()->ProjectPoint(x, y, z, fDepth); + fManager->GetProjection()->ProjectPoint(pntsOut[3*i], pntsOut[3*i+1], pntsOut[3*i + 2], fDepth); } } From b7319d9eacbf5635d699fcb6d8f3fbdc5ab4c0d2 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 28 Nov 2022 12:11:00 -0800 Subject: [PATCH 55/84] Follow up on changes in Texture constants in RenderCore. --- ui5/eve7/lib/EveElementsRCore.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 147ebd3fa5d50..9a820d4bc39e1 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -640,10 +640,10 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) sm.transparent = true; sm.addInstanceData(new RC.Texture(vbuff, - RC.Texture.ClampToEdgeWrapping, RC.Texture.ClampToEdgeWrapping, - RC.Texture.NearestFilter, RC.Texture.NearestFilter, - // RC.Texture.R32F, RC.Texture.R32F, RC.Texture.FLOAT, - RC.Texture.RGBA32F, RC.Texture.RGBA, RC.Texture.FLOAT, + RC.Texture.WRAPPING.ClampToEdgeWrapping, RC.Texture.WRAPPING.ClampToEdgeWrapping, + RC.Texture.FILTER.NearestFilter, RC.Texture.FILTER.NearestFilter, + // RC.Texture.FORMAT.R32F, RC.Texture.FORMAT.R32F, RC.Texture.TYPE.FLOAT, + RC.Texture.FORMAT.RGBA32F, RC.Texture.FORMAT.RGBA, RC.Texture.TYPE.FLOAT, instX, instY)); sm.instanceData[0].flipy = false; @@ -736,9 +736,10 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) callback, (image) => { return new RC.Texture - (image, RC.Texture.ClampToEdgeWrapping, RC.Texture.ClampToEdgeWrapping, - RC.Texture.LinearFilter, RC.Texture.LinearFilter, - RC.Texture.LUMINANCE_ALPHA, RC.Texture.LUMINANCE_ALPHA, RC.Texture.UNSIGNED_BYTE, + (image, RC.Texture.WRAPPING.ClampToEdgeWrapping, RC.Texture.WRAPPING.ClampToEdgeWrapping, + RC.Texture.FILTER.LinearFilter, RC.Texture.FILTER.LinearFilter, + RC.Texture.FORMAT.LUMINANCE_ALPHA, RC.Texture.FORMAT.LUMINANCE_ALPHA, + RC.Texture.TYPE.UNSIGNED_BYTE, image.width, image.height); }, () => { this.viewer.request_render() } @@ -753,9 +754,10 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) callback, (image) => { return new RC.Texture - (image, RC.Texture.ClampToEdgeWrapping, RC.Texture.ClampToEdgeWrapping, - RC.Texture.LinearFilter, RC.Texture.LinearFilter, - RC.Texture.RGBA, RC.Texture.RGBA, RC.Texture.UNSIGNED_BYTE, + (image, RC.Texture.WRAPPING.ClampToEdgeWrapping, RC.Texture.WRAPPING.ClampToEdgeWrapping, + RC.Texture.FILTER.LinearFilter, RC.Texture.FILTER.LinearFilter, + RC.Texture.FORMAT.RGBA, RC.Texture.FORMAT.RGBA, + RC.Texture.TYPE.UNSIGNED_BYTE, image.width, image.height); }, () => { this.viewer.request_render() } From 8df7c96c3317d70af6fa24f1307565d7d36cfd1a Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 28 Nov 2022 12:48:08 -0800 Subject: [PATCH 56/84] Apply window.devicePixelRatio when calculating width and height. --- ui5/eve7/lib/GlViewer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui5/eve7/lib/GlViewer.js b/ui5/eve7/lib/GlViewer.js index ae549eecc4361..e50a04451f274 100644 --- a/ui5/eve7/lib/GlViewer.js +++ b/ui5/eve7/lib/GlViewer.js @@ -29,8 +29,8 @@ sap.ui.define([], function() { get_name() { return "EVE.GlViewer" + this.viewer_class; } get_view() { return this.controller.getView(); } - get_width() { return this.controller.getView().$().width(); } - get_height() { return this.controller.getView().$().height(); } + get_width() { return this.controller.getView().$().width() * window.devicePixelRatio; } + get_height() { return this.controller.getView().$().height() * window.devicePixelRatio; } //============================================================================== From aeac9f72d42ce12b86bc002f7c9b21a07ad65be2 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 28 Nov 2022 14:12:08 -0800 Subject: [PATCH 57/84] Code to render without tone mapping. --- ui5/eve7/lib/GlViewerRCore.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 59df4374cbc6a..4a1dc943c3e3a 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -507,6 +507,7 @@ sap.ui.define([ if (this.rqt.queue.used_fail_count == 0) { this.rqt.render_tone_map_to_screen(); + // this.rqt.render_final_to_screen(); } this.rqt.render_end(); From e3233fcd368dbdc11a7a35ab2b0bdee3362c71b8 Mon Sep 17 00:00:00 2001 From: alja Date: Mon, 28 Nov 2022 15:34:34 -0800 Subject: [PATCH 58/84] Fix typo in the default argument --- tutorials/eve7/projection_prescale.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorials/eve7/projection_prescale.C b/tutorials/eve7/projection_prescale.C index 51640dcc3f88c..c161c72f6293e 100644 --- a/tutorials/eve7/projection_prescale.C +++ b/tutorials/eve7/projection_prescale.C @@ -84,7 +84,7 @@ TGeoNode* getNodeFromPath( TGeoNode* top, std::string path) } -void projection_prescale(std::string type = "RhPhi") +void projection_prescale(std::string type = "RPhi") { eveMng = REX::REveManager::Create(); From 4df5cbe0f018a7fec1500622aa28780737cf1389 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Tue, 29 Nov 2022 00:27:36 -0800 Subject: [PATCH 59/84] Fix resizing and event handling for high-dpi/retina. --- ui5/eve7/controller/GL.controller.js | 4 +- ui5/eve7/lib/EveElementsRCore.js | 11 ++-- ui5/eve7/lib/GlViewer.js | 4 +- ui5/eve7/lib/GlViewerRCore.js | 76 ++++++++++++++++------------ 4 files changed, 54 insertions(+), 41 deletions(-) diff --git a/ui5/eve7/controller/GL.controller.js b/ui5/eve7/controller/GL.controller.js index 88f2a32261aaa..f06e03a57a16a 100644 --- a/ui5/eve7/controller/GL.controller.js +++ b/ui5/eve7/controller/GL.controller.js @@ -220,7 +220,9 @@ sap.ui.define([ onResize: function(event) { // TODO: should be specified somehow in XML file - this.getView().$().css("overflow", "hidden").css("width", "100%").css("height", "100%"); + if (this.viewer_class != "RCore") { + this.getView().$().css("overflow", "hidden").css("width", "100%").css("height", "100%"); + } if (this.resize_tmout) clearTimeout(this.resize_tmout); diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 9a820d4bc39e1..1ebf04afbd777 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -677,12 +677,13 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return s; } - RcApplyStripesMaterials(eve_el, stripes) + RcApplyStripesMaterials(eve_el, stripes, pick_width_scale = 2) { if (eve_el.fPickable) { let m = stripes.material; stripes.pickingMaterial = new RC.StripesBasicMaterial( - { lineWidth: m.lineWidth, mode: m.mode, color: m.color }); + { lineWidth: m.lineWidth * pick_width_scale / this.LINE_WIDTH_FAC, + mode: m.mode, color: m.color }); let pm = stripes.pickingMaterial; pm.programName = "custom_GBufferMini_stripes"; pm.addSBFlag("PICK_MODE_UINT"); @@ -691,7 +692,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) pm.deltaOffset = m.deltaOffset; stripes.outlineMaterial = new RC.StripesBasicMaterial( - { lineWidth: m.lineWidth, mode: m.mode, color: m.color }); + { lineWidth: m.lineWidth / this.LINE_WIDTH_FAC, mode: m.mode, color: m.color }); let om = stripes.outlineMaterial; om.programName = "custom_GBufferMini_stripes"; om.prevVertex = m.prevVertex; @@ -844,7 +845,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) geom.vertices = new RC.Float32Attribute(buf, 3); const line = this.RcMakeStripes(geom, track_width, track_color); - this.RcApplyStripesMaterials(track, line); + this.RcApplyStripesMaterials(track, line, 2); this.RcPickable(track, line); return line; @@ -1326,7 +1327,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let line_color = RcCol(el.fMainColor); const line = this.RcMakeStripes(geom, el.fLineWidth, line_color); - this.RcApplyStripesMaterials(el, line); + this.RcApplyStripesMaterials(el, line, 2); this.RcPickable(el, line); obj3d.add(line); diff --git a/ui5/eve7/lib/GlViewer.js b/ui5/eve7/lib/GlViewer.js index e50a04451f274..ae549eecc4361 100644 --- a/ui5/eve7/lib/GlViewer.js +++ b/ui5/eve7/lib/GlViewer.js @@ -29,8 +29,8 @@ sap.ui.define([], function() { get_name() { return "EVE.GlViewer" + this.viewer_class; } get_view() { return this.controller.getView(); } - get_width() { return this.controller.getView().$().width() * window.devicePixelRatio; } - get_height() { return this.controller.getView().$().height() * window.devicePixelRatio; } + get_width() { return this.controller.getView().$().width(); } + get_height() { return this.controller.getView().$().height(); } //============================================================================== diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 4a1dc943c3e3a..6960ecda32848 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -102,19 +102,13 @@ sap.ui.define([ createRCoreRenderer() { - let w = this.get_width(); - let h = this.get_height(); + this.canvas = new RC.Canvas(this.get_view().getDomRef()); + let w = this.canvas.width; + let h = this.canvas.height; + this.fixCssSize(); + this.canvas.parentDOM.style.overflow = "hidden"; + this.canvas.canvasDOM.style.overflow = "hidden"; - //this.canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - this.canvas = document.createElement('canvas'); - this.canvas.id = "rcore-canvas"; - this.canvas.width = w; - this.canvas.height = h; - this.get_view().getDomRef().appendChild(this.canvas); - - this.canvas.canvasDOM = this.canvas; // RCore wants this in GLManager ctor ? - - let gl = this.canvas.getContext("webgl2"); this.renderer = new RC.MeshRenderer(this.canvas, RC.WEBGL2, { antialias: false, stencil: false }); @@ -245,9 +239,9 @@ sap.ui.define([ glc.removeMouseupListener(); - if (event.buttons === 0 && event.srcElement === glc.canvas) { + if (event.buttons === 0 && event.srcElement === glc.canvas.canvasDOM) { glc.removeMouseMoveTimeout(); - glc.mousemove_timeout = setTimeout(glc.onMouseMoveTimeout.bind(glc, event.offsetX, event.offsetY), glc.controller.htimeout); + glc.mousemove_timeout = setTimeout(glc.onMouseMoveTimeout.bind(glc, event), glc.controller.htimeout); } else { // glc.clearHighlight(); } @@ -549,8 +543,8 @@ sap.ui.define([ this.rqt.pick_end(); - state.w = this.get_width();; - state.h = this.get_height(); + state.w = this.canvas.width; + state.h = this.canvas.height; state.mouse = new RC.Vector2( ((x + 0.5) / state.w) * 2 - 1, -((y + 0.5) / state.h) * 2 + 1 ); @@ -583,6 +577,18 @@ sap.ui.define([ //============================================================================== + fixCssSize() { + let s = this.canvas.canvasDOM.style; + s.width = this.canvas.canvasDOM.clientWidth + "px"; + s.height = this.canvas.canvasDOM.clientHeight + "px"; + } + + floatCssSize() { + let s = this.canvas.canvasDOM.style; + s.width = "100%"; + s.height = "100%"; + } + onResizeTimeout() { if ( ! this.canvas) { @@ -591,20 +597,19 @@ sap.ui.define([ return; } - let w = this.get_width(); - let h = this.get_height(); - + this.floatCssSize(); + this.canvas.updateSize(); + let w = this.canvas.width; + let h = this.canvas.height; //console.log("GlViewerRCore onResizeTimeout", w, h, "canvas=", this.canvas, this.canvas.width, this.canvas.height); - this.canvas.width = w; - this.canvas.height = h; - this.camera.aspect = w / h; - this.rqt.updateViewport(w, h); - this.controls.update(); + this.render(); + + this.fixCssSize(); } @@ -636,10 +641,12 @@ sap.ui.define([ } } - onMouseMoveTimeout(x, y) + onMouseMoveTimeout(event) { delete this.mousemove_timeout; + let x = event.offsetX * this.canvas.pixelRatio; + let y = event.offsetY * this.canvas.pixelRatio; let pstate = this.render_for_picking(x, y, false); if ( ! pstate) @@ -664,17 +671,17 @@ sap.ui.define([ let offs = (mouse.x > 0 || mouse.y < 0) ? this.getRelativeOffsets(dome) : null; if (mouse.x <= 0) { - this.ttip.style.left = (x + dome.offsetLeft + 10) + "px"; + this.ttip.style.left = (event.offsetX + dome.offsetLeft + 10) + "px"; this.ttip.style.right = null; } else { - this.ttip.style.right = (pstate.w - x + offs.right + 10) + "px"; + this.ttip.style.right = (this.canvas.canvasDOM.clientWidth - event.offsetX + offs.right + 10) + "px"; this.ttip.style.left = null; } if (mouse.y >= 0) { - this.ttip.style.top = (y + dome.offsetTop + 10) + "px"; + this.ttip.style.top = (event.offsetY + dome.offsetTop + 10) + "px"; this.ttip.style.bottom = null; } else { - this.ttip.style.bottom = (pstate.h - y + offs.bottom + 10) + "px"; + this.ttip.style.bottom = (this.canvas.canvasDOM.clientHeight - event.offsetY + offs.bottom + 10) + "px"; this.ttip.style.top = null; } @@ -731,7 +738,9 @@ sap.ui.define([ // See js/modules/menu/menu.mjs createMenu(), menu.add() - let pstate = this.render_for_picking(event.offsetX, event.offsetY, true); + let x = event.offsetX * this.canvas.pixelRatio; + let y = event.offsetY * this.canvas.pixelRatio; + let pstate = this.render_for_picking(x, y, true); menu.add("header:Context Menu"); @@ -739,7 +748,7 @@ sap.ui.define([ if (pstate.eve_el) menu.add("Browse to " + (pstate.eve_el.fName || "element"), pstate.eve_el.fElementId, this.controller.invokeBrowseOf.bind(this.controller)); - let data = { "p": pstate, "v":this, "cctrl": this.controls}; + let data = { "p": pstate, "v": this, "cctrl": this.controls}; menu.add("Set Camera Center", data, this.setCameraCenter.bind(data)); } @@ -768,7 +777,6 @@ sap.ui.define([ // console.log("picked camera vector ", e); // pthis.camera.testMtx.dump(); - let mvMtx = pthis.camera.testMtx; e.applyMatrix4(pthis.camera.testMtx); // console.log("picked word view coordinates ", e); @@ -778,7 +786,9 @@ sap.ui.define([ handleMouseSelect(event) { - let pstate = this.render_for_picking(event.offsetX, event.offsetY, false); + let x = event.offsetX * this.canvas.pixelRatio; + let y = event.offsetY * this.canvas.pixelRatio; + let pstate = this.render_for_picking(x, y, false); if (pstate) { let c = pstate.ctrl; From ab6436b66c025738b5e2453c3577e62b3dc0c11f Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Tue, 29 Nov 2022 09:56:43 -0800 Subject: [PATCH 60/84] Scale markers and lines by device-pixel-ratio. --- ui5/eve7/lib/GlViewerRCore.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 6960ecda32848..9d4b0a73fa616 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -208,12 +208,12 @@ sap.ui.define([ else if (this.RQ_Mode == "Simple") { this.rqt.initSimple(this.RQ_SSAA); - this.creator.SetupPointLineFacs(this.RQ_SSAA, this.RQ_SSAA); + this.creator.SetupPointLineFacs(this.RQ_SSAA * this.canvas.pixelRatio, this.RQ_SSAA * this.canvas.pixelRatio); } else { this.rqt.initFull(this.RQ_SSAA); - this.creator.SetupPointLineFacs(this.RQ_SSAA, this.RQ_SSAA); + this.creator.SetupPointLineFacs(this.RQ_SSAA * this.canvas.pixelRatio, this.RQ_SSAA * this.canvas.pixelRatio); } this.rqt.updateViewport(w, h); } From 68e4a778f40eb4725fd8fcec30e8f245ac3e82f1 Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Tue, 29 Nov 2022 15:39:36 -0800 Subject: [PATCH 61/84] Use the same scaling factor in tracks and line segments --- ui5/eve7/lib/EveElementsRCore.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 1ebf04afbd777..d790ae81d03b6 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -1326,7 +1326,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let line_color = RcCol(el.fMainColor); - const line = this.RcMakeStripes(geom, el.fLineWidth, line_color); + let line_width = 2 * (el.fLineWidth || 1) * this.LINE_WIDTH_FAC; + const line = this.RcMakeStripes(geom, line_width, line_color); this.RcApplyStripesMaterials(el, line, 2); this.RcPickable(el, line); obj3d.add(line); From f8d8c599d21162a3da8b9d9e5d0ae5436d44e098 Mon Sep 17 00:00:00 2001 From: alja Date: Thu, 1 Dec 2022 11:16:01 -0800 Subject: [PATCH 62/84] Correction in view navigation --- ui5/eve7/controller/EveTable.controller.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/ui5/eve7/controller/EveTable.controller.js b/ui5/eve7/controller/EveTable.controller.js index 43bcd792a04e3..ddc3162308c7a 100644 --- a/ui5/eve7/controller/EveTable.controller.js +++ b/ui5/eve7/controller/EveTable.controller.js @@ -34,8 +34,6 @@ sap.ui.define([ let args = oEvent.getParameter("arguments"); this.setupManagerAndViewType(EVE.$eve7tmp.eveViewerId, EVE.$eve7tmp.mgr); delete EVE.$eve7tmp; - - this.checkViewReady(); }, setupManagerAndViewType: function(eveViewerId, mgr) { From 1224c47de3b2949973ed71ab07c31d4f3ae6293b Mon Sep 17 00:00:00 2001 From: alja Date: Thu, 1 Dec 2022 11:31:19 -0800 Subject: [PATCH 63/84] Unregister scene from receivers when viewer removes the scene from its scenes --- ui5/eve7/lib/EveManager.js | 12 ++++++++++++ ui5/eve7/lib/EveScene.js | 1 + 2 files changed, 13 insertions(+) diff --git a/ui5/eve7/lib/EveManager.js b/ui5/eve7/lib/EveManager.js index 6561e9b08ab12..4e31ee20d4238 100644 --- a/ui5/eve7/lib/EveManager.js +++ b/ui5/eve7/lib/EveManager.js @@ -207,6 +207,18 @@ sap.ui.define([], function() { elem.$receivers.push(receiver); } + /** Disconnect scene from the updates */ + UnRegisterSceneReceiver(id, receiver){ + let elem = this.GetElement(id); + + if (!elem) return; + let idx = elem.$receivers.indexOf(receiver); + if (idx > -1) { // only splice array when item is found + console.log("unregister scene receiver"); + elem.$receivers.splice(idx, 1); // 2nd parameter means remove one item only + } + } + /** Returns list of scene elements */ getSceneElements() { diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index 5184dcd717219..bfbe2bfc913a1 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -155,6 +155,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { while (cont.children.length > 0) cont.remove(cont.children[0]); + this.mgr.UnRegisterSceneReceiver(this.id, this); this.first_time = true; } From 1cacb1b5835d61cfd5bad578e85f4de94cc73fc2 Mon Sep 17 00:00:00 2001 From: alja Date: Thu, 1 Dec 2022 11:32:43 -0800 Subject: [PATCH 64/84] Implement clenup function for the case of view navigations/routing --- ui5/eve7/lib/GlViewerRCore.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 9d4b0a73fa616..5ea246cf9c096 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -84,6 +84,11 @@ sap.ui.define([ this.controller.glViewerInitDone(); } + cleanup() { + if (this.controller) this.controller.removeScenes(); + super.cleanup(); + } + //============================================================================== make_object(name) @@ -220,14 +225,14 @@ sap.ui.define([ setupEventHandlers() { - let dome = this.get_view().getDomRef(); + let dome = this.canvas.canvasDOM; // Setup tooltip this.ttip = document.createElement('div'); this.ttip.setAttribute('class', 'eve_tooltip'); this.ttip_text = document.createElement('div'); this.ttip.appendChild(this.ttip_text); - dome.appendChild(this.ttip); + this.get_view().getDomRef().appendChild(this.ttip); // Setup some event pre-handlers let glc = this; @@ -340,7 +345,7 @@ sap.ui.define([ } }); - this.controls = new RC.REveCameraControls(this.camera, this.get_view().getDomRef()); + this.controls = new RC.REveCameraControls(this.camera, this.canvas.canvasDOM); this.controls.addEventListener('change', this.render.bind(this)); // camera center marker @@ -727,7 +732,7 @@ sap.ui.define([ { if (this.mouseup_listener) { - this.get_view().getDomRef().removeEventListener('pointerup', this.mouseup_listener); + this.canvas.canvasDOM.removeEventListener('pointerup', this.mouseup_listener); this.mouseup_listener = 0; } } From 5a2c19c383031dc877b51f09c42a810ce83bc844 Mon Sep 17 00:00:00 2001 From: alja Date: Thu, 1 Dec 2022 12:19:57 -0800 Subject: [PATCH 65/84] Save clear color in EveViewer attributes --- ui5/eve7/lib/GlViewerRCore.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 5ea246cf9c096..0076813febc02 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -123,19 +123,23 @@ sap.ui.define([ this.renderer.pickObject3D = true; // add dat GUI option to set background - let vd = this.controller.getView().getViewData(); - if (vd) { - let name = vd.mgr.GetElement(vd.eveViewerId).fName; - name = name.substring(0, 3); - let parName = name + "_WhiteBG"; - let conf = {}; conf[parName] = true; - let pr = this; + let eveView = this.controller.mgr.GetElement(this.controller.eveViewerId); + let name = eveView.fName; + name = name.substring(0, 3); + let parName = name + "_WhiteBG"; + let conf = {}; conf[parName] = true; + let pr = this; + if (this.controller.getView().getViewData()) { datGUI.__folders.background.add(conf, parName).onChange(function (wbg) { conf[parName] = wbg; - pr.renderer.clearColor = wbg ? "#FFFFFF00" : "#00000000"; + eveView.clearColor = wbg ? "#FFFFFF00" : "#00000000"; + pr.renderer.clearColor = eveView.clearColor; pr.request_render(); }); } + else if (eveView.clearColor) { + pr.renderer.clearColor = eveView.clearColor; + } this.scene = new RC.Scene(); From c2bb2e2474481c8bf31b6de6561805776a2ed5ef Mon Sep 17 00:00:00 2001 From: alja Date: Fri, 2 Dec 2022 14:21:08 -0800 Subject: [PATCH 66/84] Add support boxset hex type --- ui5/eve7/lib/EveElementsRCore.js | 209 ++++++++++++++++++++----------- 1 file changed, 138 insertions(+), 71 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index d790ae81d03b6..1de12c405779e 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -79,37 +79,31 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) { DrawForSelection(xsec_idcs, res, extra) { - let sec_idcs = extra.shape_idcs; // XXXX MT we have sec_idcs argument here - - console.log(xsec_idcs, res, extra); + let sec_idcs = extra.shape_idcs; let body = new RC.Geometry(); body._vertices = this.top_obj.geometry._vertices; + let origIndices = this.top_obj.geometry._indices; + + let protoIdcsLen = 3 * 12; + let indicesPerDigit = 8; + if (this.top_obj.eve_el.boxType == 6) { + protoIdcsLen = 3 * 24; + indicesPerDigit = 14; + } - let protoIdcs = [0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 1, 2, 3, 1, 3, 0, 4, 7, 6, 4, 6, 5]; let idxBuff = []; - let eve_el = this.top_obj.eve_el; - let N = eve_el.render_data.idxBuff.length / 2; + let N = this.top_obj.eve_el.render_data.idxBuff.length / 2; for (let b = 0; b < sec_idcs.length; ++b) { let idx = sec_idcs[b]; - if (eve_el.fDetIdsAsSecondaryIndices) { - for (let x = 0; x < N; ++x) { - if (eve_el.render_data.idxBuff[x + N] === idx) - { - idx = x; - break; - } - } + let idxOff = idx * indicesPerDigit; + for (let i = 0; i < protoIdcsLen; i++) { + idxBuff.push(idxOff + origIndices.array[i]); } - let idxOff = idx * 8; - for (let i = 0; i < protoIdcs.length; i++) - idxBuff.push(idxOff + protoIdcs[i]); } body.indices = RC.Uint32Attribute(idxBuff, 1); - body.computeVertexNormals(); - let mesh = new RC.Mesh(body, null); mesh._modelViewMatrix = this.invoke_obj._modelViewMatrix; mesh._normalMatrix = this.invoke_obj._normalMatrix; @@ -118,9 +112,12 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) res.geom.push(mesh); } - extractIndex(instance) - { - return Math.floor(instance / 8); + extractIndex(instance) { + let verticesPerDigi = 8; + if (this.top_obj.eve_el.boxType == 6) + verticesPerDigi = 14; + let idx = Math.floor(instance / verticesPerDigi); + return idx; } elementSelectedSendMIR(idx, selectionId, event) @@ -969,60 +966,129 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return new RC.Geometry(); // AMT TODO test when digits are filtered let vBuff; - if (boxset.boxType == 1) // free box - { - vBuff = rnr_data.vtxBuff; - } - else if (boxset.boxType == 2) // axis aligned + let idxBuff; + let nVerticesPerDigit = 0; + + if (boxset.boxType == 6) // hexagon { - let N = rnr_data.vtxBuff.length/6; - vBuff = new Float32Array(N*8*3); + nVerticesPerDigit = 14; + let stepAngle = Math.PI / 3; + let N_hex = rnr_data.vtxBuff.length / 6; + vBuff = new Float32Array(N_hex * 7 * 2 * 3); + for (let i = 0; i < N_hex; ++i) { + let rdoff = i * 6; + let R = rnr_data.vtxBuff[rdoff + 3]; + let hexRotation = rnr_data.vtxBuff[rdoff + 4]; + let hexHeight = rnr_data.vtxBuff[rdoff + 5]; + let off = i* 3 * 7 * 2; + + // position + let pos = [rnr_data.vtxBuff[rdoff], rnr_data.vtxBuff[rdoff + 1], rnr_data.vtxBuff[rdoff + 2]]; + + // center + vBuff[off] = pos[0]; + vBuff[off + 1] = pos[1]; + vBuff[off + 2] = pos[2]; - let off = 0; - for (let i = 0; i < N; ++i) - { - let rdoff = i*6; - let x = rnr_data.vtxBuff[rdoff]; - let y = rnr_data.vtxBuff[rdoff + 1]; - let z = rnr_data.vtxBuff[rdoff + 2]; - let dx = rnr_data.vtxBuff[rdoff + 3]; - let dy = rnr_data.vtxBuff[rdoff + 4]; - let dz = rnr_data.vtxBuff[rdoff + 5]; - - // top - vBuff[off ] = x; vBuff[off + 1] = y + dy; vBuff[off + 2] = z; - off += 3; - vBuff[off ] = x + dx; vBuff[off + 1] = y + dy; vBuff[off + 2] = z; - off += 3; - vBuff[off ] = x + dx; vBuff[off + 1] = y; vBuff[off + 2] = z; - off += 3; - vBuff[off ] = x; vBuff[off + 1] = y; vBuff[off + 2] = z; - off += 3; - // bottom - vBuff[off ] = x; vBuff[off + 1] = y + dy; vBuff[off + 2] = z + dz; - off += 3; - vBuff[off ] = x + dx; vBuff[off + 1] = y + dy; vBuff[off + 2] = z + dz; - off += 3; - vBuff[off ] = x + dx; vBuff[off + 1] = y; vBuff[off + 2] = z + dz; - off += 3; - vBuff[off ] = x; vBuff[off + 1] = y; vBuff[off + 2] = z + dz; off += 3; + for (let j = 0; j < 6; ++j) { + let angle = j*stepAngle + hexRotation; + let x = R * Math.cos(angle) + pos[0]; + let y = R * Math.sin(angle) + pos[1]; + let z = pos[2]; + + // write buffer + vBuff[off] = x; + vBuff[off + 1] = y; + vBuff[off + 2] = z; + off += 3; + } + + // copy for depth + let ro = i* 3 * 7 * 2; + for (let j = 0; j < 7; ++j) + { + vBuff[ro + 21] = vBuff[ro]; + vBuff[ro + 22] = vBuff[ro+1]; + vBuff[ro + 23] = vBuff[ro+2] + hexHeight; + ro += 3; + } + } // end loop vertex buffer + + let protoIdcs = [0,1,2, 0,2,3, 0,3,4, 0,4,5, 0,5,6, 0,6,1]; + let protoIdcs2 = [2,1,0, 3,2,0, 4,3, 0, 5,4,0, 6, 5, 0, 1, 6, 0]; + let sideIdcs = [8,1,2,2,9,8, 9,2,3,3,10,9, 10,3,4,4,11,10, + 11,4,5,5,12,11, 5,6,13,5,13,12, 13,6,1,1,8,13 ]; + let idxBuffSize = N_hex * (protoIdcs.length * 2 + sideIdcs.length); + idxBuff = new Uint32Array(idxBuffSize); + let b = 0; + for (let i = 0; i < N_hex; ++i) { + let off0 = i * 7 * 2; + for (let c = 0; c < protoIdcs.length; c++) { + idxBuff[b++] = off0 + protoIdcs2[c]; + } + for (let c = 0; c < protoIdcs.length; c++) { + idxBuff[b++] = off0 + protoIdcs[c] +7; + } + for (let c = 0; c < sideIdcs.length; c++) { + idxBuff[b++] = off0 + sideIdcs[c]; + } } } + else { + nVerticesPerDigit = 8; + if (boxset.boxType == 1) // free box + { + vBuff = rnr_data.vtxBuff; + } + else if (boxset.boxType == 2) // axis aligned + { + let N = rnr_data.vtxBuff.length / 6; + vBuff = new Float32Array(N * 8 * 3); + + let off = 0; + for (let i = 0; i < N; ++i) { + let rdoff = i * 6; + let x = rnr_data.vtxBuff[rdoff]; + let y = rnr_data.vtxBuff[rdoff + 1]; + let z = rnr_data.vtxBuff[rdoff + 2]; + let dx = rnr_data.vtxBuff[rdoff + 3]; + let dy = rnr_data.vtxBuff[rdoff + 4]; + let dz = rnr_data.vtxBuff[rdoff + 5]; + + // top + vBuff[off] = x; vBuff[off + 1] = y + dy; vBuff[off + 2] = z; + off += 3; + vBuff[off] = x + dx; vBuff[off + 1] = y + dy; vBuff[off + 2] = z; + off += 3; + vBuff[off] = x + dx; vBuff[off + 1] = y; vBuff[off + 2] = z; + off += 3; + vBuff[off] = x; vBuff[off + 1] = y; vBuff[off + 2] = z; + off += 3; + // bottom + vBuff[off] = x; vBuff[off + 1] = y + dy; vBuff[off + 2] = z + dz; + off += 3; + vBuff[off] = x + dx; vBuff[off + 1] = y + dy; vBuff[off + 2] = z + dz; + off += 3; + vBuff[off] = x + dx; vBuff[off + 1] = y; vBuff[off + 2] = z + dz; + off += 3; + vBuff[off] = x; vBuff[off + 1] = y; vBuff[off + 2] = z + dz; + off += 3; + } + } - let protoSize = 6 * 2 * 3; - let protoIdcs = [0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 1, 2, 3, 1, 3, 0, 4, 7, 6, 4, 6, 5]; - let nBox = vBuff.length / 24; - let idxBuff = new Uint32Array(nBox * protoSize); - let iCnt = 0; - for (let i = 0; i < nBox; ++i) - { - for (let c = 0; c < protoSize; c++) { - let off = i * 8; - idxBuff[iCnt++] = protoIdcs[c] + off; + let protoSize = 6 * 2 * 3; + let protoIdcs = [0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 1, 2, 3, 1, 3, 0, 4, 7, 6, 4, 6, 5]; + let nBox = vBuff.length / 24; + idxBuff = new Uint32Array(nBox * protoSize); + let iCnt = 0; + for (let i = 0; i < nBox; ++i) { + for (let c = 0; c < protoSize; c++) { + let off = i * 8; + idxBuff[iCnt++] = protoIdcs[c] + off; + } } } - let body = new RC.Geometry(); body.indices = new RC.BufferAttribute(idxBuff, 1); body.vertices = new RC.BufferAttribute(vBuff, 3); @@ -1035,14 +1101,15 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) if ( ! boxset.fSingleColor) { let ci = rnr_data.idxBuff; - let off = 0 - let colBuff = new Float32Array( nBox * 8 * 4 ); + let off = 0; + let nVert = vBuff.length /3; + let colBuff = new Float32Array( nVert * 4 ); for (let x = 0; x < ci.length; ++x) { let r = (ci[x] & 0x000000FF) >> 0; let g = (ci[x] & 0x0000FF00) >> 8; let b = (ci[x] & 0x00FF0000) >> 16; - for (let i = 0; i < 8; ++i) + for (let i = 0; i < nVerticesPerDigit; ++i) { colBuff[off ] = r / 255; colBuff[off + 1] = g / 255; From 450a3e4200efe6616bcefdfda9436113f5bb6f47 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Fri, 2 Dec 2022 19:11:23 -0800 Subject: [PATCH 67/84] Fix line/track scaling with ssaa, pixelScale. --- ui5/eve7/lib/EveElementsRCore.js | 11 ++++++----- ui5/eve7/lib/GlViewerRCore.js | 27 +++++++++++++++++++++------ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 1de12c405779e..d3b0550c85768 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -577,8 +577,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) mat._transparent = true; mat._depthWrite = false; } - mat._lineWidth = this.LINE_WIDTH_FAC; - if (line_width !== undefined) mat._lineWidth *= line_width; + mat.lineWidth = this.LINE_WIDTH_FAC; + if (line_width !== undefined) mat.lineWidth *= line_width; if (props !== undefined) { mat.update(props); } @@ -667,7 +667,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) lineWidth: line_width * this.LINE_WIDTH_FAC, color: this.ColorBlack, emissive: line_color - }) + }), + GBufferMaterial: null } ); s.lights = false; @@ -799,10 +800,10 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) if (this.TestRnr("track", track, rnr_data)) return null; let N = rnr_data.vtxBuff.length / 3; - let track_width = 2 * (track.fLineWidth || 1) * this.LINE_WIDTH_FAC; + let track_width = 2 * track.fLineWidth; let track_color = RcCol(track.fLineColor); - if (EVE.JSR.browser.isWin) track_width = 1; // not supported on windows + // if (EVE.JSR.browser.isWin) track_width = 1; // not supported on windows let buf = new Float32Array((N - 1) * 6), pos = 0; for (let k = 0; k < (N - 1); ++k) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 0076813febc02..15816aa7825a5 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -18,20 +18,27 @@ sap.ui.define([ let mode_mm = /^(?:Direct|Simple|Full)$/.exec(urlParams.get('RQ_Mode')); let ssaa_mm = /^(1|2|4)$/. exec(urlParams.get('RQ_SSAA')); + let marker_scale = /^([\d\.]+)$/. exec(urlParams.get('RQ_MarkerScale')); + let line_scale = /^([\d\.]+)$/. exec(urlParams.get('RQ_LineScale')); this.RQ_Mode = (mode_mm) ? mode_mm[0] : "Simple"; this.RQ_SSAA = (ssaa_mm) ? ssaa_mm[0] : 2; + this.RQ_MarkerScale = (marker_scale) ? marker_scale[0] : 1; + this.RQ_LineScale = (line_scale) ? line_scale[0] : 1; let jsrp = EVE.JSR.source_dir; // take out 'jsrootsys' and replace it with 'rootui5sys/eve7/' this.eve_path = jsrp.substring(0, jsrp.length - 10) + 'rootui5sys/eve7/'; - console.log("GlViewerRCore RQ_Mode:", this.RQ_Mode, "RQ_SSAA:", this.RQ_SSAA); + this._logLevel = 1; // 0 - error, 1 - warning, 2 - info, 3 - debug + + if (this._logLevel > 2) { + console.log("GlViewerRCore RQ_Mode:", this.RQ_Mode, "RQ_SSAA:", this.RQ_SSAA, + 'RQ_MarkerScale', this.RQ_MarkerScale, 'RQ_LineScale', this.RQ_LineScale); + } this._selection_map = {}; this._selection_list = []; - - this._logLevel = 1; // 0 - error, 1 - warning, 2 - info, 3 - debug } init(controller) @@ -113,7 +120,12 @@ sap.ui.define([ this.fixCssSize(); this.canvas.parentDOM.style.overflow = "hidden"; this.canvas.canvasDOM.style.overflow = "hidden"; - + // It seems SSAA of 2 is still beneficial on retina. + // if (this.canvas.pixelRatio > 1 && this.RQ_SSAA > 1) { + // console.log("Correcting RQ_SSAA for pixelRatio", this.canvas.pixelRatio, + // "from", this.RQ_SSAA, "to", this.RQ_SSAA / this.canvas.pixelRatio); + // this.RQ_SSAA /= this.canvas.pixelRatio; + // } this.renderer = new RC.MeshRenderer(this.canvas, RC.WEBGL2, { antialias: false, stencil: false }); @@ -151,6 +163,7 @@ sap.ui.define([ this.lights.add(a_light); let light_class_3d = RC.PointLight; // RC.DirectionalLight; // RC.PointLight; + let args_3d = { smap_size: 0 }; let light_class_2d = RC.DirectionalLight; if (this.controller.isEveCameraPerspective()) @@ -217,12 +230,14 @@ sap.ui.define([ else if (this.RQ_Mode == "Simple") { this.rqt.initSimple(this.RQ_SSAA); - this.creator.SetupPointLineFacs(this.RQ_SSAA * this.canvas.pixelRatio, this.RQ_SSAA * this.canvas.pixelRatio); + this.creator.SetupPointLineFacs(this.RQ_MarkerScale * this.RQ_SSAA * this.canvas.pixelRatio, + this.RQ_LineScale * this.RQ_SSAA * this.canvas.pixelRatio); } else { this.rqt.initFull(this.RQ_SSAA); - this.creator.SetupPointLineFacs(this.RQ_SSAA * this.canvas.pixelRatio, this.RQ_SSAA * this.canvas.pixelRatio); + this.creator.SetupPointLineFacs(this.RQ_MarkerScale * this.RQ_SSAA * this.canvas.pixelRatio, + this.RQ_LineScale * this.RQ_SSAA * this.canvas.pixelRatio); } this.rqt.updateViewport(w, h); } From f7c56fa975cbd377a9625b6c9d09d24b985dea1e Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Fri, 2 Dec 2022 19:24:05 -0800 Subject: [PATCH 68/84] Correction in straightlineset width --- ui5/eve7/lib/EveElementsRCore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index d3b0550c85768..5d53c194a178c 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -1394,7 +1394,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let line_color = RcCol(el.fMainColor); - let line_width = 2 * (el.fLineWidth || 1) * this.LINE_WIDTH_FAC; + let line_width = 2 * (el.fLineWidth || 1); const line = this.RcMakeStripes(geom, line_width, line_color); this.RcApplyStripesMaterials(el, line, 2); this.RcPickable(el, line); From 1c65df5dff3ac84b53d40a9742eaa5716900a2b6 Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Tue, 6 Dec 2022 09:57:22 -0800 Subject: [PATCH 69/84] Correct the test for empty boxsets --- ui5/eve7/lib/EveElementsRCore.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 5d53c194a178c..12f3dafb3e644 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -963,8 +963,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) makeBoxSet(boxset, rnr_data) { - if (!rnr_data.vtxBuff) - return new RC.Geometry(); // AMT TODO test when digits are filtered + if (this.TestRnr("boxset", boxset, rnr_data)) return null; let vBuff; let idxBuff; From c1f18ef036c8f287ed5df4dc31649df63fc3a8a0 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Tue, 6 Dec 2022 11:26:30 -0800 Subject: [PATCH 70/84] Poperly handle point/line scales and ssaa, creator needs to know both. --- ui5/eve7/lib/GlViewerRCore.js | 10 ++++++---- ui5/eve7/lib/RenderCore.js | 12 ++++++------ ui5/eve7/textures/dot-32a.png | Bin 985 -> 5404 bytes ui5/eve7/textures/star5-32a.png | Bin 984 -> 5229 bytes 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 15816aa7825a5..b15b26d6a587c 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -230,14 +230,16 @@ sap.ui.define([ else if (this.RQ_Mode == "Simple") { this.rqt.initSimple(this.RQ_SSAA); - this.creator.SetupPointLineFacs(this.RQ_MarkerScale * this.RQ_SSAA * this.canvas.pixelRatio, - this.RQ_LineScale * this.RQ_SSAA * this.canvas.pixelRatio); + this.creator.SetupPointLineFacs(this.RQ_SSAA, + this.RQ_MarkerScale * this.canvas.pixelRatio, + this.RQ_LineScale * this.canvas.pixelRatio); } else { this.rqt.initFull(this.RQ_SSAA); - this.creator.SetupPointLineFacs(this.RQ_MarkerScale * this.RQ_SSAA * this.canvas.pixelRatio, - this.RQ_LineScale * this.RQ_SSAA * this.canvas.pixelRatio); + this.creator.SetupPointLineFacs(this.RQ_SSAA, + this.RQ_MarkerScale * this.canvas.pixelRatio, + this.RQ_LineScale * this.canvas.pixelRatio); } this.rqt.updateViewport(w, h); } diff --git a/ui5/eve7/lib/RenderCore.js b/ui5/eve7/lib/RenderCore.js index 815c299388a7a..36b45492c3b5d 100644 --- a/ui5/eve7/lib/RenderCore.js +++ b/ui5/eve7/lib/RenderCore.js @@ -1,9 +1,9 @@ // Standard import from ROOT build -export * from '../rcore/REveRenderCore-min.mjs'; -export const REveShaderPath = "rcore/shaders/"; -export const REveDevelMode = false; +// export * from '../rcore/REveRenderCore-min.mjs'; +// export const REveShaderPath = "rcore/shaders/"; +// export const REveDevelMode = false; // Development import from a RenderCore checkout in RC directory -// export * from '../RC/src/contrib/REveRenderCore.js'; -// export const REveShaderPath = "RC/src/shaders/"; -// export const REveDevelMode = true; +export * from '../RC/src/contrib/REveRenderCore.js'; +export const REveShaderPath = "RC/src/shaders/"; +export const REveDevelMode = true; diff --git a/ui5/eve7/textures/dot-32a.png b/ui5/eve7/textures/dot-32a.png index 4690caf02260e2a8c2f7fcfca1b0fc26d8e96487..21487416e45748bd4ce513598f05ddbbf31a3059 100644 GIT binary patch literal 5404 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 Qd;kCd07*qoM6N<$f~ZlV?EnA( diff --git a/ui5/eve7/textures/star5-32a.png b/ui5/eve7/textures/star5-32a.png index 7da206afd254c8da51dd1e66989684090761bbe3..d69f72cf3cd88d3a8bde04dfda290423abe96f8b 100644 GIT binary patch literal 5229 zcmeHKc~lcu7f%3Lf)-E;XhmWuib%*Fl1M-{AwVRANKrtYOeQdr&18T;izrxBECM1f zND)zM0i|CRtB6t*5i3;0QWe3yYF$vPxGR1yK@m@T&UZZL>wo5)N#@;q=lAaY-6iu@ zh-QY2B8(&8aJW%|&>%7RB^oYEGw|K5+m(gGnRaGKVlgq4M$~B4a#Vp3v2+bWMD(Z} zhtr>HS%5S9PYq@`FB1)-~G~!1$&rVds^{F-;L?p^mD^= zYscawWapg`>VewPdk-*;YLd`p~G975yr!x$k8KU*vxAd)|smsFbnTfBdUBw>pC*3bOM{%ZE3qAJbdk?$?bM=q;k z4^hgi!d>%nEq^aShyj@+e*YDBukQwH-#A;0(T@Ktf@d?TX_Irp>b8iJ=GM;7cis)X zC0=ZM$kZZH6tlK2B%x?Bxjk&T?J?YRtJ>W^mM!_Z>?&b$_qd!ZmztW{7wk&IyZ@SW zbOpioli*}CMWtXdvNLdC`KV)?|M+J23GTfkBODVR94)ARIQJ!|wAks#D@Rs_7P<>Y zj8SL~Sy)XxQb-EP+0qm2;+E?Khfzx_xcLiOve(cPiid{TL$2#hS<5z>SPqzTStk$r-}T=6W!J5z0c!+`sm*p0r6`mC*kSb5?~iPMg#NHd*#GkO z`3ZBYI(J;y{iM9IH{)l<-eke6feAQrbpw&8p^e+uWOSE9=YAA&T84@nBMQ(+S_&c!m{2ju6pht zowLpkoTWV4;F4DJI_lHRfIdly^5Fiso~$Ne<|6ih_wQNP6}^pt>NDpEFRnjw-gWC) z`YT^^yv!>Facz+TJ_uVFkQBDu#SFVC|W0w{5c9E*+nn zu_a_3YdjBsE*h5GAPWsvV zE$`#B!G9I&C!dfu%TITlLi@L%KizbD)>2-IJq?V=}b?dmVl&02+BE8i6^ zIL809NE=ppE`rbUt_%zFvZ&k~+Ee#b$y!t%KjYN;&^AtQk>Izd(7=-~?_Axnp^kkc zI5t;^`ge{kxctg4#xyo7x8%0N57#d4-P6wzcKE4Znp}Azl6E(+Ey0Y`qhJ=s3L|*1 zTImJJ)KbJtuhf89iNpE$=`|3Xj9^45l8CDKq;Fp+%xI zW=i0UWSA=>`S}uj^gIBdL@7b2UH=Vgw;NSc_^fRIMT!Fd?Zr1>=)QKu>(@pHd?f4#BH*Z&(0)Q1p<7 zLi3_hluF9*Cv;eFDgb%o&_6z*lYqYziWt$UQ?xJ=oQkM0*WnN$0-R z0_457nG7DX)1+t>MjIJSK@^A*fa-vMwD;^WRQ`^v_k1&GjNuG-1Z+2i|DN^R*p0@( zN+{$7so@mErh*_o$>1+friM`&&v?sXz%(g?!6Gx|EGC&rm$AtlmK-9}xH3q}meQD1 zDq|RwK&8VV6^t050Js+la1a?A;d0niGE3?$Co`pN7Fo(hm}Dx<;LvF>m%))D!yqEH zD5y$EG2ANylng*IWi%?44SADUGBylcqI1X)jV&cJz3Flpo5qmC9Ig?{kO!W>NWdr2 zy{PXbA_auW)mkN=6oINz^zRfBREb1mkbyKB+ndT@F=cyZNH8Pkt10X`6a8MsvYc z52Zk5aHZZX83&XC6J!l!j4YMGQZgt9E>jB25gL7vq#<;jT8^bbTEssQ@Cdj9MtKu3#V|A8M(jiR8z(+SgJDAkJU1uEv}C=A7kTD zYv+Cnh@7zCSS(PjG`x}Hj4z6aj3`YfMyMBLAfL0fb>J`@CJ6GEgtl&zOcOU#?Ryiq zS&77Ajj8kEQrACm_0v6Ejx>+eTB`~Pd23FHL}KZr4J+#GXO8EtD))Wykh4BjThkQRlk9;Cmsegn>%U(v{g3mW%&FhqZv3iZO_R^Htk#5kkDd3l2Dg{Z;bNAwr$0y*j_fIwHa|?R%*wLe)xyiOigm45dJYFZ2h8IH!83zu1LkM{7hUqsfdBvi delta 889 zcmV-<1BU$VDA)&(BYy!TX+uL$Nkc;*aB^>EX>4Tx04R~2kiSa9P!z_0sYOL}secA> zh~QdqF_TMG2!cY46|7Eal43E5AxSB|fp4M@(?Jk?1Rp@b+3!XN2eWwL@clTP^L_VT zXxT}amhD|gv#N0Y-r#a@WiPzZro%ehbb_$Vd!BbfPYDi*%cYyv;h#Q_4^tV|kf` zJ5qU?Jk0-ouP}X_)tlDFEDwsHZq2D$qY=D6!pZv?CAZbljjm9e*zUrL_t(Y$DNh2N?bt{hQGVfL}Zf{0xGG5 zB|`9)25b~8?2J_k(`AdifQ^sfL!>aZrjgW=B485)!EGd1Ed)eTm~352b z>qzz-rkOeCpL72CXC@+GLJTycK+FVTTLYS*fJ!jE$_5)$8PCK`TejSE>AQelD$ z5K$Qb$PviN$Vust@|#O8`HtA|f6TNbFUt{XwyRblwXh`X|7Exp2;YW43e?Mn2dda=$ z>W9Tck=yKB?Lj_3Ej(c-o(uiY;T z5o7ngw&k|>axlkNzVQ+6FMg*HHfivIRpy50|LZTl8xsvIQMPj_$Ux*@nJOjUHQfv& P00000NkvXXu0mjf&H}W1 From d252d957d3a91e0470e72ce171bf7c3bbd1335fa Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Tue, 6 Dec 2022 11:45:52 -0800 Subject: [PATCH 71/84] Missing stuff from prev commit. Add bottom light. --- ui5/eve7/lib/EveElementsRCore.js | 16 ++++++++++------ ui5/eve7/lib/GlViewerRCore.js | 4 +++- ui5/eve7/lib/RenderCore.js | 12 ++++++------ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 12f3dafb3e644..107757a15f9b8 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -528,8 +528,9 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) GenerateTypeName(obj) { return "RC." + obj.type; } - SetupPointLineFacs(pf, lf) + SetupPointLineFacs(ssaa, pf, lf) { + this.SSAA = ssaa; // to scale down points / lines for picking and outlines this.POINT_SIZE_FAC = pf; this.LINE_WIDTH_FAC = lf; } @@ -628,7 +629,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) RcMakeZSprite(colIdx, sSize, nInstance, vbuff, instX, instY, textureName) { - let col = RcCol(colIdx); + let col = RcCol(colIdx); + sSize *= this.POINT_SIZE_FAC; let sm = new RC.ZSpriteBasicMaterial( { SpriteMode: RC.SPRITE_SPACE_SCREEN, SpriteSize: [sSize, sSize], color: this.ColorBlack, @@ -651,7 +653,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // Now that outline and picking shaders are setup with final pixel-size, // scale up the main size to account for SSAA. - sm.setUniform("SpriteSize", [sSize * this.POINT_SIZE_FAC, sSize * this.POINT_SIZE_FAC]); + sSize *= this.SSAA; + sm.setUniform("SpriteSize", [sSize, sSize]); this.GetLumAlphaTexture(textureName, this.AddMapToAllMaterials.bind(this, s)); @@ -660,11 +663,12 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) RcMakeStripes(geom, line_width, line_color) { + // Setup width for SSAA, scaled down for picking and outline materials. let s = new RC.Stripes( { geometry: new RC.StripesGeometry({ baseGeometry: geom }), material: new RC.StripesBasicMaterial({ baseGeometry: geom, mode: RC.STRIPE_SPACE_SCREEN, - lineWidth: line_width * this.LINE_WIDTH_FAC, + lineWidth: line_width * this.LINE_WIDTH_FAC * this.SSAA, color: this.ColorBlack, emissive: line_color }), @@ -680,7 +684,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) if (eve_el.fPickable) { let m = stripes.material; stripes.pickingMaterial = new RC.StripesBasicMaterial( - { lineWidth: m.lineWidth * pick_width_scale / this.LINE_WIDTH_FAC, + { lineWidth: m.lineWidth * pick_width_scale / this.SSAA, mode: m.mode, color: m.color }); let pm = stripes.pickingMaterial; pm.programName = "custom_GBufferMini_stripes"; @@ -690,7 +694,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) pm.deltaOffset = m.deltaOffset; stripes.outlineMaterial = new RC.StripesBasicMaterial( - { lineWidth: m.lineWidth / this.LINE_WIDTH_FAC, mode: m.mode, color: m.color }); + { lineWidth: m.lineWidth / this.SSAA, mode: m.mode, color: m.color }); let om = stripes.outlineMaterial; om.programName = "custom_GBufferMini_stripes"; om.prevVertex = m.prevVertex; diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index b15b26d6a587c..cc26aafe4cfb4 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -176,7 +176,8 @@ sap.ui.define([ this.lights.add(new light_class_3d(0xaa8888, l_int, 0, 1, l_att)); // R this.lights.add(new light_class_3d(0x88aa88, l_int, 0, 1, l_att)); // G this.lights.add(new light_class_3d(0x8888aa, l_int, 0, 1, l_att)); // B - this.lights.add(new light_class_3d(0x999999, l_int, 0, 1, l_att)); // gray + this.lights.add(new light_class_3d(0xaaaa66, l_int, 0, 1, l_att)); // Y + this.lights.add(new light_class_3d(0x666666, l_int, 0, 1, l_att)); // gray, bottom // Lights are positioned in resetRenderer. @@ -424,6 +425,7 @@ sap.ui.define([ lc[2].position.set(-extR, extR, extR); lc[3].position.set( extR, extR, extR); lc[4].position.set(-extR, extR, -extR); + lc[5].position.set(0, -extR, 0); // console.log("resetRenderer 3D scene bbox ", sbbox, ", look_at ", this.rot_center); } diff --git a/ui5/eve7/lib/RenderCore.js b/ui5/eve7/lib/RenderCore.js index 36b45492c3b5d..815c299388a7a 100644 --- a/ui5/eve7/lib/RenderCore.js +++ b/ui5/eve7/lib/RenderCore.js @@ -1,9 +1,9 @@ // Standard import from ROOT build -// export * from '../rcore/REveRenderCore-min.mjs'; -// export const REveShaderPath = "rcore/shaders/"; -// export const REveDevelMode = false; +export * from '../rcore/REveRenderCore-min.mjs'; +export const REveShaderPath = "rcore/shaders/"; +export const REveDevelMode = false; // Development import from a RenderCore checkout in RC directory -export * from '../RC/src/contrib/REveRenderCore.js'; -export const REveShaderPath = "RC/src/shaders/"; -export const REveDevelMode = true; +// export * from '../RC/src/contrib/REveRenderCore.js'; +// export const REveShaderPath = "RC/src/shaders/"; +// export const REveDevelMode = true; From 1de30dbec0bfd4ca22de529519b736ad97e4e6b9 Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Tue, 6 Dec 2022 14:06:44 -0800 Subject: [PATCH 72/84] Make specular reflection in RcFancyMaterial almoust white --- ui5/eve7/lib/EveElementsRCore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 107757a15f9b8..397fdf4cf4d7e 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -613,7 +613,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // let mat = new RC.MeshBasicMaterial; mat._color = color; - mat._specular = new RC.Color(0.3, 0.8, 0.0); // this.ColorWhite; + mat._specular = new RC.Color(0.3, 0.4, 0.3); // this.ColorWhite; mat._shininess = 64; if (opacity !== undefined && opacity < 1.0) { From 04d983330ae9571e32eeaa1efc3cd8a89e0f638a Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Thu, 8 Dec 2022 16:06:39 -0800 Subject: [PATCH 73/84] Improve check for empty calo 2d and calo 3d to remove lint warnings --- ui5/eve7/lib/EveElementsRCore.js | 148 ++++++++++++++----------------- 1 file changed, 65 insertions(+), 83 deletions(-) diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 397fdf4cf4d7e..05beebf349657 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -1139,48 +1139,41 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) makeCalo3D(calo3D, rnr_data) { + if (this.TestRnr("calo3D", calo3D, rnr_data)) return null; let body = new RC.Geometry(); - if (rnr_data.vtxBuff) { - let vBuff = rnr_data.vtxBuff; - let protoSize = 6 * 2 * 3; - let protoIdcs = [0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 1, 2, 3, 1, 3, 0, 4, 7, 6, 4, 6, 5]; - let nBox = vBuff.length / 24; - let idxBuff = new Uint32Array(nBox * protoSize); - let p = 0; - for (let i = 0; i < nBox; ++i) { - let off = i * 8; - for (let c = 0; c < protoSize; c++) { - idxBuff[p++] = protoIdcs[c] + off; - } + let vBuff = rnr_data.vtxBuff; + let protoSize = 6 * 2 * 3; + let protoIdcs = [0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 1, 2, 3, 1, 3, 0, 4, 7, 6, 4, 6, 5]; + let nBox = vBuff.length / 24; + let idxBuff = new Uint32Array(nBox * protoSize); + let p = 0; + for (let i = 0; i < nBox; ++i) { + let off = i * 8; + for (let c = 0; c < protoSize; c++) { + idxBuff[p++] = protoIdcs[c] + off; } + } - body.indices = new RC.BufferAttribute(idxBuff, 1); - body.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); - // body.computeVertexNormals(); + body.indices = new RC.BufferAttribute(idxBuff, 1); + body.vertices = new RC.BufferAttribute(rnr_data.vtxBuff, 3); + // body.computeVertexNormals(); - let ci = rnr_data.idxBuff; - let off = 0 - let colBuff = new Float32Array(nBox*8*4); - for (let x = 0; x < nBox; ++x) { - let slice = ci[x * 2]; - let sliceColor = calo3D.sliceColors[slice]; - let tc = RcCol(sliceColor); - for (let i = 0; i < 8; ++i) { - colBuff[off] = tc.r; - colBuff[off + 1] = tc.g; - colBuff[off + 2] = tc.b; - colBuff[off + 3] = 1.0; - off += 4; - } + let ci = rnr_data.idxBuff; + let off = 0 + let colBuff = new Float32Array(nBox * 8 * 4); + for (let x = 0; x < nBox; ++x) { + let slice = ci[x * 2]; + let sliceColor = calo3D.sliceColors[slice]; + let tc = RcCol(sliceColor); + for (let i = 0; i < 8; ++i) { + colBuff[off] = tc.r; + colBuff[off + 1] = tc.g; + colBuff[off + 2] = tc.b; + colBuff[off + 3] = 1.0; + off += 4; } - body.vertColor = new RC.BufferAttribute(colBuff, 4); - } - else - { - body.indices = new RC.BufferAttribute(new Uint32Array(0), 1); - body.vertices = new RC.BufferAttribute(new Float32Array(0), 3); - body.vertColor = new RC.BufferAttribute(new Float32Array, 4); } + body.vertColor = new RC.BufferAttribute(colBuff, 4); let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); mat.useVertexColors = true; @@ -1195,54 +1188,47 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) makeCalo2D(calo2D, rnrData) { + if (this.TestRnr("calo2D", calo2D, rnrData)) return null; let body = new RC.Geometry(); - if (rnrData.vtxBuff) { - let nSquares = rnrData.vtxBuff.length / 12; - let nTriang = 2 * nSquares; - - let idxBuff = new Uint32Array(nTriang * 3); - for (let s = 0; s < nSquares; ++s) { - let boff = s * 6; - let ioff = s * 4; - - // first triangle - idxBuff[boff] = ioff; - idxBuff[boff + 1] = ioff + 1; - idxBuff[boff + 2] = ioff + 2; - - // second triangle - idxBuff[boff + 3] = ioff + 2; - idxBuff[boff + 4] = ioff + 3; - idxBuff[boff + 5] = ioff; - } + let nSquares = rnrData.vtxBuff.length / 12; + let nTriang = 2 * nSquares; + + let idxBuff = new Uint32Array(nTriang * 3); + for (let s = 0; s < nSquares; ++s) { + let boff = s * 6; + let ioff = s * 4; + + // first triangle + idxBuff[boff] = ioff; + idxBuff[boff + 1] = ioff + 1; + idxBuff[boff + 2] = ioff + 2; + + // second triangle + idxBuff[boff + 3] = ioff + 2; + idxBuff[boff + 4] = ioff + 3; + idxBuff[boff + 5] = ioff; + } - body.indices = new RC.BufferAttribute(idxBuff, 1); - body.vertices = new RC.BufferAttribute(rnrData.vtxBuff, 3); - // body.computeVertexNormals(); + body.indices = new RC.BufferAttribute(idxBuff, 1); + body.vertices = new RC.BufferAttribute(rnrData.vtxBuff, 3); + // body.computeVertexNormals(); - let ci = rnrData.idxBuff; - let colBuff = new Float32Array(nSquares * 4 * 4); - let off = 0; - for (let x = 0; x < nSquares; ++x) { - let slice = ci[x * 2]; - let sliceColor = calo2D.sliceColors[slice]; - let tc = RcCol(sliceColor); - for (let i = 0; i < 4; ++i) { - colBuff[off] = tc.r; - colBuff[off + 1] = tc.g; - colBuff[off + 2] = tc.b; - colBuff[off + 3] = 1.0; - off += 4; - } + let ci = rnrData.idxBuff; + let colBuff = new Float32Array(nSquares * 4 * 4); + let off = 0; + for (let x = 0; x < nSquares; ++x) { + let slice = ci[x * 2]; + let sliceColor = calo2D.sliceColors[slice]; + let tc = RcCol(sliceColor); + for (let i = 0; i < 4; ++i) { + colBuff[off] = tc.r; + colBuff[off + 1] = tc.g; + colBuff[off + 2] = tc.b; + colBuff[off + 3] = 1.0; + off += 4; } - body.vertColor = new RC.BufferAttribute(colBuff, 4); - } - else - { - body.indices = new RC.BufferAttribute(new Uint32Array(0), 1); - body.vertices = new RC.BufferAttribute(new Float32Array(0), 3); - body.vertColor = new RC.BufferAttribute(new Float32Array, 4); } + body.vertColor = new RC.BufferAttribute(colBuff, 4); let mat = this.RcFlatMaterial(this.ColorBlack, 1); mat.useVertexColors = true; @@ -1417,10 +1403,6 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) p_buf[k+2] = rnr_data.vtxBuff[j+off+2]; p_buf[k+3] = 0; } - - console.log("straight line set = ",p_buf ); - console.log("eve el = ", el.fTexX, el.fTexY); - let marker = this.RcMakeZSprite(el.fMainColor, el.fMarkerSize, nPnts, p_buf, el.fTexX, el.fTexY, "star5-32a.png"); From db8a0cebc8344757f08466d3ce551285010ed707 Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Mon, 12 Dec 2022 11:11:46 -0800 Subject: [PATCH 74/84] Optimize visibility changes --- ui5/eve7/lib/EveScene.js | 62 ++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index bfbe2bfc913a1..74c5d91cb1557 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -10,19 +10,19 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { class EveScene { - constructor(mgr, scene, glctrl) + constructor(mgr, sceneInfo, glctrl) { this.mgr = mgr; - this.scene = scene; - this.id = scene.fSceneId; + this.id = sceneInfo.fSceneId; this.glctrl = glctrl; this.creator = glctrl.viewer.creator; this.id2obj_map = new Map; // base on element id this.first_time = true; + this.need_visibility_update = false; // register ourself for scene events - this.mgr.RegisterSceneReceiver(scene.fSceneId, this); + this.mgr.RegisterSceneReceiver(this.id, this); if(this.mgr.is_rcore) { this.SelectElement = this.SelectElementRCore; @@ -31,8 +31,6 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { this.SelectElement = this.SelectElementStd; this.UnselectElement = this.UnselectElementStd; } - // AMT temporary solution ... resolve with callSceneReceivers in EveManager.js - scene.eve_scene = this; } //============================================================================== @@ -195,8 +193,15 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { endChanges() { - if (this.glctrl) + if (this.glctrl) { + if (this.need_visibility_update) { + let p = this.mgr.GetElement(this.id); + this.update3DObjectsVisibility(p.childs, true); + this.need_visibility_update = false; + } this.glctrl.viewer.render(); + + } } elementAdded(el) @@ -206,41 +211,36 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { let obj3d = this.makeGLRepresentation(el); if ( ! obj3d) return; - // AMT this is an overkill, temporary solution - let scene = this.mgr.GetElement(el.fSceneId); - this.update3DObjectsVisibility(scene.childs, true); - + // let scene = this.mgr.GetElement(this.id); let container = this.glctrl.getSceneContainer("scene" + this.id); container.add(obj3d); this.id2obj_map.set(el.fElementId, obj3d); + + this.need_visibility_update = true; } replaceElement(el) { if (!this.glctrl) return; + let container = this.glctrl.getSceneContainer("scene" + this.id); + try { let obj3d = this.getObj3D(el.fElementId); - let all_ancestor_children_visible = obj3d.all_ancestor_children_visible; - let visible = obj3d.visible; - let container = this.glctrl.getSceneContainer("scene" + this.id); - - container.remove(obj3d); + if(obj3d) container.remove(obj3d); obj3d = this.makeGLRepresentation(el); - obj3d.all_ancestor_children_visible = all_ancestor_children_visible; - obj3d.visible = visible; - container.add(obj3d); - - this.id2obj_map.set(el.fElementId, obj3d); - - this.glctrl.viewer.render(); + if (obj3d) { + container.add(obj3d); + this.id2obj_map.set(el.fElementId, obj3d); + } } catch (e) { console.error("replace element", e); } + this.need_visibility_update = true; } elementsRemoved(ids) @@ -277,21 +277,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { // visibility if (msg.changeBit & this.mgr.EChangeBits.kCBVisibility) { - // self - if (msg.rnr_self_changed) - { - let obj3d = this.getObj3D( el.fElementId ); - if (obj3d) - { - obj3d.visible = obj3d.all_ancestor_children_visible && el.fRnrSelf; - } - } - // children - if (msg.rnr_children_changed && el.childs) - { - let scene = this.mgr.GetElement(el.fSceneId); - this.update3DObjectsVisibility(scene.childs, true); - } + this.need_visibility_update = true; } // other change bits From 5a148b6f754f09bf0824333aa4f489cc273e9b50 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 12 Dec 2022 14:34:18 -0800 Subject: [PATCH 75/84] GlViewverRCore: point light construction with shadow-map size = 0. --- ui5/eve7/lib/GlViewerRCore.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index cc26aafe4cfb4..3172f73511e5e 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -162,9 +162,9 @@ sap.ui.define([ let a_light = new RC.AmbientLight(new RC.Color(0xffffff), 0.05); this.lights.add(a_light); - let light_class_3d = RC.PointLight; // RC.DirectionalLight; // RC.PointLight; - let args_3d = { smap_size: 0 }; - let light_class_2d = RC.DirectionalLight; + let light_3d_ctor = function(col, int, dist, decay, args) { return new RC.PointLight(col, int, dist, decay, args); }; + // let light_3d_ctor = function(col, int, dist, decay, args) { return new RC.DirectionalLight(col, int); }; + let light_2d_ctor = function(col, int) { return new RC.DirectionalLight(col, int); }; if (this.controller.isEveCameraPerspective()) { @@ -172,12 +172,12 @@ sap.ui.define([ this.camera.isPerspectiveCamera = true; let l_int = 1.4; - let l_att = { constant: 1, linear: 0, quadratic: 0 }; - this.lights.add(new light_class_3d(0xaa8888, l_int, 0, 1, l_att)); // R - this.lights.add(new light_class_3d(0x88aa88, l_int, 0, 1, l_att)); // G - this.lights.add(new light_class_3d(0x8888aa, l_int, 0, 1, l_att)); // B - this.lights.add(new light_class_3d(0xaaaa66, l_int, 0, 1, l_att)); // Y - this.lights.add(new light_class_3d(0x666666, l_int, 0, 1, l_att)); // gray, bottom + let l_args = { constant: 1, linear: 0, quadratic: 0, smap_size: 0 }; + this.lights.add(light_3d_ctor(0xaa8888, l_int, 0, 1, l_args)); // R + this.lights.add(light_3d_ctor(0x88aa88, l_int, 0, 1, l_args)); // G + this.lights.add(light_3d_ctor(0x8888aa, l_int, 0, 1, l_args)); // B + this.lights.add(light_3d_ctor(0xaaaa66, l_int, 0, 1, l_args)); // Y + this.lights.add(light_3d_ctor(0x666666, l_int, 0, 1, l_args)); // gray, bottom // Lights are positioned in resetRenderer. @@ -194,8 +194,8 @@ sap.ui.define([ this.camera.isOrthographicCamera = true; let l_int = 0.85; - this.lights.add(new light_class_2d( 0xffffff, l_int )); // white front - // this.lights.add(new light_class_2d( 0xffffff, l_int )); // white back + this.lights.add(light_2d_ctor(0xffffff, l_int)); // white front + // this.lights.add(light_2d_ctor(0xffffff, l_int)); // white back // Lights are positioned in resetRenderer. } From 0626fae3d9483167f59a587521dec3a8ef16a064 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 12 Dec 2022 14:50:28 -0800 Subject: [PATCH 76/84] Update RenderCore.tar.gz --- builtins/rendercore/RenderCore.tar.gz | Bin 95882 -> 96328 bytes cmake/modules/SearchInstalledSoftware.cmake | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/builtins/rendercore/RenderCore.tar.gz b/builtins/rendercore/RenderCore.tar.gz index 14abaa7f3ba4a051ab494ea7760bb16baf38a8fb..151b818ca4d0154a1a3048fa4ef6ad67baee224d 100644 GIT binary patch literal 96328 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�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 D-^AJ~ diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index ec904e0c00bc2..5c636741e3962 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -2148,7 +2148,7 @@ if(webgui) ExternalProject_Add( RENDERCORE URL ${CMAKE_SOURCE_DIR}/builtins/rendercore/RenderCore.tar.gz - URL_HASH SHA256=17fa2e093cf4315ace5c784ed370f00478d248797fef1aeaec281c42e0b5d5d3 + URL_HASH SHA256=b9c8558a3df90f8e08f013a856c495adda73f8ac900afbfe61581b9823fa2404 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From 86f72b2c90687622095ef60bc81990f2fd797870 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Tue, 13 Dec 2022 11:50:41 -0800 Subject: [PATCH 77/84] Add missing shader. --- builtins/rendercore/RenderCore.tar.gz | Bin 96328 -> 96465 bytes cmake/modules/SearchInstalledSoftware.cmake | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/builtins/rendercore/RenderCore.tar.gz b/builtins/rendercore/RenderCore.tar.gz index 151b818ca4d0154a1a3048fa4ef6ad67baee224d..49ac844962cca797714591a7e3f4607ad521c8dd 100644 GIT binary patch delta 39148 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%0Amcl?llf}~mkn!v;92W~@vSSEX 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/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 z∨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 diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index 5c636741e3962..cd00a3fd0ed3f 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -2148,7 +2148,7 @@ if(webgui) ExternalProject_Add( RENDERCORE URL ${CMAKE_SOURCE_DIR}/builtins/rendercore/RenderCore.tar.gz - URL_HASH SHA256=b9c8558a3df90f8e08f013a856c495adda73f8ac900afbfe61581b9823fa2404 + URL_HASH SHA256=e809e9e2684efa6b2a986f073fc9e81011dda6f047d518e1218a90b73c8e98b1 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From ecab6c92732ca640b4d101104e2628753267e357 Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Tue, 13 Dec 2022 11:51:28 -0800 Subject: [PATCH 78/84] Pass x,y to mouse-move handler timeout, not event -- the event gets modified in Firefox. --- ui5/eve7/lib/GlViewerRCore.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 3172f73511e5e..451b75b80bad3 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -268,7 +268,7 @@ sap.ui.define([ if (event.buttons === 0 && event.srcElement === glc.canvas.canvasDOM) { glc.removeMouseMoveTimeout(); - glc.mousemove_timeout = setTimeout(glc.onMouseMoveTimeout.bind(glc, event), glc.controller.htimeout); + glc.mousemove_timeout = setTimeout(glc.onMouseMoveTimeout.bind(glc, event.offsetX, event.offsetY), glc.controller.htimeout); } else { // glc.clearHighlight(); } @@ -669,13 +669,11 @@ sap.ui.define([ } } - onMouseMoveTimeout(event) + onMouseMoveTimeout(x, y) { delete this.mousemove_timeout; - let x = event.offsetX * this.canvas.pixelRatio; - let y = event.offsetY * this.canvas.pixelRatio; - let pstate = this.render_for_picking(x, y, false); + let pstate = this.render_for_picking(x * this.canvas.pixelRatio, y * this.canvas.pixelRatio, false); if ( ! pstate) return this.clearHighlight(); @@ -699,17 +697,17 @@ sap.ui.define([ let offs = (mouse.x > 0 || mouse.y < 0) ? this.getRelativeOffsets(dome) : null; if (mouse.x <= 0) { - this.ttip.style.left = (event.offsetX + dome.offsetLeft + 10) + "px"; + this.ttip.style.left = (x + dome.offsetLeft + 10) + "px"; this.ttip.style.right = null; } else { - this.ttip.style.right = (this.canvas.canvasDOM.clientWidth - event.offsetX + offs.right + 10) + "px"; + this.ttip.style.right = (this.canvas.canvasDOM.clientWidth - x + offs.right + 10) + "px"; this.ttip.style.left = null; } if (mouse.y >= 0) { - this.ttip.style.top = (event.offsetY + dome.offsetTop + 10) + "px"; + this.ttip.style.top = (y + dome.offsetTop + 10) + "px"; this.ttip.style.bottom = null; } else { - this.ttip.style.bottom = (this.canvas.canvasDOM.clientHeight - event.offsetY + offs.bottom + 10) + "px"; + this.ttip.style.bottom = (this.canvas.canvasDOM.clientHeight - y + offs.bottom + 10) + "px"; this.ttip.style.top = null; } From 8f2732227d3be3a1c35e1d288bb5ecff56017ff9 Mon Sep 17 00:00:00 2001 From: alja Date: Wed, 14 Dec 2022 09:44:18 -0800 Subject: [PATCH 79/84] Correction in outline colors and selection/highligt sorting --- ui5/eve7/lib/EveScene.js | 4 ++-- ui5/eve7/lib/GlViewerRCore.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index 74c5d91cb1557..dcd465103bc8e 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -329,11 +329,11 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { /** interactive handler */ processElementHighlighted(eve_el, indx, event) { - if (this.mgr.MatchSelection(this.mgr.global_selection_id, eve_el, indx)) + // RenderCore viewer is organizing selection on stack, the last selection will set the color + if (!this.mgr.is_rcore && this.mgr.MatchSelection(this.mgr.global_selection_id, eve_el, indx)) return true; // Need check for duplicates before call server, else server will un-higlight highlighted element - // console.log("EveScene.processElementHighlighted", obj3d.eve_el.fElementId, indx, evnt); if (this.mgr.MatchSelection(this.mgr.global_highlight_id, eve_el, indx)) return true; diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index 451b75b80bad3..37a07ef26d2eb 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -594,7 +594,7 @@ sap.ui.define([ { let idx = this._selection_list.indexOf(sid); if (idx >= 0) - this._selection_list.splice(idx); + this._selection_list.splice(idx,1); } make_selection_last_in_list(sid) From 3c5b6225370a271ef922208aa86b443b478fb78d Mon Sep 17 00:00:00 2001 From: alja Date: Wed, 14 Dec 2022 10:02:04 -0800 Subject: [PATCH 80/84] Make RenderCore the default render engine. --- graf3d/eve7/src/REveManager.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graf3d/eve7/src/REveManager.cxx b/graf3d/eve7/src/REveManager.cxx index fa3cccc02c6f9..a8dd8830f08ff 100644 --- a/graf3d/eve7/src/REveManager.cxx +++ b/graf3d/eve7/src/REveManager.cxx @@ -144,7 +144,7 @@ REveManager::REveManager() fWebWindow->UseServerThreads(); fWebWindow->SetDefaultPage("file:rootui5sys/eve7/index.html"); - const char *gl_viewer = gEnv->GetValue("WebEve.GLViewer", "Three"); + const char *gl_viewer = gEnv->GetValue("WebEve.GLViewer", "RCore"); const char *gl_dblclick = gEnv->GetValue("WebEve.DblClick", "Off"); Int_t htimeout = gEnv->GetValue("WebEve.HTimeout", 250); Int_t table_row_height = gEnv->GetValue("WebEve.TableRowHeight", 0); From 28f56ad4147f1a1af36b2f305e8382f464551aac Mon Sep 17 00:00:00 2001 From: Alja Mrak Tadel Date: Mon, 12 Dec 2022 15:50:48 -0800 Subject: [PATCH 81/84] Correct warning on implied digitset collection --- graf3d/eve7/inc/ROOT/REveDigitSet.hxx | 2 +- graf3d/eve7/src/REveDigitSet.cxx | 2 +- graf3d/eve7/src/REveSelection.cxx | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/graf3d/eve7/inc/ROOT/REveDigitSet.hxx b/graf3d/eve7/inc/ROOT/REveDigitSet.hxx index 580a736d55498..6b1f8ac162d66 100644 --- a/graf3d/eve7/inc/ROOT/REveDigitSet.hxx +++ b/graf3d/eve7/inc/ROOT/REveDigitSet.hxx @@ -182,7 +182,7 @@ public: void NewShapePicked(int shapeId, Int_t selectionId, bool multi); - bool RequiresExtraSelectionData() const override { return true; }; + bool RequiresExtraSelectionData() const override { return GetAlwaysSecSelect(); }; void FillExtraSelectionData(nlohmann::json& j, const std::set& secondary_idcs) const override; Int_t WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) override; diff --git a/graf3d/eve7/src/REveDigitSet.cxx b/graf3d/eve7/src/REveDigitSet.cxx index 59d2e3df39802..bf9804aa3c327 100644 --- a/graf3d/eve7/src/REveDigitSet.cxx +++ b/graf3d/eve7/src/REveDigitSet.cxx @@ -504,7 +504,7 @@ int REveDigitSet::GetShapeIdxFromAtomIdx(int iAtomIdx) const } } - printf("REveDigitSet::GetShapeIdxFromAtomIdx:: Atom with idx %d dose not have a visible shape \n", iAtomIdx); + printf("REveDigitSet::GetShapeIdxFromAtomIdx:: Atom with idx %d does not have a visible shape \n", iAtomIdx); return -1; } diff --git a/graf3d/eve7/src/REveSelection.cxx b/graf3d/eve7/src/REveSelection.cxx index c0fdd5fab54a1..5ba6a370435e6 100644 --- a/graf3d/eve7/src/REveSelection.cxx +++ b/graf3d/eve7/src/REveSelection.cxx @@ -703,7 +703,8 @@ Int_t REveSelection::WriteCoreJson(nlohmann::json &j, Int_t /* rnr_offset */) // XXX if not empty ??? for (auto &imp_el : i.second.f_implied) { imp.push_back(imp_el->GetElementId()); - imp_el->FillExtraSelectionData(rec["extra"], sec); + if (i.first->RequiresExtraSelectionData()) + imp_el->FillExtraSelectionData(rec["extra"], sec); } rec["implied"] = imp; From a5798bfa7379b8b1ce1ec2456c7db696e3543a6e Mon Sep 17 00:00:00 2001 From: alja Date: Thu, 15 Dec 2022 12:06:50 -0800 Subject: [PATCH 82/84] Check for extra selection data in implied selected elements --- graf3d/eve7/inc/ROOT/REveCalo.hxx | 1 + graf3d/eve7/src/REveSelection.cxx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/graf3d/eve7/inc/ROOT/REveCalo.hxx b/graf3d/eve7/inc/ROOT/REveCalo.hxx index bb8f2133aafdf..4b5b775541302 100644 --- a/graf3d/eve7/inc/ROOT/REveCalo.hxx +++ b/graf3d/eve7/inc/ROOT/REveCalo.hxx @@ -72,6 +72,7 @@ public: virtual ~REveCaloViz(); + bool RequiresExtraSelectionData() const override { return true; }; virtual REveElement* ForwardSelection(); virtual REveElement* ForwardEdit(); diff --git a/graf3d/eve7/src/REveSelection.cxx b/graf3d/eve7/src/REveSelection.cxx index 5ba6a370435e6..86ddbaa89d7be 100644 --- a/graf3d/eve7/src/REveSelection.cxx +++ b/graf3d/eve7/src/REveSelection.cxx @@ -703,7 +703,7 @@ Int_t REveSelection::WriteCoreJson(nlohmann::json &j, Int_t /* rnr_offset */) // XXX if not empty ??? for (auto &imp_el : i.second.f_implied) { imp.push_back(imp_el->GetElementId()); - if (i.first->RequiresExtraSelectionData()) + if (imp_el->RequiresExtraSelectionData()) imp_el->FillExtraSelectionData(rec["extra"], sec); } From 108a32d1d47c09b55c15f9162e60f8954eabbfdb Mon Sep 17 00:00:00 2001 From: Matevz Tadel Date: Mon, 19 Dec 2022 19:59:30 -0800 Subject: [PATCH 83/84] [RCore] Fix reading of depth value in Firefox. --- builtins/rendercore/RenderCore.tar.gz | Bin 96465 -> 96470 bytes cmake/modules/SearchInstalledSoftware.cmake | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/builtins/rendercore/RenderCore.tar.gz b/builtins/rendercore/RenderCore.tar.gz index 49ac844962cca797714591a7e3f4607ad521c8dd..2083c5708433a02e61c0dd563fda0d9800cf548c 100644 GIT binary patch delta 93792 zcmV(;K-<63@deiL1qUCC2nY-^p^*off6@OJ@prx5?R7-LzqC8O%}(!MYVCjd4gNPz zvmmL}{^dHz!mszmL2r|jTs`(Hc0C3h+(Oc37br?>wF!5xBw^>N!b91sJe+s5o zlkhN3u7ioMK$vDbw^6R{%kRFsoKJ^Y6i;h!;@e(5Yu3U>?Qh@JvT>BQ#4HsxzQ)n0 z)~-E!^{STDUW@;>Eg+rR_qBGj#{Y;WseW*4*AGSg(5b&BYubMWYQHk%(ja>mCp))c ziYPW~QL~mbYboM-87H+mFjyd3e-jV@>8v#gr&rmywpQ!C6d8XKJ%_)muWCK4WQfwb zOycXEBnj>Sb|6}=)c{&7z@)9)+Vk3nARD)Wi?nX)+%{^fBKOXpdq=tV{@i;(pRoWQ zwnlMg(nacAq(-?^7}3N@1tg=(S{=a)I@j0qud#q5Dv64e6iszfqxR=of83}gVKz^u zwPzgx<=5}@XB%n$@#4S4$h3kqjjpD3;EL8PiL*Gnn+duL%0($8Zj18G?`mn7ZP(N= z8TL^y6&tmN@l24HF$SfCG6fJJXz$cuaIgeZk8>ypBDp0pKNIs47+vvGzX`{}?_&UVwqgf6n4_8VvDEjBf{oiT>)I!;pxAe-h~Z`@h%ffaDxU?@t0t zNC8}7SOy{`!4yDw&;We@Bx*uRDr*Uj6*VCxkhK8%RHP0tb&55i$zMIx7Idu3Ny14E z$*F)X2;rssoB8EsnCxUio?Ohc@HZWSVLYE^W&l=KUFx^4!tCdIe=O$%etyQ!f%^O+ zKL7a#;RqMWJnbcbU&6iXS$0>)X07p%V_}#%gieb;KufG0-p+#Q=*=BAQP0l8bA-YW zw^7-}rD$h5I*IN>?=**Y^@6IVbnALP$)efh?qnEDf~4MBcbnlNp_R@rv>Y&!L1YA@ zQGtLU8I`Az)r28cf79+h)fROm(BUMW^6pu%V5!2|!+4rz$sD>`Z%7=+B#9A-NLYZ7 z?lb(%cNl)!z13YPLQcblbyk1e@sE2mCv|(KwD`E=ANOo}N}iLrL}>*~5cZ!qT7UmL zZ|P4QNuG7jv+iY+VoDPS7SdI!7Ozk>ff)&d6i>p|O^{6Me=D?3wKN=ovQWasr|3;> z8s7*of1O83I9j2pow@pv8YJ0yQD5jkID-X!;Qt#!naO}rsY+T`oiNlcm=3ao?#y~v z_W;Vb>YSLKcISfIrXDNR6HBrzo(7y3M4hY7$%4j3nqw<0+=)si(v{7 za?sXX&@#QCe}SBUQu4AjpN+&0@TWMLjD&iYM7Q;4ou*L5wAz`WW_T6G*I}02DLs!X z;cR6jf&Vp3vS=8lxcK3kFcEA3fZ8v`AF&Fw0#K>+%8-G66Sbl&yav{3Fc}WxFN>dL zLc`I&rN+a*yXSIAG}VKdV07wOza9!=!7uEsD}`whf6_JeGOE|K1PL)5N0U(!PD!PZ z+C-vz0*iJa{^Zs;Dddy0v}lnNlPL?LX5-7#wwtJ5%G%s&Qx4xHmQKO^ti229w`M zK@tc)f3`)qyGdYTE-V#u8rmXR7kXq}h^&pHxyESL5Q|-%k;lqwiY!3@mUd^Cck;0O zJx{y0%R6~$m?K!7Qh{vgKtHQzMN6#wnP+YH&Z9jl(1?=hNXN zxSmPJ->p%UX2EnAp2jDCod;rYe|3!pF<}ynqIoLz*y?8vqoYYM^&o^A zGil3h=xb|=h7&=v*R*9|DbE?Ho4yR7HLR3H6(OG%U_VeUoh)qb2%FVcJc-r3gC6*E zVLT;H#RU+ls06+k4GW?BJVN)p!o3ILJ#X^fgOgpLSy&zCi=5nI^w%;{$b%_rMp5n0 ze^y$K6HcXxtax%cx)8`AOfuS|G|e$voL@OI<-p7YHbtvkE8s=YxM=5J*!f+z{?KjW zvds%1L}|<<)1#d$;K^pm25INEDYuJt1@LFjnC-4Ha3NQY@ z^?NZmWE95&+ZrZunrfO}wh?2Zr`4`o?>1-5#lAU7_Z2#+x3)^$K7IjaqWeM1uiDll z9N$Js;%wx8xn}0r9m*if&4JV!>umq^CZ116(e!G;+U4%V6oJAdi4(4(*zgwaf5~hC zqt~~lS>0aMTI)&(s-2!$FLjSZ4Oiw>*oMKb%QZ&e-i+BIY?+uht=MLQ`Bb!5aRZoZ znb2{qAbd+v4%uKTbe6h2ZaQn9qvmHV<7^FO%Zt5x$)t3ZU^-R6;3Ag?qhNH4V9K__w+F`IgfBdP|UEjc;uogk7 zGx7Tz)<4SbY>2gQrM)6ny_FSkpApHeEIturoL<#C8(PbNc`m96^xy8i?;h{G-KMF3 zv|sza*4YB56p`2!f0^6xDH3HiGU+r-1RXzp+JBo{4b%WVqLlK2=b5O zYuHx65*t=16ICdaEG)yMNgYYnU0<(>;W!uM!SAg0=ReoBM3Ts`69qXvsolOwU0GXE zc?34pWkUxnD;jFxoppiYM&GVf(7;Bo1~$6C*E-!TT_GxNefGWWIk7sn1R|36V8W|XcPw15AkR|iOUpF zp_>1j;IUOm{x>aNuY=h^G!26!j|%gIQ!o-yUBFob7|+3p0HFX%;R5k&#yLT1fqE0pU-i;&;Fj46{w4sga|`1lB$A*@cgW z)ud1czFni(F#fZFUu%NRK^S$~3JI8>`{m{|AQiH~>7!OTu7OEbpOaYh6^e;AsO~cy$^dFQ|`lf4C(@ux@{J8ov#%DpZsrT055< z#W!K{@$&R0F02e%0}Rf;)41TuB=?MZ(;H1H073+2@lCxerz_N>VVcBOP*|=R2Zvov z6dcQk0B1~441E}1&*oW3>Q7o|lytPwvvchP<{bEk=BVHDq{B1yv+O*lU(p6Kp*=qx zvEy0Be^gZzvKEvanBr1o*^&i|PUr7D@)i;}VP4A9{WEKbS`Z2(?pp_KxzXOWe1 zV_SL>A;A+N!8;yHk3oQJJpQFkA*Co686QNb0Lyox7aK@CR= zqGRg-e~xh2@#i&~#RGH*T&qo`11>C%b(jDXA)Eo1f%rQTe~04lwOsYnhFm_^I>-a{ zxr8znnPYG(Kb&7*2xi?oI@v$?c!*oOe|e50$0{Wd9Nh&jhx#$`RiKLt?I|F*-vdFX zJY%Xeq$e<-4Wvk5QNxLBKmzdxGJgaWX#|Ec>6(&o7-UjPNdXcJ$%I`Ijl8POr7NZB z6SO^%BpXPQ4JFAUg#y%scIj_~e{qj`7J}%S;4d6!z*c>A;cKYAdhiv={Z_Lkf0=(2 zUJ9M?D2Zp_02Zcf8aPHzu^|UOy|Qeda$VqC$iXcN&L$jGh8{x{pU-NV#?#$#Fue+Q zgURF~82(aM!WY2YRc-jLQp0zZ8@{jF@O`C*?<+TaQ?=onN)6vsYnZb|PA29qaG0#Z zYaAYN=^6VwV-A-RoD1)y7;o3af3ds;Sz@Cx(O75|Oxt*mv&JC?QXdDpVm zP4&)6Jz{S@DR6{Cg^n*PO~?^y^OD06-$(uQ(Zj@k`6r zVVoj%Vnh>`TX-zczst}jG7Ox zwMBTXI(U8g`SSw2)+*q&x(KhO>GkFF&%Xs;OVjJ~m!F?t93PLDORt~5=yBA3WDg+N z+M@@O6O7!sI`W`V`Eq#0f0vY9;%^e)p!nUR4Fg{|T3oCNfem)~@OB0#HML+`!{nM+ zcmmuaBmtOi1VoV)sEw8=H>#nC5}OO>4&ZH+?zkR%mcR^g3n3&8Nj+FEzi zTrgH~nzXu5La+QlU!m@=!R6BDkZdtD+8@U<$B?=nkXiD14bQr#>WUujm=z{nWfw<8 zI;dO2v{Me^>^IHKyc|Ft}?tDL{pe_I-RKpSBXn=pIFSJUkE8|XT=9g4_ zm62y^=8`~k0Vw?J;{Y-Cu{0{_&0Jmg1P@M0FRF#sevf4` ze-g`CV8pGZ4JTIit=_fpp|FbFxmtQ)W#3C}xoGD2qJ&g+&H{vAnWYGAfq>yFv-D8f zJxi0fbAc8*O|9#fz8E`RM`&6D&q8w&_v)2#tO(C7Wm}$NSZkm>%W$?R>QJLuP148{ z;00bYuWaYS*R`{An2e2L?75&}XE2)6e*tH67-P)K=14|QE9HWqyRtwbbbD-!>MkHv z!d8R0-@UvI)b|Ab`m0{=bf_|RR%?0at7_bx264?D-saA3&C#vrXja0_ok7U-vIB@b z-T2`HKYL(D4`w@BCCY;fFk=8S7vRs8VVOFg%j?|v>U=4$Ce{oGg z8wNtFYj10L2bhPrEM6pG@QYvzS*Byk+!dASnlksEGNbS^5Zae45UynHUQj4@&jqj@;b=fCf_Cc3* z&ZUeEqtV0n9D0tUQ*yPv2D^n+f40TomzC7cLK25=kee>9+I?JQootw1R+AR1TwJVj zd9mtFN`v9TWmegzSHTcu4-KX{1B7Y0VL})3Q9fKwL5r)}4&@MvB`IQ=Bqea>7f-<=lQ7(_epZT1CC!UcMt$g%yIN%f>=X)f+IU7j%Sv2rEY1S_DP}fipNUj2YsBB zmD zxG4*M$5bjf&eLVrP1!95w9;**hxL=JFdYnJM12Yks)R`gJCo4w^<2a)Bu(9-P2cSX z)$N|cUO#1os#}y|y??=~^;9)Zwz@^P4Tf!-RqgW@ITg9V^r3`If0ecsC`D_kbu8sY z6l;?lnWz$Z?jOmsT#5EnTJ2IA^SR7Qq>T%X0s~s70kO4I77t_|R8M@v63fdSU`AQP zGeYP(GvWgVJ8ax36a$te@s{>PRxNKbw^un7Cugk0+?%cpB(YPcm&)L z7K5qfpv$77%`bGo!M^qp3@;}OcTZN$BILVDRFOAgW1*9yBAX)?4b@O+n@{OyP-mfd zii~5*m9bG92Gjp1tBr%{XcE@$#X>A)bd9=`e_E_fn4`PyOIMVF2d3qCsogDev7gGX zl$)OV;tu7Z$-G6oOmb1>drk65Z5j_d>FUb57Rqg4r1pS7a(AJ5Td`wiwIN(QYYw60 zS$POE=jH%j>y89>E#OY4^sdlRM&MMe!-utIV>nZ8W#cdliW;G6Me<_q-0|Mn(6|cJC(9bX1)rth|RPNDbOp7B*8(l$;LBdmi$hN8C8h z`|5udhAc2gaT@szEL99Ao$k49AJJYaWCQ8+&x@PJBe(@q&Z@8*Pv+N1o;Hu=8Z9W? zu>!v?DBNunZW(Wx3q_9J#oZ*>3soxif36y{CHK)&s;ci3bA6JYPt5U2`aLnXr~9Qn zoT@oEdHkEa?oGdu!;;5e$?vXoZ#-cLp!Uk(CPqRW*=ga4UYFm8A5T@%hD>^Yyti|@cPvsiRf;OIrE2Z{ zhy`BA@1296c0NP99f9vpdvD$!e}Jpk%GIQ^BEP%z-4)+pRM?#-Ujs41;T{G15FO~Z z+mv@QiDy>2==4uXFxx?+1kZp@PlD`Z9LO|L@_jr{g89g#i9$!?czR`01aVF>ls!9a2jtr^ow8z6w0uQ(<@Ke`xS_@7>O) zgHx*lq`&!edYUVIBB*~X2bm=wfBba#R(6L{|M$oJLoaB|_^?l-+Od=0h_O7dfMYU) ze!BPbY4>fuqgFca=nwnve>mDXIT?KT_;zpb=2(259ui}=-Q2hP@80bl?;Y++_C6Ag zpURR4`=S;l!_UFN$B##Ze<^+>vKPx9fObf`(83!6TeIKj%wy z@STBF1)EjU+RT7HJEwJdQ*q9viD`x3mka|)1Z0;=!?bg z$>PdF+hw~j+$oLRf5P@Nvs$aSko3kv_8_cojEQYSL5yly099x|a&3jZjTqCdABCEy zWf!@-Du~%GzG`UEvsWz8^iD-dKoO?gB%Ua+=CPKRhPEgKY~l%yn{XRi)IO#kU z5=M8eo9o(3wh0Aj_=@n?w%lWwln%c4l38gG!h;_8g!Xv3z)4k+K@xVeDDuZbP8W{1 zrp=-uPd!79K?32{Hg1RNYh5jg#b{6(+$h0IsdRHhU4)X6GRe_p+JKna_`qvDVRx=F z^c87fgqEv)i2vpLP)1w)}BE~cn6O`?Kn zk{Jo0W;?Jm@-PH1r^xS~NJ@Id7QH0kHE{&aI|3K>f792kA$>8XH9nIj#__a!JA~d2?cNS& zf6mSVVv|w`B>44OA(P@|h(Ml#Or=}zuwi#^N}*mc?X}<$yaoL|Xt8Uxp?cn$cT5r=ViyLni5zLI zsMn|HHN8q9Rb@+aI*(sGlEqZ0dOi_Ye{W_4^0|x)EA>LA4(<0f8U@;>HbOj1-82u4 zSmub(u>eH>2!*fUktT_vI&kG^n)62PDf>%!5?q$M84*bB?+7uan9HMjF=VYq8LCRd ztAy*Ljw*+zL6U{3SRVAzDSGMNH9aTQPT8eKmpKJ6Kl_jcA8xzPwdgnzinwiae+Wb5 zV$rcw85W;Gt{Ep^QNG5AL^A^mgTjsy0Iv$(`GylD1F=)ta-|%O*s*HT!i$^G0~SAV+Nt# z)dT}w!L_+C7^MtWZI1U=Lr@2ee?y$ddMaV(0wm}*OCvNpA%l&>!CdK#9)E{9+z-K7 zGC#v3WVldthR4QJ_=T}8Lip7`r=T=*xE=BenwZ1g51d7FxB>PG8W)h~aJl4_3RJ4J z_K|2fTJZ87+T@DH=<#+5=7qqiQ9gAoj}7CyQ0PDsN`hj{&X8zIAv!}Me=9}g42iOE ziw-{e=Q_G)Nc5#(o}j1^l_`8@NQ8zPckr=wu0w$qd1&;Pb$-F;(hz&XM}o&L5Kl~io(?&&s)8xafzRS^CV_S%MdO9!+1W;Ucv+KwMhKIm%@|)aNPt{pe{EU2R$Khz-twm@xpG~6B?&PYhL4YZW&ru`L96^iA6oay zC%MTwA!+T|kZ6uiHB$$gX{UM$#G1>;nv3UpPE0i0XPT`C`07ksK9~_AA+s0puC}0?3#63n1gFf{?K@0x}OYN;5W*FE^y}u?yH-T*5mue?65ul(|1ozcPMkOWG({VRJkLWJCnHzI7*bc1U`|#GX;EI zXUF{Po1dHJXIK41k+^O$ zw$Afc^G9J8CPKRpf2LV^%t)KdiG?H0u8C$%m#zDrkjonuTPqfJoMi)f&=lhCoeUL` z4APzHP<<3njE5ahWZl@<3HNhxQO!KoVF2VJP^QSV3@mi@S87ZqHdjK8sVNZJ-+x7$ zH@wlR%SA&+)3B>)*z<^nbt`Q3Bu7^g4Ves=2yE}L>Z^8U=otJ0>n#)oI;X^tTNtm>u@=$`*$MRl7K!F8i9!kC;6E`TW z>Y2Qn4u$8sfAG3)WGV+F(RnB&N9qfuT0NEHG+`yN5tK{yST=%zFdMnBGkA-77N_BI z^Si_6W2Uq-bnMltZm794QySZb)O2`(b*T?&&P1on&GX!|;QDZ+DD=B$zh)kd<;+I+ zGj!MM4VM`EQ;)xCH5r`|&xBI*>zwQ5R#G99R3I`*e|4~buGd{ji_p-5=p`vhgppL+ zI+x3^tG9modaAC+SAK1a`^Bg7(Gu-MPNrC`*ve?B5t#+o;BP%<4?ayB(ufGRGvsBS zgzDgDeNDZl5UbJ{SJUiLR9{^GZ~qNm&p|G8V8j)>3CJV}VM?&4o`ZFE?tdGDZioJa$K?te?xS=#;H< z*^O1|9o14j(1}!WlchMbrpPdDZLFM8jGT2lf1wu&6S3WTA^za=jbg0|&ysU;{Q|!L z)zxP_O8>KVB|rPzDH`tf8ZSAXk$fYXkca>Y3+=OrWG&n?3eR79!vU7L+bTZZpJb`N(`uq!^z*?vMe~3Sef9jG2 z=#g$Ltx-710wn;zkgq*j7#BqOhdUBnX7$-+et^Yyk~NHXgihI3{oDqxUBSO9D<||^ z)&s8uaskC46ygV9p`jU10%w2{IT8|soU@WUAf8=WQUBP*&U}$@I%-%prax)#42spA z@s#kvPE>N0XHwGSEt;LBV1`A@f7&u$fr@P{U=Q;PtT+`lzbpv1s3%^iVx?P(Rm-ss z)UDyRyQ3$N6J^d!LO!RgbB(Zck>zTEdW~!G-l$~7SmUuQyz0e5cN*CX?kA&WEVYP^K0iG?OOJ~iVKEK8x(B%T^1q|9y=gJQbzSiYe@C2_2SJngb8*A!clkZ?RR}Q8Dnk_itV; z+uwqymz(Xf4!#-?|p4}U)P5B4Q+Ve)P{F$ZpV|~p?O1cL_gKT^fG9| zm5G-yW1$l0=lZ#GGSss6Q|NsOE(P>3{Rk|?O*}HWwqzI`8s+M)Qr%UmyGnIeb9M0$ zsq3qrQ1zIq52*T8uIZi+?S#;d3GD%)edTMq@2j3t^)Xc+QuSG`f9Z7}+9{zuCbWly z_AKAD^{$>;lxfnJ#U;85?)V&@PbQ>Bwl3gCcr?8t=?d~0)THa#JPY4gStxi( zAj=8w)GZC5YP^J8)uS$f`c#u7Dp|HPGPqN)uIL#|wRcl%v%T4AZ)|RLI$Im-{ml(i z=E>3aYgFa3N9}lMfAX&x2eXs}Q%ZsJa96G^32cDb_?w`@6fYDZsyL=4_mBDJ==W5;OYu&>wQI~8Q z2JRgk^8M-|;etCDOOcQUGdlNd5IxvfnB+a|d{)9VyxK+9fAZ(OjeHrS=FdQq0W;8(B|GNOKWRc2EUpjN@N+vPHHgn+OdI zamRt#D=$Bie+!2}nk_+pyiR~-V?9H2L4%*0;Dm|7ZbXq{3dMN3`Mc%eqHanFF6y^zJ zxlRgZ^9CC9bonI2*eoSSB4#1c69*a(b6B<3&C;SIe<97WyiSV?O`b(4>ZEQ^+a$G@ zbVl#nLy$<*L6o?mjv{O(I^NSFgyhqd)UIcYXe+g5@=d+Du4h6@&@M{{H0((CFe`>6 zlmNYC0#`Qzc_1FsZec1Np(Zj?0A7g-)h#$MkFHJW(i`mh|3py{!2jkIf`zk&iHvzb z2jk$yfAgw_w$Uy*1d)SOU7gJbGH2YtrytafG#rh!ddjcc2wi%uu1@dcMx&uYU^^U+ zzS_11-WQJogWX(%e){07h0@!O0m6oX!eBdD%T&N>eMJZ=BVJ>Wy;!ZDBLkQpS zc-;Sru%Hh`6evUdA$V)Dqk&lU{?UWkq)>5De7X2_pr7nnZ5hfauOVysdrVo(3GvBt> z09o!1%VDVaDQ}RcV}q$_(5~YFWbp~cq7q{j;7S1Uq8_QAk=V?Fs|Kk2&?7LO*P%v0 zHJ;%EdDi+cK|g&XhjXxg~W6rfAMtz zggj!K+TD-`A3?*Bd}_{Mht%;(;GIBaC!z@LnL2Ue%x>?`T%aaQL}`#OG>zoK{VUsu z<5`m#fr#>rk1+NEvp+@2DA^=@@K*e~u1sqfV5u`wt*>_xUV|)VV%#XBo(j@>&8|jfQpz zz#D0JHv^#HQUPF?sxN8TkV~yAvthwtkyy%K>GRkGa!0>T5Ax58)w3m!US&)C=v6J3 zc=T!-<3+61*fJ~njD6P~%cZc7i5OnrF3YU(@aBX+cBaU@^|W#4NxNTse|@-L<@&I5 zJJs{K^qu1V6Wu9x-f{0brqPl|+zYQH_Y1Bh_m{hp+=SaV6cT0Ftc{wr>t^lBs0FhU z=iHgTr#zFF4&c|8ynj4{b4PNZoRMdE3cuFnrQ{jBV)sg}yfZkMqzlY5y4f&>U+7^w z$NJdP1b<>v1NcdIVc-|~f8CBS8=JaTV6nNY$6tG1%v(zug*9LQ_r3xh(lFB@btuPC z9#n^Nu;gJi0_{j-I)qI}qSGOKIufA{VbqZ*b=Gb7dmvfyI|Iv;ZV9BgOurR!U+5u0 z8Z8Xi;C~$eZymSEa9fxUj2D&UcRg2c%;{&A;Ds;%c8T_loE7s=@t(KDcFQ_VlRgG33Ny1u@3KrfQWNf^>o9#`blYDu!98;V(XQx<%Q_JjlKNS*h>Gdv?k{H z@LD}-b)`bV%+!-sm;46Tb%V<48(ffJJsJbINUwMaNI2ysATZgCm$0Iet^EA?%ZfCr zVCR%A`cjPPDeZpY=ZrS#*OWSzKSk<@IQ5P)1mKaptaYdIf4AfkI#So><)wH?q19a8 zEyWb%w6$xx&_0rjxxAQqB^yA_jpeJ!1R0S4MDbz6mCrxtdlgAEXEg7x7{*u|?=N9L zz#fEKWhgU)t?YGE^((;(`RL9hyLPFOI5)&Xu;(xPd3XJ~>F-x64>(Ns)-+u%}CQP2f)Hlt1jDhvbflxETOb9u=e!$9axO(mGvbc%IIv1pF>zT`VKS0%9d ziQ$@ofi#pquL?Rfl#h0sks8PV4-?+0S+j`q)Tiu;fBMAUs8|sL)1x^C{zGmNz54l! z!+v13d5UhWF(IKcIx39Cj2z#JW)oq(Mp$=)lfp6HzZiKIF0oBH!|zk z$gE={vyP3-IyS1bj+H$&Z#!FG<0Ww1H8){Rg&lIS6NB$DvZCGA;NBB0n+(Dti#@Oh z11nNse^-s$@caDX?5%B_iJ+8$cI!gxV7fjGjlewk8UW+7oSks3FE|XFl%Ld!)3Co) z%CHOGIkuyFC?gM_WEh28d{B}&P?X0Hnp5}m(UHaAb#`JsQ4Bv`$YOUAU{{s|7cycw zQ4&9hJ7fBK>iv4=hXTShtRYme$J6XmF@U8*~t zSSByDOEqrj26{6*)cf0!*|c7pz224HDbMug_tNZVGqX3n(@`8wb!>)P9d6--f;T{u zdpeH8u@23!gTDaFBg%yqzv?g!H#!c)2g-(KF6bw;bD)Dp?CMYu?o+@@Ciyg^g z7qXZY{%Ii58%p#>61{6hx(!w8RF*oHf2D3@Da5U#W5(RdVmq?f2U+Z$ifGkWB~N6@ zBU$o7mNe00t|W3ZiQJ_`E>p;D>cw1^I+mqwWGOYSw9Z~h{ALorONn2miMOtboycNG zve?CM65gusiA+U1Tu-Pg7RKs@72m4U^F+R~17@){JAH3>txX#wYqzuR37Yi{e-gjFJwY(AzP?YhWdd253pE{2G_V(1`lAeW zqugz1>ECIaD>Z#PJQ0j#t-hL~s}}`tO3e^S`Y2_mwU1gQ`U83GFAL?RimKzdUNQX#KEqTQ*! zmarnBropNPullM2TSXfCRo(A-<68ub>a*ZS-hfeCEX zu{2?knsTAkl&N5pd+Mbu>YX>jOa6}BQ-`D*=pi5KvCV679dj|RYc9t1j2_p| z>v6EQUP|tsVWdWy0W+KxWD*+7GS_koK9??nV_7~UMes^jU&EzafxXh8$kcWze-AV$ zikl}v-Rga_sXmlgUCC*De=V!b8pURfVIpyv2{RfAP)kYc5=220J&U9dR8f9pdHYE3h#!d$Hs zDP#7r?!}r0d);uO5}w*|2nP)JE8Ph3r~;O-nKNLxCq9y(+^%0S++(K+g?pk&LcFUe zo%l$yse>IVG7K1{2aM7Qo4_#}*u+N?TzPI4NnU8&hpdqq!#!odW=sO44ELdnJM9?i zu>)(&NS!j|XAJq2f025egWJ(VIA*lwxTlQPLq_YA4ei(^3avFKdhYaeGc)u1MN38iv*8HW_Okb0GEaApZ8^p$j+;fKhB}3nayROMSl&}W64KrMGHe7Q??hzyR zsNvfOr4`<+ch5&}<#LKo3DC;!*%?JCUZnGF@p?0PKp<{zxBuPJdQO`Fk$42(@p(gg#}j)7LtEZP3>S zi)o7qTa-=5r|@T$6bWjm&Gk{^1g<^w>5$RfNCNBfsf^xHqTv;~qh!qgBxLR=QL#G; zH)#L-u+Wn)e;0em2xQhWhGkglBExa|{B$^lj7Ho|M`BhTr!P;6Qz>C8$`c#kJ1lXr3i}9H? zYbw5LL_byZ?NpalDS;}mstP3dDI;?)ax}rmh&*9me~VpRavaS+qlE)?G7fEX)q)uv zDxevg!c=L2gBcw)Eww$QQ4d=KIqc%s9Syhmb+7F0gBu$6ltNgH@$?msRp;{fe@Z*8 zlzhhr^5>Yqrxeh8s9t@erUFWx%2U}nH6a7Rj@8{bi2@aX*3jQ*gg@>`fJfG1CXa*Y z)nG7Te@yZI(_Ehb)xq!(>a?y5bG-&PqGXyn6~rxWUshV9N+W%GL`_U|6C-_ERHutq zDove2%JV3^z=w@RvWXY6(i&BY%t@1JW7sfR9SyK(3(q#^nLN4j9BPijhx3edfT|}H z#)cyC3u1j=(W;q9 z`wZGM6KRP-GiE}2`N1{2fZJ%|UM_7IN3y`&WtsA`S5Zxeywxg>mD=&9cD<=u>jFC~ z&(PYImAc_gC4DV+QeUW47qryOV&+V!78M!gOcX~~!dr6HjgW`|`txZ=T}Rp-iCsDP ze_%yl!^P33%tiNr`&;KuL~XcYyvIRWy9h%u+rv?K8BN0x`f@>XfIE8diVnm;g{|7r zBn;B9HXMh;U(j`X6c1D8@HNfzHw<_em$L7{BWDfov5d+4X0?Xb$?73q;UfuDM_-x- zFHPYLG3HN0y;hmZDY4d-8^hG(IAOOqe*&td>6vm-nCiEirpB9Lde+gu)Z0(sZX-SY zus~0jFts*J{kHVZo=VXXP-HKaziGtcR0<)uDKeF^rJY;)J|@{XzDk1GI2tY&i_9L2 z4kyD{B`8wQRf3{%$VLiRlZ=fK1twQQ8edqL`-vZWNZvLiUkg1n?-G1TbWN+?f4RIb zT}F6hi@BlxTC|Y-ZA1Oew+uJl+4w!g8}DrV5pevG0mm^xyZ&nQjNh+LQYc$EcO=ps zgLOxu-7$E}LjiT1fk_f|^2>LhlO!2_l*F?z$)Yf=%R4d7eU_VOl#RD>(5}M#DWRoI z-=ck14842nMV2*}Y@{I<%8tY6e`=gnY~ij-3wOK)&kLIVj;eE-?h?V#Z`muFcfRAJ zqI2^yAejr~=gRd>ozLZUyzS_?dES1fH&Hem*A%oNtnck@YgqB-V(lUcgI`{Lr^>ZPR||;IZ@4zPLx#Mg=HReteEzllVre0 zLs+L)S+5$VTh->_DxZj}IVTW}MK!qq0O`68Cpf0%$j;x_t^l1nZC-xT9nU=mmCi4o zVn`ugP_-dt&aq`fntSPhe+}uHJ)~=%Ar;lD4e1&m(zTq>(^ym<(lyVJuH}Zbn#blX z?n)WB=lMCg$O9`6&w}Q>Lhv;jg^OT(Z{zfR9w&lR1tTXO4F;$1-0$u!I9j=7PN#Rx z1+TQ;n!^a(kC3lWBu^Ij(9szM73!Np>Xj}w2+?%0Y}LVqw195ie>PZic0Rr@edk&( zZ>u&F+?F?^@_o(V1LTz$-oS!}bO+1~xNZ2GhIU!;JH1+YqEQQE@~l(=CEmgUbUa0i zP&q)m*Wyh}(X%6bZqzaCNGBJTsR*&Cp%14nC$Y5>ln?`pN^Zz?pJlpS5Jr<~4M52v z_$JQ*pFr^9YVfgWe^CQ0)7Qdj{3T4{h3&{66n7%mDHR#4h?4S$xAvW{_Fay*Dm*H4 zt0U|2^<_;@VMhI!PK}@nb}VGv1O7e>D5ma_0oOu@BS<1A%+D z&Ieqemkas{Hk%CeJuqEiy`%j`vzC7uXxXrxJcMOF5~$2uv{K`XLbvRp4&$;|T=XO7L8OJjZf?y3BDZu^{LZA@RWdf_^|C_iou!zO{jOQnocKtq zp%%KvZm1?9NO9KFk{bY?VX>Yq$(^<6-Bo;fDVUR=uUyAp!x1)EYk8U#tjYIM&P4*Y zHPJT-a_^q*xa;#nd>HH*pBB$}jb?&MHaRPz2(Z?=e?+FHN)_kpUM?ED6|Sgjhbwv$ z-@3tlt``SA@8SlfP3MvNnJWk9% zM<}B`P~Bg`z3Z9srS;!eq2QKh{e{jbyi)n(Ei7-bR9X$CT5hC88hmRuUaD$(DmlYhAQbmKJD!wuwck&Rf&6+R; zFizsD+8QgNLNBEi8berr;w?kCO9Po@-7&i>4*5ghDuX#fuI2=1xo66{b-n$QJ*;E= zQT=ua-nq4`iLwWVeg*6&d*|};!}@lD+Qm2Mf0-L9Q1qv%M@cXHd=f8an|-B*?t|(hrk@l{1*6mv~`TvNA#NKV{^tueqR|r$4JbGNKMuQG?4(1M%n2 ze4b#MJttHeE60rW)OP6$gQi7{5==i)4U=>86~_QFOxwD~ovCqW)nIe>C`f|q(3!SN zzDi-ZTYp1a?rDUsdKy7+G}oH3+vv@~I&0-MEj=1LZI^fQmJ4h8Ovkv*GXed~GeTZK zn(_q<0j8(NzPT#Lz`%Og2&e@V;rK-4l8;1K>w6ho^@ss8ty$w#L0F;f(OGm+g5}rT z`QkVtTK?rgQadilif=(makW?kF4~}7JE2Igb$=XEfN15&VdIZK!UL*DzDJ87V{bYt z3kM2Mw)Pwa8|zhnS18059`K?Nw*3H2njX2eb!mabKk_jlj*@xN)lwMEHThSCD9B@kk z%YQ+6)Z+h7y^;)Sy>q1b zN^o1zrEpNmYjME6^ak;CcMSeqyTN2~5e$E+bC0gOsts3iW*ppAZuq`x!}paMzOURc za%9!UV`9<@2q;FcfP}}()5jAs)a`=M?0Fewk3RGCl=IU&HCd8bJw1JRq~a+N)W~VX zETpRIq|{dqk-qPEk24oOr7hW6?|%iDMc1O(>YI;WlIr*+fsRlz)iFq_1fT2bs3qq5 zv3<4J#QLp=N?>wIgCCut9GywRsYz0wHu3HTzEP>qDyMLhs`Y~YXX@VChr(-fde!7R zK0A4S054}4FFLpWK=ir6N3h+nBm9QGrUC7>q&{bO3j{Rkb3f{LcGFYB+<%KU+&bh~ zJ5|>v&06aAT4JsP`4(cHK(F%zA5_8`nqEZk9O~`jZl;Zf9jiAi;uAseNddtpm3U=P zPVgL?v={c$4#>+ezjp{87a$&2W^%)&US23c-N$wfJLqm9=7Q!y0qQ|jnipa|EuWgX zsePxJ+*a)6+Es9Guu;2;zJG?(+I*VMXR|oT!jW2-SMc&Jm&;OQ3+ei-W6r0S5!(J( zyq-gFsY17kgZUbLzvxD!3^0VSZ8YRgWwG%`y`Mm5%J@oxE4cM5#FA`9_DrMtD}<$v zFXQmBp0G}`YAm|z!X3E}u-J+wCts;ozMs@w*Tf2M=JU$*iDrdZYo_K>la)e z>o2{vD7Zq_;`@plx_=@3WLL{td~0{}kGyjBrM%9)ug*{9b#8t)SKF{mciUoKZ<*e< z#eV;duE;SGICI_ZyE9FHFPH1obWu~~NiN&Tc)s_3lUgPcUgN*paJ}62B7cGldi~$g z1wDGHfRh40Z#3Yiy1^$KvYPqEcl*>RV;Uc87+OfX@eJV%*i}9Z9GFm?z^;6u&42%I-BfzPD)r3UZ-(X+%`h~v3L_SYP*&{o)^6n9 zN7ve9wK}ZUx_{l=lis%!Y7oS&+kty1i(b>wSnE3`0mj**CD0DQhZjjY=<|Jp7lm%D zC-@+S2s};mTF+MJgGW@Or9)0!s1_e{9a6!@M=EjuvItwl&YRt@%=Kn(s<&&DshD@qgm4(Gu0}z{Xl^gUS5 z2rvU?gVC?lwKYJ%2p{e?0H+NZC<}ll%q~@DZ>uAKiB+!-iwr((r+%&06qh~MzeE~F zRmU{?<+W9}i7T-U6*>{;wgUb=PAxUR6?l^h6MtMa^}T$eO-m;unJjjcL+|+5f8#sc zt@~X5Jz5$Y9-MU%Slxuc{7tWcGfY)}38t!u57XbrO>(C{&>2=kX-44z7>Qn9s zo+@~N)rvH5u!fYK|49Q3RB7|+gAnAB?(<1E-y~GQKhafrvTxPN45FyS?OJ5*s*_Db z&AflEoA#8#&UfYU?u|*g`OR+QOA82{j(^%>U!9NsPOj}cC%B#i+?(b%zTDsc%`W%5 zj|4Jfph)|v9@;Al^Kc%AdJ}z@h0yl>Qal+}PY~cl%K7VuI(;ZTdMKj>AzfxsE}*fl}ReA3-6i-F5Z*Ya|9j ztYI(O>+9Wi7gCe>Mr{8&?X7OV+e66nWFq<;1El`?i;Zrt13FzW3Nr$?(cRcs?`}cj zI7qT2oTsu!z4b1p#)5RXICpxRTYoS5n{7N9N`eU@*Y9^XyOc5&OZ-ikNVw}SIxn_5 zGAE5DzffP+1!RoQ6J4iZlIsWny-pi}-UU-b;8BqLA_u4ULVi<;-uh;@CsVHC$tavA z*uQT3MfZg+dxg`nBmVcI-PzQMf;oYP8`z>u%9s0P9Q+ai$bPTaT~{ElgMX`V3O9OQ zblNXA`U;155`7INRC)0N2>b_PJNxBD_F zMK%D2>b1A}9R(l_1KFNnvloKUDjf!jh}Pfi^?UtIoABcQ8 zACA)~AWSC}FCN<7s#|3U8D=LCnT+rm5ZA+U&RS z>gXs6rpP{>UVnXSz1x?mS22;l*TZsO9yhPrGaS;L%GQf>RPHHi$#nkGn zR3%Z?H#Y>j8#)ThV=^?VfRVl=xtT~Ekvr{CRrp%KxOK%}*MecdRVkbj$7J+Z*_oSe{;lZD|# zQBRen}3@~ZJ9L__*}_)8~qOQ7iBSl))(yGYnxgm)a3kW_cuG6h(L#V7V==*rUZR`83~3Zjr!Y}Pv5iff9YV?aihqJzEO=cKaJKkC-H**4(c^Y|Lnlgc z)Ds+n48kRmNt`M5u4HTNQXyT!3Gp z+=VTQwFxV@?QGqQWrvX&-p`d^$M4^0SoUSf@jUD%R~NpPA{}}$0((LSA1(S5?fll@ z(GYwqqxOAm14ACHioeg*^C@`Lzl|kY>whxH0eo~t@t(JMowC;GFfg;RJP{o@jp3Fr z8d?~V8J@WH#imF=Z3*$wd+`Fe3ZH3{)Mfy*Zh^ep+K?}}wc6`Kc6K+#05)sg zR^K5EHFg@GAno!^3T0HN;iAz_xAmeco9hUm>&krqniXViiD|yE(GWd@OiyqJ9DnMZ zb1kMy*IJmzpcB%c3;N@A=+!8qwM0TuY$4-7!1a)+SeC;CZiv*N&G?f1v?aUz5Z=mi zX$BM8E~joyfJ1I}Hwo)m&V*ahSC`*(ykfsEeEzHgsgnNMM;FQ(kkFC)pZ_f8Z|&b< zyNt)ALc=zVQvQ~ct!xp1N?oLg?0?LvYY-C*QpJMib~a?4jdGnmIamZ!-wO=q!$~v> zgXxEOG@ry!x+4P`@N4^_e#oa~4PdW(T_Bu;ojpjA%|49D*Z&oKp;PDSsoUG{xzu zo@sY@D~^lc^I4Fj;k!v3U=fgZIjfhPr#q9`IH0Ey!M_+hbnyz3_;00l6HO+yi?AkU zyV#75*M?Xtk+*}i{AWQED??1b>lDfzogIWXaD(^#`*KcUmD-H!rO3I z2PZ)NSh?l51N1=Gn;3s}(SM^xJ2g*bHFQ5-5zVY@Tb}`aBRUbG^Ow+)=M}~1cr1&?B0Qs-S5(La%1q8vY0)n{Jx=yt`LEIWWZ+}C1f*9v~$v1*i zIU9*j4;y(1@^n-L0SXXw`gpqEwIq;Wc4;2kg+e( zg^m0gm#^2c>UHdT`hRN1g|}|ks@u)CsXMaq(2jH}cf>}fw^T>^R^4@fM}FmwokIM# z#X1nm5o0&t^KizI49lzgdvNra*%BwXn;VDRh030XP2dmmh12Y*WaUn&w5Y9w44G>SRk zpihmi?5wM%b$9r}&b?^5j<7fN?~2pT$-D3n z&tQDw>;(L%*nb;K8x<$dLdD6uC>qBC!uW}8_s?AB_K%>`!SeAVJaZtg+?|{SrHk8V zNvl7>Q=GN`7xe}2lk&Jl)l1`%Wn>(xDf3WG8Hj3RB7YLAk-3b(E|MhdBFPoINOD0+ zj&?j$KG3vb&?=!xMwfJWXg$Dn@TJ_MOzH9D20EmN^inG7JzArox7yd>0>K=;z17Zd zOfTlba>in4I~!1o8)5%d z2Ue_G%>VZqYD6ndH|wf6>q2KWR%Gksi&4Rxpyq+#P_$zVNaxWUb%cX!v zet-6{8)wd(%Xq>YE$of84*=S8><#<~ExR5ol&V506$*WYCaTcHiMz=sc7}GgaLI6# zEEY>bR_QB~az!Z@CgoyjufC*`SKn3MtM9_+)%P2@@FjT{zALW_-vy7g^1n|$9+v7~ zN|DhIU(?yb;m(J>liVItdc*Ao!*NJ@M}IgCE+%l``K*I(Hj_|{?BB|6;mc4;GL$IR zHZgDzfY`~x3dwY+JhOm`;elkE4HPsTvIv|C^RPzYB+No@mEpvv5}T4hgkOnt&DuV= zKQP)1;pb>u21T9K8|YOtjIUAA>xti?9Ux(o8Q;F*x7 z=Tf^A45fo=Bjmcw$XfAq5(jVtR(~+lt3ONBBt$4Vfb4KYKGRg`*Cy5rA*@HGiqrXI z!t18VP)AJp)dc?F)x6xMkB2KzjRO-p$#58^DUyp>n?edqQdEmN2p@*jisvPls+*ab zjgu0N!iSsGP>B5p9K$C1;ilD9!C{G*>+(408Ep-0U?dyrVPk;|;W)}VEPu3jp%9TZ zu!NGqLdXs$L7LW1!&@QCB%%I>TWb?Y-@wSi+rdyu9V1js-Yf}=vemG@67v)rS8^j4 zj0s4s_lUYhq&0CVo4BdI#a_fVR?kRifW0P#f?=I5+%kZ5t7X+6*?42Q*5=6sw$W;U zVR{F%SvUoj6B3(ZdadYKgMVo&fK{F32@j}YVS?ThO`4L?^;I_mb47%ka6!=E4yIRv zp8@FzXJUar$GtgUHd>7Oxq02Xh~!N%dH2trzy2_=MMR?wKPVYVOCn5mVUQeZ4RFR< zb`tjdVr%W6TSP2-hEXESGmIlbql_*gNlQ}4%dhr4Qd7^Ga0WT2tbd$PzLM5lQ&a7L zWX^|RDkz$`ldX`nL`Jb_qs^pEHj=iMBJuRZdhMgBk`HJF$aKO{5?>`kV6sF0c)BO$ zePpCyl!ey{W-c<@bafRYRldSGXdHbo2DwHC=`KH@XK)lO`QcfcV!xTT=z)`5O98ax zK-XQ64XAI{Mu4bIQGeZ2gma((Wf}?ueCX;q)FgFs$T<+HoP&4O&6VjTZm zqM})XSA+sJ(0^)<2x`mt9Y9y*-Q<=--isQFvd`ee(mJQZoo&9eGdYud9S#*UOL)He zs8;zZGj#o^7GRp^Y}~*t9AqMk3+N`w#=A*45;#Y}B$cq-RDWTqAd0m~3<7GsZdXXo zMGX~A77tgC#6+?d5}a8S(vnIXGqkOeZXb1xpKQ$R7=Jr!_iU}gE(zx4bOIM1}$9iVqi!$ zx~>08S#!F`5-+_2gQ{rsOu|ih>={dw5fj4 z*ndD2(s>3ZF6rM(d2;7IRS8*~flquOQGr-VutTynFNPKB7vnl30ce8thOr$e#nm%P zZWlw^y=9I61|2uvS}uE|e0iykRqZ)?63>%in8L#ZgJx~mtc{3RZS~5fZ`x_+Xm_$} zE$_O*B#)Q^1jN2(Ts=8=&1;!2UyL9ui||0TSmr_NKg(@~-T z*3X2C5+h3jbw({z4k8iQh!u;`o(Y3_8RN{()sQo)$fcD3>`dE7%59f2?=J_ z)Rl@m%oau#B^9*!lui8)bQ~EvA|Nx-}2Hb1fv6I!su&^^R%LaYSuW zLDWk8oIxla0Y(0RJ|*p^-$}wJB!6YyC=X2PMsjKVl^j?7JGPfzqe2-+eXH&uAHhaK zpuqP>)p|H5Q8pK%Y%2bM40A=hW)Lw&ardug+*mRd`1#EEGQf}QxD>XPWo;x&II^lFIEs!P=8(ZSfTYMg?Sn7hbT;fWH`Rlr9)3?2KxgRwsh^VhXWpp64| zZ?p38Gqv2lIu-My$?7^ib*kpZmDP0m>D0^(a%S_e6R3xo7*2PN-+%9&N?ma0_;}~@ z;LWFZ@Ai(R!{Xk--iN)z(}A4@C*rl;k4K*e$9p?(b#hlH|8%^6x~J3O+IQ{rc<1os z-N)k(gLiv-Z{O_f{)f(oOUSiPhx?eT65-lz?P&k!y@SCKFT7#WKOI^*o8O`RSoZAg z@y<_!)6YkHvU4Y=JAbG9yRus+rvmX0`-kskU*3K`6rUouOE5fBoc7)%r8)KSB!xe+ zh!(EsKICsLLin;&9UQ2nB)gNMPNpQmjWl671J=@=X;C+rJeaF7f2LwnOUG3Ey;GI? z+Wg$kHACFc;)Bi3IYyHZjMMzJxJf+3*wo5Ah3+I`vr+=AmO7asai1Tfc&G0-H zvsvA$X&c>KYP8kGX%D6Kn3={@^LBe|EVKN;ncA3US5?JW8)|@^f@at=BiN|(MZ`1Z zG~S+~Hc6p$>Mu!Ty|@$WoKk&d1?rdwHfES|^FsMMcckvzBf;j5#G{sR%J|#HEKYtZ z>kNRJa~!G~0)HP^nP*DVMDdlS9D{)@X(6EJA!}bx7#~obY2cdj7HB^2By?*8a+5)= z2l}?`{xsV%k=vMz<9Fm?O1nYc(0v9f%h~CTNAM|n40x)&5dJP)dk#mBYeoSnYfW^w zv+)>WiQ0>L^N0py^#wiXbsy6MQF~Dj9?^iTUe*HM4S#(^6RQ5gHa7Z?YeUrcv_X2< z`vYB}$gP3T->V5c|8Kv?R%0b(U1_s{}3fCye$`2K)^=AP{_8Zcut^1YH- zI@XSuc@A?$WPKOv6T72jc$=Uo1){<3ZUHDlOrn+Z%ZC!+M<(+_a_2HxnEW=#0`>fb zm1|X$r|nvR*doL77Lzn16@f`S&s#?>80D@OJ%5s_KnS23D$4MptkR+tMd?&_f!NOOLNoMWTj9t;ouAD`@ z`z~ih#sTVwuNgIp2CbClTy5k$Azg+!ba$>j07dQ(62i@=>q~vti@CX(QFO~7`c;~~OTB_89nor&GHaRMSQ}-4$r!u;` zx8ST^X!qaTwB(J3MX=M#%mb}iT$#hrW*zB!&a9ws_ulP%IyfEdf7p4C+B11v%YWQ= z`v<2&(;zeAVHiLl;&;&`gX=(OO_XULqM2YKr$8rHfNs{Se6*R`Nj;O~1=)A=?dt26 z85Fd(9c|z}IQn5nnouzaz^42q61NcQC!yHy9PaLI*IroP16dUVZwh)Ho&GS`{rKVN zH%d@AGY9E3(+{< zdy5}k`7zi(Jl%Vbc59JHkO<6Xt0%wq@vAStKGCO5$)ApQj*i5(N7C{*oQcW&QxZU^ zY>4TH1VnSfX}mYO3RxD?@-KA-ME9Dm{_PdxeI z2OoDJ1-qs`kOow8gBmx=3BIC?&v86!7aGI!ZwFRD7t=N6wes(-obXzGKI;7fT6AZRph#L%AD074l&Qvp!C)bj94lYu$4 z!9*B?uPPX0#h$`*nZe{8JbU6C48S9R0q+{hixx~Zg~+9+8n~=ai>et5D2*zs7mIo^ ztB3l!#pmjFBwPu3rz|t-RYJLtNDdOx?>d;J{On_J6OGVqc&rk}A%8@CmQfw3Ka*&t z6v~{rUTc}wgkUqmTzFu5x%6U%_hWbC>1A|fyBbS|$mmzoq@L>3Q<=&+Ff(5&mvMMz zzStp+JJgwzBmrHT{7arLM=Wb)`T~G&G%`D7x$}Z*2PWU@sd-sg8Js)T-ff#5ml}bT7Y=7z-D_ekZ{~%Ygm9}(Q z*utd?`LY^BVr<_4;*!G#P%c4PvwUqq)05kZoEDyDM!&$St}OkYLf8bKi}w!fDu0^8dU0nXFEYStz~S3?Nn3Ar+Yu2emdT3WB5qNT<)}CTRCWM zoW}1D>X|zS8!U90Q}9w1pwQj6lu(6q0ylGLF{MkXgodRU%UqPbg*m4UM;TR_@VlYR z^m4|^dz)%rkrTW#{(2mJM*Ir2S7}#p-wk*v<93%1JAXgJCi%@i=)$rZZE^;m4);$_ z8u&tV-X>JkYOF8S&VF$M5yd-tusaGNf_;>ND6_Id89LZw!v)!R4!lznSTK&RGG zL@77AfUJ{-6Hw&B|e=i8TjoPM7y zNrx?bZGW=Pdnzz#gqQ9n_*-!3*kV$5)uTJOt`aDK&Z66Jav~OwFfxhqc=6rA{?Xv` z;HSMe?+>6lu7XZS1)?YOi$%E7{}Z}|t3-xR%<8C!?&Q(XBNzG6$R&yq9FP^mIc|Iq zu>C^~EO-Lsz^pMi$&0Rs0TMgwSaC+qbfAx>aDN8yJYN&;$!ir6i0zt#MQ8EdonM6i zQx;%1^H^6~dTCC1+|!h}F8HTku6IAZfth(k{i!4mRh7Zf$CLfj{U7%RKeJUlEnmee z0Y2P&zw=E1Ym7gCD~vyXD~!Kf_Mx!$Dd-ysT!)h@673a-rXm`@9Yg;=E`C5tORoHoFj{)LXQLMMZ$$lK~Wuu zdK6B7tG&{LFB=cjVoz{A^NM{=6}-^b z%46NGRr`zlt`!o?IbIv+9#D^Vy=KrC_+HnneLBHcul~qSe1^yM3ERSFd0g|`@fN<^ zf!6I;g$Lfg6#$B2Wupx4#svc{vdU@}wNF{4{8-ZH&Vp8V zN}Am%ZMU$|(iRJwD{TvWuM2AJm(}`ISnU(l8-1U=#);;SMR zfG@zj_)bYN8LHx4cpqgk=-&%V8q@w_Zq%Ol&TS6A>T$HU5(wUD2qoTe}ll=QL99rb~Y5D zC=R;)!B#mWRcaA5x~NkM3X4?0Y9T@eFp8=c*PyFHzB-swP>WqT@>Mn2PswP&Ef%BI z>hlzyj*;*idB$_NL4PuyaXyvt)O^oQ*wMeL-)vGa&DEyqC>o+SDv!S3QpvB`?`^pY z*UiFnzP`#j{Wbqk)v4|j6q-q{s!D#%e&^cFf~n|amaDAOU-J*U-HWKGHp_W!e|kHP zHUwYKDdV;EW#cga>edq}ujx;&t(zzb(Xz7dAE{jaYhPjx?0<(3?q#a1g=w$V4;$w! z38v{JkT-8^va_t$&Udce3ortTY4Ik$l~-JwPR_|}9HK`t&y1(LV;Bw{0rQm$7))S4 zscthf^Tj-xjC95ueg|2_JSAUK+aY_Z!+GPI#T57Tl{0Dn{oh#xZ<*MV0q5B5{TTi2 z=1m=x-xOAH)PLN-0AvH2m~a3PCIJ4dzN+;a6kY!;J13t2@k_o%IoDtE8A|z9NidBv z2)Y(DB{JHnjb{;(-mE!RlyASVpy2r0qDvk<PQiqAw++>4IF?F-^Ek`h(pN@@=b%k z|GlR3lU#nJ-^HXSp45k&JemdE2(y4Tf8h%LPUYWN{snf@FNWcfMcB~q%aHwaOm8Hc zmmYoLF@MH(Pz(S!);(51$fx?1D*Yn2dD4)f5GfP_iNai?5EY{^&!aF`D1-`yxDk$DynhJ8@Tch!G367Qi@>Q+fj6@Mz8^5TIhP5_}w;8sxy_xx0ckvOwS{G#C! zE0Sbz2nM9><%tH#8%T_5L?Z%o!r^3)M2OT2*0Mv9db?VZ0FiLY_jP%q3Z$(&bvB$j zn@$^BvOJ5Zl$Vswwxu-`= zv@EBsTa3m}kBx@v(NQt-?Q;t@rU<&W?kbn>NVy~`-B+#zLMkXks^dip8wmv%B> z3X$q~ks?K^5VNiqvuPnx-C}Z03x6@|dNGR;sicU!iI-e4VpgpZU^Xsnq*L6;xUi9q zw~={aBi-Ug=7o)Py^UA`IiLm463A2SXIB&JF3T8`8`{W`=;{$OkW@3NzSW1KE6+vI zJF#0Cihtqvtt@!W0Zdxg^cK$D$uO7%NnO-IjGSZvq|tB_X9~~jmKMt>Eq@kHWqj=F zc5%rLm6VIf!s1;je(wVAl%U`N+$q81YT;y6D0l#OE0dzT94Wemc$hcQWaxiwVdL7X zR%x%Au0-c11>mvE{MvWN*S^#I>T#P-I>{&P+J9W?LFC}1fH_6kQdp#eMefUr=%wSfytSSvcU#_CAB&W> zwys(`DQ|5wzj2O+r!rGSh+iwl6%-%VG*F@aXA!C$>VZRK*^nQP<<>? z3Pn@$hzn~WCBUoiD^EM2v>TpwEIJJA&C_-u&8!r=YNfcrmEr@g6n{6kQhd-W#RUg& z~#Lv>3{sO)A?hkQ*o!`+0wvT;n@J){;|_}ik;44VO?pjBTt0(N4LiS zj@=B)oiOWbSNUB~^uQD6B~Rwz#2L@fA9vy$Fr}kIA zgXNS$QeH{VpO9#CW!x3i!SS_nS->r%Op!t?wo3^l6C_M}g>z;y<*j_fk52vie-NF+04Scsq`6GwmQD4_iyfysZu6>+_ zH8CNt<0OQOl?sUXaa#*+qZGn4i)Lz~oz_a@rH}gLbm`p6HdG}mP0r&(yGG_mOL}qU z2h6y43TUd?+^8{GnG|>e^2kg!@YXP#Qe5&H`Bs^+#(&G&GQXaZFas4+#mn_;or&#s z2hL7xh9`8zIMh*;f?Iq)4PIpuYtAq{jZgkM50Y>M-e+v~I9MmaD4Oe-a_ATZPEbDn zuxeCc5jD=Wl*ljJ;!Gi@r6AYaB)D-`H{0>`wTXv43U5!cAh9AqW9lv_>elnq3hW8K zNBgV|lYeXh-W;2nP<|%isCE%v0;elnZlFJ+oMvr`M6d8FdSh2(^17Dm$~KRkY&x?X zDC+;Vy*jDg3x^IF{#f~#Wy&i4_Z3!oru5YEe^ZZ!+Ot(D0!mZyJJ2~Yoxe@B5E&J9?R$?sF%EU0E$2funB zhLFyvYW(NDgf-dri_#jQB0kjx*qG#2UwcqYcD|0aX80+XUkx~$xr>kgCIFAyPh*z( zL=qD}xyu5$3aLj_;Ihm%yExNC)eI}7+tQkV3(U69S6{xv*h(iNt=?{6ZT_Y%*^8ro^uVG)nr;Q3b6bKLhUkx$oo3i@eaiwNi^ zoD!oJ-OL8+TanG$MOCAks`3;>Q?MRJGcD(xm+1BW`&&^>HL(oYbe*T5n+EnU!m%aN zBAsQt_*TR-jVwbxR_iGU$iO{}ghpq`Nq;(ZW$#;xI&5QESx1$gO4t#!hfz;xQ1J5c&=MzMatA8mqFCPtj6U@|cQ>~LKBf;N(wW8OlyU1+X$amaSBE9LByGU6#7k`cA z{9959tDuAZnzs&7%S;c-H(f!4siMIA>MpLbZKF%%n_jF1R8Rtb%}WQ?Z6y@_{az%_ zDoHa$K(Ze_FAByJhdCyWetEkV~ef$8jwwakF-?$tj*7hUE zm^Ex{FZp(r#>5(C>Y}G*ThD8ffU-Jq40sd~JABBeU#9WRv^GoPnW%gBj2T;Xs1KoYgh>=k+)y9p zWKl>)ts}g8r7J)*#w5N$!Fehc);%(#?grCooEcEH;6nTe#1GvPHY_c_%SI7VKvt@U zXPA-}vZAY`(FhXW9e)(c+JDLZ+dXY24rkdI-gJfBPlvmMgT4RrY3IPoJ`K|>_jWF1 z{FFrUpvh9QWZal#V9BG<0zs z4BcFg+l(+jltXbLCXE@6aR4T_QySru>p0HFCzQs(Papt&YN0CMK0Z6w(NO0XVJ>kL zU0w?0KLoQpYoxPqIG+Rw&*aKXKAj$}$frkBI&gU#WPxnnG1f0oCK1RGpSeqiX^8`HZ#& zMUDPn1k2h66tnvi>?F{z#AZqpAC zWWIi&fHVD&^6n}70U)r7@=%>#0B+Jc1y$Ec7Gdxf)2vUQP@FTR-6vX zrRK>y2ynOE#-E^rxB?dTkk&`1i)zt)@;)Nq?Ogkh>m^&zy-)qJ^`5=>YiR*b*--|0 zJCDNSx+--PUpJNdV!CJ)ny2iZgt~1v`?zj7dX}$yt}3RxSy>BnG`Wl|*-teCa2KySNkJ&q7sd-f5+sMbpog6rf@Ob88n+imL!2tnJ0 zLQ=@x#6yUoHzMDH90Ytj-`*qFJhM~sE_!SuwIoUGJ=hbIgaO~qxA$ndVQ&%(Bj0Ipxa&XhZ6B9#&-geu1B0`*cjz4`g;r5S*lIPStQT-;AVy$eK zVDLElF$CHzBvdJw;24%>5%54$C+~y5DuE)0R z&)0RwI)At%4RW@{C*}ql{X(69mJJxI9v0N(s-}-QO*X$op>#3tH42&ODSuk-YVRv&pzwv;Q<-Hm z-+5fwe4h4@!H;{a^}u_|!%LW&QcikmP>v}HhjhMjkj_R@9_M+-Q06gS)8~9%R@1p` zynoH>BSG=Hp9?w2J%%byt(~}kc_Oj=A zE?*DdcE)<<5g4Sie8R;XUGiG;)qiKJIYPK~`02wyWZPV*LsOVW^njK&1h3S~#!iY_ z<7M*9r<>*;9TwhfJymR<=V1Rf>##7K8UURsZ zuYUA#|Bx8Md+tRXj9i*&x~{^7|fyte$-*Km>Lwgk)oaS;;d-v&N zZ}4H~$c#E)puM$Dj`nsx9e==Mo>a~8`YWt=2oL!l*o~Q0)?4L=JrIWl4WTw())K10 zjc;(BrltJkw4nzQmD8D)6Y|o4<+^2Ca+)ezIX>Bj8=bA4h8#PMY{7B3aTyrEFozXx zh=DAR|Auefk!=}M9$U+bubk+Z7Lv+!=tc;kSm^yXvc%OJjr^UH(0}+Nwur`|@$749 z0*8)sT#HdRbo|O%jI^QakkxYN8s&TG%%K!=f`-Sfs0BcQ zKXO2QEMxX@pxoM90F-pB99ZMG(_-H)Xl)kuaD!39 zEOxLxU|Q^(GlXS7_R`o^*&JHuy+~TQRGaoWqjSE|VPT7TXMc>=u&Ax!;)a+mXo(Kn zt$`cRxFE5N*?Hhv@#3H@7lD@kvM$IOi+2f7rp|8ETTV-`WS#Ol1rezb{f2)-Zbx-O@<CA>@P45@}Lq~oKJ&|{GxLnjg>#4cO; zJG@XGo~8J%tGc61 z0VdiI-W4v(35FlV*YyV95Dev|LsPu7vAMa~?W}uh<*e3pJu4cn7|WqTL0iLG;a}$% zna08pV+z)DSU+LR3k7xCp$$Bu`a^hIZ#?9e)gYAToTbte661Ss`?CKWVzdF z&YbCTA#Mq9h|jpVxspve5m9AX8+1O!{IdZAPAV?-@YFJ~5pn{`!Ui|8gsZ*VZ4?MF zgMI_|h`R9#U6>hy(;^HX+4f!%i7d3Z0Xu6*2gq|9-Idlo6$ zc>RiG<{y9S>hEG*U9e)d`0VsgBrL`G-X3Sdd#RPzSs^N~y=BX4SRlGh4;#uXYjvi@ zI`Wk3vVSFoAlg7wgLj2RS#`j&i>Oi309iMUUBt{?pT$LX+_twA(1zJs%mkNf|4X%- zq&;@;t$!g`+zKr{BwC7su2*<%sCEKj49C%AB(i_3!}?jAM$!c1JbfVj0OKrR`FryT z#Uj>F#r8>X?9>$bKRUrcNu>pmH_>TAtdfq29u}q1g$`6={0owKn$53w=NO!u$IDQt z8R=iYoKJ_$+fs~+K~F_$r!HhIRlQkz)}fd=8WmQl47NrtPC^y^OUPjNCCRVZ?3KZU@@6$$7F<*)l`qt z6Izsbgcw?%Bc9}=-yNRv@}+++E8e=zSNMNi zTH!8V;Y(?Sd*Q8oDMpi*Vsn2$N*M1Hka_Mn6%Ucw-O7^I)>g03+2SR)twGT$ z$ld_TgJdtfWR1$Ou|xK1?(LafB!9J`s3OnzwCFDSrER-~nd7>g2DazA)c>68c1$mP z${Usv>bBkZV!J|&+O|J>hFmH9M++*OpDt*5J&b3Z4IXbgQINOYl_86X=Nf;@ch%F^ zpPd_ndWFl4BFlQ(f&3Od&3E*3K}YY3J9_s|+0icr9lbB^=>0!cN3}lWpQb9CPgAXx zJoz*=+RJu+>-jWO)o65f{6($HJ33+OjS%~Sq7}9 z>@0)4ok!s@9o5@uUz{Rkc{5#P#<-{Kp8~t>wEUQ!<+lF5a9yq$kwt$g&RZCtG-9y> ze!Bpp$1|~Iz9{5n%UbHPv|~zrdd}tzY!~A7s7-@1#Q35`Dl;(KF&NA6lkOKJ*lnlf z$Mnp#vDgNj+;NKMQg^VCkt%|3dD+G>$5z%Fh2ZWRr=hbg z&7b92hmnnvuuR`#%i3H*Wo&)}-HV^$Tedrkm=7i8LhB`?_NSw_JEwbtHy=M8zCB^4 zO^zE`)#)jPJesyjh&gu0nzo*p!$|1N83`KOF-D%8zs~nZ?jCboPHTnus;SIL}D3vWNG|S6@%p z-M$xeKG%EfKJ-7V#ttBd$X!SJ7$(8jFcGU`B(*7==0@rQX)gvmr=p<{q*{ zw1cJI4&`rrvYCNvACwE_ECRjWa8zR?U!6$kx0CRQdC3hJh`Pw zMc{MfYB{6|7bv-*-!$3E6Vcpvk#vlN=AC3eC^4jNmKugmNHZXwMuC&m#H_V0a5jwF zZG8?cpC#uFWNYq(3lkl^Tj`T-SF?owGY>}W^B|hado+LsynGg(&CMgxVg%2dHDKjP zBx`@adq_qHTTlT5F}Iw$J#Z#vH#?#A=Us0ObMUWzrhrX>;(ARC9Z zYtfhO8eBS^BQr^l@!Hf-V#)}hD4=e|Y}1QfHS^@5L2ZgsihBq%`q}q585lROB0T%D zjt$Ro3@?Sq0}vtrA}f~rwH8i9d(*1KR%3rzOl$<3p3&F2MAzUqZ`K0A8jX_2EP3VQ zUGV{9bqraB|)d zj9Q;F4Q|rVnz>-qaf22xgO!wZW17q1ZGIA~!y8gZC=ivJJ&_DdrKe3w=Q+Bt45EL= z%TtmP+OifTB2Lymj9+~~K`h;*dTnvO zw%q?9;Ftvfw>LP?Y`7$DYvUlT;Vs(fl~@_FaV)l94t6<^55WmcJ8<=c-X4EG6swca zl_ue}5MW|3@ze|~U>(PHdfoD)tncc)5@K+4Zqi;UtDe1Xyhj(Xu)XWb$A1E+Y z(iwo&?B`sw{6;IgveS9eX1`Qz7FvF~W_hawf!{q7x{W@Wl++PPcXrYjk#sL0ivia+ z%8F+IyGfTUJt^dswfsRIO@l;DkYni)C=U}N%zJ=eUGlW&so&JKP7Z%-{`y|=Sm+CD zrBs(WZFU$CDYwHGo_q5fqAqpa8@X_hF6t`*1>yCA1dQ@e{d(rpdt2w^lywF2sYR7D zkh%G5U9Vi+_;LcPa^qjBHok<|s@!;i@G`@~<(Hus7h$F&N{Z?G?Ym-U6kkJt>M*Gs z#U`Uu60l`NWWJ~n*2aI=lD_vopGIPnea$264T4O_wTpSC!tB{$>rdWz0@q`r4qfkr zrWqmv12BOZkDHS>5G2F%aK_0S=gEU>r>HT>%i={34%nsmO9JeOj(~f@^NT9-43FWA z0X-}gnA6}a1KUYx@Rr4?tlFo#RV-vYj|Es1*8WeQXy9_Vr~!YqalzwRUB!bBtERPF zr@Z~nlv`e)w4?YYhm_$c4_d662QjOvMlDyzLe5j?X@bW%XO?s@Y4eOevedRO7INGw zDsZ#yX&D;1tTAsm-z~8L`gk)H7z%93lT^D3%0Q5rvEMN!TNwI=B#ZJKLKhUXH~8-z z3dh+up8l|ZQagXyd;ekY@U$j=zTG=I-rLRJc@?DMD!|>N6vc}fxqeF zt)uSZ+zdr3Bo^IDVxN51=Z};Bqd^$KC@LJyHTe?I`Kz!*e zF(9#Zh=LV&!6CicUU*i(c{EH&!0Xtq?lR;>#l&9`xgUSxQJ9Os!ZMN;ICFwR?eA8O z0QT)?fKqh(8S-owT`XPTqKo)ce$l3$>tRMNO%(+zf9ws zDUKF;18;xV&X5J+eX;Y_%2Vt7a{RU(MtFEwwLb!yX(|2`@yx71#9GAiI8stjrf=yi z^@s;ud07;rT6qv~iKl@2B1meHrY(T4a>1CTH;y{lcLV>>I$%``MYT{?%SRlgQ+kTU zSQKE=ilH>43I4&f6>0XJXOn0evaCdAy?-;mykvh1)vH=Ajg1ufU_m%8`BOC@WWxZX zb+f3=Iz)|h0u`cx%Cw!Ai9Ql`mS-=IzV1o2W2Rd%o>ZCLc#a3xsxrHDfrs-h$5gpD z;2fd)FAq4TVSgbK0}HMQ$fzAM0mBB;>dAnY%=2Wg@?Jp!9$D?0@PjXuVyrY_?8yLns$Li%|JS%L!$` zY8hq0V=FqFJ8@1bbM5UBa=*d~Vz7{M(!y7-w5*(xl2$>p-m;QhMp~uqbvP@&+E}-R zBkgPR%U&X$#Ea-IUbXUbSKG8u?V@kFH(wM1BETOKhvR)+{L(bVb^geVc!? zP_S4V7H5td5T&!&*B!o~Jfvri^m;@m9Y~MtuL~{Tby@|zeO4M@_OMXM+>tl$Zm0d^ zxnpnMt4&ctSs|qti2)X7cfl)#En>PEd7wQt)TnUfU0}eU$!{ z+w>sZU+1ArX@GJ%fg2aJWEW-oR{ZiJ z#~yVIe&!BNZcp8)F3vKV@%!QscKpz~S?;@uE_r_hXsRY0 z>^s>V0)1smPjD#wlc2?A0!Li0;Z}jzqCE);yoS5D#hYA#4|E~Q7elG1-WwHt*dyPjbl)s}t%LnT z2u)j#e``n^3=ndk4o~*qAMSs>9S9`?_wf-~60H`V0B}QJIn}izs#IkJqTf5=$-L!8 znrP;G49_pl>A6;$LjBrvUuiKdldNb|zHO^!$i4v$aTTjV!M58SAxAQs**I|s?jyi8 zxbxn?7{c?10eV9hnC+^0?|KENg$)wh>fbOF^+X zW)A9N(S^TFv7$V$!Tg#RWd_ifqD;E*0z`@7N2;8?)qW3;B((**9;5Zq`$Bsp7%+pC zVwjzZ%IL{B5ok4Q<0kHghcMQ@Qe!M7%1X%3{13PTgobrC3i!!8@{bH^e`Bhy&MccJ63@7RuK5xc&*A~$Xo+#g0sl+b^myA{zR&>~8RH>0u9 z00&-kUn&76bo;j+!6GJgow^LUGN5L#X2S*ydcUUwZ{l0v7}?~2H79cFR=I|{{Dr<% zdcMC@_rX9&#cKT|0TpYRr*A9jSPA2X*Gpndlbv1ZUVT;THBgd`&$4rpSmIZ0wbnVO z`-rJd>53G*8hd|@av5dO0B5VjRuT_p#}IUh@RqJ83Q0AI@mTwN(VD#GNJ=hT)u+pS zK736VeTcsx#1Se1O>og#g(HMi{_Ix8IgKosM^anZKEqb}zWY8m~m+$kGvsT=IYVu#id7)wIrOGE3qtrl=4CjSv_O z!-2X^xoCQ6S^1oz9@OOwr&2oPW?%cAIT0$$LdtBqtWp#L#*oqELCKhxC#dvGawzc(EX z>ezoFueanm^f zcLF#z*OV)!7vunm#L`?RR$5ylW@=dd3~hfxgfwV$0osJgpd4O63{-@hluj_j=itvbw0F z3UNWlTmS;Ar*7N;Qy3&p7OH}(C%-mP1IdJvlIq|_(u3nfrVqBknGsFHEXjGUjJJQM z0BXC03s5!;iu#FJatC?2mw#cNukcJD@|By3LcMa69L&V#IicAlgn2-U!OPm}s+c(8 zS%85F&Qifq0k>a=5?xNlT>t5UC%X{|%UvytYr%!kGy=Gzi+3ZNAx?S^@Yq`W0C};+(S_hFTQF(t%RY6G`dHE$25HN0g>ol5e@ zdNzQW9h{BDxQL(6MGY~<&tmmC_tM&By z0sra&`$sbQfQZ_zeF>9zcP^x#=t;PTIZa(ge0xhQ6r1^oR%Plktp{sL+seoufoj%S zdQL2uoY6wyEcPt+lQg%P-qwE`E!I^QdIfrPGKpuhH`~f+lTo8x!H1zhC-Q~<_$diy zI|-PfSmh~3KU)QKSwK(d(Yg31!F5b(m<6GcOzV+S8=RiTReCCLTF}pcT8d>qaSB)N zXDm%bVlZH$Q|H=c9Sh{pcBsjaM|c8p(gKHHDM(1F*z(83owRnPV-SBjFh)~n*DAN0 zm=B_gUG?YN*AzqzKeFa~)j-OjUw>!v*6oLkbmeq_8JZc*NFKYCBCX9M$H^@C9D0bG z2Kos{F>4vlj#cCyRN_RHjPl`JrVhIRG1;h4eXS!#c#R4-urwr!G+9X69}aXIisa!W|o>6EHyJ&YKCxvb2b+M#OJC&@wr@m@bel! zWA%B3pA-D_E=0DR_82i7Z7@nbWwzls2X*}gTDFYo{DQ}C=2i{};Y@eV#jl3r<{=sQ zUdVu)hP;$51!9#7T(!5mza6~Yxb3?tufvqJZsm5MrA|Xy_f3B@V|bff<)<#DLe4bY z8}hC0R=53P9fLi>WgUD%Cp`m0e5=2;wb6zny2Q=yTG^S3ILS)%tP+t6pnu-P*#Xm{ z(`vuyuJ^axGV6FWKvRU3aa-DemU^A_-V2x_^`5Ljx`PXIQ?|PR<`%$Q?{9QB`y^aR z%qK{TMpJL1;J|+-fq<=W2=@;dJVD=Xchfg`qI2C|ue((=dMv+a_*fC|__emyx7u49 zNE=Tp>sFDZpdlQ+&3>=bU1tN=>h?D`+grZTvs=xI2Cv_J(eC$32TxRa0_lN4#NE__ z87?0wcyyZ%8)OB|!LH29lD=mvUhpR>tOld=7C>@)8J&O2gAh;46cc5+o}!7?+g%l5 zB}Zj#rlQc(>Z8ppGUYoC5Xv@KWzfLG>ms`l7)B(f=H#VeLggzU+T+1582HJY3SjQM zOAz^_Lz4$!d?BMPf`yPr4{V|eK+@YkNHS!}BHS{4WAg00(fk%ztJo=pI9FF5P-PHO z8ICv8hX{XU4E`x(EhyHsG>UpcqQbXX4NO(I}_icPLodod+ z9ogk2j)_3E?m90uVej`hdEuYDudI;#f@21k(FFGoP&pU+eXNm#J!V}#pe0haRThQO z2eoy(wsLWoh3N{~z6Gtu8vffL3&7dP!7py`$oUpBhHVLT<^T2bhl3xoYzE%VAq2d~ zjeUPBo{DiC-ND&+NVk~tv265lz9@J?vAWdZ{M(O*d*}>Yp9M(@b{uj_IhKR?LkKr8 zAo8);(@nFr1KgyqG^Ec$6EK*C)B4H}dpmDe&@TTB?sh_ix#_6x^bd)l$q*KfR8e=w zEr+@C90#<27)|uO|AUV^Z}$)1^V`v?P}6@C__B{3hv!o$kbNWAkD_mLQpB@)Gl!b#x;+$1ZhQCc)cewK&vDyF;;&y z`S01K@PH!WRK+j>KC%Y*7RzD)!9|>8J^)i|_#RF%N49CA<*AoaR%H z-X41r(G5wbw=Kx_V>2L#w3m&O4%dGL>{LOBD@H~L@Dw#1kG(?6N#9Hx(R~RHrT*)<~e&ko~abKwDz>tnKSI zFWuD7_0;JR5?=*FJuO#WYiglbAvLauU=ev!q7QLBv{XA6Mk0L|a*st>v^m&&zq9*! zU`TZI5w7iW!pQh{_O2`ks0@OB4Xp)a6x}r=tl40`jw2R zS`O&l$Kww>r-Vb(czyFqAK$$@**hJaejJ$UvgNU_{LcfbA@ov? zTPM3af?MD1?4Eu+mL-S&7Cj|L{&qbjubJ%7e#?5N&6hhe=!DXsqlM3vJj{o~nMk{D zXW;I11E|*YY=8sn7*lrk_RU^4c=@sN#R)zPjr8OI=H;<4#Ij z-YBNhXQS-=vyEL0^Xr`^MZMuW`|K>L*YVfuE~?k{*Xu2+*YnrwFRIt~*IQpyZ{1&S zV^O^gf4$8`^)~(Wwieaf^4EK@sNRc$abL(Vojk|z)9!*$Zvqg=BvGGURLWe}KzZGm zX;hY?Y$C`4TAzQ!oY_*>1)3ULmP|Ft0Wm`}acJ(-YcXeOlRke9SLK9rl+=$zkWWqu zBacS%q%okNpF%zWP56Op!W9mwe_1H9$9$q`&C=selRJ23A&YBRyEew^H6b3xNPK8) zrG~p%rtF~sN{V{2=Ic*4cqv8Ud#3Zj2rP=cMGfz7YGr@2vc+EaBOcJhO*p6x%1+HH zqOPgyQvs_}Gub%yAi*BU3Tcgu7~a-&Pgj(ZNiMuraaf>>*Fe~avC{0h3PkK!ls8Ci z=aJFc*{|*y2aGS%ul;W)nK8+V#)Fhqj#X%I(Y4?xM&ZI|0q>~i61{YI30ve~!B?8F zMRPj$=H7pB93=E0kmc75#YQ+cx?-a$cogp^?3;Pix{wB-p2+vH^6(3)K?A;elX!aNZKT&NX~bU( z+VE9_(gjuCL|3A%jsAkRifcogzUr57^DAFNUI>57mmkG*{YqA@g55x+Md?e8=7wCG z(EQ(8X_)t?JS=4&LsB9h-0cdc+>J*eUGuCj~LO!)B5$D>4yEb+wxk?V-dus#pSe1~Q z?4o~tyP*TOip~1ox{!0=Ysyz=E8kvunpo~6FaA$j`z0n z_O^X2Utf6_O~TrVAR&6!*6RQ7|NZ}pa_@is-~apnYpmo@XaRpWYki6b(54IW)YQjM z$Gdxj{kIF7is#8NtnI(`K({y;U&erD`qa$(gO6`^4hDONyC301sid9vllUT-)b^&s z7!2~28`_W!ecFFZCYDY~BS-SJwf(oXHLQYW&swLXHQ-%pO#HXyHr8Ffv2L}liT{5( zUAMX3^3Co4D2zofZc&nKsQAH@9GJ3QTgx4&1`!pU8lh1a$HQ8>+_ z%P33=Cu*-NTT!gNcer=Fb1J5fn6Q8EPJh}d6%Fsn?g5*bllU^b350xD*wp$KlM1`X zd!jW#w6{B-7YT-4xNLw|lY={WXZLd$B$cP`i?*-T&wD$^m786zJvpD?q<-&M2-+`Y zgrp5d4c3h6El9TW8E;FPlKU>P`9#we&ZJ5r37V8#vhXmWr2WJB^+kwph5vsTBoW4P zlZ)DMIE<4~S{0d2TMlWF$-7LT=&s9FYh*lGI2$|deo>=Dfu$Oi{vB0EywjGlp!~q1 z1cig}Dj43?%oq?(OH+Qc6puHb1u89!>@oem*m9~6`{{c{aH zS!?eCP_jG?ktS!l+mkJPuG)XX=cQYCK`nf#+QOG*Tj*~pDv`V>r4Px73Q*VA6=fDe z{ahXDMo&>=A=EF`p>E1i{IK)$;O7#MAA;N3&sE^PFz`MvfcLoqysb?G@5=&sUn;#rd9geZTAek&kNvH=xe?46a*WS9jz%M|v+Dg9w#mWm$x8HN|tGe<%Y{_$4 z-}JVAQfa|+5J)R8brOGvb+sK>Z3hGLc zvBGyAMDSoQ!d%y+Esr~`IeyCOq=AL7kkgjEHp7VSB)sU-%c%%ycw z>)^%8rRXEfODQ*HQ$}HHmt%e4A?>jj&Z`5eXFNnac(2&8;pKlB2pdA^r*Hg3x+x`l z>M2J#rX=>&Q!b@TuCkQwt*4~QW6zmTe|@i*sM8Ada0v9+_hJZn-za9MQ>=Ra`K4#C zycP6GQ!x(O4OAYMDC?aHziJ5J+U=YPp`yp-X3XN5VnWK9jC_+n9vnZwRJh)MoTc!1 z?_}@z$GzN=B(Q%`!tFQ|f4_#K#ao%KiSj15Z=VEok6DmG|0MqS?SW)j=xj*YNC4%2 zY`+{~+<;XvGIo`IWV7dIz|WCtRt)M(FNx&5vr*W105-Q)cuFkh53 z_%=+3Ni+kyMX5nXjYYTn4_j3<*1z36I(qw$Xi_@#RGELl*U?n^+IHKIo4k3=|E*>c zpVmJ?ZNs+Te=dRXc@Ye0FZogeih* zQPKh_ZPIeF&;qUZ-?r*_EEUF+l7@`NNKK}-`upf>IISJcCu!JNw&|1Iox{P~eIdWl z^!e^!=Y4-k<0r!aVn8M#1w({q3YTqg@9q0N-0vLhzyINM0HI7v8r&OQg}AAiK z434@~gS+6OzW;82cgH6kSzEg>|Dwxi7!(Lde>3ZhkUNL(_rzxCc<1mx7Ey5rfUbm_y7KX#ENj4)lQ;OSiFC@DWeEmExjh*xAuCuz^-e022)^@ z8#Rkh>P!=~iCW^Q&a9$lox%6fNYXjaqiONS6hu|h_XHnhJ#HOxyiZAh3h@bI@;i`$ zAnU#ZK?VZrJ1&h@^l!*;1j&l^4Fx%l| z@ZV)&&A13yXCRgA)N1jQhcUWcNe%FW5Of#-dM67=felM?Ao-(d?G3t$FFG!e+s59e zwX-AjLt}LCap68eZuLmn)hHdrh5LU7^cXZ-U%7f6?HuoX*gHMm-yOUy8~-B;Jefqp z+URyM^z}US&lREHEr$Lg5B*C;==TeuulE)Tj{ZXhNBQJiDa%I5QaW)~%Ce#Q0)}5H z&1buZLS|hlFMyi2&2KB#w_D(|Q{b~(;EPkBc=27YB5-@l3EYj|?_A*a`oDh*fvZk# z|Dgg`9nb#51n%ay6u9f1Zz*us*T1R2eX&sBt}i8Udw&Srf4som_y$}1Ui*)egg;Ia zmawy<0rI4>wH=QV(#n=;W^+Fj-QE2G{vIqaxlcuBA>{isoIJ?5|C^kWtpC=hBH8bZ)y`+Unm$}JXG}lVH5dB*+e?+DiU{VNh|d4 z{n)Sf`#ARN{T`0}`v2f#zx8i=?6>|+kNwua>9OC&;$y!~dnu8-^@qs)O+~JL)M7W7 zehu<>z_=IZ5R1J1_(6Y#Zc|}0cU6Xou09KraGFtB8PyYC2&lcTWe~4P$no8AG#S+$ z(2W+=+?#~g;!jP!N^EY3&F2wZ!5VxBvav?s)2IEntnKJFoE*d476osj=_tNwjl!?d zFg!9jfB!p(S_O7K6D&>-NSH?#Y6g(c@zmrR?^jmCBAta2yB2?@`&~k523--=0nTW> z3~`&L`PNM|!n;LTYdC?|XMTcjq>m{x#z*{Ep&u~8;0I%4qb5g-mBEGzdTX#S<*Cu4 z3I-)JYKEqsLDQLRlr>d-gRC-5dF-X9D5RTG)Xy>usJHxv4)(OP%9v3+Kl^|XE6H$; z%CDH1f}rw@;^BWBMqR$~DtQ22s;0u$6KXVS7_u+Bn}m8`RyytWzpa>bO@B9I7K|Vg z6Xdj4q7cQ7FhYQul4Ov4ZGY;+V%C=6`U8pe}Y zJ{=LYzKT^_2sT(>We~reOsw7)^DL~N)z*ZFga7FN%`f+R&H2w)&6Do}Tm)~;3$WRG3xP&QlHe5Bk<+`4t#|P;0`YGT z6{U5dC*gk&@$V*T)-NFB3jXR~z!NxWgrFgCA}4?M>4rGmgzRj>afbX2e_v3rlrA*Y zmA~O{4?5jZk!6SR^-N&(qv%R_dkD(aB(39XF7vN`ZlTvUJL=z(A8q^p`A8L|l$7sy zbD=X`>J07T@abE*#>+RXS75%a*i-O*63=IP4w8S;*?U{IJyc~};0Q_Uz?aE9&F0s; zLLHG0r^rPr6LMgPPuKnL)I49IU$21a4S?#_o9@tX%hZuC0}61L(PVNA!4(o2(7g6H zkvgM*Y4Yoep3H%p*+=kpQgEF*Q8LfYxm;C`VsSwQkCp^aLM8&WV&2se9CiCsoJ>ah zQ!#&$QbmOin9;9uQ7roS*1Dt zjJ47n-Il+hwZfLxikqUWLM0@zwT=WHy~aq!ijMdyI;1+!*LG^(Q~Hfs>u2+HT*rT; zTUq5!{=L_uq+E(=g4{6KPJ?Pf3)8`Mfk5LF#|I4kR`!1rQM}` zD~@HxvtSryclf62y0c=@>LfYNY#hvREgFn7!5MAIDQ(Fq;_p5D?a1_wOc#IeNtKrP z7ipDfP>iM^L^LK(j%PRU zFR|-Otk-4wx=dgHU19CR4*qV)^bMK5@w>v>haLRgly0q6XFur89< zzi+II+~Z ze(y)5D3#_S&a(L0$)`kBWDw3pJH(BWR;$fuIf7QEuOE+qI6wc4`I%zJ`wRMt+t>w$i6?^lp~=J!QXR{hJ$o z2)1kT$>CzGWbs#g-0$yyudVBgCjl0Q0FlnI+h8g-lK9?{NN;sC5KMneuyELGS_3tO zR95*p+3vGoTE`zp`(k(0*=mc7*1C@PC(zgX-jtDd9B{nKt+Xy z_*iSLdj>mTkcnXzk9Dmm*RZR*krsP~UqUt<^<0aDQL||BH5oA({Ta1v3k5uU#d@O6 z1oDk5N-dpaOAnhfW_*9Rn7t3$g;p&@95k%Cx@bu4@nl2EV{v}<2jcu{%1|@DVw7V_ zPSL88F9+$YO@E661+@3U`LC!hIwXrUFOjr^0cr!`EsB^!8pF8R=OUW-eo{}p=A8bogLG>6mAG$tkRKc3Wp z$Tq|AF~q*~cm2}p`K8tI;!ZvtGno!vKCXW_zdap9`DS{k#NBV#MQCxGA@i6{CYIv| z>m`X~(@m{k{dRx-#3r{nK9A`s2v|=)VbL_bluPJu*GJLdw!!2v{gaD>r;Bn?H@!3p z_ixuxYIEB{>7m`tVm#0_XTYdO;%TqSV#mN)OD=S3g#jzDlE_>wYhALmOH3*_eWsJ% z@640JIbFSut>W&08k6v=olmo~BDG0q=`?*JM8`Yy^eca!ebCdY4fB#If4x+oLr+Xv zi$7sG3MXL}sxO4v_C2J$0zKhS6d7d~H5~dZ0d#4@k(6&;T2L+*00H60p(s(@BF$XG zq0bUPC|o!sE$v!TvDdKVcL^{tk2xqQQd+1=YcTj#0)!?AhhrvfOKmDNG?icg!nBH< zZA8(AXc~VcNql2+-^B^+B3x_)7pP)@!xjNjKPWoqDUZ$bit^h+tTX3 zu6Q3~W1UJigWvmp?+;z|4_);SUG?{?iQHCJ zomPLk0b0=RD*Q>rpAi16nTNif^whv_tT*OuN8l_knUJXSQH}?Dn5%xBpFd zut3qNGt*0UV?IF_k`H3h$7Who5sj(~?|7&YLse(jYg zCD0}T4MHZRo4jyQI0>iZ7}9RDUj@59@^^oTbP z)bdjTUM}(oKE%swX`E#B%lVYZXCRwpd=$~(<4~y&6x#s6i(y)bq9id84=;Zxw4zj9 zxoF_DjNx`{kWA|plv2E3y<%Xj;M^@9Le|`GdjoUtD+CsZ(pex> ziq(Xj)Z5T`@b-4@?gkNb1LGDNS zFcTaf4I!pM)4HYm$j|Sd3YNJN=t5Oj2zB6`12hmUS^%Z$M$@puVu(=nVyHqsm^*t} z!$ftLVa@Hcrcfy6p-_f9`K!y;MLreoBF#?5!6?2-Z7@-bXTg6==LrnMvswpx$}k5vzR7VosZCp_3L zKUJYVr__IEiC2T2uP8k!e>|fx=in@YacXIRT$!Sshc{*lp3ULQE2#cWz+wtb=!=a{ z5Kl#K_;;=^BHV%U{Q`Y?HVb@{!0q{JgTSG!R5r};T7CwpaxAF3r0v+jq++*xdmx$a z_Rs~ccSAFIqM)qnJgyUw-g84m+vIWcV7}y(VPSuw$XJg@PsOLLYa0-TME-{#fJk@C zT$SZgMP2a43~P%bpq~n&%@Zr|s7B8xM0KVSou<6ChVVW=;R>R`ZoBO~er-PV`y+Wp zbo;zzyD2dcoDOA`pO!KPf$hajKb~0cmZH^Vo>cEDQtI;C5bE7RIz7gnX|XgMITGdx zBqD#t7_Tl1_3dn*L`-wnt~GEInOhy)*jAg`Yw_PU$Rr~S!eQXph!RmOAsdler}5x4 zb3B_{I{h{Ou#HQT$m0{;lBuuF&+S^PtsDI7JQyW7PEI|O@!I+lZH8-oH>Oqoj>`*L z7q&a@7pTBp2={V^UFO03V>>bk{dbn0~1+kl1kb1uaaTR9zsb+fFNwF)n|i zFmsTX^6e=x2awww{$ti`O>?hKr;prKY3!k|C}ccFZCZa?waHto!;6&y>{bKVs|>JT z4dA*D;BTe^uKxp6!1X6o0gDE`La8n*RoZB;61aY)QtO^Ze=9Y1{ZVQxoiCBbck-jaWw=)KMs*@8=!wEC&l&?oFA!Q8f5cuWtqI_vAC z&NTfr<*lxA<@pJFtHEx&?fh1LNL&xGmPfC(lvc!L+>^{c%DdxhG8FJPz<-Fp`~%IW zs%>uaRB6&tRef?Js^zxl+EK9&7C@ygwIulr9I0Svj}7VQH;XH6Z1bC0KZ$>H?tcot zZ*R+Zg8Z1jE9i#|Fjlsm&G>dUTV^|(neA-0%yu@jwzFAoJImiDnP>6kC3)u3PthS0 zA*-)v-aHGFT~nBU0|{Ck<<(DM3M`>n1xsj?ht$sm1A9v128x?ZEA3w&Zzip(QU9~= zd8+OR{#o}%e`q*=XgL4O8V-N*FbY~P2V)N7Un*&Hua@Oc$h!!0+iKx4J!FfFubV8} z^p)4KI_#`qPuFV(cst+L<19FT9LxQ2EceH;++*z-{;;Wqjj3p=#nD4cs+!9XWrfNO zLyrm^TGH$TX=uGRDAi)UDO2Bn(>vj}d+&BW9h?sKY@K6lVBxp!YtGcRZA{InZQFJ` z^{%G2ZQGjKHl~=`wsCv@x%Zx&7`VSU)ide{4`-y?AL<=qpP6)R*2%!t15 zpu>y%7_ySgVkR=IRArE*W|b0_JUvLV`C!Thr51-M zR8M?ql{27FJ&CYtYEJcQJ%YL&=JGy%Bzw_gFmbv)S|>hfeXgpx*uJ}TIJ-0gPhCws zu+`=z*BeJ))m>tm=#^2E6(0n2i}pP95KGvvsPaizK384w08 zVeQ;IQ|5xBH%+m$|F<4+TY-EAV|w|{MOK=i{VT1zqNu<^{Np3s*5A_6(Rp(yA?3C# zrzn|OIk1uoXLz3W5OQmf!;0^5uyNj2gUIRIgGlGq<1tcY?A{Dp61(6M`uBv%qD)I% zJ?91j?H{1jhh+-D7K3Ce8a0CNnF(Xf>Ap`FWiTtcil{&f4;b@k=KcgRTT-qNK!d!5et&MO2n3p4yD!lAtl zymm!UcYiL3KfWxu+1JnU<`6ZBa1k}1KcLH@KKI7f6Dn~{`!?c(AdUE2JfAR0NO5WD zg=9>aB_7_410s7Hi~n?_Kw<-aF1zhgm^wt&>QwE_!^TO6 zP5l1`AOEGy4eoW89@)T0BU)E9{eS>KJ|z+sxJv#GP!v_b84iGEt&cCCAD&bnD*bSx z&VV=~hrd<6o3Qz+-I;s8E!s%vyG>B927tzQQxV4Q1?yEm(KC!$WlXJ{3S+2^@QUyx5;J=0sx6(gqt}6CH!t*1yUOf#gcKf8K>sMzmI*n0*V40Ey53nm(+q)3%S3tKjta z(=r5pR_&Jvfz{rF?mtN))X6WRRvu}nR`%TEngN-abA(XheZS)_Ux$15ZUm>b-ANz4ik21V;Cn$g1Tjdm0MR-> zB{vv&ql(Ibg&r+t-aYH_y>txC?-jZcxSFRET881A8dyU&!&mBUyz$-DhK7c9rG)Ux z1HA!`8Jm2v=FXJt%EOMTyOpQI19cmmipqSq4Py*rXDB3I>PdS)z9X-(-G%>Bjcc$T zvHDayT^gXX`8l(`R~hp1>KsS$2p}862L>34kpVSkhpDm|w11RJI+PAOj#ZA5)sH;2 zkLkrGt7r5h)w+`IMN9pA%B0v}dNw^k{<(CLOO%|_N%FxDheI@8X$J&<8y@P@b(u?) zsdD=|Z3+ae2T3@i_Hhu-%{?RSh5Rtp)tsDgfO?*tK!=2bd`6x~I(-p*0N}I{Z@~9$ zxuKmpb6rhNA$@9gpV(yUu{*7b2J{L zt>?f8{+|425B|THI^@{42*OGzGV}mG^4FILdkvAu_|@OU=CfKYaP@>X^emYk4TXlsHN0Y%6iyk<_3MS@>qg;jW&Q3HUh>}4eBTIy)+0L0 z>G2LlpN@kL4;&+kFr8aSIm|PJy>CkQKySgbkvcJEyTe~TsE~z=HR#vAN)rv>ci+X^ z`7(Jx*9v_N=f_lNo#>lr&F&Gpv=V9Q=r9PkZE7HmgxhNozDpK?v?Ia3-z$!;>HNTH zDrjeui<=xHcJC$^^NWrk;sBw+RVvA@ag$-@(jnLo+Sfb_lwyS-j_f%Y3o6(?5P3|= zE5TMmzP$ zYn+5w-cRqK5S?#|W;2|WHnGrxy@K6q7?Js0jd9$(g8eq$T1gBsL;H;mp~t-#1Rj|L zOduY_Ok1Q8*sx|Dd*(Q2uy|p$fHx>*QVeb*ibL+70Du7mw3Pm~9>cRjKaU6b@-C^6 zKi*e8eZ$A8myXlzsmM-r{Jh+RG_V+SUbf!Xg&Hm%S4O2qhnHwYglacZQ}f)+PM1}sBA?fS_Nh2 z+ag`X2|$w@4b(+ci_LI}G(o0mE=stnG~37vXu)tI%zGP|5I@f}V-TC5$?h;`Zx8%8 z__DJ}pb|8S+<2h>J~CpUeWL#ie&UK-7^!wFdvq$RHq!)sUrbq7{uj66XFW%uO0Ese z80BeNrRM!-o`07O$ZvTCfQSe30xH-%Oj6izXsW zspc&irPJliL4{SnnFbT4)TTOGYo?nY(LhuC_fM~j7$Gp&V7QH21V&7D*ws~kFIUfN z^KCjqtSDMUqLZs4 zVpATXni$>($6u6R>ky};7#>}rl9<1vOd~bxm=tbG^}l5hohvJKo|+nys@w#`2W*#y88m1%lxmoX0-yNesbG zw9FSr_MhO58#(wZFPPFGR0C6*kmu@5Oyr?FVVPv7ttg>Oy6BKWXqbew*$CY_K+t1I z&YJQ9yP022IBMRn^o^znD!@qB9q&T*I_Utcwz3j(1rev?s3L&h#I(XsY+v51o-W7^ zGbN^ps`cfjKj>c*NWiJF?&kG-So;8V)^nf>oqoDm^=Iml`+G&e8JDc))UN^%=LNL( zOnK^b5_7tC@8XU2;R3@Pkmh$+V983i=8qYfyu0Heji)XDFKhra#>H z-p9u=nP_eyZ`$h8Q71pf+}gf43-|d#b>qqfep4RfiphazG>&qxMdfHJ=ZR{N%z6rS z+FEtmOJ?@O?U3lN@Nx7u&OXHLE}YqMIoE-snY@V;qy7IKfW(R8pBAUYE-y&Jhurb} zK_}V75`-)eZF)tB*of0xg^1XACF(>mJWT?=aObKtEjRi zO_XWc*79HGM<1!KpA!uX{l7!yn-RD+-kH}vc&3}hWojRc4^&?r=Z||?OW#|=ep&=- z`IxQvUd>Du08=JB0%|Efi06UH8jw&2QGpQ@eyB-elQ`q`=r&s5mZMBeM; z>*vV7=Vp?=re9R}SW>&-w#B%9QRc&Vx{wQFgRy2(Z!!O)NY{iEKC>#Y`A6X4{T4}p zxnO!Rnglk}&)hV|pki>b=N@r`OBkzpYJ$7UIez~Zq=EaBzln4A(qU&icSPcD@@@}ZXw zY9Dx10s2-Ewf$AcY)!ITN)i)tPkA{>X*Cry4^i>iAQLvb)AaS~r4i*6zH_`bQQB&| z=8?Cf>gme}mq74s!O6MOh>G1RTI}Lh|1L(4^vRp_U$+pBPN#_(>`^GH(pXzAj!El& z+~4Np9HR3bf3)CMfXZPBrCAMzgvobi3!kO_1|%DTGHdRaqCs`m=B8Czg>os<(rM7e zKrT6853rWYA+xsH=~_qLo@M%wzGiZZ)9pM@AaF*>;~X+#FRGjHVNAf7M-2L`&CNap zro1xQU|gwHV_jkV9uiIsmUbeS#Smu2i>0-!uO-9X)KN?}*Ryon-%#deSVKZ*bgD7_ z0}Kea7{8zRU-Lc)Q#tT`ROy5eI{I{<$livmv*fko3;C;9)lSb zM}(y@6q=HkC>++`#N&d0b{aQf=urs6rs-c!QKFU^SAawqEhE9O2bX-`YHs*L+S9mv zGVEr%uiygZdkfN%a?PfE$M8xLzHhHAqVdO(fAr-)?{WoWzd6ZIF8PLaUYEGKQI=sRTs*6=H2K#- ziX9t$U5-UI*fwBct>Hke-7Nc*CcH}>Cnt-8x9YiBD0}KK9Z{?Rv9~hYn1(lkf%HJ0 zFa~ks#X=I_?t9~EwKu1O5Jd$7mlKbWQ5)8#^TqbavLjFd& z)^jssz5x)X?>B;DqsaHErIHDUS7uhhz?u#WS=sJ;|9P-{8E5P29kNpKbH{a3|2r-= zBkrY4z8}0ZO=)V{AlvW8m%%1+czJT1y(Y2BLgPHjks0Lww|H{S({=171OSn(AVAY> z?nP_2E1)7LT1z*=Mii9bh`n(7&w?ZRrx}a3a$Bfu$aTh#$p@W(W5Y+!0n29(>0zG{ z;;md_R`4eUoWIB1f8t`2#_ES{J((xWHl%gMdI=#{V?Cd)#Z1fn2>(f3f`cb{^O-5J zi3%~L3&Q-}nk;1#sWQ-A!G*1Bf1SqmgiiW<<0_NuHB(}I#2Ej4g?-+Y#as&Z8&(IsBTjze}H}KJ-WnS>m z`4n=7WwF_vIbcNW1SgypOoz?M$mrjtqg~OvtECL6@qyAH#{y7;4Run-I^fj03PWJe z@gb!~tZaUMh}m2?g5O}K(XtN4AF1A_5CR8_tukvGeXkFb+h+Ob;w+MMw+=R4yrQbm(hIUH zsBlkSO=UvOUJN+s@3oLUn-#+On_6)vSe@#sE6ogE%Pw$kDG=-9NsOQyEwxn89eU`y zQRIGh$%fi|GWwHe2{K2e-kcOTSHWJaPRB`Wx`d=F@&K=`#$c%JZazt@efXp_QP|li z7?o31HT0gfpLCYSvWdfwH13cEuHvyo=EBHv<(npoSeDtDv=froFNOnyv-YpB2v^LO zVdFW91A;1(GYdQgv#lDryqiW}Ry~kWn&|d%HgT{t7QaMLdBZ@3)IKZbBTuB(G)~&J zb<+sOE`aTNg0EmwYj#rJmChblb(2!DNWymLynxg=&$V3}DSig_{%BPj^g}94ananL zUEWM4piC({dh6G}NQ)YV{v`Gz0aSOU-<_b5m0eAJbPN}w z#-M4P>ds4MfPR z`9LJ^QTwV+R72u4v7$<(BwHu9RK9hu&Xd`E@5lBAEPW;hjpe_MR6#oB)PG;N?o;v$ zbOpI8QCVye`HvCCTw$+@D%-oFQ}yQNB?p>r5OP7#o*3TPDQTz0&7&{U8A@nuh@fdH zLtr5UJ!oo8DR=xn(ZbRcD+~rAh8@)2Ai#j0hsI`oZjbfyCw=jQ&X=sdq-apJ1f}V> z1Kek_Ew(@pUYYj|OH0GjUAT=Wwb=<<)l>3$J%T6#BV%=iCngu&S(Rl&HFZ6N6#5B9 z?p}>%UupFg9CPwT{oAVAc@t*B<~C)y|I|V`x39`Uof1gQFe9Qnath~D5?JlQZ(wPq z%lq}$SvTEl?7PnextE<2i3Q<+nIPJh{#7$sR!)Y;_VrBxfDRRbov`SHg-_cEmND6Q3KXYWr017au0~X$IE^s)N_E`KV9-HtcC03kD`~=bTdO>mWp;DG<7K#iWSlSZZTjJX+1Z(r;qj$S8N)d%#ng7wgLEpVdj3I1#g-v5rNJ0Zf4K{ z^PH)|g+*e+zQRmLmjkz zL+$KMsh#XTUF(aEo1gp7D*(R$pa*omryN%7 z9O`!o3N8v0(~K~|!uNP@dLsOuoSz-uw&4Hf8rSgoCVi7~{9F#{m>iTc zdp`Px@{tAEe+96GRl6p=03YPK?|+^y^>Lxt+)RJK*0o|aZDS!zKpL2P$+!gQ#d2$exA_P?p0N?Jtwfm@yF+LSoWOqaKle&YkDJX294Uq z2A>H=EXwe*qbj0aoagi+`uYgIG(`p8sUTE2OGohBc>)?+UuIu0m_4*`LzXB`0X=+y z<{E2u!#>WE@&&a?LHRQZX*!)98XyvS9Z&a^Hx6k$B^B-%o2l)8mx4D zINz!p4it!rkXV`-v~agAQJ4N!xuo`B7qb105p}qKn^&?=@!SkgRv5?DzjO7w8lI0_(nM2f?T$g0-H@S-irRUn_BB)FWDzaTu#sv;K zq%1a`QZv?si%J2X=I_4ffe_yGjq1RO2L@32@3PXzvZfO&Qvh>wb|E2k&@LaEc4aKa zU!f$(+Yz_?_NC(cq6$AYu5&!!By0d|PkYiQ1l)&p*CiLWTA?ZDR)O?9sDP?r?1Lut zQ?MR7#zAZNG;lx5Wb~VXR31>sy%?HD&hE^N>>nMlFm}zG#O~v(fOmpBd4J#hd^0JRk^+DV(Ua9p~OA%$vW%NGhV;;@XF z+(0vj7?d><+keco%dBvFwDM2^4p^AZ`|EDHZRqaI(k;jrtb0V43`$RY!CK(94=*j| zGFC^Mcl-u+u@{jgHC;-tO5tD7rLxP~2hMOP@v^e$@;%qjAl`rlQ)ITRRwpxyc96IR zTx+qY3@BoHn=c}Gkl zZK1-)7|c0FyR?&f$-*Yq$ro5Lw5^Hxd7hPlZcFSwOut%mOqKXH;s$9$Nn~9;!hxAK zHsrJj-ZTkTr8})+ihm_zc1hM8(*{K?OYoj)VOQ=`l6Wq_#eQe-SG~B3#e9PXscz&* z*x-(MT*+Hg@ayA*^am|dz`C`JDCA|Hts^T;w+!n@HzFnzVMdZ%Gvnq)ydH^K#4rN& zrbsH$>0C7p% zAg!9{w-SX7*R4XMowsC5k{k&!aLq*MCP9pM9fAKajQjT&tlIPiaH9BA0DzxYb?DhR zuk5<%{=mHG57Ow;Qj|9Y6Cs}`-nrFu*|6A?g`CP<+%vprgoMaLwYP;gVBOEO-8f5C zeknLlfwfBK6{IlH%VQ!lC_VW!E&r}>N-JQw1ql`;q|0s~T~tt}L_-cw-M7?4NhNisgZur*1~Ap>8LSp*PRVw)@r!sVIfYVRo^sQ{?vQh z93;v8q=l$=T16^0^aGhf2JgjS#`aZ(5{X-IAab3p4TT~i{7ba^WF5NVj&;}s2MzC^ zAjOvJ&}4`XP$_*ie_kBB!ZbQ~>u=xDjY}vg7n`u1 zRY3HgRm8-+N+HPEE7g|@LH6{qM|OV_b#N!rFj(3H!`wA139-6C1kz`4$|0Zd-3eRi z0=>+WonR%^YTFqd_m>+BEx~h}hKEkRADyXL0Nq4heJ#qRL|Q=ALSjSJg&m3^pVPiG z*4&ZtUQ*w#Q~)*3X`9m570EiiI$5%~^8P}8a#;GvFFL9W$n1GR+`Kg9C{MPzn`6Wn zC8!P{RTMXNsidLbKulDK1`SeF89#(HDLrUMGismTmqkwaL&yoih(9bOOOh+HFEC4C zTT-yLX+TNE=ek-(rPM<}WP`RPi}0ewm{~rCGJH4|Spc-HP96VG2AVANxr(Q1j{V2eG-tMy<%o>} zEbbZ72HVwqR=F=n7jxl`zJ69}Wl!HBwM>j~4%1nbI%yi*rMCpfr7#&-*jY$EVP;QY z{;_BWL54D3@r2n5s*KBL#3Nm=PpjnQv^Iz0j?*WOVwtFn$_sZS3MhdaKOvco^z5Ks zqiCDT(8T7R*LxbUnknl{wY~JJRlC>TRcs{Yh?Rc5Xc`dB?UAoytD7cC;~`C-hf!0H z^bn!LoawkMV0e|3C7_6e`Z+`mV&o3s?q{uON^ApY; zi>lE2bpyefzLv&Ywwm;{k%toD{=`8+iL8cUhF}@^eQnNgW^Dj147~mdao+BE-T$`A5^8LSg?nI^ku*Uhp zC61gM>gF{dq7^)6zWgpoHQD<|5#e+zYdglZZ*n4vSI$L^aUocPB3_m?fu!PlTTk$o zQ>lV0BaFy*-SoRY^=y++WE{)a6A)!^PMm!#L;9au45xY2IpQ8J5x|Vi>U@{47^0dAKvEVyk7X02koSpPi zYXIGN>c|@j1(xzHs?lTF$kh8!#(H!xEI4!RgbyEmy4at{ULT8`%x2(o<@BSmX^p@4 zb&#g%L9Tg&un|$-l&?+(3ViJ<)t!itE%Ez3nX24J8M3R+4$GQ>2tS%`hUwK_`i=6W z_|qe5Q@M(>;Myi`b+OYkO>+Z0?%wu_ko~Xj+mDiY1{?S|8J;D}I+@dx#zcFKk6yIH zBPSlIV@SzK@#9D^@J)ct{;3K?NIsL(VybQ|Y|x84enmCSK|b=`J!IS2kcRDf5G~v> zB1D{TmesKZqs`RK6?O>;E&QMGFh%MDJ+WlzuVW~_y;N>eE3!4bUQ#n_Ee_FA(^V0pGU|w-dfP<|bJW+#lD*X+;{%0O zM<{6P@aXN`mk7g#^(hA#ORob?>}^gV?UunQ94eE^-Xkw`bH^CJfvb|F%u+4z@KpY8M(jKr^w;Ersf8a{MGMrx_QJrKp)^`oX`a$1oQKUGL(vxvmEdAVBHO0?! zkVOEwW}fw~E0nPHw0HDAy5!&JgV2HRxH)nSEv}xA>LP?8!&u++qs2{*hj6vCYJNUp z>S4w5k9NxJkwR&-r~%7-b{5FyNuV}!6DE2}m$XFfoy3~!Ky40!S|M^8~utjK=8;ndt9}kQ@kNpK0 zmFH?tn)legGq+X=z}v~N0dP~e0R0rM0P|syd149Cz+Q!-(al0(ta(?--+(R*bggS= zTcMl8S2Wz2<@_P7w+`G`-hTpv54TMg^#nlFx%umn#i!xK`>5&Y#ZvFJ?`z@ms?RBQ z*N)E55My-O<0O_o1$_AHT4LkQYc>Ez)ZJ}P5A>e;=wISak9H*cT5gHuFX+(hY&{iGEaee37*j$s zNI%!*S`YD(q!eMjy{z^E$-Q2UX(l5ws~~W9$~R*J|Ea@ILGT8F7(>qt0}}{i&hI9| zTO|Lx#)Q9!an0?I>4ocVy@;v!OOP11g+1~&gA@G>Nl@b`5DE|L$}OT$@X7+c;MGnaI_G8 zv$Cme>cafu@!!S;^^=hPL;4?Jo? z|A59&{+33{!Q#+B{}aUv+=QGEKyGe3m!e=z_q1^;0rQv!06HyvMnkzoX$7e(2VT&q{6 zr;eD~`Myt&;(HO}&f+cgbKf)dj6_oye|dKqcg%UNtjP}wOwebTGGU8xm%I~UiB#!f zN@wxN($Nh7n7oAl(qpJ+4~LP1O}wxx6E@UL49m;!B5KyFqO$>b|B4a_=vzdzOBw@tU8U>{2_aBiQ z_8!fdjjQH1v+-tj~0Y$}r0c{+qiE_79 zIl$U907cr5VgR<=5wB06W&;x3gWzBwktr^nVDHLAy&C^6*Lw z{gL(^>sk1<(WULARF1(a4;;ChB}xOj`mewVP?q7E1-BqOkaV&?%P)(G;Aw60!vQD%Z46^fg89~A){;ltoOs6 z5XY0Imjxf@)WBl{b=aGW^6Q7V8~fdFHN$U1Q*54Pv<22NH11&Cg%P~NvM=vcI5b-W z_(wVE3hwwClg{@fQwj%74jz!~x4GRKaQ0+S_QFOLXeYR&oRYD)V_cM8AYHejEY0T9 z%z@1Chy0N3KZ3GfIKyZ`OAPwAr_{NZjd0Ses|RB~LL?6cLi?SVHc#g}I`!GeXkoKa z_aD+uOb^=7G}vRxCFb^GbMxvu{W1PMfHX$uS#prdF?#zROjU5+nt?FFvQp<;#BQq& zt>a3V{%l#aIi7NGi+Wbu?}K85DWxl_C5r4_seZ9eGA4s9Ij6}1h#zN4HM`?B2qqGy zFl?c7#O#fYa523^Qs}HEtQ96dr$_l8;70-8AOL79rgT>aY^Egzna(~FvGg6$gA%m;T_ekP~i-3p_L-pjnCN45o=H} z6PZR#s}lG}ckK<=D`}a#I}!KKm94cmPe%d-is}~gcS;x^U%g`al5GKK&p2dnYBSV1 zkJExwBnB1J*oi9KhIDb419HV1fT9Ra2(CJL@eUlToQYR@h1y?|vsgf*UAYcUgQ_MW zMNSFTu+xzQjvr+}BITj;AwG@l2-*7rO_aZ0g@8wmh)h>Ke~1s^6MvmS|7{vX=VPhj z?c-}~>janmky=+Hf~Q^R9Sy_&-Tmx%X-F)PH-0cf5SY?3oZ_A=o3CX6JeSHtN8>T) z{izpj2aB^A+3&oAwHWiIc$tWj=$(_$SJ>y6&e9j$nC^*lPz zHOXo}OqEs!$?2-y_!T@&x}i+x3BP2r0zVa_oM=3{?97}PpkJFexLjfD_a?2Qu2&?|O<(yu)ThRVyd@fKq124osI1x`2@l$1WnU*%&OAtTTMmLzb z`62>%|t+PK&k`_zcg?WX$!9(GWV>^t>k+^B{9=T>J zRFjB3AXdSn z*^q(?Gcv}B{$mfWSo?fCx^(S$c;$n-I9dWodO2XfPlQMA&KA)C+{Vud*kk&`1)c7x zf&P(|4a+M6wmEEwX(I%tT+{oe{o`Y%*FsBFcmcE{OqA%+a$mJe#-H=u`5aFJOc$3C z_cbl+8e)}IbSYy+jhFVVW5!`yyP2po?4eE3u3l~p+HA^FRO4|xCB;ZjZ;2=lAs3a5L z(_Pi8<4YUeZHYH?9HrQc3@FT)u1*KZwUkN7|s_&M=T~vZnY*Es)-r zCBE_eL#lg-lS1_i9)?92yW2>_Hy$ah^R?C>_a()y$5JR@_J}YUIVn zZ3tlYl8n-!5sm6^U06MFveLN$yGNpy790GDNFi~;zIk?$*|-)$z^Y0he`O28=(X*X z1d1;obVM=;(~3s&M%oSMY>1XDgdwor&1AP8nPjn3c`%qjI%!NGy>e)%f%-#eW(X*= zEH~gf9U)I4x3IT&<>Aqp6<6ACJI?jF>6&z9CwqJ<_44#~YW#xzVP;|Uk5-MbEOihS zwQ-_ZG~*DUbOnYSqwU#w*`L~cHvYQ#DKEsuy?)wph%>SxGPnXUXjF&Ds~ubxzZY)G zU$KSef4K*(RxH@TV|iIG6C-GD#Rv>6{h_>2*o3m)LRk`@Zc;l$6jWRqS4uDM?@VdN zPb{DhZw{ySd>AG=UNN??I+DZNsm4Hle19PHYrJfchKWd%9{~|;x)&!pR-=|}$<8hf zIj>4^d%WWzsjl)YtuB0;8u|0$d5OqmuE|J91oPI|)V-W=l0^-Xq&j}^0SKNb%N&A;T#!`r{=NH*+0nV)_<+!C*CgO|16ixZzNspnSg;BMmU=BRqU z!X@tW2Ypacw$=#GHoU)YWLBz;!NmQ}CX&wbN&fKG|WR^U>ZaEfbQ}Y+=tDdJMt~tBlY*vfYqO)z=I$9*bOUCu?8o zGc5HA6X}#?(UbB%Cv4yEP_z}l@~{h49Gh2o=KB`z3&df{i)A#2#T(}QpG#2x7*zW-bHvju$bjYKnyQZVjhr89KGvw!>0SWMVo?flC6M~0btkU-ua(y53L zm=SbjPtaEZGkweJOo^>KkaF^Fzn6iQhX5sEi`DDFu|^a8h$r^Fl8bK_@A<$2bhN2V z*2EKEoaHK|k<-yU6-w{44eXW6REWcB2Ql8A231~iCrpMHISeov#$#U$nOOKk22s$> z#&VwJxWJ~2GnUgn(v>^vt&Ep9S}svvxv=0~x<8;BjJ{GL30JCzi_gNnwNpNuzzJ#h zdS6_p-#@{j9CT(`p2 z)p>h_A_IZXIt|cugh6#?)a~+_$Bkgi!jT!R~OADMd(Zq<7KRR!-lt@;Enc2*T z`O)gJU19mi=EQx|%9ts=V5B0H%fJo~`8@nA&0#aBm|(SnNs-YIZ8xv) z2FEH892|zN?u!K7>BR{%Md#S?5F+h4g#4DN-LP=ZWzE+Vkwl5tR4^cWosZxfzU<

4oS|4 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

F#Ooo(H*=%PV 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 Date: Tue, 20 Dec 2022 09:28:57 +0100 Subject: [PATCH 84/84] [eve7] fix compiler warning with REvePointSet --- graf3d/eve7/src/REvePointSet.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/graf3d/eve7/src/REvePointSet.cxx b/graf3d/eve7/src/REvePointSet.cxx index 6af817cb3efd9..6b8413ca9e014 100644 --- a/graf3d/eve7/src/REvePointSet.cxx +++ b/graf3d/eve7/src/REvePointSet.cxx @@ -45,8 +45,10 @@ REveProjectionManager class. REvePointSet::REvePointSet(const std::string& name, const std::string& title, Int_t n_points) : REveElement(name, title), + REveProjectable(), TAttMarker(), - TAttBBox() + TAttBBox(), + REveSecondarySelectable() { fMarkerStyle = 20; @@ -65,7 +67,8 @@ REvePointSet::REvePointSet(const REvePointSet& e) : REveElement(e), REveProjectable(e), TAttMarker(e), - TAttBBox(e) + TAttBBox(e), + REveSecondarySelectable() { fAlwaysSecSelect = e.GetAlwaysSecSelect(); ClonePoints(e);