diff --git a/builtins/rendercore/RenderCore.tar.gz b/builtins/rendercore/RenderCore.tar.gz new file mode 100644 index 0000000000000..2083c5708433a Binary files /dev/null and b/builtins/rendercore/RenderCore.tar.gz differ diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index 5559cd8e7a80e..503223a6d311e 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -2145,6 +2145,17 @@ if(webgui) endif() install(DIRECTORY ${CMAKE_BINARY_DIR}/ui5/distribution/ DESTINATION ${CMAKE_INSTALL_OPENUI5DIR}/distribution/ COMPONENT libraries FILES_MATCHING PATTERN "*") endif() + ExternalProject_Add( + RENDERCORE + URL ${CMAKE_SOURCE_DIR}/builtins/rendercore/RenderCore.tar.gz + URL_HASH SHA256=a0b1cc0d4e8d739b113ace87e33de77572cf019772899549cb082088943513e1 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + SOURCE_DIR ${CMAKE_BINARY_DIR}/ui5/eve7/rcore + TIMEOUT 600 + ) + install(DIRECTORY ${CMAKE_BINARY_DIR}/ui5/eve7/rcore/ DESTINATION ${CMAKE_INSTALL_OPENUI5DIR}/eve7/rcore/ COMPONENT libraries FILES_MATCHING PATTERN "*") endif() #------------------------------------------------------------------------------------ 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/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/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/inc/ROOT/REveManager.hxx b/graf3d/eve7/inc/ROOT/REveManager.hxx index 022de4f4d7fbc..e0b35de7bf996 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); @@ -253,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. @@ -266,6 +270,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..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; @@ -45,6 +47,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/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/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); } } 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()); 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/REveManager.cxx b/graf3d/eve7/src/REveManager.cxx index f0def3d183695..a8dd8830f08ff 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); @@ -142,13 +144,16 @@ 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); 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); }, @@ -158,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); } //////////////////////////////////////////////////////////////////////////////// @@ -939,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(); } @@ -1112,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/graf3d/eve7/src/REvePointSet.cxx b/graf3d/eve7/src/REvePointSet.cxx index 5d1fbf7969ee0..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,8 +67,11 @@ REvePointSet::REvePointSet(const REvePointSet& e) : REveElement(e), REveProjectable(e), TAttMarker(e), - TAttBBox(e) + TAttBBox(e), + REveSecondarySelectable() { + fAlwaysSecSelect = e.GetAlwaysSecSelect(); + ClonePoints(e); } //////////////////////////////////////////////////////////////////////////////// @@ -208,10 +213,19 @@ 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(); + j["fSecondarySelect"] = fAlwaysSecSelect; return ret; } @@ -223,8 +237,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); + } } } @@ -544,6 +567,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/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/graf3d/eve7/src/REveSelection.cxx b/graf3d/eve7/src/REveSelection.cxx index fa0efce754b6c..86ddbaa89d7be 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(); @@ -715,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 (imp_el->RequiresExtraSelectionData()) + imp_el->FillExtraSelectionData(rec["extra"], sec); } rec["implied"] = imp; @@ -728,7 +717,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/graf3d/eve7/src/REveStraightLineSet.cxx b/graf3d/eve7/src/REveStraightLineSet.cxx index 2ff64a80cc34e..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" @@ -162,12 +163,21 @@ 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; + 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/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 dd3e64005ac88..a7128b05ab5eb 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; } @@ -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,12 +136,12 @@ 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)); jet->SetFillColor(kPink - 8); - jet->SetLineColor(kViolet - 7); + jet->SetLineColor(kBlack); jetHolder->AddElement(jet); } @@ -159,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). @@ -199,16 +201,22 @@ 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); } } if (eventp) { + int depth = 50; for (auto &ie : eveMng->GetEventScene()->RefChildren()) { + mngRhoPhi->SetCurrentDepth(depth); mngRhoPhi->ImportElements(ie, rPhiEventScene); + mngRhoZ ->SetCurrentDepth(depth); mngRhoZ ->ImportElements(ie, rhoZEventScene); + depth -= 10; } } @@ -252,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/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/tutorials/eve7/points.C b/tutorials/eve7/points.C index 8e51cedaa0e77..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; } @@ -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/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(); 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({ 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) { 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/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/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/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/EveElements.js b/ui5/eve7/lib/EveElements.js index 9e1d8cbb9dcbe..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,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 d17468ebde608..05beebf349657 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -9,48 +9,467 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // EveElemControl //============================================================================== - class EveElemControl { - + class EveElemControl + { - constructor(o3d) + constructor(iobj, tobj) { - this.obj3d = o3d; + this.invoke_obj = iobj; + this.top_obj = tobj ? tobj : iobj; } - invokeSceneMethod(fname, arg) + invokeSceneMethod(fname, arg, event) { - if ( ! this.obj3d) return false; + if ( ! this.top_obj || ! this.top_obj.eve_el) return false; - let s = this.obj3d.scene; + let s = this.top_obj.scene; if (s && (typeof s[fname] == "function")) - return s[fname](this.obj3d, arg, this.event); + return s[fname](this.top_obj.eve_el, arg, event); return false; } - getTooltipText(intersect) + getTooltipText() { - let el = this.obj3d.eve_el; + let el = this.top_obj.eve_el; return el.fTitle || el.fName || ""; } - elementHighlighted(indx) + extractIndex(instance) + { + return instance; + } + + 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) + { + if (this.top_obj.eve_el.fSecondarySelect) { + if (sec_idcs.length > 0) { + 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(); + } + } + else + { + res.geom.push(this.top_obj); + } } } // class EveElemControl - /// is it necessary? - EveElemControl.prototype.separateDraw = false; + + // =================================================================================== + // Digit sets control classes + // =================================================================================== + + class BoxSetControl extends EveElemControl + { + DrawForSelection(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 idxBuff = []; + + 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]; + let idxOff = idx * indicesPerDigit; + for (let i = 0; i < protoIdcsLen; i++) { + idxBuff.push(idxOff + origIndices.array[i]); + } + } + + body.indices = RC.Uint32Attribute(idxBuff, 1); + 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); + } + + 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) + { + let boxset = this.top_obj.eve_el; + let scene = this.top_obj.scene; + let multi = 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, event) + { + return this.elementSelectedSendMIR(idx, this.top_obj.scene.mgr.global_selection_id, event); + } + + elementHighlighted(idx, event) + { + return this.elementSelectedSendMIR(idx, this.top_obj.scene.mgr.global_highlight_id, event); + } + + checkHighlightIndex(idx) // XXXX ?? MT Sept-2022 + { + 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) + { + 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 == eve_el.fElementId) { + cells = extra[i].cells; + break; + } + } + + let rnr_data = eve_el.render_data; + let ibuff = rnr_data.idxBuff; + let nbox = ibuff.length / 2; + let nBoxSelected = parseInt(cells.length); + let boxIdcs = []; + 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 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(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 = 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]; + } + + // fix top corners, select can be partial + for (let c = 0; c < 4; c++) { + // fix vertex 1 + 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]; + 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 = 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 + + 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); + + console.log(body, mesh, res); + } + + extractIndex(instance) + { + return Math.floor(instance / 8); + } + + 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) ); + } + + return caloData.sliceInfos[slice].name + "\n" + Math.floor(val*100)/100 + + " ("+ Math.floor(eta*100)/100 + ", " + Math.floor(phi*100)/100 + ")"; + } + + elementSelected(idx, event) + { + 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, event) + { + 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) + { + let eve_el = this.invoke_obj.eve_el; + let cells; + for (let i = 0; i < extra.length; i++) { + if (extra[i].caloVizId == eve_el.fElementId) { + cells = extra[i].cells; + break; + } + } + 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 = []; + 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]; + 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 = 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; + mesh._material = this.invoke_obj._material; + + res.geom.push(mesh); + } + + extractIndex(instance) + { + return Math.floor(instance / 4); + } + + getTooltipText(idx) + { + 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 + ")"; + } + } + + 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.top_obj.scene.mgr.global_selection_id, event); + } + + elementHighlighted(idx, event) + { + return this.elementSelectedSendMIR(idx, this.top_obj.scene.mgr.global_highlight_id, event); + } + + } // class Calo2Control + //============================================================================== // EveElements @@ -65,40 +484,124 @@ 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. + // get_ctrl property needs to be set at least at the top-level object. + + class EveElements + { + constructor(rc, viewer) + { + if (viewer._logLevel >= 2) + console.log("EveElements -- RCore instantiated."); - class EveElements { + RC = rc; + this.viewer = viewer; - constructor(rc) { - console.log("EveElements -- RCore"); + RC.Cache.enabled = true; - RC = rc; + this.tex_cache = new RC.TextureCache; 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) + //---------------------------------------------------------------------------- + // Helper functions + //---------------------------------------------------------------------------- + + GenerateTypeName(obj) { return "RC." + obj.type; } + + 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; } + 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; + } + + RcCol(root_col) + { + return RcCol(root_col); + } + + 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; + mat.lineWidth = this.LINE_WIDTH_FAC; + if (line_width !== undefined) mat.lineWidth *= line_width; + if (props !== undefined) { + mat.update(props); } - if (props !== undefined) - { + return mat; + } + + RcFlatMaterial(color, opacity, props) + { + 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) { + mat._opacity = opacity; + mat._transparent = true; + mat._depthWrite = false; + } + if (props !== undefined) { mat.update(props); } return mat; @@ -110,28 +613,110 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) // let mat = new RC.MeshBasicMaterial; mat._color = color; - if (opacity !== undefined && opacity < 1.0) - { + mat._specular = new RC.Color(0.3, 0.4, 0.3); // this.ColorWhite; + mat._shininess = 64; + + 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; } - RcPickable(el, obj3d, ctrl_class = EveElemControl) + RcMakeZSprite(colIdx, sSize, nInstance, vbuff, instX, instY, textureName) + { + 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, + emissive: col, + diffuse: col.clone().multiplyScalar(0.5) } ); + sm.transparent = true; + + sm.addInstanceData(new RC.Texture(vbuff, + 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; + + 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. + sSize *= this.SSAA; + sm.setUniform("SpriteSize", [sSize, sSize]); + + this.GetLumAlphaTexture(textureName, this.AddMapToAllMaterials.bind(this, s)); + + return s; + } + + 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 * this.SSAA, + color: this.ColorBlack, + emissive: line_color + }), + GBufferMaterial: null + } + ); + s.lights = false; + return s; + } + + RcApplyStripesMaterials(eve_el, stripes, pick_width_scale = 2) + { + if (eve_el.fPickable) { + let m = stripes.material; + stripes.pickingMaterial = new RC.StripesBasicMaterial( + { lineWidth: m.lineWidth * pick_width_scale / this.SSAA, + 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; + pm.deltaOffset = m.deltaOffset; + + stripes.outlineMaterial = new RC.StripesBasicMaterial( + { lineWidth: m.lineWidth / this.SSAA, 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) { - obj3d.get_ctrl = function() { return new ctrl_class(obj3d); } - obj3d.colorID = el.fElementId; - // console.log("YES Pickable for", el.fElementId, el.fName) + 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) + obj3d.children[i].pickable = true; + } + // using RCore auto-id to get Object3D that got picked. return true; } else { - // console.log("NOT Pickable for", el.fElementId, el.fName) return false; } } @@ -146,6 +731,52 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return true; } + GetLumAlphaTexture(name, callback) + { + let url = this.viewer.eve_path + 'textures/' + name; + + this.tex_cache.deliver(url, + callback, + (image) => { + return new RC.Texture + (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() } + ); + } + + GetRgbaTexture(name, callback) + { + let url = this.viewer.eve_path + 'textures/' + name; + + this.tex_cache.deliver(url, + callback, + (image) => { + return new RC.Texture + (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() } + ); + } + + 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 + //---------------------------------------------------------------------------- //============================================================================== // makeHit @@ -155,32 +786,15 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) { if (this.TestRnr("hit", hit, rnr_data)) return null; - 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) - let col = RcCol(hit.fMarkerColor); - - let mat = new RC.MeshBasicMaterial; - mat.color = col; - mat.pointSize = size; - mat.usePoints = true; - mat.drawCircles = true; - - let pnts = new RC.Point(geo, mat); - - let pm = pnts.pickingMaterial; - pm.pointSize = size; - pm.usePoints = true; - pm.drawCircles = true; + let s = this.RcMakeZSprite(hit.fMarkerColor, hit.fMarkerSize, hit.fSize, + rnr_data.vtxBuff, hit.fTexX, hit.fTexY, + "star5-32a.png"); - // mesh.get_ctrl = function() { return new EveElemControl(this); } + this.RcPickable(hit, s); - this.RcPickable(hit, pnts); - return pnts; + return s; } - //============================================================================== // makeTrack //============================================================================== @@ -190,10 +804,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) @@ -218,7 +832,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]; @@ -228,32 +843,13 @@ 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); + + const line = this.RcMakeStripes(geom, track_width, track_color); + this.RcApplyStripesMaterials(track, line, 2); this.RcPickable(track, line); + return line; } @@ -280,7 +876,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; @@ -302,17 +898,18 @@ 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; let line2 = new RC.Line(geo_rays, this.RcLineMaterial(lcol, 0.8, 1)); line2.renderingPrimitive = RC.LINES; mesh.add(line1); mesh.add(line2); + this.RcPickable(jet, mesh, false); - // mesh.get_ctrl = function () { return new EveElemControl(this); } - this.RcPickable(jet, mesh); return mesh; } @@ -334,7 +931,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; @@ -351,30 +948,302 @@ 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.RcFancyMaterial(fcol, 0.5)); - let line1 = new RC.Line(geo_rim, this.RcLineMaterial(lcol, 0.8, 2)); - - let line2 = new RC.Line(geo_rays, this.RcLineMaterial(lcol, 0.8, 0.5)); - line2.renderingPrimitive = RC.LINES; + let mesh = new RC.Mesh(geo_body, this.RcFlatMaterial(fcol, 0.5)); + mesh.material.normalFlat = true; + 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); - // mesh.get_ctrl = function () { return new EveElemControl(this); } - this.RcPickable(jet, mesh); return mesh; } + //============================================================================== + // make Digits + //============================================================================== + + makeBoxSet(boxset, rnr_data) + { + if (this.TestRnr("boxset", boxset, rnr_data)) return null; + + let vBuff; + let idxBuff; + let nVerticesPerDigit = 0; + + if (boxset.boxType == 6) // hexagon + { + 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]; + + 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; + 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 }); + mat.normalFlat = true; + if ( ! boxset.fSingleColor) + { + let ci = rnr_data.idxBuff; + 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 < nVerticesPerDigit; ++i) + { + 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 { + mat.color = RcCol(boxset.fMainColor); + } + + let mesh = new RC.Mesh(body, mat); + this.RcPickable(boxset, mesh, false, boxset.fSecondarySelect ? BoxSetControl : EveElemControl); + + return mesh; + } + //============================================================================== + // make Calorimeters + //============================================================================== + + makeCalo3D(calo3D, rnr_data) + { + if (this.TestRnr("calo3D", calo3D, rnr_data)) return null; + let body = new RC.Geometry(); + 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(); + + 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); + + let mat = this.RcFancyMaterial(this.ColorBlack, 1.0, { side: RC.FRONT_SIDE }); + mat.useVertexColors = true; + mat.normalFlat = true; + + let mesh = new RC.Mesh(body, mat); + + this.RcPickable(calo3D, mesh, false, Calo3DControl); + + return mesh; + } + + makeCalo2D(calo2D, rnrData) + { + if (this.TestRnr("calo2D", calo2D, rnrData)) return null; + let body = new RC.Geometry(); + 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 = 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); + + let mat = this.RcFlatMaterial(this.ColorBlack, 1); + mat.useVertexColors = true; + let mesh = new RC.Mesh(body, mat); + + this.RcPickable(calo2D, mesh, false, Calo2DControl); + + return mesh; + } //============================================================================== // makeEveGeometry / makeEveGeoShape //============================================================================== - makeEveGeometry(rnr_data) + makeEveGeometry(rnr_data, compute_normals) { let nVert = rnr_data.idxBuff[1] * 3; @@ -383,9 +1252,14 @@ 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); - geo.computeVertexNormalsIdxRange(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); + } // 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. @@ -401,16 +1275,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; } @@ -430,13 +1304,12 @@ 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); + let meshes = []; for (let ib_pos = 0; ib_pos < ib_len;) { if (rnr_data.idxBuff[ib_pos] == GL.TRIANGLES) @@ -450,6 +1323,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]; } @@ -473,6 +1347,19 @@ 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; + } + 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; } @@ -481,71 +1368,61 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) makeStraightLineSet(el, rnr_data) { - console.log("makeStraightLineSet ..."); + // console.log("makeStraightLineSet ..."); 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 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); + 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); obj3d.add(line); // ---------------- 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; + } + let marker = this.RcMakeZSprite(el.fMainColor, el.fMarkerSize, nPnts, + p_buf, el.fTexX, el.fTexY, + "star5-32a.png"); + obj3d.add(marker); + } + // For secondary selection, see EveElements.js + // 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); + }; + return octrl; } - - let p_geom = new RC.Geometry(); - 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; - - let marker = new RC.Point(p_geom, p_mat); - marker.pickingMaterial.pointSize = 2 * el.fMarkerSize;; - - this.RcPickable(el, marker); - obj3d.add(marker); - - // ???? - 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; }; - */ return obj3d; } @@ -554,6 +1431,7 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) //============================================================================== - return EveElements; + EVE.EveElements = EveElements; + return EveElements; }); diff --git a/ui5/eve7/lib/EveManager.js b/ui5/eve7/lib/EveManager.js index 8015bf269fc5f..4e31ee20d4238 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; } @@ -56,6 +54,7 @@ sap.ui.define([], function() { UseConnection(handle) { this.handle = handle; + this.is_rcore = (handle.getUserArgs("GLViewer") == "RCore"); handle.setReceiver(this); handle.connect(); @@ -146,8 +145,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); @@ -201,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() { @@ -427,11 +445,21 @@ sap.ui.define([], function() { let lastoff = offset; - for (let n=1; n 0) cont.remove(cont.children[0]); + this.mgr.UnRegisterSceneReceiver(this.id, this); this.first_time = true; } @@ -184,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) @@ -195,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) @@ -251,10 +262,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); - 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(); + } } } @@ -264,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 @@ -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)) + // 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, 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 + // when send queue below threshold, ignore 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; } @@ -395,59 +394,107 @@ 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 opass = this.glctrl.viewer.outline_pass; - opass.id2obj_map[element_id] = opass.id2obj_map[element_id] || []; + let outline_map = this.glctrl.viewer.outline_map; + // console.log("EveScene.SelectElement ", selection_obj.fName, element_id, selection_obj.fElementId, outline_map); - if (opass.id2obj_map[element_id][selection_obj.fElementId] !== undefined) - { + outline_map[element_id] = outline_map[element_id] || []; + + if (outline_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 && + outline_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) outline_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); + } + outline_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) + UnselectElementStd(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 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]; + } + } + + 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/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 eac9058485557..37a07ef26d2eb 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -5,7 +5,8 @@ sap.ui.define([ "use strict"; - let RC, RP, RendeQuTor; + let RC; + let datGUI; class GlViewerRCore extends GlViewer { @@ -15,21 +16,29 @@ sap.ui.define([ const urlParams = new URLSearchParams(window.location.search); - console.log("XXXX", window.location.search, 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')); + let marker_scale = /^([\d\.]+)$/. exec(urlParams.get('RQ_MarkerScale')); + let line_scale = /^([\d\.]+)$/. exec(urlParams.get('RQ_LineScale')); - 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_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/'; + + this._logLevel = 1; // 0 - error, 1 - warning, 2 - info, 3 - debug - this.RQ_Mode = (mode_mm) ? mode_mm[0] : "Simple"; - this.RQ_SSAA = (ssaa_mm) ? ssaa_mm[0] : 2; + 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); } - console.log("UseRenderQueue", this.UseRenderQueue, "RQ_Mode", this.RQ_Mode, "RQ_SSAA", this.RQ_SSAA); + this._selection_map = {}; + this._selection_list = []; } init(controller) @@ -38,6 +47,14 @@ sap.ui.define([ let pthis = this; + 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); + } + // For offline mode, one needs a a full URL or the request // gets forwarded to openi5.hana.ondemand.com. // This has to be understood and fixed. Loading of shaders @@ -45,43 +62,38 @@ 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) => { - 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 { + 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(); + } } bootstrap() { - this.creator = new EveElements(RC); + 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(); this.controller.redrawScenes(); - this.setupRCoreDomAndEventHandlers(); + 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); + cleanup() { + if (this.controller) this.controller.removeScenes(); + super.cleanup(); } //============================================================================== @@ -102,122 +114,147 @@ sap.ui.define([ createRCoreRenderer() { - let w = this.get_width(); - let h = this.get_height(); - - //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; - - // 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); - - 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/shaders"); - this.renderer.pickDoNotRender = true; + 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"; + // 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 }); + this.renderer._logLevel = 0; + this.renderer.clearColor = "#FFFFFF00"; // "#00000000"; + this.renderer.addShaderLoaderUrls(this.eve_path + RC.REveShaderPath); + this.renderer.pickObject3D = true; + + // add dat GUI option to set background + 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; + 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(); - 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.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; - 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()) { - this.camera = new RC.PerspectiveCamera(75, w / h, 1, 5000); - 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 = new RC.PerspectiveCamera(75, w / h, 20, 4000); this.camera.isPerspectiveCamera = true; - let l_int = 0.85; - 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_int = 1.4; + 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. - 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.lookAt(new RC.Vector3(0, 0, 0), new RC.Vector3(0, 1, 0)); + this.camera = new RC.OrthographicCamera(-w/2, w/2, -h/2, h/2, 20, 2000); 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(light_2d_ctor(0xffffff, l_int)); // white front + // this.lights.add(light_2d_ctor(0xffffff, l_int)); // white back // 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.kind === "3D") + if (this.controller.isEveCameraPerspective()) { - /* - let c = new RC.Cube(100, new RC.Color(1,.6,.2)); - c.material = new RC.MeshPhongMaterial(); - c.material.transparent = true; - c.material.opacity = 0.5; - c.material.depthWrite = false; - this.scene.add(c); - */ - let ss = new RC.Stripe([0,0,0, 100,50,50, 100,200,200]); - ss.material.lineWidth = 20.0; - ss.material.color = new RC.Color(0xff0000); - this.scene.add(ss); + // 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); + // this.scene.add(ss); } 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 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_MarkerScale * this.canvas.pixelRatio, + this.RQ_LineScale * this.canvas.pixelRatio); } + else + { + this.rqt.initFull(this.RQ_SSAA); + this.creator.SetupPointLineFacs(this.RQ_SSAA, + this.RQ_MarkerScale * this.canvas.pixelRatio, + this.RQ_LineScale * this.canvas.pixelRatio); + } + this.rqt.updateViewport(w, h); } - setupRCoreDomAndEventHandlers() + setupEventHandlers() { - let dome = this.get_view().getDomRef(); - dome.appendChild(this.canvas); + 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; @@ -229,11 +266,11 @@ sap.ui.define([ glc.removeMouseupListener(); - if (event.buttons === 0) { + 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); } else { - glc.clearHighlight(); + // glc.clearHighlight(); } }); @@ -247,7 +284,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); @@ -256,11 +293,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)); } @@ -277,7 +314,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; @@ -331,10 +367,28 @@ 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.canvas.canvasDOM); 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(); } @@ -357,31 +411,27 @@ 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.controller.kind === "3D") // (this.camera.isPerspectiveCamera) + 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; - 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; - - // console.log("resetThreejsRenderer 3D scene bbox ", sbbox, ", camera_pos ", posC, ", look_at ", this.rot_center); + // 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); + lc[5].position.set(0, -extR, 0); + + // 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; @@ -398,66 +448,196 @@ 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("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 ); - // this.composer.reset(); + this.controls.setFromBBox(sbbox); this.controls.update(); } //============================================================================== + request_render() + { + // console.log("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); - if (this.UseRenderQueue) - this.rqt.render(); - else - this.renderer.render( this.scene, this.camera ); + this.render_requested = false; + + if (this.canvas.width <= 0 || this.canvas.height <= 0) return; + + 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 ]; + + let obj_list = this.rqt.RP_GBuffer.obj_list; + // let instance_list = []; + + 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 + + if (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) { + if (geo === undefined) + console.warning("Processing viewer selection, undefined object for element", this.mgr.GetElement(el_idx)); + else + obj_list.push(geo); + } + } + } + + 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_main_and_blend_outline(); + + 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(); + + 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); + } // if (this.controller.kind === "3D") // 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); - let o3d; + // console.log("RENDER FOR PICKING", this.scene, this.camera, this.canvas, this.renderer); + + if (this.canvas.width <= 0 || this.canvas.height <= 0) return null; - this.renderer.pick(x, y, function(id) { o3d = id; } ); - this.rqt.pick(this.scene, this.camera); + this.rqt.pick_begin(x, y); - // Render to FBO or texture would work. - // let d = pthis.renderer.pickedDepth; - console.log("pick result", o3d /* , d */); - return o3d; + let state = this.rqt.pick(x, y, detect_depth); + + if (state.object === null) { + this.rqt.pick_end(); + 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.rqt.pick_end(); + + 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 ); + + let ctrl_obj = state.object; + while (ctrl_obj.get_ctrl === undefined) + ctrl_obj = ctrl_obj.parent; + + state.ctrl = ctrl_obj.get_ctrl(ctrl_obj, top_obj); + + // console.log("pick result", state); + return state; } //============================================================================== - onResizeTimeout() + get selection_map() { return this._selection_map; } + + remove_selection_from_list(sid) { - let w = this.get_width(); - let h = this.get_height(); + let idx = this._selection_list.indexOf(sid); + if (idx >= 0) + this._selection_list.splice(idx,1); + } - //console.log("GlViewerRCore onResizeTimeout", w, h, "canvas=", this.canvas, this.canvas.width, this.canvas.height); + make_selection_last_in_list(sid) + { + this.remove_selection_from_list(sid); + this._selection_list.push(sid); + } - this.canvas.width = w; - this.canvas.height = h; + //============================================================================== - this.camera.aspect = w / h; + fixCssSize() { + let s = this.canvas.canvasDOM.style; + s.width = this.canvas.canvasDOM.clientWidth + "px"; + s.height = this.canvas.canvasDOM.clientHeight + "px"; + } - this.renderer.updateViewport(w, h); + floatCssSize() { + let s = this.canvas.canvasDOM.style; + s.width = "100%"; + s.height = "100%"; + } - if (this.UseRenderQueue) this.rqt.updateViewport(w, h); + onResizeTimeout() + { + if ( ! this.canvas) { + if (this._logLevel >= 2) + console.log("GlViewerRCore onResizeTimeout -- canvas is not set yet."); + return; + } + + 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.camera.aspect = w / h; + this.rqt.updateViewport(w, h); this.controls.update(); + this.render(); + + this.fixCssSize(); } @@ -471,10 +651,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"; } @@ -489,87 +669,59 @@ 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) - { - 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]; - } - } - */ - } - onMouseMoveTimeout(x, y) { delete this.mousemove_timeout; - let intersect = this.getIntersectAt(x,y); + let pstate = this.render_for_picking(x * this.canvas.pixelRatio, y * this.canvas.pixelRatio, false); - if ( ! intersect) + if ( ! pstate) return this.clearHighlight(); - let c = intersect.object.get_ctrl(); - - let mouse = intersect.mouse; + let c = pstate.ctrl; + let idx = c.extractIndex(pstate.instance); - // c.elementHighlighted(c.extractIndex(intersect)); + c.elementHighlighted(idx, null); - this.highlighted_scene = c.obj3d.scene; - - if (c.obj3d && c.obj3d.eve_el) - this.ttip_text.innerHTML = c.getTooltipText(intersect); - 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(idx); + else + this.ttip_text.innerHTML = ""; + } + this.highlighted_top_object = pstate.top_object; - 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 = (this.canvas.canvasDOM.clientWidth - 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 = (this.canvas.canvasDOM.clientHeight - y + offs.bottom + 10) + "px"; this.ttip.style.top = null; } 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: @@ -601,7 +753,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; } } @@ -612,43 +764,62 @@ sap.ui.define([ // See js/modules/menu/menu.mjs createMenu(), menu.add() - let intersect = this.getIntersectAt(event.offsetX, event.offsetY); + 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"); - 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)); + + 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); - 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); } - defaultContextMenuAction(arg) + setCameraCenter(data) { - console.log("GLC::defaultContextMenuAction", this, arg); + 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(); + + e.applyMatrix4(pthis.camera.testMtx); + // console.log("picked word view coordinates ", e); + + pthis.controls.setCameraCenter(e.x, e.y, e.z); + pthis.request_render(); } handleMouseSelect(event) { - let intersect = this.getIntersectAt(event.offsetX, event.offsetY); - - if (intersect) { - let c = intersect.object.get_ctrl(); - c.event = event; - c.elementSelected(c.extractIndex(intersect)); - this.highlighted_scene = intersect.object.scene; + 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; + 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 @@ -656,6 +827,69 @@ sap.ui.define([ } } + timeStampAttributesAndTextures() { + try { + this.renderer.glManager._textureManager.incrementTime(); + this.renderer.glManager._attributeManager.incrementTime(); + } + catch (e) { + console.error("Exception caught in timeStampAttributesAndTextures.", e); + } + } + + clearAttributesAndTextures() { + try { + let delta = 2; + this.renderer.glManager._textureManager.deleteTextures(true, delta); + this.renderer.glManager._attributeManager.deleteBuffers(true, delta); + } + catch (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/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 deleted file mode 100644 index fcde8a65e0c07..0000000000000 --- a/ui5/eve7/lib/RendeQuTor.js +++ /dev/null @@ -1,500 +0,0 @@ -import * as RC from "../rnr_core/RenderCore.js"; - -function iterateSceneR(object, callback) -{ - // if (object === null || object === undefined) return; - - if (object.children.length > 0) { - for (let i = 0; i < object.children.length; i++) { - iterateSceneR(object.children[i], callback); - } - } - - callback(object); -} - -export class RendeQuTor -{ - constructor(renderer, scene, camera) - { - 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(); - - // 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.SSAA_value = 1; - - 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 - } - - initDirectToScreen() - { - this.make_RP_DirectToScreen(); - } - - initSimple(ssaa_val) - { - this.SSAA_value = ssaa_val; - - this.make_RP_SSAA_Super(); - //this.make_RP_SSAA_Down(); - this.make_RP_ToScreen(); - this.RP_ToScreen.input_texture = "color_ssaa_super"; - } - - 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) - { - 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); - } - } - - render() - { - this.queue.render(); - } - - pick() - { - let foo = this.pqueue.render(); - console.log(foo); - - { - 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; - console.log(x, y); - - let d = new Float32Array(9); - gl.readPixels(x-1, y-1, 3, 3, gl.RED, gl.FLOAT, d); - 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); - } - } - - - //============================================================================= - // Picking RenderPasses - //============================================================================= - - make_PRP_plain() - { - var pthis = this; - - this.PRP_plain = new RC.RenderPass( - RC.RenderPass.BASIC, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { return { scene: pthis.scene, camera: pthis.camera }; }, - RC.RenderPass.TEXTURE, - null, - "depth_picking", - [ { id: "color_picking", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG } ] - ); - this.PRP_plain.view_setup = function (vport) { this.viewport = vport; }; - - this.pqueue.pushRenderPass(this.PRP_plain); - } - - make_PRP_depth2r() - { - this.PRP_depth2r_mat = new RC.CustomShaderMaterial("copyDepth2RReve"); - this.PRP_depth2r_mat.lights = false; - var pthis = this; - - this.PRP_depth2r = new RC.RenderPass( - RC.RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.PRP_depth2r_mat, textures: [ textureMap["depth_picking"] ] }; - }, - RC.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 } ] - ); - this.PRP_depth2r.view_setup = function (vport) { this.viewport = vport; }; - - this.pqueue.pushRenderPass(this.PRP_depth2r); - } - - //============================================================================= - - make_RP_DirectToScreen() - { - var pthis = this; - - this.RP_DirectToScreen = new RC.RenderPass( - RC.RenderPass.BASIC, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { return { scene: pthis.scene, camera: pthis.camera }; }, - RC.RenderPass.SCREEN, - null - ); - this.RP_DirectToScreen.view_setup = function (vport) { this.viewport = vport; }; - - this.queue.pushRenderPass(this.RP_DirectToScreen); - } - - //============================================================================= - - make_RP_SSAA_Super() - { - var pthis = this; - - this.RP_SSAA_Super = new RC.RenderPass( - // Rendering pass type - RC.RenderPass.BASIC, - - // Initialize function - function (textureMap, additionalData) { - iterateSceneR(pthis.scene, function(object){ - if (object.pickable === false || object instanceof RC.Text2D || object instanceof RC.IcoSphere) { - object.visible = true; - return; - } - pthis.OriginalMats.push(object.material); - }); - }, - - // Preprocess function - function (textureMap, additionalData) { - let m_index = 0; - - iterateSceneR(pthis.scene, function(object) { - if(object.pickable === false || object instanceof RC.Text2D || object instanceof RC.IcoSphere) { - object.visible = true; - return; - } - object.material = pthis.OriginalMats[m_index]; - m_index++; - }); - - return { scene: pthis.scene, camera: pthis.camera }; - }, - - // Target - RC.RenderPass.TEXTURE, - - // Viewport - null, - - // Bind depth texture to this ID - "depthDefaultDefaultMaterials", - - [ { id: "color_ssaa_super", textureConfig: RC.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 }; }; - - this.queue.pushRenderPass(this.RP_SSAA_Super); - } - - make_RP_SSAA_Down() - { - this.RP_SSAA_Down_mat = new RC.CustomShaderMaterial("copyTexture"); - this.RP_SSAA_Down_mat.lights = false; - var pthis = this; - - this.RP_SSAA_Down = new RC.RenderPass( - // Rendering pass type - RC.RenderPass.POSTPROCESS, - - // Initialize function - function (textureMap, additionalData) {}, - - // Preprocess function - function (textureMap, additionalData) { - return { material: pthis.RP_SSAA_Down_mat, textures: [textureMap[pthis.input_texture]] }; - }, - - // Target - RC.RenderPass.TEXTURE, - - // Viewport - null, - - // Bind depth texture to this ID - null, - - [ { id: "color_ssaa_down", textureConfig: RC.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; }; - - this.queue.pushRenderPass(this.RP_SSAA_Down); - } - - //============================================================================= - - make_RP_ToScreen() - { - this.RP_ToScreen_mat = new RC.CustomShaderMaterial("copyTexture"); - this.RP_ToScreen_mat.lights = false; - var pthis = this; - - this.RP_ToScreen = new RC.RenderPass( - RC.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, - null - ); - this.RP_ToScreen.input_texture = "color_ssaa_down"; - this.RP_ToScreen.view_setup = function(vport) { this.viewport = vport; }; - - this.queue.pushRenderPass(this.RP_ToScreen); - } - - //============================================================================= - - 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, - targetColor: [0x0/255, 0x0/255, 0xff/255], threshold: 0.1}); - console.log("XXXXXXXX", hp); - // let hp = new RC.CustomShaderMaterial("highPassReve"); - this.RP_HighPass_mat = hp; - this.RP_HighPass_mat.lights = false; - - this.RP_HighPass = new RC.RenderPass( - RC.RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_HighPass_mat, textures: [textureMap["color_ssaa_super"]] }; - }, - RC.RenderPass.TEXTURE, - null, - // XXXXXX MT: this was "dt", why not null ???? - null, // "dt", - [ {id: "color_high_pass", textureConfig: RC.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.lights = false; - - this.RP_Gauss1 = new RC.RenderPass( - RC.RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_Gauss1_mat, textures: [textureMap["color_high_pass"]] }; - }, - RC.RenderPass.TEXTURE, - null, - null, - [ {id: "color_gauss_half", textureConfig: RC.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.lights = false; - - this.RP_Gauss2 = new RC.RenderPass( - RC.RenderPass.POSTPROCESS, - function (textureMap, additionalData) {}, - function (textureMap, additionalData) { - return { material: pthis.RP_Gauss2_mat, textures: [textureMap["color_gauss_half"]] }; - }, - RC.RenderPass.TEXTURE, - null, - null, - [ {id: "color_gauss_full", textureConfig: RC.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.lights = false; - - this.RP_Bloom = new RC.RenderPass( - RC.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, - null, - null, - [ {id: "color_bloom", textureConfig: RC.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); - } -}; - - -/* -export const RenderPass_MainMulti = new RC.RenderPass( - // Rendering pass type - RC.RenderPass.BASIC, - - // Initialize function - function (textureMap, additionalData) { - iterateSceneR(scene, function(object){ - if(object.pickable === false || object instanceof RC.Text2D || object instanceof RC.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 - MultiMats.push(multi); - }); - }, - - // Preprocess function - function (textureMap, additionalData) { - let m_index = 0; - - iterateSceneR(scene, function(object){ - if(object.pickable === false || object instanceof RC.Text2D || object instanceof RC.IcoSphere) { - object.visible = false; - return; - } - object.material = MultiMats[m_index]; - m_index++; - }); - - - return { scene: scene, camera: camera }; - }, - - // Target - RC.RenderPass.TEXTURE, - - // Viewport - { width: predef_width*SSAA_value, height: predef_height*SSAA_value }, - - // Bind depth texture to this ID - "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} - ] - ); -*/ - -/* -const outline = new RC.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( - // Rendering pass type - RC.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"]]}; - }, - - // Target - RC.RenderPass.TEXTURE, - - // Viewport - { width: predef_width*SSAA_value, height: predef_height*SSAA_value }, - - // Bind depth texture to this ID - null, - - [ - {id: "color_outline", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} - ] - ); - -const fog = new RC.CustomShaderMaterial("fog", {MODE: 1, fogColor: [0.5, 0.4, 0.45, 0.8]}); -fog.lights = false; -export const RenderPass_Fog = new RC.RenderPass( - // Rendering pass type - RC.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 - RC.RenderPass.TEXTURE, - - // Viewport - { width: predef_width*SSAA_value, height: predef_height*SSAA_value }, - - // Bind depth texture to this ID - null, - - [ - {id: "color_fog", textureConfig: RC.RenderPass.DEFAULT_RGBA_TEXTURE_CONFIG} - ] - ); -*/ \ No newline at end of file diff --git a/ui5/eve7/lib/RenderCore.js b/ui5/eve7/lib/RenderCore.js new file mode 100644 index 0000000000000..815c299388a7a --- /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 c95c4605eddb2..0000000000000 --- a/ui5/eve7/shaders/custom/copyDepth2RReve.frag +++ /dev/null @@ -1,36 +0,0 @@ -#version 300 es -precision highp float; -precision highp usampler2D; - -struct Material { - #if (TEXTURE) - // usampler2D texture0; // this fails in MeshRenderer, uniform setter for material - sampler2D texture0; - #fi -}; - -uniform Material material; - -#if (TEXTURE) - in vec2 fragUV; -#fi - -out vec4 color; - - -void main() { - #if (TEXTURE) - // 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 :) - #fi -} \ No newline at end of file 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" - } - } -} diff --git a/ui5/eve7/textures/dot-32a.png b/ui5/eve7/textures/dot-32a.png new file mode 100644 index 0000000000000..21487416e4574 Binary files /dev/null and b/ui5/eve7/textures/dot-32a.png differ diff --git a/ui5/eve7/textures/star5-32a.png b/ui5/eve7/textures/star5-32a.png new file mode 100644 index 0000000000000..d69f72cf3cd88 Binary files /dev/null and b/ui5/eve7/textures/star5-32a.png differ 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"> - +