From 0e25a2ac7a249284c663859ba8bab5b9d00d49d2 Mon Sep 17 00:00:00 2001 From: Mourtz Date: Mon, 15 Apr 2019 17:32:45 +0200 Subject: [PATCH 01/15] Add support for THREE.Group and Object3D to OutlinePass --- ui5/eve7/lib/OutlinePass.js | 154 ++++++++++++++++++++++++------------ 1 file changed, 104 insertions(+), 50 deletions(-) diff --git a/ui5/eve7/lib/OutlinePass.js b/ui5/eve7/lib/OutlinePass.js index 86f6864192146..ec0dbe8d5485c 100644 --- a/ui5/eve7/lib/OutlinePass.js +++ b/ui5/eve7/lib/OutlinePass.js @@ -128,6 +128,52 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype constructor: THREE.OutlinePass, + parseAtts: function(object, groups){ + // treat Mesh, Line and LineSegments as the same + if(object.type === "Mesh" || object.type === "Line" || object.type === "LineSegments" ) + { + groups[0].push(object); + } + else if(object.type === "Points") + { + let found = false; + // loop over groups + for (let z = 1; z < groups.length; ++z){ + // loop over all the elements of a group + for (let w = 0; w < z.length; ++w){ + // if the objects have the same attributes + if( + this.selectedObjects[z][w].type === object.type && + this.selectedObjects[z][w].material.size === object.material.size && + this.selectedObjects[z][w]["vertShader"] === object["vertShader"] && + this.selectedObjects[z][w]["fragShader"] === object["fragShader"] + ){ + groups[z].push(object); + found = true; + break; + } + } + if(found) + break; + } + + if(!found){ + groups.push([object]); + } + } + else if(object.type === "Group" || object.type === "Object3D") + { + for (const child of object.children){ + this.parseAtts(child, groups); + } + } + else + { + console.error("unknown type of geometry! fallback to 0"); + groups[0].push(object); + } + }, + checkForCustomAtts: function(){ /* this.atts = { @@ -150,54 +196,62 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype } */ - let groups = []; - for (let i = 0; i < this.selectedObjects.length; ++i){ - const object = this.selectedObjects[i]; - - // treat Mesh and LineSegments as the same - if(object.type === "Mesh" || object.type === "LineSegments" ) - { - groups[0] = groups[0] || []; - groups[0].push(object); - } - else if(object.type === "Points") - { - let found = false; - // loop over groups - for (let z = 1; z < groups.length; ++z){ - // loop over all the elements of a group - for (let w = 0; w < z.length; ++w){ - // if the objects have the same attributes - if( - this.selectedObjects[z][w].type === object.type && - this.selectedObjects[z][w].material.size === object.material.size && - this.selectedObjects[z][w]["vertShader"] === object["vertShader"] && - this.selectedObjects[z][w]["fragShader"] === object["fragShader"] - ){ - groups[z] = groups[z] || []; - groups[z].push(object); - found = true; - break; - } - } - if(found) - break; - } - - if(!found){ - groups[i+1] = groups[i+1] || []; - groups[i+1].push(object); - } - } - else - { - console.error("unknown type of geometry! fallback to 0"); - groups[0] = groups[0] || []; - groups[0].push(object); - } - } - this.groups = groups/*.filter(Array)*/; - // console.log(groups); + let groups = [[]]; + + for (const obj of this.selectedObjects) + this.parseAtts(obj, groups); + + // for (let i = 0; i < this.selectedObjects.length; ++i){ + // const object = this.selectedObjects[i]; + + // // treat Mesh and LineSegments as the same + // if(object.type === "Mesh" || object.type === "LineSegments" ) + // { + // groups[0] = groups[0] || []; + // groups[0].push(object); + // } + // else if(object.type === "Points") + // { + // let found = false; + // // loop over groups + // for (let z = 1; z < groups.length; ++z){ + // // loop over all the elements of a group + // for (let w = 0; w < z.length; ++w){ + // // if the objects have the same attributes + // if( + // this.selectedObjects[z][w].type === object.type && + // this.selectedObjects[z][w].material.size === object.material.size && + // this.selectedObjects[z][w]["vertShader"] === object["vertShader"] && + // this.selectedObjects[z][w]["fragShader"] === object["fragShader"] + // ){ + // groups[z].push(object); + // found = true; + // break; + // } + // } + // if(found) + // break; + // } + + // if(!found){ + // groups.push([object]); + // } + // } + // else if(object.type === "Group") + // { + // for (const child of object.children){ + + // } + // } + // else + // { + // console.error("unknown type of geometry! fallback to 0"); + // groups[0] = groups[0] || []; + // groups[0].push(object); + // } + // } + this.groups = groups.filter(Array); + console.log(this.groups); }, dispose: function () { @@ -340,8 +394,8 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype }, render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { - this.selectedObjects = Object.values(this.id2obj_map).flat(); - console.log(this.selectedObjects); + this.selectedObjects = Object.values(this.id2obj_map).flat(); + // console.log(this.selectedObjects); // debugger; if ( this.selectedObjects.length > 0 ) { From e6ecf73f15d3b31a5bb4b87b0834761a90a98a2f Mon Sep 17 00:00:00 2001 From: Mourtz Date: Tue, 16 Apr 2019 12:36:37 +0200 Subject: [PATCH 02/15] Fix: highlighting for secondary selection --- ui5/eve7/lib/EveElements.js | 8 +++++--- ui5/eve7/lib/EveScene.js | 15 ++++++++------- ui5/eve7/lib/OutlinePass.js | 17 ++++++++++++++--- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/ui5/eve7/lib/EveElements.js b/ui5/eve7/lib/EveElements.js index 4dfc930974177..49fa68457f0ce 100644 --- a/ui5/eve7/lib/EveElements.js +++ b/ui5/eve7/lib/EveElements.js @@ -573,7 +573,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { var color = JSROOT.Painter.root_colors[m.eve_el.fMainColor]; var lineMaterial = new THREE.LineBasicMaterial({ color: color, linewidth: 4 }); var line = new THREE.LineSegments(geom, lineMaterial); - dest.add(line); + dest.push(line); var el = m.eve_el, mindx = [] @@ -592,7 +592,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { if (mindx.length > 0) { - var pnts = new JSROOT.Painter.PointsCreator(mindx.length, true, 5); + let mark_size = 5; + var pnts = new JSROOT.Painter.PointsCreator(mindx.length, true, mark_size); var arr = m.children[1].geometry.getAttribute("position").array; @@ -602,7 +603,8 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { pnts.AddPoint(arr[p], arr[p+1], arr[p+2] ); } var mark = pnts.CreatePoints(color); - dest.add(mark); + mark.material.size = mark_size; + dest.push(mark); } } diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index 04feff67dc84a..fc6df77e732d4 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -462,7 +462,7 @@ sap.ui.define([ var obj3d = this.getObj3D( element_id ); if ( ! (selection_obj.fElementId in this.viewer.outlinePass.id2obj_map)) - this.viewer.outlinePass.id2obj_map[selection_obj.fElementId] = []; + this.viewer.outlinePass.id2obj_map[selection_obj.fElementId] = []; var dest = this.viewer.outlinePass.id2obj_map[selection_obj.fElementId]; @@ -475,13 +475,14 @@ sap.ui.define([ else { var ctrl = obj3d.get_ctrl(); - // AMT todo check for memory leaks - var x = new THREE.Object3D(); + // AMT todo check for memory leaks + var x = []; ctrl.DrawForSelection(sec_idcs, x); - console.log("draw for selection exit ", x); - // AMT for debugging purposes take only first child - var fe = x.children[0]; - dest[element_id] = fe; + console.log("draw for selection exit ", x); + // AMT for debugging purposes take only first child + // this.viewer.getThreejsContainer("scene" + this.element_id).add(x[0]); + this.viewer.outlinePass.sec_sel = x; + dest[element_id] = x; } this.viewer.render(); diff --git a/ui5/eve7/lib/OutlinePass.js b/ui5/eve7/lib/OutlinePass.js index ec0dbe8d5485c..815dc56c3a743 100644 --- a/ui5/eve7/lib/OutlinePass.js +++ b/ui5/eve7/lib/OutlinePass.js @@ -7,8 +7,11 @@ THREE.OutlinePass = function ( resolution, scene, camera ) { // [{ "index": number, "isPoints": boolean, "pointSize": number, "vertShader": string, "fragShader":string },......] this.renderScene = scene; this.renderCamera = camera; + this.selectedObjects = []; this.id2obj_map = {}; + this.sec_sel = []; + this.visibleEdgeColor = new THREE.Color( 1, 1, 1 ); this.hiddenEdgeColor = new THREE.Color( 0.1, 0.04, 0.02 ); this.edgeGlow = 0.0; @@ -251,7 +254,6 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype // } // } this.groups = groups.filter(Array); - console.log(this.groups); }, dispose: function () { @@ -309,7 +311,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype } - for(const obj of ((Array.isArray(object) ? object : (object && [object])) || this.selectedObjects)){ + for(const obj of (object || this.selectedObjects)){ obj.traverse( gatherSelectedMeshesCallBack ); } @@ -394,11 +396,15 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype }, render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { - this.selectedObjects = Object.values(this.id2obj_map).flat(); + this.selectedObjects = Object.values(this.id2obj_map).flat().flat(); // console.log(this.selectedObjects); // debugger; if ( this.selectedObjects.length > 0 ) { + // add sec_sel elements in renderScene + for(const obj of this.sec_sel) + this.renderScene.add(obj); + this.oldClearColor.copy( renderer.getClearColor() ); this.oldClearAlpha = renderer.getClearAlpha(); var oldAutoClear = renderer.autoClear; @@ -436,6 +442,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype renderer.clear(); this.checkForCustomAtts(); + //console.log(this.groups); for(const group of this.groups){ if(group.length > 0) @@ -543,6 +550,10 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype renderer.setClearColor( this.oldClearColor, this.oldClearAlpha ); renderer.autoClear = oldAutoClear; + + // remove sec_sel elements from renderScene + for(const obj of this.sec_sel) + this.renderScene.remove(obj); } else { this.quad.material = this.materialCopy; this.copyUniforms[ "tDiffuse" ].value = readBuffer.texture; From 2e8ad1ff53fc64f8e3a5f9b054f946fd09138a7c Mon Sep 17 00:00:00 2001 From: Mourtz Date: Tue, 16 Apr 2019 15:10:53 +0200 Subject: [PATCH 03/15] Optimize OutlinePass groups creator --- ui5/eve7/lib/OutlinePass.js | 59 +++++++++++++++---------------------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/ui5/eve7/lib/OutlinePass.js b/ui5/eve7/lib/OutlinePass.js index 815dc56c3a743..3e7f660a03367 100644 --- a/ui5/eve7/lib/OutlinePass.js +++ b/ui5/eve7/lib/OutlinePass.js @@ -132,48 +132,35 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype constructor: THREE.OutlinePass, parseAtts: function(object, groups){ - // treat Mesh, Line and LineSegments as the same - if(object.type === "Mesh" || object.type === "Line" || object.type === "LineSegments" ) - { - groups[0].push(object); - } - else if(object.type === "Points") - { - let found = false; - // loop over groups - for (let z = 1; z < groups.length; ++z){ - // loop over all the elements of a group - for (let w = 0; w < z.length; ++w){ - // if the objects have the same attributes - if( - this.selectedObjects[z][w].type === object.type && - this.selectedObjects[z][w].material.size === object.material.size && - this.selectedObjects[z][w]["vertShader"] === object["vertShader"] && - this.selectedObjects[z][w]["fragShader"] === object["fragShader"] - ){ + let found = false; + // loop over groups + for (let z = 0; z < groups.length; ++z){ + // loop over all the elements of a group + //for (let w = 0; w < groups[z].length; ++w) + + const w = 0; // check only the first element of the group! + { + let pass = (object.type === "Points") ? (groups[z][w].material.size === object.material.size) : true; + + if( pass ){ + // final check + if( groups[z][w]["vertShader"] === object["vertShader"] && + groups[z][w]["fragShader"] === object["fragShader"] && + groups[z][w].visibleEdgeColor === object.visibleEdgeColor && + groups[z][w].hiddenEdgeColor === object.hiddenEdgeColor + ) { groups[z].push(object); found = true; break; } } - if(found) - break; - } - - if(!found){ - groups.push([object]); } + if(found) + break; } - else if(object.type === "Group" || object.type === "Object3D") - { - for (const child of object.children){ - this.parseAtts(child, groups); - } - } - else - { - console.error("unknown type of geometry! fallback to 0"); - groups[0].push(object); + + if(!found){ + groups.push([object]); } }, @@ -199,7 +186,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype } */ - let groups = [[]]; + let groups = []; for (const obj of this.selectedObjects) this.parseAtts(obj, groups); From 1846150015eed7e18a19091eb7fe0a8a399a4234 Mon Sep 17 00:00:00 2001 From: Mourtz Date: Tue, 16 Apr 2019 15:54:50 +0200 Subject: [PATCH 04/15] Moved everything composer related to JSRootGeoPainter --- js/scripts/JSRootGeoPainter.js | 18 ++++++++++++++++++ ui5/eve7/controller/GL.controller.js | 21 ++------------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/js/scripts/JSRootGeoPainter.js b/js/scripts/JSRootGeoPainter.js index a21c7ded055bc..069066163782a 100644 --- a/js/scripts/JSRootGeoPainter.js +++ b/js/scripts/JSRootGeoPainter.js @@ -1915,6 +1915,23 @@ this._effectComposer = new THREE.EffectComposer( this._renderer ); this._effectComposer.addPass( new THREE.RenderPass( this._scene, this._camera ) ); + this.outlinePass = new THREE.OutlinePass( new THREE.Vector2( w, h ), this._scene, this._camera ); + this.outlinePass.edgeStrength = 7.5; + this.outlinePass.edgeGlow = 0.5; + this.outlinePass.edgeThickness = 1.0; + this.outlinePass.usePatternTexture = false; + this.outlinePass.downSampleRatio = 2; + this.outlinePass.visibleEdgeColor.set('#dd1111'); + this.outlinePass.hiddenEdgeColor.set('#1111dd'); + this._effectComposer.addPass( this.outlinePass ); + + this.effectFXAA = new THREE.ShaderPass( THREE.FXAAShader ); + this.effectFXAA.uniforms[ 'resolution' ].value.set( 1 / w, 1 / h ); + this.effectFXAA.renderToScreen = true; + this._effectComposer.addPass( this.effectFXAA ); + + // this.composer.addPass( new THREE.ShaderPass( THREE.CopyShader ) ); + if (this._enableSSAO) this.createSSAO(); @@ -3574,6 +3591,7 @@ this._camera.updateProjectionMatrix(); this._renderer.setSize( this._scene_width, this._scene_height, !this._fit_main_area ); this._effectComposer.setSize( this._scene_width, this._scene_height ); + this.effectFXAA.uniforms[ 'resolution' ].value.set( 1 / this._scene_width, 1 / this._scene_height ); if (!this.drawing_stage) this.Render3D(); } diff --git a/ui5/eve7/controller/GL.controller.js b/ui5/eve7/controller/GL.controller.js index 1d196c1c37fa8..40c184d8c6ef8 100644 --- a/ui5/eve7/controller/GL.controller.js +++ b/ui5/eve7/controller/GL.controller.js @@ -325,24 +325,8 @@ sap.ui.define([ // this.geo_painter._highlight_handlers = [ this ]; // register ourself for highlight handling this.last_highlight = null; - this.composer = this.geo_painter._effectComposer; - let width = this.geo_painter._scene_width; - let height = this.geo_painter._scene_height; - - this.outlinePass = new THREE.OutlinePass( new THREE.Vector2( width, height ), this.geo_painter._scene, this.geo_painter._camera ); - this.outlinePass.edgeStrength = 7.5; - this.outlinePass.edgeGlow = 0.5; - this.outlinePass.edgeThickness = 1.0; - this.outlinePass.usePatternTexture = false; - this.outlinePass.downSampleRatio = 2; - this.outlinePass.visibleEdgeColor.set('#dd1111'); - this.outlinePass.hiddenEdgeColor.set('#1111dd'); - this.composer.addPass( this.outlinePass ); - - this.effectFXAA = new THREE.ShaderPass( THREE.FXAAShader ); - this.effectFXAA.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height ); - this.effectFXAA.renderToScreen = true; - this.composer.addPass( this.effectFXAA ); + // outlinePass passthrough + this.outlinePass = this.geo_painter.outlinePass; // create only when geo painter is ready this.createScenes(); @@ -364,7 +348,6 @@ sap.ui.define([ this.getView().$().css("overflow", "hidden").css("width", "100%").css("height", "100%"); if (this.geo_painter){ this.geo_painter.CheckResize(); - this.effectFXAA.uniforms[ 'resolution' ].value.set( 1 / this.geo_painter._scene_width, 1 / this.geo_painter._scene_height ); } } From b1c7957ca6f0d4a4e16edb2d1f8965d67d68b605 Mon Sep 17 00:00:00 2001 From: Mourtz Date: Tue, 16 Apr 2019 20:00:06 +0200 Subject: [PATCH 05/15] Backup Changes --- js/scripts/JSRootGeoPainter.js | 32 +++++++++++++--------------- ui5/eve7/controller/GL.controller.js | 2 +- ui5/eve7/lib/EveScene.js | 3 +-- ui5/eve7/lib/OutlinePass.js | 7 +++--- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/js/scripts/JSRootGeoPainter.js b/js/scripts/JSRootGeoPainter.js index 069066163782a..76655e5adde5f 100644 --- a/js/scripts/JSRootGeoPainter.js +++ b/js/scripts/JSRootGeoPainter.js @@ -1915,22 +1915,20 @@ this._effectComposer = new THREE.EffectComposer( this._renderer ); this._effectComposer.addPass( new THREE.RenderPass( this._scene, this._camera ) ); - this.outlinePass = new THREE.OutlinePass( new THREE.Vector2( w, h ), this._scene, this._camera ); - this.outlinePass.edgeStrength = 7.5; - this.outlinePass.edgeGlow = 0.5; - this.outlinePass.edgeThickness = 1.0; - this.outlinePass.usePatternTexture = false; - this.outlinePass.downSampleRatio = 2; - this.outlinePass.visibleEdgeColor.set('#dd1111'); - this.outlinePass.hiddenEdgeColor.set('#1111dd'); - this._effectComposer.addPass( this.outlinePass ); - - this.effectFXAA = new THREE.ShaderPass( THREE.FXAAShader ); - this.effectFXAA.uniforms[ 'resolution' ].value.set( 1 / w, 1 / h ); - this.effectFXAA.renderToScreen = true; - this._effectComposer.addPass( this.effectFXAA ); - - // this.composer.addPass( new THREE.ShaderPass( THREE.CopyShader ) ); + this._outlinePass = new THREE.OutlinePass( new THREE.Vector2( w, h ), this._scene, this._camera ); + this._outlinePass.edgeStrength = 7.5; + this._outlinePass.edgeGlow = 0.5; + this._outlinePass.edgeThickness = 1.0; + this._outlinePass.usePatternTexture = false; + this._outlinePass.downSampleRatio = 2; + this._outlinePass.visibleEdgeColor.set('#dd1111'); + this._outlinePass.hiddenEdgeColor.set('#1111dd'); + this._effectComposer.addPass( this._outlinePass ); + + this._effectFXAA = new THREE.ShaderPass( THREE.FXAAShader ); + this._effectFXAA.uniforms[ 'resolution' ].value.set( 1 / w, 1 / h ); + this._effectFXAA.renderToScreen = true; + this._effectComposer.addPass( this._effectFXAA ); if (this._enableSSAO) this.createSSAO(); @@ -3591,7 +3589,7 @@ this._camera.updateProjectionMatrix(); this._renderer.setSize( this._scene_width, this._scene_height, !this._fit_main_area ); this._effectComposer.setSize( this._scene_width, this._scene_height ); - this.effectFXAA.uniforms[ 'resolution' ].value.set( 1 / this._scene_width, 1 / this._scene_height ); + this._effectFXAA.uniforms[ 'resolution' ].value.set( 1 / this._scene_width, 1 / this._scene_height ); if (!this.drawing_stage) this.Render3D(); } diff --git a/ui5/eve7/controller/GL.controller.js b/ui5/eve7/controller/GL.controller.js index 40c184d8c6ef8..8d1681f3dc451 100644 --- a/ui5/eve7/controller/GL.controller.js +++ b/ui5/eve7/controller/GL.controller.js @@ -326,7 +326,7 @@ sap.ui.define([ this.last_highlight = null; // outlinePass passthrough - this.outlinePass = this.geo_painter.outlinePass; + this.outlinePass = this.geo_painter._outlinePass; // create only when geo painter is ready this.createScenes(); diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index fc6df77e732d4..6f4c0ce2caa47 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -481,8 +481,7 @@ sap.ui.define([ console.log("draw for selection exit ", x); // AMT for debugging purposes take only first child // this.viewer.getThreejsContainer("scene" + this.element_id).add(x[0]); - this.viewer.outlinePass.sec_sel = x; - dest[element_id] = x; + this.viewer.outlinePass.sec_sel = (dest[element_id] = x); } this.viewer.render(); diff --git a/ui5/eve7/lib/OutlinePass.js b/ui5/eve7/lib/OutlinePass.js index 3e7f660a03367..3c94c1b068292 100644 --- a/ui5/eve7/lib/OutlinePass.js +++ b/ui5/eve7/lib/OutlinePass.js @@ -186,10 +186,9 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype } */ - let groups = []; - + this.groups = []; for (const obj of this.selectedObjects) - this.parseAtts(obj, groups); + this.parseAtts(obj, this.groups); // for (let i = 0; i < this.selectedObjects.length; ++i){ // const object = this.selectedObjects[i]; @@ -240,7 +239,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype // groups[0].push(object); // } // } - this.groups = groups.filter(Array); + // this.groups = groups.filter(Array); }, dispose: function () { From 1642cde38771ce3645c03682381aeed9183747b3 Mon Sep 17 00:00:00 2001 From: Mourtz Date: Wed, 17 Apr 2019 16:38:39 +0200 Subject: [PATCH 06/15] Add support for multiple selection types --- ui5/eve7/lib/EveScene.js | 20 ++++--- ui5/eve7/lib/OutlinePass.js | 116 ++++++++++++++++++++++++++---------- 2 files changed, 94 insertions(+), 42 deletions(-) diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index 6f4c0ce2caa47..54ad8241db36d 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -459,6 +459,12 @@ sap.ui.define([ EveScene.prototype.SelectElement = function(selection_obj, element_id, sec_idcs) { + let res = { + "sel_type": THREE.OutlinePass.selection_enum["select"], + // "sel_type": THREE.OutlinePass.selection_enum["highlight"], + "sec_sel": false, + "geom": [] + }; var obj3d = this.getObj3D( element_id ); if ( ! (selection_obj.fElementId in this.viewer.outlinePass.id2obj_map)) @@ -470,20 +476,16 @@ sap.ui.define([ if(sec_idcs === undefined || sec_idcs.length == 0) { - dest[element_id] = obj3d; + res.geom.push(obj3d); } else { var ctrl = obj3d.get_ctrl(); - // AMT todo check for memory leaks - var x = []; - ctrl.DrawForSelection(sec_idcs, x); - console.log("draw for selection exit ", x); - // AMT for debugging purposes take only first child - // this.viewer.getThreejsContainer("scene" + this.element_id).add(x[0]); - this.viewer.outlinePass.sec_sel = (dest[element_id] = x); + ctrl.DrawForSelection(sec_idcs, res.geom); + res.sec_sel = true; } - + dest[element_id] = res; + this.viewer.render(); } diff --git a/ui5/eve7/lib/OutlinePass.js b/ui5/eve7/lib/OutlinePass.js index 3c94c1b068292..432993bed2353 100644 --- a/ui5/eve7/lib/OutlinePass.js +++ b/ui5/eve7/lib/OutlinePass.js @@ -10,7 +10,6 @@ THREE.OutlinePass = function ( resolution, scene, camera ) { this.selectedObjects = []; this.id2obj_map = {}; - this.sec_sel = []; this.visibleEdgeColor = new THREE.Color( 1, 1, 1 ); this.hiddenEdgeColor = new THREE.Color( 0.1, 0.04, 0.02 ); @@ -187,9 +186,18 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype */ this.groups = []; - for (const obj of this.selectedObjects) - this.parseAtts(obj, this.groups); - + // ES6 (could be replaced with vanilla Js) + this.sel = Array.from(Array(THREE.OutlinePass.selection_enum.total), () => []); + // this.sel = Array(THREE.OutlinePass.selection_enum.total).fill([]); + for (const obj of this.selectedObjects){ + // stored at the top level + obj.sel_type = (obj.sel_type == undefined) ? THREE.OutlinePass.selection_enum["highlight"] : obj.sel_type; + + for(const geom of obj.geom){ + this.sel[obj.sel_type].push(geom); + this.parseAtts(geom, this.groups); + } + } // for (let i = 0; i < this.selectedObjects.length; ++i){ // const object = this.selectedObjects[i]; @@ -298,7 +306,12 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype } for(const obj of (object || this.selectedObjects)){ - obj.traverse( gatherSelectedMeshesCallBack ); + if(obj.geom){ + for(const geom of obj.geom) + geom.traverse( gatherSelectedMeshesCallBack ); + } else { + obj.traverse( gatherSelectedMeshesCallBack ); + } } }, @@ -313,11 +326,9 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype } - for ( var i = 0; i < this.selectedObjects.length; i ++ ) { - - var selectedObject = this.selectedObjects[ i ]; - selectedObject.traverse( gatherSelectedMeshesCallBack ); - + for(const obj of this.selectedObjects){ + for(const geom of obj.geom) + geom.traverse( gatherSelectedMeshesCallBack ); } function VisibilityChangeCallBack( object ) { @@ -382,13 +393,20 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype }, render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { - this.selectedObjects = Object.values(this.id2obj_map).flat().flat(); + this.selectedObjects = Object.values(this.id2obj_map).flat(); // console.log(this.selectedObjects); // debugger; if ( this.selectedObjects.length > 0 ) { + // fetch objects that were created after secondary selection + let sec_sel = this.selectedObjects.map(function(v){ + if(v.sec_sel) return v.geom; + }); + sec_sel = sec_sel.flat(); + // debugger; + // add sec_sel elements in renderScene - for(const obj of this.sec_sel) + for(const obj of sec_sel) this.renderScene.add(obj); this.oldClearColor.copy( renderer.getClearColor() ); @@ -454,12 +472,12 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype // this.draw(renderer, writeBuffer, readBuffer, maskActive, this.selectedObjects, -1); // } - // enable back all selected elements - this.changeVisibilityOfSelectedObjects(true); - this.renderScene.overrideMaterial = null; + + // enable all elements + this.changeVisibilityOfSelectedObjects(true); this.changeVisibilityOfNonSelectedObjects( true ); - + this.renderScene.background = currentBackground; // 2. Downsample to Half resolution @@ -468,27 +486,30 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype renderer.setRenderTarget( this.renderTargetMaskDownSampleBuffer ); renderer.clear(); renderer.render( this.scene, this.camera ); - - this.tempPulseColor1.copy( this.visibleEdgeColor ); - this.tempPulseColor2.copy( this.hiddenEdgeColor ); - - if ( this.pulsePeriod > 0 ) { - - var scalar = ( 1 + 0.25 ) / 2 + Math.cos( performance.now() * 0.01 / this.pulsePeriod ) * ( 1.0 - 0.25 ) / 2; - this.tempPulseColor1.multiplyScalar( scalar ); - this.tempPulseColor2.multiplyScalar( scalar ); - - } - - // 3. Apply Edge Detection Pass + + this.changeVisibilityOfSelectedObjects(false); + this.quad.material = this.edgeDetectionMaterial; this.edgeDetectionMaterial.uniforms[ "maskTexture" ].value = this.renderTargetMaskDownSampleBuffer.texture; this.edgeDetectionMaterial.uniforms[ "texSize" ].value = new THREE.Vector2( this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height ); - this.edgeDetectionMaterial.uniforms[ "visibleEdgeColor" ].value = this.tempPulseColor1; - this.edgeDetectionMaterial.uniforms[ "hiddenEdgeColor" ].value = this.tempPulseColor2; renderer.setRenderTarget( this.renderTargetEdgeBuffer1 ); renderer.clear(); - renderer.render( this.scene, this.camera ); + + for(let i = 0; i < THREE.OutlinePass.selection_enum.total; ++i){ + const sel = this.sel[i]; + if(sel.length > 0){ + this.changeVisibilityOfSelectedObjects(true, sel); + + // 3. Apply Edge Detection Pass + const att = THREE.OutlinePass.selection_atts[i]; + this.edgeDetectionMaterial.uniforms[ "visibleEdgeColor" ].value = att.visibleEdgeColor; + this.edgeDetectionMaterial.uniforms[ "hiddenEdgeColor" ].value = att.hiddenEdgeColor; + renderer.render( this.scene, this.camera ); + + this.changeVisibilityOfSelectedObjects(false, sel); + } + } + this.changeVisibilityOfSelectedObjects(true); // 4. Apply Blur on Half res this.quad.material = this.separableBlurMaterial1; @@ -538,7 +559,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype renderer.autoClear = oldAutoClear; // remove sec_sel elements from renderScene - for(const obj of this.sec_sel) + for(const obj of sec_sel) this.renderScene.remove(obj); } else { this.quad.material = this.materialCopy; @@ -769,3 +790,32 @@ if(false){ THREE.OutlinePass.BlurDirectionX = new THREE.Vector2( 1.0, 0.0 ); THREE.OutlinePass.BlurDirectionY = new THREE.Vector2( 0.0, 1.0 ); + +THREE.OutlinePass.selection_enum = { + "select": 0, + "highlight": 1, + "total": 2 +}; + +THREE.OutlinePass.selection_atts = [ + { + visibleEdgeColor: new THREE.Color( 1, 0, 0 ), + hiddenEdgeColor: new THREE.Color( 0.1, 0.04, 0.02 ) + // edgeGlow: 0.0, + // usePatternTexture: false, + // edgeThickness: 1.0, + // edgeStrength: 3.0, + // downSampleRatio: 2, + // pulsePeriod: 0 + }, + { + visibleEdgeColor: new THREE.Color( 0, 0, 1 ), + hiddenEdgeColor: new THREE.Color( 0.1, 0.04, 0.02 ) + // edgeGlow: 0.0, + // usePatternTexture: false, + // edgeThickness: 1.0, + // edgeStrength: 3.0, + // downSampleRatio: 2, + // pulsePeriod: 0 + } +]; From 4e3272dffe97a2cbf55238e140177aa6143b2d34 Mon Sep 17 00:00:00 2001 From: Mourtz Date: Wed, 17 Apr 2019 16:59:00 +0200 Subject: [PATCH 07/15] Add some comments --- js/scripts/JSRootGeoPainter.js | 7 +++++-- ui5/eve7/lib/OutlinePass.js | 13 ++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/js/scripts/JSRootGeoPainter.js b/js/scripts/JSRootGeoPainter.js index 76655e5adde5f..74a9f1b14f737 100644 --- a/js/scripts/JSRootGeoPainter.js +++ b/js/scripts/JSRootGeoPainter.js @@ -1921,8 +1921,11 @@ this._outlinePass.edgeThickness = 1.0; this._outlinePass.usePatternTexture = false; this._outlinePass.downSampleRatio = 2; - this._outlinePass.visibleEdgeColor.set('#dd1111'); - this._outlinePass.hiddenEdgeColor.set('#1111dd'); + + const sh = THREE.OutlinePass.selection_enum["select"]; // doesnt stand for spherical harmonics :P + THREE.OutlinePass.selection_atts[sh].visibleEdgeColor.set('#dd1111'); + THREE.OutlinePass.selection_atts[sh].hiddenEdgeColor.set('#1111dd'); + this._effectComposer.addPass( this._outlinePass ); this._effectFXAA = new THREE.ShaderPass( THREE.FXAAShader ); diff --git a/ui5/eve7/lib/OutlinePass.js b/ui5/eve7/lib/OutlinePass.js index 432993bed2353..3094e1a27f755 100644 --- a/ui5/eve7/lib/OutlinePass.js +++ b/ui5/eve7/lib/OutlinePass.js @@ -8,17 +8,20 @@ THREE.OutlinePass = function ( resolution, scene, camera ) { this.renderScene = scene; this.renderCamera = camera; + // R: Primitives this.selectedObjects = []; + // [fElementId][elementId] -> { "sel_type": THREE.OutlinePass.selection_enum, "sec_sel": boolean, "geom": Primitive<> } this.id2obj_map = {}; + // [C]: Selection Types - [R]: Primitives + this.sel = []; + // [C]: Attributes(color, size, etc...) - [C]: Primitives + this.groups = []; - this.visibleEdgeColor = new THREE.Color( 1, 1, 1 ); - this.hiddenEdgeColor = new THREE.Color( 0.1, 0.04, 0.02 ); this.edgeGlow = 0.0; this.usePatternTexture = false; this.edgeThickness = 1.0; this.edgeStrength = 3.0; this.downSampleRatio = 2; - this.pulsePeriod = 0; THREE.Pass.call( this ); @@ -805,8 +808,6 @@ THREE.OutlinePass.selection_atts = [ // usePatternTexture: false, // edgeThickness: 1.0, // edgeStrength: 3.0, - // downSampleRatio: 2, - // pulsePeriod: 0 }, { visibleEdgeColor: new THREE.Color( 0, 0, 1 ), @@ -815,7 +816,5 @@ THREE.OutlinePass.selection_atts = [ // usePatternTexture: false, // edgeThickness: 1.0, // edgeStrength: 3.0, - // downSampleRatio: 2, - // pulsePeriod: 0 } ]; From fd619bfb24d5971d1c77ff1bec352b5b639cfb7c Mon Sep 17 00:00:00 2001 From: alja Date: Wed, 17 Apr 2019 15:48:50 -0700 Subject: [PATCH 08/15] Use server-client highlight --- ui5/eve7/lib/EveScene.js | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index 54ad8241db36d..f95c763262e70 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -252,7 +252,6 @@ sap.ui.define([ EveScene.prototype.processElementSelected = function(obj3d, col, indx, evnt) { // MT BEGIN - console.log("EveScene.prototype.processElementSelected", obj3d, col, indx, evnt); var is_multi = evnt && evnt.ctrlKey; @@ -344,17 +343,23 @@ sap.ui.define([ /** interactive handler */ EveScene.prototype.processElementHighlighted = function(obj3d, col, indx, evnt) { - var id = obj3d.mstrId; - // id = obj3d.eveId; + console.log("EveScene.prototype.processElementHighlighted", obj3d, col, indx, evnt); - // MT XXXX - // console.log("EveScene.prototype.processElementHighlighted", obj3d, col, indx, evnt); + var is_multi = false; + var is_secsel = indx !== undefined; - this.setElementHighlighted(id, col, indx, true); + var fcall = "NewElementPicked(" + obj3d.eveId + `, ${is_multi}, ${is_secsel}`; + if (is_secsel) + { + fcall += ", { " + (Array.isArray(indx) ? indx.join(", ") : indx) + " }"; + } + fcall += ")"; - this.mgr.invokeInOtherScenes(this, "setElementHighlighted", id, col, indx); + this.mgr.SendMIR({ "mir": fcall, + "fElementId": this.mgr.global_highlight_id, + "class": "REX::REveSelection" + }); - // when true returns, controller will not try to render itself return true; } @@ -459,9 +464,11 @@ sap.ui.define([ EveScene.prototype.SelectElement = function(selection_obj, element_id, sec_idcs) { + var stype = selection_obj.fName.endsWith("Selection") ? "select" : "highlight"; + var estype = THREE.OutlinePass.selection_enum[stype]; + let res = { - "sel_type": THREE.OutlinePass.selection_enum["select"], - // "sel_type": THREE.OutlinePass.selection_enum["highlight"], + "sel_type": estype, "sec_sel": false, "geom": [] }; From 1a673f1a0e50b9bd9175e2f159321440bce4f511 Mon Sep 17 00:00:00 2001 From: alja Date: Wed, 17 Apr 2019 15:50:05 -0700 Subject: [PATCH 09/15] Use same color for visible and hidden edge to debug highlight and selection --- ui5/eve7/lib/OutlinePass.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ui5/eve7/lib/OutlinePass.js b/ui5/eve7/lib/OutlinePass.js index 3094e1a27f755..cabafda4883db 100644 --- a/ui5/eve7/lib/OutlinePass.js +++ b/ui5/eve7/lib/OutlinePass.js @@ -802,16 +802,18 @@ THREE.OutlinePass.selection_enum = { THREE.OutlinePass.selection_atts = [ { - visibleEdgeColor: new THREE.Color( 1, 0, 0 ), - hiddenEdgeColor: new THREE.Color( 0.1, 0.04, 0.02 ) + visibleEdgeColor: new THREE.Color( 1, 0, 1 ), + hiddenEdgeColor: new THREE.Color( 1, 0, 1 ) + // hiddenEdgeColoe: new THREE.Color( 0.1, 0.04, 0.02 ) // edgeGlow: 0.0, // usePatternTexture: false, // edgeThickness: 1.0, // edgeStrength: 3.0, }, { - visibleEdgeColor: new THREE.Color( 0, 0, 1 ), - hiddenEdgeColor: new THREE.Color( 0.1, 0.04, 0.02 ) + visibleEdgeColor: new THREE.Color( 0, 1, 1 ), + hiddenEdgeColor: new THREE.Color( 0, 1, 1 ) + // hiddenEdgeColor: new THREE.Color( 0.1, 0.04, 0.02 ) // edgeGlow: 0.0, // usePatternTexture: false, // edgeThickness: 1.0, From bc2a6e8440caca2a69b04c436333d1c8c1abf66e Mon Sep 17 00:00:00 2001 From: alja Date: Wed, 17 Apr 2019 15:58:01 -0700 Subject: [PATCH 10/15] Introduce 100ms timeout in MainProcessMouseMove --- js/scripts/JSRoot3DPainter.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/js/scripts/JSRoot3DPainter.js b/js/scripts/JSRoot3DPainter.js index 210ec7cdc6255..10a178a0f2936 100644 --- a/js/scripts/JSRoot3DPainter.js +++ b/js/scripts/JSRoot3DPainter.js @@ -503,6 +503,27 @@ } control.MainProcessMouseMove = function(evnt) { + // check timeout + var toutval = 100; + + // first time + var dt = new Date(); + if (!this.mouse_tmout) { + this.mouse_tmout = setTimeout(this.MainProcessMouseMove.bind(this,evnt), toutval); + this.tt = dt.getTime(); + return; + } + else { + var tdiff = dt.getTime() - this.tt; + if (tdiff < toutval) { + clearTimeout(this.mouse_tmout); + this.mouse_tmout = setTimeout(this.MainProcessMouseMove.bind(this,evnt), tdiff); + return; + } + } + this.tt = dt.getTime(); + //console.log("control.MainProcessMouseMove"); + if (this.control_active && evnt.buttons && (evnt.buttons & 2)) this.block_ctxt = true; // if right button in control was active, block next context menu From 8ec94e45db4c06f40ee5bf67b8e36e6fa717fc86 Mon Sep 17 00:00:00 2001 From: Mourtz Date: Thu, 18 Apr 2019 16:26:16 +0200 Subject: [PATCH 11/15] Bug Fix --- ui5/eve7/lib/OutlinePass.js | 155 +++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 57 deletions(-) diff --git a/ui5/eve7/lib/OutlinePass.js b/ui5/eve7/lib/OutlinePass.js index cabafda4883db..1d7488f6e6d7e 100644 --- a/ui5/eve7/lib/OutlinePass.js +++ b/ui5/eve7/lib/OutlinePass.js @@ -8,14 +8,12 @@ THREE.OutlinePass = function ( resolution, scene, camera ) { this.renderScene = scene; this.renderCamera = camera; - // R: Primitives - this.selectedObjects = []; // [fElementId][elementId] -> { "sel_type": THREE.OutlinePass.selection_enum, "sec_sel": boolean, "geom": Primitive<> } this.id2obj_map = {}; - // [C]: Selection Types - [R]: Primitives - this.sel = []; - // [C]: Attributes(color, size, etc...) - [C]: Primitives - this.groups = []; + // R: Primitives + this._selectedObjects = []; + // [C1]: Selection Types - [C2]: Attributes(color, size, etc...) - [R2]: Primitives + this._groups = Array.from(Array(THREE.OutlinePass.selection_enum.total), () => []); // ES6 (could be replaced with vanilla Js) this.edgeGlow = 0.0; this.usePatternTexture = false; @@ -34,9 +32,20 @@ THREE.OutlinePass = function ( resolution, scene, camera ) { this.maskBufferMaterial = new THREE.MeshBasicMaterial( { color: 0xffffff } ); this.maskBufferMaterial.side = THREE.DoubleSide; - this.renderTargetMaskBuffer = new THREE.WebGLRenderTarget( this.resolution.x, this.resolution.y, pars ); - this.renderTargetMaskBuffer.texture.name = "OutlinePass.mask"; - this.renderTargetMaskBuffer.texture.generateMipmaps = false; + + this.renderTargetMaskBuffer = []; + // +1 extra for the "accumulated" result + for(let i = 0; i < THREE.OutlinePass.selection_enum.total; ++i){ + let maskBuffer = new THREE.WebGLRenderTarget( this.resolution.x, this.resolution.y, pars ) + maskBuffer.texture.name = "OutlinePass.submask"+i; + maskBuffer.texture.generateMipmaps = false; + + this.renderTargetMaskBuffer.push(maskBuffer); + } + + this.renderTargetMaskBufferMain = new THREE.WebGLRenderTarget( this.resolution.x, this.resolution.y, pars ); + this.renderTargetMaskBufferMain.texture.name = "OutlinePass.mask"; + this.renderTargetMaskBufferMain.texture.generateMipmaps = false; this.depthMaterial = new THREE.MeshDepthMaterial(); this.depthMaterial.side = THREE.DoubleSide; @@ -70,8 +79,8 @@ THREE.OutlinePass = function ( resolution, scene, camera ) { this.renderTargetEdgeBuffer2.texture.name = "OutlinePass.edge2"; this.renderTargetEdgeBuffer2.texture.generateMipmaps = false; - var MAX_EDGE_THICKNESS = 4; - var MAX_EDGE_GLOW = 4; + const MAX_EDGE_THICKNESS = 4; + const MAX_EDGE_GLOW = 4; this.separableBlurMaterial1 = this.getSeperableBlurMaterial( MAX_EDGE_THICKNESS ); this.separableBlurMaterial1.uniforms[ "texSize" ].value = new THREE.Vector2( resx, resy ); @@ -187,20 +196,17 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype } } */ + + // one array for each selection type + this._groups = Array.from(Array(THREE.OutlinePass.selection_enum.total), () => []); - this.groups = []; - // ES6 (could be replaced with vanilla Js) - this.sel = Array.from(Array(THREE.OutlinePass.selection_enum.total), () => []); - // this.sel = Array(THREE.OutlinePass.selection_enum.total).fill([]); - for (const obj of this.selectedObjects){ - // stored at the top level - obj.sel_type = (obj.sel_type == undefined) ? THREE.OutlinePass.selection_enum["highlight"] : obj.sel_type; - + // fill in "this._groups" + for (const obj of this._selectedObjects){ for(const geom of obj.geom){ - this.sel[obj.sel_type].push(geom); - this.parseAtts(geom, this.groups); + this.parseAtts(geom, this._groups[obj.sel_type]); } } + // for (let i = 0; i < this.selectedObjects.length; ++i){ // const object = this.selectedObjects[i]; @@ -250,12 +256,15 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype // groups[0].push(object); // } // } - // this.groups = groups.filter(Array); + // this._groups = groups.filter(Array); }, dispose: function () { - this.renderTargetMaskBuffer.dispose(); + this.renderTargetMaskBufferMain.dispose(); + for(const fbo of this.renderTargetMaskBuffer) + fbo.dispose(); + this.renderTargetDepthBuffer.dispose(); this.renderTargetMaskDownSampleBuffer.dispose(); this.renderTargetBlurBuffer1.dispose(); @@ -267,7 +276,9 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype setSize: function ( width, height ) { - this.renderTargetMaskBuffer.setSize( width, height ); + this.renderTargetMaskBufferMain.setSize( width, height ); + for(const fbo of this.renderTargetMaskBuffer) + fbo.setSize( width, height ); var resx = Math.round( width / this.downSampleRatio ); var resy = Math.round( height / this.downSampleRatio ); @@ -308,7 +319,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype } - for(const obj of (object || this.selectedObjects)){ + for(const obj of (object || this._selectedObjects)){ if(obj.geom){ for(const geom of obj.geom) geom.traverse( gatherSelectedMeshesCallBack ); @@ -329,7 +340,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype } - for(const obj of this.selectedObjects){ + for(const obj of this._selectedObjects){ for(const geom of obj.geom) geom.traverse( gatherSelectedMeshesCallBack ); } @@ -382,7 +393,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype }, - draw: function(renderer, writeBuffer, readBuffer, maskActive, group, index){ + draw: function(renderer, group, selection_type){ this.changeVisibilityOfSelectedObjects(true, group); if(group[0].type === "Points"){ @@ -390,19 +401,24 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype if(group[0]["vertShader"]) this.prepareMaskMaterial.vertexShader = group[0]["vertShader"]; if(group[0]["fragShader"]) this.prepareMaskMaterial.fragmentShader = group[0]["fragShader"]; } + renderer.setRenderTarget( this.renderTargetMaskBufferMain ); + renderer.render( this.renderScene, this.renderCamera ); + + renderer.setRenderTarget( this.renderTargetMaskBuffer[selection_type] ); + renderer.clear(); renderer.render( this.renderScene, this.renderCamera ); this.changeVisibilityOfSelectedObjects(false, group); }, render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { - this.selectedObjects = Object.values(this.id2obj_map).flat(); + this._selectedObjects = Object.values(this.id2obj_map).flat(); // console.log(this.selectedObjects); // debugger; - if ( this.selectedObjects.length > 0 ) { + if ( this._selectedObjects.length > 0 ) { // fetch objects that were created after secondary selection - let sec_sel = this.selectedObjects.map(function(v){ + let sec_sel = this._selectedObjects.map(function(v){ if(v.sec_sel) return v.geom; }); sec_sel = sec_sel.flat(); @@ -445,15 +461,16 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype this.prepareMaskMaterial.uniforms[ "depthTexture" ].value = this.renderTargetDepthBuffer.texture; this.prepareMaskMaterial.uniforms[ "textureMatrix" ].value = this.textureMatrix; - renderer.setRenderTarget( this.renderTargetMaskBuffer ); + renderer.setRenderTarget( this.renderTargetMaskBufferMain ); renderer.clear(); this.checkForCustomAtts(); - //console.log(this.groups); + //console.log(this._groups); - for(const group of this.groups){ - if(group.length > 0) - this.draw(renderer, writeBuffer, readBuffer, maskActive, group); + for(let i = 0; i < THREE.OutlinePass.selection_enum.total; ++i){ + for(const group of this._groups[i]) + if(group.length > 0) + this.draw(renderer, group, i); } // if(this.atts.total > 0){ @@ -479,40 +496,64 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype // enable all elements this.changeVisibilityOfSelectedObjects(true); - this.changeVisibilityOfNonSelectedObjects( true ); + this.changeVisibilityOfNonSelectedObjects(true); this.renderScene.background = currentBackground; // 2. Downsample to Half resolution - this.quad.material = this.materialCopy; - this.copyUniforms[ "tDiffuse" ].value = this.renderTargetMaskBuffer.texture; - renderer.setRenderTarget( this.renderTargetMaskDownSampleBuffer ); - renderer.clear(); - renderer.render( this.scene, this.camera ); - - this.changeVisibilityOfSelectedObjects(false); - this.quad.material = this.edgeDetectionMaterial; - this.edgeDetectionMaterial.uniforms[ "maskTexture" ].value = this.renderTargetMaskDownSampleBuffer.texture; - this.edgeDetectionMaterial.uniforms[ "texSize" ].value = new THREE.Vector2( this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height ); + // clear stuff renderer.setRenderTarget( this.renderTargetEdgeBuffer1 ); renderer.clear(); for(let i = 0; i < THREE.OutlinePass.selection_enum.total; ++i){ - const sel = this.sel[i]; - if(sel.length > 0){ - this.changeVisibilityOfSelectedObjects(true, sel); + let group = this._groups[i]; + if(group.length > 0){ + this.quad.material = this.materialCopy; + this.copyUniforms[ "tDiffuse" ].value = this.renderTargetMaskBuffer[i].texture; + renderer.setRenderTarget( this.renderTargetMaskDownSampleBuffer ); + renderer.clear(); + renderer.render( this.scene, this.camera ); + + // this.changeVisibilityOfSelectedObjects(false); + + // this.changeVisibilityOfSelectedObjects(true, group); // 3. Apply Edge Detection Pass + this.quad.material = this.edgeDetectionMaterial; + this.edgeDetectionMaterial.uniforms[ "maskTexture" ].value = this.renderTargetMaskDownSampleBuffer.texture; + this.edgeDetectionMaterial.uniforms[ "texSize" ].value = new THREE.Vector2( this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height ); + renderer.setRenderTarget( this.renderTargetEdgeBuffer1 ); + const att = THREE.OutlinePass.selection_atts[i]; this.edgeDetectionMaterial.uniforms[ "visibleEdgeColor" ].value = att.visibleEdgeColor; this.edgeDetectionMaterial.uniforms[ "hiddenEdgeColor" ].value = att.hiddenEdgeColor; renderer.render( this.scene, this.camera ); - this.changeVisibilityOfSelectedObjects(false, sel); + // this.changeVisibilityOfSelectedObjects(false, group); } + + // this.changeVisibilityOfSelectedObjects(true); } - this.changeVisibilityOfSelectedObjects(true); + + + + //>----------------- + // for(let i = 0; i < THREE.OutlinePass.selection_enum.total; ++i){ + // const sel = this.sel[i]; + // if(sel.length > 0){ + // this.changeVisibilityOfSelectedObjects(true, sel); + + // // 3. Apply Edge Detection Pass + // const att = THREE.OutlinePass.selection_atts[i]; + // this.edgeDetectionMaterial.uniforms[ "visibleEdgeColor" ].value = att.visibleEdgeColor; + // this.edgeDetectionMaterial.uniforms[ "hiddenEdgeColor" ].value = att.hiddenEdgeColor; + // renderer.render( this.scene, this.camera ); + + // this.changeVisibilityOfSelectedObjects(false, sel); + // } + // } + // this.changeVisibilityOfSelectedObjects(true); // 4. Apply Blur on Half res this.quad.material = this.separableBlurMaterial1; @@ -543,7 +584,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype // Blend it additively over the input texture this.quad.material = this.overlayMaterial; - this.overlayMaterial.uniforms[ "maskTexture" ].value = this.renderTargetMaskBuffer.texture; + this.overlayMaterial.uniforms[ "maskTexture" ].value = this.renderTargetMaskBufferMain.texture; this.overlayMaterial.uniforms[ "edgeTexture1" ].value = this.renderTargetEdgeBuffer1.texture; this.overlayMaterial.uniforms[ "edgeTexture2" ].value = this.renderTargetEdgeBuffer2.texture; this.overlayMaterial.uniforms[ "patternTexture" ].value = this.patternTexture; @@ -802,17 +843,17 @@ THREE.OutlinePass.selection_enum = { THREE.OutlinePass.selection_atts = [ { - visibleEdgeColor: new THREE.Color( 1, 0, 1 ), - hiddenEdgeColor: new THREE.Color( 1, 0, 1 ) - // hiddenEdgeColoe: new THREE.Color( 0.1, 0.04, 0.02 ) + visibleEdgeColor: new THREE.Color( 1, 0, 0 ), + hiddenEdgeColor: new THREE.Color( 1, 0, 0.5 ) + // hiddenEdgeColoe: new THREE.Color( 0.1, 0.04, 0.02 ) // edgeGlow: 0.0, // usePatternTexture: false, // edgeThickness: 1.0, // edgeStrength: 3.0, }, { - visibleEdgeColor: new THREE.Color( 0, 1, 1 ), - hiddenEdgeColor: new THREE.Color( 0, 1, 1 ) + visibleEdgeColor: new THREE.Color( 0, 1, 0 ), + hiddenEdgeColor: new THREE.Color( 0, 1, 0.5 ) // hiddenEdgeColor: new THREE.Color( 0.1, 0.04, 0.02 ) // edgeGlow: 0.0, // usePatternTexture: false, From f8b4f4f50d651e7768772c6d8f56067252915e8d Mon Sep 17 00:00:00 2001 From: Mourtz Date: Thu, 18 Apr 2019 17:34:40 +0200 Subject: [PATCH 12/15] undefined in Array cant be flattened --- ui5/eve7/lib/OutlinePass.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui5/eve7/lib/OutlinePass.js b/ui5/eve7/lib/OutlinePass.js index 1d7488f6e6d7e..74f7c1ee06f47 100644 --- a/ui5/eve7/lib/OutlinePass.js +++ b/ui5/eve7/lib/OutlinePass.js @@ -426,7 +426,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype // add sec_sel elements in renderScene for(const obj of sec_sel) - this.renderScene.add(obj); + if(obj) this.renderScene.add(obj); this.oldClearColor.copy( renderer.getClearColor() ); this.oldClearAlpha = renderer.getClearAlpha(); @@ -604,7 +604,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype // remove sec_sel elements from renderScene for(const obj of sec_sel) - this.renderScene.remove(obj); + if(obj) this.renderScene.remove(obj); } else { this.quad.material = this.materialCopy; this.copyUniforms[ "tDiffuse" ].value = readBuffer.texture; From ada6e108a1059234a89d005fa1ce354b5eccfcd1 Mon Sep 17 00:00:00 2001 From: alja Date: Tue, 23 Apr 2019 11:49:12 -0700 Subject: [PATCH 13/15] Create teo Straight line sets. --- tutorials/eve7/lineset.C | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/tutorials/eve7/lineset.C b/tutorials/eve7/lineset.C index 609d51a7b7e89..aa4616d61e9ff 100644 --- a/tutorials/eve7/lineset.C +++ b/tutorials/eve7/lineset.C @@ -1,5 +1,5 @@ /// \file -/// \ingroup tutorial_eve7 +/// \ingroup tutorial_eve /// Demonstrates usage of class REveStraightLineSet. /// /// \macro_code @@ -15,29 +15,43 @@ //#include namespace REX = ROOT::Experimental; -void lineset(Int_t nlines = 40, Int_t nmarkers = 4) -{ - auto eveMng = REX::REveManager::Create(); +REX::REveStraightLineSet* makeLineSet(Int_t nlines = 40, Int_t nmarkers = 4) +{ TRandom r(0); Float_t s = 100; auto ls = new REX::REveStraightLineSet(); - ls->SetMainColor(kBlue); - ls->SetMarkerColor(kRed); - for (Int_t i = 0; i < nlines; i++) { + for (Int_t i = 0; iAddLine( 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()); - for (Int_t m = 0; m < nm; m++) - ls->AddMarker(i, r.Rndm()); + for (Int_t m = 0; m < nm; m++) ls->AddMarker(i, r.Rndm()); } - ls->SetMarkerSize(1.5); - ls->SetMarkerStyle(4); - eveMng->GetEventScene()->AddElement(ls); + ls->SetMarkerSize(0.5); + ls->SetMarkerStyle(1); + REX::gEve->GetEventScene()->AddElement(ls); + + return ls; +} + +void lineset() +{ + auto eveMng = REX::REveManager::Create(); + + auto ls1 = makeLineSet(10, 50); + ls1->SetMainColor(kViolet); + ls1->SetName("LineSet_1"); + + auto ls2 = makeLineSet(3, 4); + ls2->SetMainColor(kBlue); + ls2->SetName("LineSet_2"); + //ls2->InitMainTrans(); + // ls2->RefMainTrans().Move3LF(40, 100, 100); + eveMng->Show(); } From 51f85ed48f698f4a67dfe33cb7aefe3f12b08747 Mon Sep 17 00:00:00 2001 From: alja Date: Tue, 23 Apr 2019 11:50:34 -0700 Subject: [PATCH 14/15] Alternate JSRootGeoPainter's ProcessMouseMove --- ui5/eve7/controller/GL.controller.js | 46 +++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/ui5/eve7/controller/GL.controller.js b/ui5/eve7/controller/GL.controller.js index 8d1681f3dc451..1e6ae8a777665 100644 --- a/ui5/eve7/controller/GL.controller.js +++ b/ui5/eve7/controller/GL.controller.js @@ -295,7 +295,8 @@ sap.ui.define([ var options = ""; - if (this.kind != "3D") options = "ortho_camera"; + // options += " black, "; + if (this.kind != "3D") options += "ortho_camera"; // TODO: should be specified somehow in XML file @@ -321,6 +322,49 @@ sap.ui.define([ this.geo_painter._camera.bottom = -this.getView().$().height(); this.geo_painter._camera.updateProjectionMatrix(); } + painter._controls.ProcessMouseMove = function(intersects) { + var active_mesh = null, tooltip = null, resolve = null, names = [], geo_object, geo_index; + + // try to find mesh from intersections + for (var k=0;k")==0) + info = painter.GetItemName() + info.substr(6); + + names.push(info); + + if (!active_mesh) { + active_mesh = obj; + tooltip = info; + geo_object = obj.geo_object; + if (obj.get_ctrl) { + geo_index = obj.get_ctrl().extractIndex(intersects[k]); + if ((geo_index !== undefined) && (typeof tooltip == "string")) tooltip += " indx:" + JSON.stringify(geo_index); + } + if (active_mesh.stack) resolve = painter.ResolveStack(active_mesh.stack); + } + } + + //painter.HighlightMesh(active_mesh, undefined, geo_object, geo_index); AMT override + if (active_mesh && active_mesh.get_ctrl()) active_mesh.get_ctrl().setHighlight( 0xffaa33, geo_index); + + if (painter.options.update_browser) { + if (painter.options.highlight && tooltip) names = [ tooltip ]; + painter.ActivateInBrowser(names); + } + + if (!resolve || !resolve.obj) return tooltip; + + var lines = JSROOT.GEO.provideInfo(resolve.obj); + lines.unshift(tooltip); + + return { name: resolve.obj.fName, title: resolve.obj.fTitle || resolve.obj._typename, lines: lines }; + } // this.geo_painter._highlight_handlers = [ this ]; // register ourself for highlight handling this.last_highlight = null; From da48c486ad30d9f7d36c7b2c539a8de4ac1b31ec Mon Sep 17 00:00:00 2001 From: alja Date: Tue, 23 Apr 2019 11:51:30 -0700 Subject: [PATCH 15/15] Compare previous and and current selections to reduce server updates and unnecessary redraws --- ui5/eve7/lib/EveManager.js | 121 +++++++++++++++++++++++-------------- ui5/eve7/lib/EveScene.js | 32 ++++++++-- 2 files changed, 101 insertions(+), 52 deletions(-) diff --git a/ui5/eve7/lib/EveManager.js b/ui5/eve7/lib/EveManager.js index f39a8fd4036a2..8633252733e43 100644 --- a/ui5/eve7/lib/EveManager.js +++ b/ui5/eve7/lib/EveManager.js @@ -301,11 +301,11 @@ sap.ui.define([], function() { var mother = this.GetElement(motherId); var mc = mother.childs; for (var i = 0; i < mc.length; ++i) { - + if (mc[i].fElementId === elId) { mc.splice(i, 1); } - } + } delete this.map[elId]; delSet.delete(elId); @@ -315,7 +315,7 @@ sap.ui.define([], function() { } //______________________________________________________________________________ - + EveManager.prototype.ImportSceneChangeJson = function(msg) { var arr = msg.arr; @@ -329,12 +329,12 @@ sap.ui.define([], function() { // notify for element removal var removedIds = msg.header["removedElements"]; - // do we need this? -- AMT this is intended to freeze redraws + // do we need this? -- AMT this is intended to freeze redraws this.callSceneReceivers(scene, "beginChanges"); // notify controllers this.callSceneReceivers(scene, "elementsRemoved", removedIds); - + var delSet = new Set(); for (var r = 0; r < removedIds.length; ++r) { var id = removedIds[r]; @@ -347,8 +347,8 @@ sap.ui.define([], function() { console.log("going to call RecursiveRemove .... ", this.map[id]); this.RecursiveRemove(this.GetElement(id), delSet); console.log("complete RecursiveREmove ", delSet); - } - + } + // wait for binary if needed if (msg.header.fTotalBinarySize) { @@ -440,7 +440,7 @@ sap.ui.define([], function() { var treeRebuild = header.removedElements.length || (arr.length != nModified ); if (treeRebuild) this.InvokeReceivers("update", null, 0, this); - + this.callSceneReceivers(scene, "endChanges", treeRebuild); }, @@ -581,64 +581,93 @@ sap.ui.define([], function() { { if (el.fName == "Global Selection") this.global_selection_id = el.fElementId; if (el.fName == "Global Highlight") this.global_highlight_id = el.fElementId; - - // el._selection_set = new Set; - el._is_registered = true; el.prev_sel_list = []; } - console.log("And now process the bloody selection.", el.prev_sel_list, el.sel_list) - - // Outline of optimized selection update (to avoid recreating selected - // representations). - /* - all_new_selected = generate_full_selection_set(el['sel_list']); + console.log("==============================And now process the bloody selection.", el.prev_sel_list, el.sel_list); + + var oldMap = new Map(); + el.prev_sel_list.forEach(function(rec) { + var iset = new Set(rec.sec_idcs); + var x = {"valid" : true, "implied" : rec.implied, "set":iset }; + oldMap.set(rec.primary, x); + }); + console.log("-- oldMap", oldMap); + + var newMap = new Map ; + el.sel_list.forEach(function(rec) { + console.log("add new primary ", rec.primary); + var iset = new Set(rec.sec_idcs); + var x = {"valid" : true, "implied" : rec.implied, "set":iset }; + newMap.set(rec.primary, x); + }); + console.log("-- newMap --", newMap); + + + // remove identicals from old and new map + for ( var id in oldMap ) { + if (id in newMap) { + var oldSet = oldMap[id].set; + var newSet = newMap[id].set; + + var nm = 0; + for (var elem of oldSet) { + if (newSet.delete(elem)) { + nm++; + } + } - for (xx in el['prev_all_selected'] and not in all_new_selected) - { - deselect(xx); - } - for (xx in all_new_selected) - { - if (xx not in el['prev_all_selected']) - { - select(xx); - } - else - { - // implied selected set or secondary indices can change. - check_if_select_records_are_the_same_and_update_if_needed(); + // invalidate if sets are empty or identical + if (nm == oldSet.length && newSet.length == 0) { + oldMap[id].valid = false; + newMap[id].valid = false; + // console.log("EveManager.prototype.UT_Selection_Refresh_State identical sets for primary", id); + } } } - el['prev_all_selected'] = all_new_selected; - */ - - // Dummy update --- unselect all, select all. - for (var srec of el.prev_sel_list) - { - this.UnselectElement(el, srec.primary); - - for (var sel of srec.implied) + var pthis = this; + var changedSet = new Set(); + for (var [id, value] of oldMap.entries()) { + console.log("unselect ", el.fName, " id == ", id); + this.UnselectElement(el, id); + var iel = pthis.GetElement(id); + changedSet.add(iel.fSceneId); + for (var imp of value.implied) { - this.UnselectElement(el, sel); + this.UnselectElement(el, imp); + changedSet.add(pthis.GetElement(imp).fSceneId); } } - for (var srec of el.sel_list) - { - this.SelectElement(el, srec.primary, srec.sec_idcs); + for (var [id, value] of newMap.entries()) { + var secIdcs = Array.from(value.set); + var iel = pthis.GetElement(id); + if (!iel) { + // console.log("EveManager.prototype.UT_Selection_Refresh_State this should not happen ", iel); + continue; + } + changedSet.add(iel.fSceneId); + this.SelectElement(el, id, secIdcs); - for (sel of srec.implied) + for (var imp of value.implied) { - this.SelectElement(el, sel, srec.sec_idcs); + this.SelectElement(el, imp, secIdcs); + changedSet.add(pthis.GetElement(imp).fSceneId); } } el.prev_sel_list = el.sel_list; el.sel_list = []; + // redraw + for (let item of changedSet) { + console.log(item); + var scene = this.GetElement(item); + this.callSceneReceivers(scene, "endChanges"); + } + // XXXX Oh, blimy, on first arrival, if selection is set, the selected // elements have not yet been received and so this will fail. Also true // for newly subscribed scenes, once we start supporting this. diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index f95c763262e70..3c0006196ca1d 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -343,11 +343,34 @@ sap.ui.define([ /** interactive handler */ EveScene.prototype.processElementHighlighted = function(obj3d, col, indx, evnt) { - console.log("EveScene.prototype.processElementHighlighted", obj3d, col, indx, evnt); - + // Need check for duplicates before call server, else server will un-higlight highlighted element + // console.log("EveScene.prototype.processElementHighlighted", obj3d, col, indx, evnt); var is_multi = false; var is_secsel = indx !== undefined; + var so = this.mgr.GetElement(this.mgr.global_highlight_id); + var a = so.prev_sel_list; + + // AMT presume there is no multiple highlight and multiple secondary selections + // if that is the case in the futre write data in set and comapre sets + + // console.log("EveScene.prototype.processElementHighlighted compare Reveselection ", a[0], "incoming ", obj3d.eveId,indx); + if (a.length == 1 ) { + var h = a[0]; + if (h.primary == obj3d.eveId || h.primary == obj3d.mstrId ) { + if (indx) { + if (h.sec_idcs && h.sec_idcs[0] == indx) { + // console.log("EveScene.prototype.processElementHighlighted processElementHighlighted same index "); + return true; + } + } + if (!indx && !h.sec_idcs.length) { + // console.log("processElementHighlighted primARY SElection not changed "); + return true; + } + } + } + var fcall = "NewElementPicked(" + obj3d.eveId + `, ${is_multi}, ${is_secsel}`; if (is_secsel) { @@ -355,6 +378,7 @@ sap.ui.define([ } fcall += ")"; + this.mgr.SendMIR({ "mir": fcall, "fElementId": this.mgr.global_highlight_id, "class": "REX::REveSelection" @@ -492,8 +516,6 @@ sap.ui.define([ res.sec_sel = true; } dest[element_id] = res; - - this.viewer.render(); } EveScene.prototype.UnselectElement = function(selection_obj, element_id) @@ -501,8 +523,6 @@ sap.ui.define([ if (selection_obj.fElementId in this.viewer.outlinePass.id2obj_map) { delete this.viewer.outlinePass.id2obj_map[selection_obj.fElementId][element_id]; - - this.viewer.render(); } }