diff --git a/builtins/rendercore/RenderCore-1.8.tar.gz b/builtins/rendercore/RenderCore-1.8.tar.gz deleted file mode 100644 index 084656c909f4e..0000000000000 Binary files a/builtins/rendercore/RenderCore-1.8.tar.gz and /dev/null differ diff --git a/builtins/rendercore/RenderCore-1.9.tar.gz b/builtins/rendercore/RenderCore-1.9.tar.gz new file mode 100644 index 0000000000000..e90160f6570fe Binary files /dev/null and b/builtins/rendercore/RenderCore-1.9.tar.gz differ diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake index c872043cf5c85..500a7f13e8a1f 100644 --- a/cmake/modules/SearchInstalledSoftware.cmake +++ b/cmake/modules/SearchInstalledSoftware.cmake @@ -1832,8 +1832,8 @@ if(webgui) endif() ExternalProject_Add( RENDERCORE - URL ${CMAKE_SOURCE_DIR}/builtins/rendercore/RenderCore-1.8.tar.gz - URL_HASH SHA256=2ab84800ec1aaf36671e463a09e3befbe97b06b2547f97ec05fe16ef1351c79a + URL ${CMAKE_SOURCE_DIR}/builtins/rendercore/RenderCore-1.9.tar.gz + URL_HASH SHA256=7728f00ee5e907c36b25aad56fbc73881c7c9faf47a36bee5efd2054bc4ecc6c CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/geom/webviewer/inc/ROOT/RGeomData.hxx b/geom/webviewer/inc/ROOT/RGeomData.hxx index f940c7374453b..a912ee4cf77d2 100644 --- a/geom/webviewer/inc/ROOT/RGeomData.hxx +++ b/geom/webviewer/inc/ROOT/RGeomData.hxx @@ -206,6 +206,7 @@ using RGeomSignalFunc_t = std::function; class RGeomDescription { +protected: friend class RGeomBrowserIter; class ShapeDescr { @@ -296,6 +297,9 @@ class RGeomDescription { int IsPhysNodeVisible(const std::vector &stack); + virtual RGeoItem MakeBrowserItem(const RGeomNode& node, std::vector& stack); + virtual bool IsFullModelStreamedAtOnce(); + /** clear drawing data without locking mutex */ void _ClearDrawData() { @@ -305,6 +309,7 @@ class RGeomDescription { public: RGeomDescription() = default; + virtual ~RGeomDescription(){}; void AddSignalHandler(const void *handler, RGeomSignalFunc_t func); @@ -460,7 +465,7 @@ public: bool IsPrincipalEndNode(int nodeid); - std::string ProcessBrowserRequest(const std::string &req = ""); + virtual std::string ProcessBrowserRequest(const std::string &req = ""); bool HasDrawData() const; void ProduceDrawData(); diff --git a/geom/webviewer/inc/ROOT/RGeomHierarchy.hxx b/geom/webviewer/inc/ROOT/RGeomHierarchy.hxx index b1b685eeeedd9..afd8659c20b5e 100644 --- a/geom/webviewer/inc/ROOT/RGeomHierarchy.hxx +++ b/geom/webviewer/inc/ROOT/RGeomHierarchy.hxx @@ -30,7 +30,7 @@ protected: RGeomDescription &fDesc; /// fWebWindow; ///path.empty() && (request->first == 0) && (GetNumNodes() < (IsPreferredOffline() ? 1000000 : 1000))) { + if (request->path.empty() && (request->first == 0) && IsFullModelStreamedAtOnce()) { std::vector vect(fDesc.size(), nullptr); @@ -823,9 +823,9 @@ std::string RGeomDescription::ProcessBrowserRequest(const std::string &msg) auto stack = MakeStackByIds(iter.CurrentIds()); while (iter.IsValid() && (request->number > 0)) { - int pvis = IsPhysNodeVisible(stack); - temp_nodes.emplace_back(iter.GetName(), iter.NumChilds(), iter.GetNodeId(), iter.GetColor(), - iter.GetMaterial(), iter.GetVisible(), pvis < 0 ? iter.GetVisible() : pvis); + + temp_nodes.emplace_back(MakeBrowserItem(fDesc[iter.GetNodeId()], stack)); + if (toplevel) temp_nodes.back().SetExpanded(true); if (stack == fSelectedStack) @@ -2060,6 +2060,27 @@ int RGeomDescription::IsPhysNodeVisible(const std::vector &stack) return -1; } +///////////////////////////////////////////////////////////////////////////////// +/// Create temprary browser item. +/// Function is called from ProcessBrowserRequest + +RGeoItem RGeomDescription::MakeBrowserItem(const RGeomNode &node, std::vector &stack) +{ + int pvis = IsPhysNodeVisible(stack); + bool test_vis = pvis < 0 ? true : pvis; + return RGeoItem(node.name, node.chlds.size(), node.id, node.color, node.material, + node.vis, test_vis); +} + +///////////////////////////////////////////////////////////////////////////////// +/// Decide if the whole model is streamed at once +/// Function is called from ProcessBrowserRequest + +bool RGeomDescription::IsFullModelStreamedAtOnce() +{ + return GetNumNodes() < (IsPreferredOffline() ? 1000000 : 1000); +} + ///////////////////////////////////////////////////////////////////////////////// /// Reset custom visibility of physical node by path diff --git a/graf3d/eve7/inc/ROOT/REveGeoPolyShape.hxx b/graf3d/eve7/inc/ROOT/REveGeoPolyShape.hxx index 21c36c6a68228..67cc73ec91ee2 100644 --- a/graf3d/eve7/inc/ROOT/REveGeoPolyShape.hxx +++ b/graf3d/eve7/inc/ROOT/REveGeoPolyShape.hxx @@ -31,7 +31,7 @@ private: REveGeoPolyShape(const REveGeoPolyShape&) = delete; REveGeoPolyShape& operator=(const REveGeoPolyShape&) = delete; -protected: +public: std::vector fVertices; std::vector fNormals; std::vector fPolyDesc; diff --git a/graf3d/eve7/inc/ROOT/REveGeoTopNode.hxx b/graf3d/eve7/inc/ROOT/REveGeoTopNode.hxx index 3163e28efb2a0..efbfaa02ca5d7 100644 --- a/graf3d/eve7/inc/ROOT/REveGeoTopNode.hxx +++ b/graf3d/eve7/inc/ROOT/REveGeoTopNode.hxx @@ -5,53 +5,175 @@ #include #include #include +#include "ROOT/REveSecondarySelectable.hxx" class TGeoNode; +class TGeoIterator; + namespace ROOT { namespace Experimental { +class REveGeoTopNodeData; +///////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// REveGeomDescription +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +class REveGeomDescription : public RGeomDescription { + static TGeoManager* s_geoManager; +protected: + std::vector fVisibilityRec; + virtual RGeoItem MakeBrowserItem(const RGeomNode &node, std::vector &stack); + virtual bool IsFullModelStreamedAtOnce() { return false; } + + class Apex { + std::vector fPath; + TGeoNode *fNode{nullptr}; + + public: + void SetFromPath(std::vector absPath); + TGeoNode *LocateNodeWithPath(const std::vector &path) const; + + TGeoNode *GetNode() { return fNode; } + std::string GetFlatPath() const; + const std::vector& GetPath() const { return fPath; } + std::vector GetIndexStack() const; + }; + + Apex fApex; -class REveGeoTopNodeData : public REveElement, - public REveAuntAsList +public: + REveGeomDescription() : RGeomDescription() {}; + virtual ~REveGeomDescription() {}; + + enum ERnrFlags { + kRnrNone = 0, + kRnrSelf = 1, + kRnrChildren = 2 + }; + + bool ChangeEveVisibility(const std::vector &stack, ERnrFlags rnrFlag, bool on); + std::vector GetIndexStack() { return fApex.GetIndexStack(); } + const std::vector& GetApexPath() const { return fApex.GetPath();} + void InitPath(const std::vector& path); + TGeoNode* GetApexNode() { return fApex.GetNode(); } + TGeoNode* LocateNodeWithPath(const std::vector &path) { return fApex.LocateNodeWithPath(path); } + + bool GetVisiblityForStack(const std::vector& stack); + + void ImportFile(const char* filePath); + static TGeoManager* GetGeoManager(); +}; + +///////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// REveGeomHierarchy +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +class REveGeomHierarchy : public RGeomHierarchy { - friend class REveGeoTopNodeViz; + REveGeoTopNodeData* fReceiver{nullptr}; +protected: + virtual void WebWindowCallback(unsigned connid, const std::string &kind); + +public: + REveGeomHierarchy(REveGeomDescription &desc, bool th) : + RGeomHierarchy(desc, th){}; + + void SetReceiver(REveGeoTopNodeData* data) { fReceiver = data; } + virtual ~REveGeomHierarchy(){}; +}; + +///////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// REveGeoTopNodeData +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +class REveGeoTopNodeData : public REveElement, public REveAuntAsList { + friend class REveGeoTopNodeViz; +private: + std::shared_ptr fWebHierarchy; /// fWebHierarchy; ///& path); + void InitPath(const std::string& path); }; -//------------------------------------------------------------------- -class REveGeoTopNodeViz : public REveElement + +///////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// REveGeoTopNodeViz +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +class REveGeoTopNodeViz : public REveElement, + public REveSecondarySelectable { - private: +public: + enum EMode { + kModeNone, + kModeVisLevel, + kModeLeafOnly, + kModeMixed + }; + +private: + struct BShape { + TGeoShape *shape; + std::vector indices; + std::vector vertices; + }; + + struct BNode { + TGeoNode *node; + int shapeId; + int nodeId; + int color; + float trans[16]; + bool visible{true}; + }; + REveGeoTopNodeViz(const REveGeoTopNodeViz &) = delete; REveGeoTopNodeViz &operator=(const REveGeoTopNodeViz &) = delete; - REveGeoTopNodeData* fGeoData{nullptr}; + REveGeoTopNodeData *fGeoData{nullptr}; + std::vector fNodes; + std::vector fShapes; + EMode fMode{kModeVisLevel}; - public: + void CollectNodes(TGeoVolume *volume, std::vector &bnl, std::vector &browsables); + void CollectShapes(TGeoNode *node, std::set &shapes, std::vector &browsables); + bool AcceptNode(TGeoIterator& it, bool skip = true) const; + +public: REveGeoTopNodeViz(const Text_t *n = "REveGeoTopNodeViz", const Text_t *t = ""); - void SetGeoData(REveGeoTopNodeData* d) {fGeoData = d;} + void SetGeoData(REveGeoTopNodeData *d, bool rebuild = true); Int_t WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) override; void BuildRenderData() override; + void GetIndicesFromBrowserStack(const std::vector &stack, std::set& outStack); + + void SetVisLevel(int); + void VisibilityChanged(bool on, REveGeomDescription::ERnrFlags flag, const std::vector& path); + void BuildDesc(); - bool RequiresExtraSelectionData() const override { return true; }; - void FillExtraSelectionData(nlohmann::json& j, const std::set& secondary_idcs) const override; + EMode GetVizMode() const { return fMode; } + void SetVizMode(EMode mode); using REveElement::GetHighlightTooltip; std::string GetHighlightTooltip(const std::set& secondary_idcs) const override; diff --git a/graf3d/eve7/src/REveGeoTopNode.cxx b/graf3d/eve7/src/REveGeoTopNode.cxx index 6778c077b9453..e987ed110ebee 100644 --- a/graf3d/eve7/src/REveGeoTopNode.cxx +++ b/graf3d/eve7/src/REveGeoTopNode.cxx @@ -1,22 +1,34 @@ #include + +#include +#include + #include #include +#include #include +#include #include - +#include +#include +#include +#include "TBufferJSON.h" #include "TMath.h" + +#include "TGeoCompositeShape.h" #include "TGeoManager.h" #include "TClass.h" #include "TGeoNode.h" -#include "TGeoManager.h" #include "TBase64.h" +#include "TStopwatch.h" + #include #include - +#include #include @@ -31,68 +43,348 @@ thread_local ElementId_t gSelId; #define REVEGEO_DEBUG_PRINT(fmt, ...) #endif -//////////////////////////////////////////////////////////////////////////////// -/// Constructor. -REveGeoTopNodeData::REveGeoTopNodeData(const Text_t *n, const Text_t *t) : REveElement(n, t) +TGeoManager* REveGeomDescription::s_geoManager = nullptr; + +/* +namespace { +void PrintStackPath(const std::vector& stack) +{ + printf("Path: "); + + for (auto idx : stack) + printf("/%d", idx); + + printf("\n"); +} +}*/ + + +bool REveGeomDescription::ChangeEveVisibility(const std::vector &stack, ERnrFlags flags, bool on) { - fWebHierarchy = std::make_shared(fDesc, true); + std::vector &visVec = (flags == kRnrSelf) ? fVisibility : fVisibilityRec; + + for (auto iter = visVec.begin(); iter != visVec.end(); iter++) { + if (iter->stack == stack) { + // AMT TODO remove path fom the vsibilirt vector if it is true + iter->visible = on; + return true; + } + } + + visVec.emplace_back(stack, on); + return true; } -void REveGeoTopNodeData::SetTNode(TGeoNode *n) +ROOT::RGeoItem REveGeomDescription::MakeBrowserItem(const RGeomNode &node, std::vector &iStack) { - fGeoNode = n; - fDesc.Build(fGeoNode->GetVolume()); - fDesc.AddSignalHandler(this, [this](const std::string &kind) { ProcessSignal(kind); }); + std::vector stack = fApex.GetIndexStack(); + stack.insert(stack.end(), iStack.begin(), iStack.end()); + + auto isVisible = [&stack](std::vector &visVec) -> bool { + for (auto &visVecEl : visVec) { + /* + printf("compare ======\n"); + PrintStackPath(stack); + PrintStackPath(visVecEl.stack); +*/ + if (stack == visVecEl.stack) + return visVecEl.visible ? 1 : 0; + } + return true; + }; + + int vis = isVisible(fVisibility); + int visRec = isVisible(fVisibilityRec); + + return RGeoItem(node.name, node.chlds.size(), node.id, node.color, node.material, + visRec, vis); } + +void REveGeomDescription::InitPath(const std::vector& path) +{ + fApex.SetFromPath(path); + Build(fApex.GetNode()->GetVolume()); // rebuild geo-webviewer +} + +bool REveGeomDescription::GetVisiblityForStack(const std::vector &nodeStack) +{ + // visibility self + for (auto &visVecEl : fVisibility) { + if (nodeStack == visVecEl.stack) { + return false; + } + } + + // visibility recurse/children + for (auto &visVecEl : fVisibilityRec) { + bool inside = + nodeStack.size() >= visVecEl.stack.size() && std::equal(visVecEl.stack.begin(), visVecEl.stack.end(), nodeStack.begin()); + if (inside) + return false; + } + + return true; +} + //////////////////////////////////////////////////////////////////////////////// +/// Table signal handling -void REveGeoTopNodeData::SetChannel(unsigned connid, int chid) +void REveGeomHierarchy::WebWindowCallback(unsigned connid, const std::string &arg) { - fWebHierarchy->Show({gEve->GetWebWindow(), connid, chid}); + using namespace std::string_literals; + REveGeomDescription &eveDesc = dynamic_cast(fDesc); + + REveGeoManagerHolder gmgr(REveGeomDescription::GetGeoManager()); + if (arg.compare(0, 6, "CDTOP:") == 0) + { + std::vector ep; + eveDesc.InitPath(ep); + fDesc.IssueSignal(this, "CdTop"); + fWebWindow->Send(connid, "RELOAD"s); + } + else if (arg.compare(0, 5, "CDUP:") == 0) + { + std::vector result = eveDesc.GetApexPath(); + result.pop_back(); + eveDesc.InitPath(result); + fDesc.IssueSignal(this, "CdUp"); + fWebWindow->Send(connid, "RELOAD"s); + } + else if (arg.compare(0, 8, "SETAPEX:") == 0) { + auto path = TBufferJSON::FromJSON>(arg.substr(8)); + + //const std::vector &sstack = fDesc.GetSelectedStack(); + // std::vector sspath = fDesc.MakePathByStack(sstack); + std::vector result = eveDesc.GetApexPath(); + if (path->size() > 1) { + result.insert(result.end(), path->begin() + 1, path->end()); + eveDesc.InitPath(result); + fDesc.IssueSignal(this, "SelectTop"); + fWebWindow->Send(connid, "RELOAD"s); + } + } + else if ((arg.compare(0, 7, "SETVI0:") == 0) || (arg.compare(0, 7, "SETVI1:") == 0)) { + { + REveManager::ChangeGuard ch; + bool on = (arg[5] == '1'); + auto path = TBufferJSON::FromJSON>(arg.substr(7)); + // Get integer stack from string stack + std::vector base = eveDesc.GetIndexStack(); + std::vector stack = fDesc.MakeStackByPath(*path); + stack.insert(stack.begin(), base.begin(), base.end()); + + if (eveDesc.ChangeEveVisibility(stack, REveGeomDescription::kRnrChildren , on)) { + std::cout << "Set visibilty rnr CHIDLREN \n"; + fReceiver->VisibilityChanged(on, REveGeomDescription::kRnrChildren, stack); + } + } + } + else if ((arg.compare(0, 5, "SHOW:") == 0) || (arg.compare(0, 5, "HIDE:") == 0)) { + { + auto path = TBufferJSON::FromJSON>(arg.substr(5)); + bool on = (arg.compare(0, 5, "SHOW:") == 0); + // Get integer stack from string stack + + std::vector base = eveDesc.GetIndexStack(); + std::vector stack = fDesc.MakeStackByPath(*path); + stack.insert(stack.begin(), base.begin(), base.end()); + + if (path && eveDesc.ChangeEveVisibility(stack, REveGeomDescription::kRnrSelf, on)) { + std::cout << "Set visibilty rnr PHY \n"; + REveManager::ChangeGuard ch; + fReceiver->VisibilityChanged(on, REveGeomDescription::kRnrSelf, stack); + } + } + } + + else { + RGeomHierarchy::WebWindowCallback(connid, arg); + } } + //////////////////////////////////////////////////////////////////////////////// -namespace { -std::size_t getHash(std::vector &vec) +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +TGeoManager* REveGeomDescription::GetGeoManager() +{ + assert(s_geoManager); + return s_geoManager; +} + +void REveGeomDescription::Apex::SetFromPath(std::vector absPath) +{ + fPath = absPath; + fNode = LocateNodeWithPath(absPath); +} + +TGeoNode *REveGeomDescription::Apex::LocateNodeWithPath(const std::vector &path) const +{ + TGeoNode *top = REveGeomDescription::GetGeoManager()->GetTopNode(); + // printf("Top node name from geoData name (%s)\n", top->GetName()); + for (size_t t = 0; t < path.size(); t++) { + std::string s = path[t]; + std::cout << s << std::endl; + TGeoNode *ntop = top->GetVolume()->FindNode(s.c_str()); + if (!ntop) + throw std::runtime_error("Apex::LocateNodeWithPath(), can't locate node with path " + s); + top = ntop; + } + return top; +} + +std::string REveGeomDescription::Apex::GetFlatPath() const +{ + if (fPath.empty()) + return ""; + + std::ostringstream oss; + + oss << fPath[0]; + + for (size_t i = 1; i < fPath.size(); ++i) + oss << "/" << fPath[i]; + + return oss.str(); +} + +std::vector REveGeomDescription::Apex::GetIndexStack() const +{ + std::vector indexStack; + + TGeoNode* current = REveGeomDescription::GetGeoManager()->GetTopNode(); + + // optional: skip first if it is top itself + size_t start = 0; + std::vector nameStack = fPath; + if (!nameStack.empty() && nameStack[0] == current->GetName()) + start = 1; + + for (size_t i = start; i < nameStack.size(); ++i) + { + const std::string& targetName = nameStack[i]; + + TGeoVolume* vol = current->GetVolume(); + + int nd = vol->GetNdaughters(); + + int foundIndex = -1; + + for (int j = 0; j < nd; ++j) + { + TGeoNode* daughter = vol->GetNode(j); + + if (targetName == daughter->GetName()) + { + foundIndex = j; + current = daughter; + break; + } + } + + if (foundIndex == -1) + { + std::cerr << "Node not found: " << targetName << std::endl; + return {}; + } + + indexStack.push_back(foundIndex); + } + + // PrintStackPath(indexStack); + return indexStack; +} + +void REveGeomDescription::ImportFile(const char* filename) { - std::size_t seed = vec.size(); - for (auto &x : vec) { - uint32_t i = (uint32_t)x; - seed ^= i + 0x9e3779b9 + (seed << 6) + (seed >> 2); + s_geoManager = TGeoManager::Import(filename); + if (!s_geoManager) { + throw std::runtime_error("Critical Error: Failed to import geometry file"); } - return seed; } -} // namespace +//////////////////////////////////////////////////////////////////////////////// +/// +/// Constructor. + +REveGeoTopNodeData::REveGeoTopNodeData(const char* filename) +{ + // this below will be obsolete + fDesc.AddSignalHandler(this, [this](const std::string &kind) { ProcessSignal(kind); }); + fDesc.ImportFile(filename); + + + fWebHierarchy = std::make_shared(fDesc, true); + fWebHierarchy->SetReceiver(this); +} + +void REveGeoTopNodeData::InitPath(const std::string &path) +{ + std::regex re(R"([/\\]+)"); // split on one or more slashes + std::sregex_token_iterator it(path.begin(), path.end(), re, -1); + std::sregex_token_iterator end; + std::vector result; + + for (; it != end; ++it) { + if (!it->str().empty()) { // skip empty parts + result.push_back(*it); + } + } + + fDesc.InitPath(result); + + for (auto &el : fNieces) { + REveGeoTopNodeViz *etn = dynamic_cast(el); + etn->BuildDesc(); + } +} + +void REveGeoTopNodeData::VisibilityChanged(bool on, REveGeomDescription::ERnrFlags flag, const std::vector& path) +{ + + for (auto &el : fNieces) { + REveGeoTopNodeViz *etn = dynamic_cast(el); + etn->VisibilityChanged(on, flag, path); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +void REveGeoTopNodeData::SetChannel(unsigned connid, int chid) +{ + fWebHierarchy->Show({gEve->GetWebWindow(), connid, chid}); +} + +//////////////////////////////////////////////////////////////////////////////// void REveGeoTopNodeData::ProcessSignal(const std::string &kind) { REveManager::ChangeGuard ch; - if ((kind == "SelectTop") || (kind == "NodeVisibility")) { - StampObjProps(); - for (auto &n : fNieces) { - n->StampObjProps(); - } - } else if (kind == "HighlightItem") { - // printf("REveGeoTopNodeData element highlighted --------------------------------"); - auto sstack = fDesc.GetHighlightedItem(); - std::set ss; - ss.insert((int)getHash(sstack)); - for (auto &n : fNieces) { - gEve->GetHighlight()->NewElementPicked(n->GetElementId(), false, true, ss); + if ((kind == "SelectTop") || (kind == "CdTop") || (kind == "CdUp")) + { + for (auto &el : fNieces) { + REveGeoTopNodeViz *etn = dynamic_cast(el); + etn->BuildDesc(); } - gSelId = gEve->GetHighlight()->GetElementId(); + } + else if (kind == "HighlightItem") { + /* + printf("REveGeoTopNodeData element highlighted --------------------------------"\n); + */ } else if (kind == "ClickItem") { - // printf("REveGeoTopNodeData element selected --------------------------------"); + printf("REveGeoTopNodeData element CLICKED selected --------------------------------\n"); auto sstack = fDesc.GetClickedItem(); std::set ss; - ss.insert((int)getHash(sstack)); for (auto &n : fNieces) { - gEve->GetSelection()->NewElementPicked(n->GetElementId(), false, true, ss); + REveGeoTopNodeViz* viz = dynamic_cast(n); + viz->GetIndicesFromBrowserStack(sstack, ss); + bool multi = false; + bool secondary = true; + gEve->GetSelection()->NewElementPicked(n->GetElementId(), multi, secondary, ss); } - gSelId = gEve->GetSelection()->GetElementId(); } } @@ -103,90 +395,490 @@ Int_t REveGeoTopNodeData::WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) { Int_t ret = REveElement::WriteCoreJson(j, rnr_offset); - if (!fGeoNode){ return ret;} return ret; } //////////////////////////////////////////////////////////////////////////////// +// REveGeoTopNodeViz //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -REveGeoTopNodeViz::REveGeoTopNodeViz(const Text_t *n, const Text_t *t) : REveElement(n, t) {} -std::string REveGeoTopNodeViz::GetHighlightTooltip(const std::set &) const +REveGeoTopNodeViz::REveGeoTopNodeViz(const Text_t *n, const Text_t *t) : REveElement(n, t) +{ + SetAlwaysSecSelect(true); +} + +void REveGeoTopNodeViz::SetVizMode(EMode mode) + { + fMode = mode; +} + +bool REveGeoTopNodeViz::AcceptNode(TGeoIterator &it, bool skip) const +{ + if (fMode == EMode::kModeVisLevel) + { + if (it.GetLevel() > fGeoData->fDesc.GetVisLevel()) { + it.Skip(); + return false; + } + } + else if (fMode == EMode::kModeLeafOnly) + { + // printf("accep mkod eleaf node ptr %p \n", (void*)it.GetNode(it.GetLevel())); + if (it.GetNode(it.GetLevel())->GetNdaughters()) + return false; + } + else if (fMode == EMode::kModeMixed) + { + if (it.GetLevel() > fGeoData->fDesc.GetVisLevel()) { + if (skip) it.Skip(); + return false; + } + // printf("accep mkod eleaf node ptr %p \n", (void*)it.GetNode(it.GetLevel())); + if (it.GetNode(it.GetLevel())->GetNdaughters()) + return false; + } + + return true; +} + +std::string REveGeoTopNodeViz::GetHighlightTooltip(const std::set & set) const { - auto stack = fGeoData->fDesc.GetHighlightedItem(); - auto sa = fGeoData->fDesc.MakePathByStack(stack); - if (sa.empty()) + REveGeoManagerHolder gmgr(REveGeomDescription::GetGeoManager()); + if (set.empty()) { return ""; - else { - std::string res; - size_t n = sa.size(); - for (size_t i = 0; i < n; ++i) { - res += sa[i]; - if (i < (n - 1)) - res += "/"; + } else { + auto it = set.begin(); + int pos = *it; + //const BNode &bn = fNodes[pos]; + std::cout << "highlight node with ID " << pos << "\n"; + + std::string res = "GeoNode name"; + + TGeoNode *top = fGeoData->fDesc.GetApexNode(); + TGeoIterator git(top->GetVolume()); + TGeoNode *node; + int i = 0; + TString path; + while ((node = git.Next())) + { + if (!AcceptNode(git)) + continue; + if (i == pos) { + git.GetPath(path); + res = path; + break; + } + i++; } return res; } } +void REveGeoTopNodeViz::BuildDesc() +{ + // locate top node + TGeoNode* top = fGeoData->fDesc.GetApexNode(); + + fNodes.clear(); + fShapes.clear(); + // shape array + std::set shapes; + TStopwatch timer; + timer.Start(); + CollectShapes(top, shapes, fShapes); + std::cout << "Shape size " << shapes.size() << "\n"; + + timer.Stop(); + + printf("Real time: %.3f s\n", timer.RealTime()); + printf("CPU time: %.3f s\n", timer.CpuTime()); + + // node array + timer.Start(); + CollectNodes(top->GetVolume(), fNodes, fShapes); + std::cout << "Node size " << fNodes.size() << "\n"; + + timer.Stop(); + + printf("NODES Real time: %.3f s\n", timer.RealTime()); + printf("NODES CPU time: %.3f s\n", timer.CpuTime()); + + StampObjProps(); +} + +void REveGeoTopNodeViz::CollectNodes(TGeoVolume *volume, std::vector &bnl, std::vector &browsables) +{ + printf("collect nodes \n"); + TGeoIterator it(volume); + TGeoNode *node; + int nodeId = 0; + + std::vector apexStack = fGeoData->RefDescription().GetIndexStack(); + + // get top node transformation + TGeoHMatrix global; + { + TGeoNode *inode = REveGeomDescription::GetGeoManager()->GetTopNode(); + for (int idx : apexStack) { + inode = inode->GetDaughter(idx); + global.Multiply(inode->GetMatrix()); + } + } + + while ((node = it.Next())) + { + if (!AcceptNode(it)) + continue; + + TGeoHMatrix full = global; // identity if global is identity + full.Multiply(it.GetCurrentMatrix()); + const TGeoMatrix *mat = &full; + + // const TGeoMatrix *mat = it.GetCurrentMatrix(); + const Double_t *t = mat->GetTranslation(); // size 3 + const Double_t *r = mat->GetRotationMatrix(); // size 9 (3x3) + + Double_t m[16]; + if (mat->IsScale()) { + const Double_t *s = mat->GetScale(); + m[0] = r[0] * s[0]; + m[1] = r[3] * s[0]; + m[2] = r[6] * s[0]; + m[3] = 0; + m[4] = r[1] * s[1]; + m[5] = r[4] * s[1]; + m[6] = r[7] * s[1]; + m[7] = 0; + m[8] = r[2] * s[2]; + m[9] = r[5] * s[2]; + m[10] = r[8] * s[2]; + m[11] = 0; + m[12] = t[0]; + m[13] = t[1]; + m[14] = t[2]; + m[15] = 1; + } else { + m[0] = r[0]; + m[1] = r[3]; + m[2] = r[6]; + m[3] = 0; + m[4] = r[1]; + m[5] = r[4]; + m[6] = r[7]; + m[7] = 0; + m[8] = r[2]; + m[9] = r[5]; + m[10] = r[8]; + m[11] = 0; + m[12] = t[0]; + m[13] = t[1]; + m[14] = t[2]; + m[15] = 1; + } + + BNode b; + b.node = node; + b.nodeId = nodeId; + b.color = node->GetVolume()->GetLineColor(); + + // TString path; it.GetPath(path); + // printf("[%d] %d %s \n", node->GetNdaughters(), it.GetLevel(), path.Data()); + + + // set BNode transformation matrix + for (int i = 0; i < 16; ++i) + b.trans[i] = m[i]; + + // find shape + TGeoShape *shape = node->GetVolume()->GetShape(); + b.shapeId = -1; // mark invalid at start + for (size_t i = 0; i < browsables.size(); i++) { + if (shape == browsables[i].shape) { + b.shapeId = i; + break; + } + } + assert(b.shapeId >= 0); + + + // set visibility flag + std::vector visStack = apexStack; + for (int i = 1; i <= it.GetLevel(); ++i) + visStack.push_back(it.GetIndex(i)); + // PrintStackPath(visStack); + b.visible = fGeoData->RefDescription().GetVisiblityForStack(visStack); + + // printf("Node %d shape id %d \n", (int)bnl.size(), b.shapeId); + bnl.push_back(b); + nodeId++; + + if (nodeId > 300000) { + R__LOG_ERROR(REveLog()) << "Max number of nodes reached ... breaking the loop \n"; + printf("num nodes locked !!! \n"); + break; + } + } +} + +void REveGeoTopNodeViz::CollectShapes(TGeoNode *tnode, std::set &shapes, std::vector &browsables) +{ + printf("collect shapes \n"); + TGeoIterator geoit(tnode->GetVolume()); + TGeoNode *node = nullptr; + while ((node = geoit.Next())) + { + if (!AcceptNode(geoit)) + continue; + + TGeoVolume *vol = node->GetVolume(); + if (vol) { + TGeoShape *shape = vol->GetShape(); + if (shape) { + auto it = shapes.find(shape); + if (it == shapes.end()) { + shapes.insert(shape); // use set to avoid duplicates + REveGeoPolyShape polyShape; + TGeoCompositeShape *compositeShape = dynamic_cast(shape); + int n_seg = 60; // default value in the geo manager and poly shape + if (compositeShape) + polyShape.BuildFromComposite(compositeShape, n_seg); + else + polyShape.BuildFromShape(shape, n_seg); + + // printf("[%d] Shape name %s %s \n",(int)browsables.size(), shape->GetName(), shape->ClassName()); + + // printf("vertices %lu: \n", polyShape.fVertices.size()); + + // create browser shape + BShape browserShape; + browserShape.shape = shape; + browsables.push_back(browserShape); + + // copy vertices transform vec double to float + browsables.back().vertices.reserve(polyShape.fVertices.size()); + for (size_t i = 0; i < polyShape.fVertices.size(); i++) + browsables.back().vertices.push_back(polyShape.fVertices[i]); + + // copy indices kip the first integer in the sequence of 4 + for (size_t i = 0; i < polyShape.fPolyDesc.size(); i += 4) { + browsables.back().indices.push_back(polyShape.fPolyDesc[i + 1]); + browsables.back().indices.push_back(polyShape.fPolyDesc[i + 2]); + browsables.back().indices.push_back(polyShape.fPolyDesc[i + 3]); + } + // printf("last browsable size indices size %lu \n", browsables.back().indices.size()); + } + } + } + } +} + void REveGeoTopNodeViz::BuildRenderData() { fRenderData = std::make_unique("makeGeoTopNode"); + for (size_t i = 0; i < fNodes.size(); ++i) { + + UChar_t c[4] = {1, 2, 3, 4}; + REveUtil::ColorFromIdx(fNodes[i].color, c); + // if (i < 400) printf("%d > %d %d %d %d \n",fNodes[i].color, c[0], c[1], c[2], c[3]); + uint32_t v = (c[0] << 16) + (c[1] << 8) + c[2]; + float pc; + std::memcpy(&pc, &v, sizeof(pc)); + GetRenderData()->PushV(pc); + } +} +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +void REveGeoTopNodeViz::SetGeoData(REveGeoTopNodeData *d, bool rebuild) +{ + fGeoData = d; + if (rebuild) + BuildDesc(); } +//------------------------------------------------------------------------------ + int REveGeoTopNodeViz::WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) { + REveGeoManagerHolder gmgr(REveGeomDescription::GetGeoManager()); Int_t ret = REveElement::WriteCoreJson(j, rnr_offset); + if (!fGeoData) { j["dataId"] = -1; } else { - std::string json = fGeoData->fDesc.ProduceJson(); - j["geomDescription"] = TBase64::Encode(json.c_str()); - printf("REveGeoTopNodeViz::WriteCoreJson stream geomDescription json size = %ld\n", (long) json.size()); + // std::string json = fGeoData->fDesc.ProduceJson(); + // j["geomDescription"] = TBase64::Encode(json.c_str()); j["dataId"] = fGeoData->GetElementId(); } + j["visLevel"] = fGeoData ? fGeoData->fDesc.GetVisLevel() : 0; + + // put shapes vector in json array + using namespace nlohmann; + + json shapeVertexArr = json::array(); + int vertexOff = 0; + + json shapeIndexArr = json::array(); + json shapePolySizeArr = json::array(); + json shapePolyOffArr = json::array(); + + json nodeVisibility = json::array(); + + int polyOff = 0; + + // need four integers for + for (size_t i = 0; i < fShapes.size(); ++i) { + // vertices + + std::copy(fShapes[i].vertices.begin(), fShapes[i].vertices.end(), std::back_inserter(shapeVertexArr)); + + int numVertices = int(fShapes[i].vertices.size()); + // indices + // write shape indices with the vertexOff + for (size_t p = 0; p < fShapes[i].indices.size(); ++p) + shapeIndexArr.push_back(fShapes[i].indices[p] + vertexOff); + + int numIndices = int(fShapes[i].indices.size()); + shapePolySizeArr.push_back(numIndices); + shapePolyOffArr.push_back(polyOff); + + // printf("shape [%d] numIndices %d \n", i, numIndices); + + polyOff += numIndices; + vertexOff += numVertices / 3; + } + + // write vector of shape ids for visible nodes + json nodeShapeIds = json::array(); + json nodeTrans = json::array(); + json nodeColors = json::array(); + + for (size_t i = 0; i < fNodes.size(); ++i) { + nodeShapeIds.push_back(fNodes[i].shapeId); + nodeVisibility.push_back(fNodes[i].visible); + for (int t = 0; t < 16; t++) + nodeTrans.push_back(fNodes[i].trans[t]); + } + // shape basic array + + j["shapeVertices"] = shapeVertexArr; + + // shape basic indices array + j["shapeIndices"] = shapeIndexArr; + + // shape poly offset array + j["shapeIndicesOff"] = shapePolyOffArr; + j["shapeIndicesSize"] = shapePolySizeArr; + + j["nodeShapeIds"] = nodeShapeIds; + j["nodeTrans"] = nodeTrans; + j["nodeVisibility"] = nodeVisibility; + j["fSecondarySelect"] = fAlwaysSecSelect; + + + + + // ship bounding box info + TGeoNode* top = fGeoData->fDesc.GetApexNode(); + TGeoVolume *vol = top->GetVolume(); + TGeoShape *shape = vol->GetShape(); + shape->ComputeBBox(); + TGeoBBox *box = dynamic_cast(shape); + if (box) { + const Double_t *origin = box->GetOrigin(); + + printf("BBox center: (%f, %f, %f)\n", origin[0], origin[1], origin[2]); + //printf("origin lengths: (%f, %f, %f)\n", origin[0], origin[1], origin[2]); + + auto jbb = json::array(); + jbb.push_back(origin[0] - box->GetDX()); + jbb.push_back(origin[0] + box->GetDX()); + jbb.push_back(origin[1] - box->GetDY()); + jbb.push_back(origin[1] + box->GetDY()); + jbb.push_back(origin[2] - box->GetDZ()); + jbb.push_back(origin[2] + box->GetDZ()); + j["bbox"] = jbb; + } + // std::cout << "Write Core json " << j.dump(1) << "\n"; return ret; } -void REveGeoTopNodeViz::FillExtraSelectionData(nlohmann::json &j, const std::set &) const +void REveGeoTopNodeViz::SetVisLevel(int vl) { - j["stack"] = nlohmann::json::array(); - std::vector stack; - if (gSelId == gEve->GetHighlight()->GetElementId()) - stack = fGeoData->fDesc.GetHighlightedItem(); - else if (gSelId == gEve->GetSelection()->GetElementId()) - stack = fGeoData->fDesc.GetClickedItem(); + if (fGeoData) { + fGeoData->fDesc.SetVisLevel(vl); + StampObjProps(); + } +} - if (stack.empty()) - return; +void REveGeoTopNodeViz::GetIndicesFromBrowserStack(const std::vector &stack, std::set &res) +{ + TGeoNode *top = fGeoData->fDesc.GetApexNode(); + TGeoIterator it(top->GetVolume()); + std::vector nodeStack; + int cnt = 0; + TGeoNode *node; -#ifdef REVEGEO_DEBUG - printf("cicked stack: "); - for (auto i : stack) - printf(" %d, ", i); - printf("\n"); -#endif + while ((node = it.Next())) { + int level = it.GetLevel(); - for (auto i : stack) - j["stack"].push_back(i); + bool accept = AcceptNode(it, false); + nodeStack.resize(level); + if (level > 0) + nodeStack[level - 1] = it.GetIndex(level); -#ifdef REVEGEO_DEBUG - printf("extra stack: "); - int ss = j["stack"].size(); - for (int i = 0; i < ss; ++i) { - int d = j["stack"][i]; - printf(" %d,", d); - } - printf("----\n"); - auto ids = fGeoData->fDesc.MakeIdsByStack(stack); - printf("node ids from stack: "); - for (auto i : ids) - printf(" %d, ", i); - printf("\n"); + bool inside = nodeStack.size() >= stack.size() && std::equal(stack.begin(), stack.end(), nodeStack.begin()); + if (inside) { + res.insert(cnt); + } // rnr flags + if (accept) cnt++; + } // while it - int id = fGeoData->fDesc.FindNodeId(stack); - printf("NODE ID %d\n", id); -#endif + printf("GetIndicesFromBrowserStack stack size %zu res size %zu\n", stack.size(), res.size()); } + +void REveGeoTopNodeViz::VisibilityChanged(bool on, REveGeomDescription::ERnrFlags flag, const std::vector &iStack) +{ + // function argument is full stack, we remove the apex path + size_t apexDepth = fGeoData->RefDescription().GetApexPath().size(); + std::vector stack(iStack.begin() + apexDepth, iStack.end()); + + // PrintStackPath(stack); + + TGeoNode *top = fGeoData->fDesc.GetApexNode(); + TGeoIterator it(top->GetVolume()); + std::vector nodeStack; + int cnt = 0; + TGeoNode *node; + while ((node = it.Next())) { + + int level = it.GetLevel(); + if (!AcceptNode(it)) + continue; + + nodeStack.resize(level); + if (level > 0) + nodeStack[level - 1] = it.GetIndex(level); + + if (flag == REveGeomDescription::kRnrSelf) { + /* + printf("nODEcompare ======\n"); + PrintStackPath(stack); + PrintStackPath(nodeStack); + */ + if (nodeStack == stack) { + fNodes[cnt].visible = on; + + break; + } + } else { + bool inside = nodeStack.size() >= stack.size() && std::equal(stack.begin(), stack.end(), nodeStack.begin()); + if (inside) { + fNodes[cnt].visible = on; + } + } // rnr flags + cnt++; + } // while it + StampObjProps(); +} \ No newline at end of file diff --git a/tutorials/visualisation/eve7/eveGeoBrowser.C b/tutorials/visualisation/eve7/eveGeoBrowser.C index b8b01b46c9b45..5b94eeed66260 100644 --- a/tutorials/visualisation/eve7/eveGeoBrowser.C +++ b/tutorials/visualisation/eve7/eveGeoBrowser.C @@ -5,183 +5,44 @@ /// #include +#include #include -namespace REX = ROOT::Experimental; +#include +#include +#include -TGeoNode *getNodeFromPath(TGeoNode *top, std::string path) -{ - TGeoNode *node = top; - std::istringstream f(path); - std::string s; - while (getline(f, s, '/')) - node = node->GetVolume()->FindNode(s.c_str()); - - return node; -} +using namespace ROOT::Experimental; +const Double_t kR_min = 240; +const Double_t kR_max = 250; +const Double_t kZ_d = 300; -TGeoNode *testCmsGeo() +void makeJets(int N_Jets, REveElement *jetHolder) { - TFile::SetCacheFileDir("."); - - TGeoManager::Import("https://root.cern/files/cms.root"); - - gGeoManager->DefaultColors(); - gGeoManager->GetVolume("TRAK")->InvisibleAll(); - gGeoManager->GetVolume("HVP2")->SetTransparency(20); - gGeoManager->GetVolume("HVEQ")->SetTransparency(20); - gGeoManager->GetVolume("YE4")->SetTransparency(10); - gGeoManager->GetVolume("YE3")->SetTransparency(20); - gGeoManager->GetVolume("RB2")->SetTransparency(99); - gGeoManager->GetVolume("RB3")->SetTransparency(99); - gGeoManager->GetVolume("COCF")->SetTransparency(99); - gGeoManager->GetVolume("HEC1")->SetLineColor(7); - gGeoManager->GetVolume("EAP1")->SetLineColor(7); - gGeoManager->GetVolume("EAP2")->SetLineColor(7); - gGeoManager->GetVolume("EAP3")->SetLineColor(7); - gGeoManager->GetVolume("EAP4")->SetLineColor(7); - gGeoManager->GetVolume("HTC1")->SetLineColor(2); - - TGeoNode *top = gGeoManager->GetTopVolume()->FindNode("CMSE_1"); - TGeoNode *n = getNodeFromPath(top, "MUON_1"); - return top; -} - -TGeoNode *rootgeom() -{ - TGeoManager *geom = new TGeoManager("simple1", "Simple geometry"); - - TGeoMaterial *matVacuum = new TGeoMaterial("Vacuum", 0, 0, 0); - TGeoMaterial *matAl = new TGeoMaterial("Al", 26.98, 13, 2.7); - // //--- define some media - TGeoMedium *Vacuum = new TGeoMedium("Vacuum", 1, matVacuum); - TGeoMedium *Al = new TGeoMedium("Root Material", 2, matAl); - - //--- define the transformations - TGeoTranslation *tr1 = new TGeoTranslation(20., 0, 0.); - TGeoTranslation *tr2 = new TGeoTranslation(10., 0., 0.); - TGeoTranslation *tr3 = new TGeoTranslation(10., 20., 0.); - TGeoTranslation *tr4 = new TGeoTranslation(5., 10., 0.); - TGeoTranslation *tr5 = new TGeoTranslation(20., 0., 0.); - TGeoTranslation *tr6 = new TGeoTranslation(-5., 0., 0.); - TGeoTranslation *tr7 = new TGeoTranslation(7.5, 7.5, 0.); - TGeoRotation *rot1 = new TGeoRotation("rot1", 90., 0., 90., 270., 0., 0.); - TGeoCombiTrans *combi1 = new TGeoCombiTrans(7.5, -7.5, 0., rot1); - TGeoTranslation *tr8 = new TGeoTranslation(7.5, -5., 0.); - TGeoTranslation *tr9 = new TGeoTranslation(7.5, 20., 0.); - TGeoTranslation *tr10 = new TGeoTranslation(85., 0., 0.); - TGeoTranslation *tr11 = new TGeoTranslation(35., 0., 0.); - TGeoTranslation *tr12 = new TGeoTranslation(-15., 0., 0.); - TGeoTranslation *tr13 = new TGeoTranslation(-65., 0., 0.); - - TGeoTranslation *tr14 = new TGeoTranslation(0, 0, -100); - TGeoCombiTrans *combi2 = new TGeoCombiTrans(0, 0, 100, new TGeoRotation("rot2", 90, 180, 90, 90, 180, 0)); - TGeoCombiTrans *combi3 = new TGeoCombiTrans(100, 0, 0, new TGeoRotation("rot3", 90, 270, 0, 0, 90, 180)); - TGeoCombiTrans *combi4 = new TGeoCombiTrans(-100, 0, 0, new TGeoRotation("rot4", 90, 90, 0, 0, 90, 0)); - TGeoCombiTrans *combi5 = new TGeoCombiTrans(0, 100, 0, new TGeoRotation("rot5", 0, 0, 90, 180, 90, 270)); - TGeoCombiTrans *combi6 = new TGeoCombiTrans(0, -100, 0, new TGeoRotation("rot6", 180, 0, 90, 180, 90, 90)); + TRandom &r = *gRandom; - //--- make the top container volume - Double_t worldx = 110.; - Double_t worldy = 50.; - Double_t worldz = 5.; - TGeoVolume *top = geom->MakeBox("TOP", Vacuum, 270., 270., 120.); - geom->SetTopVolume(top); - TGeoVolume *replica = geom->MakeBox("REPLICA", Vacuum, 120, 120, 120); - replica->SetVisibility(kFALSE); - TGeoVolume *rootbox = geom->MakeBox("ROOT", Vacuum, 110., 50., 5.); - rootbox->SetVisibility(kFALSE); + for (int i = 0; i < N_Jets; i++) { + auto jet = new REveJetCone(Form("Jet_%d", i)); + jet->SetCylinder(2 * kR_max, 2 * kZ_d); + jet->AddEllipticCone(r.Uniform(-0.5, 0.5), r.Uniform(0, TMath::TwoPi()), 0.1, 0.2); + jet->SetFillColor(kPink - 8); + jet->SetLineColor(kViolet - 7); - //--- make letter 'R' - TGeoVolume *R = geom->MakeBox("R", Vacuum, 25., 25., 5.); - R->SetVisibility(kFALSE); - TGeoVolume *bar1 = geom->MakeBox("bar1", Al, 5., 25, 5.); - bar1->SetLineColor(kRed); - R->AddNode(bar1, 1, tr1); - TGeoVolume *bar2 = geom->MakeBox("bar2", Al, 5., 5., 5.); - bar2->SetLineColor(kRed); - R->AddNode(bar2, 1, tr2); - R->AddNode(bar2, 2, tr3); - TGeoVolume *tub1 = geom->MakeTubs("tub1", Al, 5., 15., 5., 90., 270.); - tub1->SetLineColor(kRed); - R->AddNode(tub1, 1, tr4); - TGeoVolume *bar3 = geom->MakeArb8("bar3", Al, 5.); - bar3->SetLineColor(kRed); - TGeoArb8 *arb = (TGeoArb8 *)bar3->GetShape(); - arb->SetVertex(0, 15., -5.); - arb->SetVertex(1, 0., -25.); - arb->SetVertex(2, -10., -25.); - arb->SetVertex(3, 5., -5.); - arb->SetVertex(4, 15., -5.); - arb->SetVertex(5, 0., -25.); - arb->SetVertex(6, -10., -25.); - arb->SetVertex(7, 5., -5.); - R->AddNode(bar3, 1, gGeoIdentity); - - //--- make letter 'O' - TGeoVolume *O = geom->MakeBox("O", Vacuum, 25., 25., 5.); - O->SetVisibility(kFALSE); - TGeoVolume *bar4 = geom->MakeBox("bar4", Al, 5., 7.5, 5.); - bar4->SetLineColor(kYellow); - O->AddNode(bar4, 1, tr5); - O->AddNode(bar4, 2, tr6); - TGeoVolume *tub2 = geom->MakeTubs("tub1", Al, 7.5, 17.5, 5., 0., 180.); - tub2->SetLineColor(kYellow); - O->AddNode(tub2, 1, tr7); - O->AddNode(tub2, 2, combi1); - - //--- make letter 'T' - TGeoVolume *T = geom->MakeBox("T", Vacuum, 25., 25., 5.); - T->SetVisibility(kFALSE); - TGeoVolume *bar5 = geom->MakeBox("bar5", Al, 5., 20., 5.); - bar5->SetLineColor(kBlue); - T->AddNode(bar5, 1, tr8); - TGeoVolume *bar6 = geom->MakeBox("bar6", Al, 17.5, 5., 5.); - - bar6->SetLineColor(kBlue); - T->AddNode(bar6, 1, tr9); - - rootbox->AddNode(R, 1, tr10); - rootbox->AddNode(O, 1, tr11); - rootbox->AddNode(O, 2, tr12); - rootbox->AddNode(T, 1, tr13); - - replica->AddNode(rootbox, 1, tr14); - replica->AddNode(rootbox, 2, combi2); - replica->AddNode(rootbox, 3, combi3); - replica->AddNode(rootbox, 4, combi4); - replica->AddNode(rootbox, 5, combi5); - replica->AddNode(rootbox, 6, combi6); - - top->AddNode(replica, 1, new TGeoTranslation(-150, -150, 0)); - top->AddNode(replica, 2, new TGeoTranslation(150, -150, 0)); - top->AddNode(replica, 3, new TGeoTranslation(150, 150, 0)); - top->AddNode(replica, 4, new TGeoTranslation(-150, 150, 0)); - - //--- close the geometry - geom->CloseGeometry(); - return gGeoManager->GetTopNode(); + jetHolder->AddElement(jet); + } } -void eveGeoBrowser(bool showDet = true) +void eveGeoBrowser() { - auto eveMng = REX::REveManager::Create(); + auto eveMng = REveManager::Create(); // eveMng->AllowMultipleRemoteConnections(false, false); - TGeoNode *gn; - int vislevel = 4; - if (showDet) { - gn = testCmsGeo(); - vislevel = 2; - } else { - gn = rootgeom(); - vislevel = 8; - } + TFile::SetCacheFileDir("."); // initialize RGeomDesc from TGeoNode - auto data = new REX::REveGeoTopNodeData(); - data->SetTNode(gn); - data->RefDescription().SetVisLevel(vislevel); + auto data = new REveGeoTopNodeData("http://xrd-cache-1.t2.ucsd.edu/alja/mail/geo/cmsSimGeo2026.root"); + data->InitPath("/tracker:Tracker_1"); + data->RefDescription().SetVisLevel(2); // make geoTable auto scene = eveMng->SpawnNewScene("GeoSceneTable"); @@ -189,12 +50,17 @@ void eveGeoBrowser(bool showDet = true) view->AddScene(scene); scene->AddElement(data); - // 3D representation - auto geoViz = new REX::REveGeoTopNodeViz(); + // 3D EveViz representation + auto geoViz = new REveGeoTopNodeViz(); geoViz->SetGeoData(data); - geoViz->SetPickable(true); data->AddNiece(geoViz); + geoViz->SetPickable(true); + + // add jets for BBox issues eveMng->GetEventScene()->AddElement(geoViz); + REveElement *jetHolder = new REveElement("Jets"); + eveMng->GetEventScene()->AddElement(jetHolder); + makeJets(7, jetHolder); eveMng->Show(); } diff --git a/tutorials/visualisation/eve7/geoTopNode.C b/tutorials/visualisation/eve7/geoTopNode.C index e88c376e6de56..7d2159f972915 100644 --- a/tutorials/visualisation/eve7/geoTopNode.C +++ b/tutorials/visualisation/eve7/geoTopNode.C @@ -6,8 +6,6 @@ #include #include -namespace REX = ROOT::Experimental; - void setDetColors() { gGeoManager->DefaultColors(); @@ -40,45 +38,24 @@ TGeoNode *getNodeFromPath(TGeoNode *top, std::string path) void geoTopNode() { - auto eveMng = REX::REveManager::Create(); - // eveMng->AllowMultipleRemoteConnections(false, false); + using namespace ROOT::Experimental; + auto eveMng = REveManager::Create(); + eveMng->AllowMultipleRemoteConnections(false, false); TFile::SetCacheFileDir("."); - TGeoManager::Import("https://root.cern/files/cms.root"); - TGeoNode *top = gGeoManager->GetTopVolume()->FindNode("CMSE_1"); - setDetColors(); - // tracker barrel - { - // Init RGeomDescription object - auto data = new REX::REveGeoTopNodeData("TRACK GeoNode-Data "); - data->SetTNode(getNodeFromPath(top, "TRAK_1/SVTX_1")); - data->RefDescription().SetVisLevel(2); - eveMng->GetWorld()->AddElement(data); // data can be added to any scene - - // 3D GL representation - auto geoViz = new REX::REveGeoTopNodeViz("CaloTopNode"); - geoViz->SetGeoData(data); - geoViz->SetPickable(true); - data->AddNiece(geoViz); - eveMng->GetEventScene()->AddElement(geoViz); - } - - // muon barrel - { - // Init RGeomDescription object - auto data = new REX::REveGeoTopNodeData("MUON GeoNode-Data"); - data->SetTNode(getNodeFromPath(top, "MUON_1/MB_1")); - data->RefDescription().SetVisLevel(2); - eveMng->GetWorld()->AddElement(data); - - // 3D GL representation - auto geoViz = new REX::REveGeoTopNodeViz("MUON TopNode"); - geoViz->SetGeoData(data); - geoViz->SetPickable(true); - data->AddNiece(geoViz); - eveMng->GetEventScene()->AddElement(geoViz); - } + auto data = new REveGeoTopNodeData("https://root.cern/files/cms.root"); + setDetColors(); + data->InitPath("/CMSE_1/TRAK_1/SVTX_1"); + data->RefDescription().SetVisLevel(2); + eveMng->GetWorld()->AddElement(data); + + // 3D GL representation + auto geoViz = new REveGeoTopNodeViz(); + geoViz->SetGeoData(data); + data->AddNiece(geoViz); + eveMng->GetEventScene()->AddElement(geoViz); + geoViz->SetPickable(true); eveMng->Show(); } diff --git a/ui5/eve7/controller/GeoTable.controller.js b/ui5/eve7/controller/GeoTable.controller.js index c76893de63161..7048a07802588 100644 --- a/ui5/eve7/controller/GeoTable.controller.js +++ b/ui5/eve7/controller/GeoTable.controller.js @@ -1,16 +1,22 @@ sap.ui.define([ - 'sap/ui/core/mvc/Controller', + 'rootui5/geom/controller/GeomHierarchy.controller', + 'rootui5/geom/model/GeomBrowserModel', 'sap/ui/table/Column', + 'sap/ui/Device', + 'sap/ui/unified/Menu', + 'sap/ui/unified/MenuItem', + 'sap/ui/core/Popup', + 'sap/ui/layout/HorizontalLayout', + 'rootui5/geom/lib/ColorBox', + 'sap/m/CheckBox', 'sap/m/Text', - "sap/ui/core/ResizeHandler", + 'sap/ui/core/Icon', 'sap/ui/core/UIComponent', - 'rootui5/geom/model/GeomBrowserModel', - 'rootui5/geom/lib/ColorBox' -], function (Controller, tableColumn, mText, ResizeHandler, UIComponent,GeomBrowserModel,GeomColorBox) { +], function (GeomHierarchy, GeomBrowserModel, tableColumn, Device, Menu, MenuItem, Popup, HorizontalLayout, GeomColorBox, mCheckBox, mText, Icon, UIComponent) { "use strict"; - return Controller.extend("rootui5.eve7.controller.GeoTable", { + return GeomHierarchy.extend("rootui5.eve7.controller.GeoTable", { onInit: function () { // disable narrowing axis range @@ -33,27 +39,125 @@ sap.ui.define([ setupManagerAndViewType: function (eveViewerId, mgr) { this.eveViewerId = eveViewerId; - this.mgr = mgr; + this.mgr = mgr; let eviewer = this.mgr.GetElement(this.eveViewerId); let sceneInfo = eviewer.childs[0]; let scene = this.mgr.GetElement(sceneInfo.fSceneId); let topNodeEve = scene.childs[0]; - let h = this.byId('geomHierarchyPanel'); + //let h = this.byId('geomHierarchyPanel'); let websocket = this.mgr.handle.createChannel(); - h.getController().configure({ - websocket, - show_columns: true, - jsroot: EVE.JSR + // h.getController().configure({ + this.configure({ + websocket, + show_columns: true, + jsroot: EVE.JSR }); + this.model.addNodeAttributes = function (node, item) { + node._node = this.provideLogicalNode(item); + + if (item.pvis !== undefined) { + node.pvisible = item.pvis != 0; + node.avisible = item.vis != 0; + node.top = item.top; + } else { + console.error("add node attributes not handled"); + } + }; + console.log('channel id is', websocket.getChannelId()); this.mgr.handle.send("SETCHANNEL:" + topNodeEve.fElementId + "," + websocket.getChannelId()); - topNodeEve.websocket = websocket; + topNodeEve.websocket = websocket; + }, + + + configureTable(show_columns) { + + // create model only for browser - no need for anybody else + this.model = new GeomBrowserModel(); + + this.model.useIndexSuffix = false; + + let t = this.byId("treeTable"); + + t.setModel(this.model); + + t.setRowHeight(20); + + this.model.assignTreeTable(t); + + t.addColumn(new tableColumn({ + label: 'Description', + tooltip: 'Name of geometry nodes', + autoResizable: true, + width: show_columns ? '50%' : '100%', + visible: true, + tooltip: "{name}", + template: new HorizontalLayout({ + content: [ + new Icon({ visible: '{top}', src: 'sap-icon://badge', tooltip: '{name} selected as top node' }).addStyleClass('sapUiTinyMarginEnd'), + new mText({ text: '{name}', tooltip: '{name}', wrapping: false }) + ] + }) + })); + t.addColumn(new tableColumn({ + label: 'Visibility', + tooltip: 'Visibility flags', + autoResizable: true, + visible: true, + width: '20%', + template: new HorizontalLayout({ + content: [ + new mCheckBox({ enabled: true, visible: true, selected: "{avisible}", select: evnt => this.changeVisibility(evnt), tooltip: '{name} Visibility Children' }), + new mCheckBox({ enabled: true, visible: true, selected: "{pvisible}", select: evnt => this.changeVisibility(evnt, true), tooltip: '{name} Visibility Self' }) + ] + }) + })); + t.addColumn(new tableColumn({ + label: 'Color', + tooltip: 'Color of geometry volumes', + width: '10%', + autoResizable: true, + visible: true, + template: new GeomColorBox({ color: "{_node/color}", visible: "{= !!${_node/color}}" }) + })); + t.addColumn(new tableColumn({ + label: 'Material', + tooltip: 'Material of the volumes', + width: '20%', + autoResizable: true, + visible: true, + template: new mText({ text: "{_node/material}", wrapping: false }) + })); + + this._columnResized = 0; + + // catch re-rendering of the table to assign handlers + t.addEventDelegate({ + onAfterRendering() { + this.assignRowHandlers(); + if (this._columnResized < 1) return; + this._columnResized = 0; + let fullsz = 4; + + t.getColumns().forEach(col => { + if (col.getVisible()) fullsz += 4 + col.$().width(); + }); + + this.viewer?.byId('geomViewerApp').getAggregation('_navMaster').setWidth(fullsz + 'px'); + } + }, this); + + t.attachEvent("columnResize", {}, evnt => { + this._columnResized++; + }, this); + }, + switchSingle: function () { let oRouter = UIComponent.getRouterFor(this); EVE.$eve7tmp = { mgr: this.mgr, eveViewerId: this.eveViewerId }; @@ -68,6 +172,110 @@ sap.ui.define([ detachViewer: function () { this.mgr.controllers[0].removeView(this.mgr.GetElement(this.eveViewerId)); this.destroy(); + }, + cdTop() { + this.websocket.send('CDTOP:'); + + let len = this.model?.getLength() ?? 0; + for (let n = 0; n < len; ++n) + this.model?.setProperty(`/nodes/${n}/top`, false); + // this.model?.setProperty(ctxt.getPath() + '/top', true); + // this.doReload(); + }, + cdUp() { + this.websocket.send('CDUP:'); + + let len = this.model?.getLength() ?? 0; + for (let n = 0; n < len; ++n) + this.model?.setProperty(`/nodes/${n}/top`, false); + // this.model?.setProperty(ctxt.getPath() + '/top', true); + // this.doReload(); + }, + + /** @summary Get entry with physical node visibility */ + getPhysVisibilityEntry(path, force) { + console.error("AMT get PHY entry unused ..."); + + let stack = this.getStackByPath(this.fullModel, path); + if (stack === null) + return; + + let len = stack.length; + + for (let i = 0; i < this.physVisibility?.length; ++i) { + let item = this.physVisibility[i], match = true; + if (len != item.stack?.length) continue; + for (let k = 0; match && (k < len); ++k) + if (stack[k] != item.stack[k]) + match = false; + if (match) + return item; + } + }, + + /** @summary invoked when visibility checkbox clicked */ + changeVisibility(oEvent, physical) { + let row = oEvent.getSource(), + flag = oEvent.getParameter('selected'), + ctxt = row?.getBindingContext(), + ttt = ctxt?.getProperty(ctxt?.getPath()); + + if (!ttt?.path) + return console.error('Fail to get path'); + + + let msg = ''; + + if (physical) { + ttt.pvisible = flag; + ttt._elem.pvis = flag; + msg = flag ? 'SHOW' : 'HIDE'; + } else { + ttt.avisible = flag; + ttt._elem.vis = flag; + msg = "SETVI" + (flag ? '1' : '0'); + } + + msg += ':' + JSON.stringify(ttt.path); + + this.websocket.send(msg); + }, + + onCellContextMenu(oEvent) { + if (Device.support.touch) + return; //Do not use context menus on touch devices + + let ctxt = oEvent.getParameter('rowBindingContext'), + colid = oEvent.getParameter('columnId'), + prop = ctxt?.getProperty(ctxt.getPath()); + + oEvent.preventDefault(); + + if (!prop?._elem) return; + + if (!this._oIdContextMenu) { + this._oIdContextMenu = new Menu(); + this.getView().addDependent(this._oIdContextMenu); + } + + this._oIdContextMenu.destroyItems(); + + this._oIdContextMenu.addItem(new MenuItem({ + text: 'Set as top', + select: () => { + this.setPhysTopNode(prop.path); + this.websocket.send('SETAPEX:' + JSON.stringify(prop.path)); + + let len = this.model?.getLength() ?? 0; + for (let n = 0; n < len; ++n) + this.model?.setProperty(`/nodes/${n}/top`, false); + this.model?.setProperty(ctxt.getPath() + '/top', true); + } + })); + + //Open the menu on the cell + let oCellDomRef = oEvent.getParameter("cellDomRef"); + this._oIdContextMenu.open(false, oCellDomRef, Popup.Dock.BeginTop, Popup.Dock.BeginBottom, oCellDomRef, "none none"); } }); }); diff --git a/ui5/eve7/controller/Main.controller.js b/ui5/eve7/controller/Main.controller.js index 8b11b42338a25..24af2f51815ba 100644 --- a/ui5/eve7/controller/Main.controller.js +++ b/ui5/eve7/controller/Main.controller.js @@ -17,7 +17,7 @@ sap.ui.define(['sap/ui/core/Component', return Controller.extend("rootui5.eve7.controller.Main", { onInit: function () { this.mgr = new EveManager(); - this.initClientLog(); + // this.initClientLog(); let conn_handle = Component.getOwnerComponentFor(this.getView()).getComponentData().conn_handle; this.mgr.UseConnection(conn_handle); diff --git a/ui5/eve7/lib/EveElementsRCore.js b/ui5/eve7/lib/EveElementsRCore.js index 999eb4da08394..3565ae99c994e 100644 --- a/ui5/eve7/lib/EveElementsRCore.js +++ b/ui5/eve7/lib/EveElementsRCore.js @@ -470,83 +470,6 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) } // class Calo2Control //============================================================================== - - - class GeoTopNodeControl extends EveElemControl { - - addMeshRec(o3, res){ - for (let c of o3.children) - { - if (c.material) { - console.log("add mesh ", c); - res.geom.push(c); - } - this.addMeshRec(c, res); - } - } - DrawForSelection(sec_idcs, res, extra) { - - if (extra.stack.length > 0) { - let topNode = this.top_obj; - let stack = extra.stack; - let clones = topNode.clones; - - // NOTE: this needs to be done diffeewnrly, this code is related to objects3d - // TODO: make same logic fro RC objects - let x = topNode.clones.createRCObject3D(stack, topNode, 'force'); - - // console.log("geo topnode control res = ",x); - this.addMeshRec(x, res); - } - } - getTooltipText() { - return this.top_obj.eve_el.fName; - } - extractIndex(instance) { - this.pick = instance; - } - - sendSocketMassage(pstate_obj, t1, t2) - { - let topNode = this.top_obj; - let aa = pstate_obj.stack || []; - - let mgr = topNode.scene.mgr; - let hbr = mgr.GetElement(topNode.eve_el.dataId); - - if (!hbr.hasOwnProperty("websocket")) - { - let websocket = mgr.handle.createChannel(); - mgr.handle.send("SETCHANNEL:" + hbr.fElementId + "," + websocket.getChannelId()); - hbr.websocket = websocket; - } - - let name = topNode.clones.getStackName(aa); - const myArray = name.split("/"); - let msg = '['; - let lastIdx = myArray.length - 1; - for (let p = 0; p < myArray.length; ++p) { - let np = "\"" + myArray[p] + "\""; - msg += np; - if (p == lastIdx) - msg += ']'; - else - msg += ","; - - } - - hbr.websocket.sendLast(t1, 200, t2 + msg); - } - - elementSelected(idx, event, pstate_obj) { - this.sendSocketMassage(pstate_obj, 'click', 'CLICK:'); - } - - elementHighlighted(idx, event, pstate_obj) { - this.sendSocketMassage( pstate_obj, 'hover', 'HOVER:'); - } - } - //============================================================================== // EveElements //============================================================================== @@ -1181,13 +1104,13 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) let lcol = RcCol(ebox.fLineColor); let line = new RC.Line(geo_rim, this.RcLineMaterial(lcol, 0.8, 1)); mesh.add(line); + this.RcPickable(ebox, mesh); - mesh.get_ctrl = function () { return new EveElemControl(this); } + // AMT dispose function outdated mesh.dispose = function () { this.children.forEach(c => { c.geometry.dispose(); c.material.dispose(); }); this.geometry.dispose(); this.material.dispose(); }; - return mesh; } //============================================================================== @@ -1586,109 +1509,55 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function (EveManager) return mesh; } - makeGeoTopNodeProcessObject(o3, ctx, eveTopNode) - { - let orc; - if (o3 instanceof THREE.Mesh) { - if (!ctx.geomap.has(o3.geometry)) { - let g = new RC.Geometry(); - g.vertices = new RC.BufferAttribute(o3.geometry.attributes.position.array, 3); - g.normals = new RC.BufferAttribute(o3.geometry.attributes.normal.array, 3); - delete o3.geometry.attributes; - ctx.geomap.set(o3.geometry, g); - } else { - ++ctx.n_geo_reuse; - } - let m3 = o3.material; - let mrc = this.RcFancyMaterial(new RC.Color(m3.color.r, m3.color.g, m3.color.b), m3.opacity); - orc = new RC.Mesh(ctx.geomap.get(o3.geometry), mrc); - this.RcPickable(eveTopNode, orc, true, GeoTopNodeControl); - orc.material.normalFlat = true; - // orc.amt_debug_name = "mesh" + o3.name; // set for debugging purposes - ++ctx.n_mesh; - } else { - orc = new RC.Group(); - // orc.amt_debug_name = "group" + o3.name; // set for debugging purposes - ++ctx.n_o3d; - } + makeGeoTopNode(topNode, rnr_data) { - orc.nchld = o3.nchld; - orc.matrixAutoUpdate = false; - orc.setMatrixFromArray(o3.matrix.elements); - for (let c of o3.children) { - orc.add(this.makeGeoTopNodeProcessObject(c, ctx, eveTopNode)); - } + const buf = new ArrayBuffer(4); + const f32 = new Float32Array(buf); + const u8 = new Uint8Array(buf); - // selection ... remore new ... - orc.stack = o3.stack; - return orc; - } + // f32[0] = rnr_data.vtxBuff[0]; // write float bits little indian test + // console.log(u8[0], u8[1], u8[2], u8[3]); - makeGeoTopNode(tn, rnr_data) { - // console.log("make top node ", tn); - let json = atob(tn.geomDescription); - let zz = EVE.JSR.parse(json); - let o3 = EVE.JSR.build(zz); - // console.log("tgeo painter builder o3 obj =", o3); - let ctx = { geomap: new Map, n_o3d: 0, n_mesh: 0, n_geo_reuse: 0 }; - let orc = this.makeGeoTopNodeProcessObject(o3, ctx, tn); - // console.log("map summary ", ctx.geomap.size, ctx.n_o3d, ctx.n_mesh, ctx.n_geo_reuse); - orc.get_ctrl = function () { return new GeoTopNodeControl(this, orc); }; - - orc.clones = o3.clones; - - // function to get stack - orc.clones.createRCObject3D = function (stack, toplevel, options) { - let node = this.nodes[0], three_prnt = toplevel, draw_depth = 0; - - for (let lvl = 0; lvl <= stack.length; ++lvl) { - let nchld = (lvl > 0) ? stack[lvl - 1] : 0; - // console.log("level ", lvl, "nchld", nchld); - // extract current node - if (lvl > 0) node = this.nodes[node.chlds[nchld]]; - if (!node) return null; - - let obj3d = undefined; - - if (three_prnt.children) - for (let i = 0; i < three_prnt.children.length; ++i) { - console.log(i, "<< comapre ",three_prnt.children[i].nchld, nchld ); - if (three_prnt.children[i].nchld === nchld) { - console.log("createRCObject3D .... reuse obj3d .... from clones ??"); - obj3d = three_prnt.children[i]; - break; - } - } + let g = new RC.Geometry(); - if (obj3d) { - three_prnt = obj3d; - // console.log("set three"); - if (obj3d.$jsroot_drawable) draw_depth++; - continue; - } + // bounding box + let bb = topNode.bbox; + g.setExternalBoundingBox(new RC.Box3(new RC.Vector3(bb[0], bb[2], bb[4]), new RC.Vector3(bb[1], bb[3], bb[5]))); - // console.log("make NEW ode ", node); - obj3d = new RC.Object3D(); + // let vatt = new RC.BufferAttribute(topNode.shapeVertices, 3); + // g.vertices = new RC.BufferAttribute(topNode.shapeVertices, 3); + g.vertices = RC.Float32Attribute(topNode.shapeVertices, 3); + // g.indices = new RC.BufferAttribute(topNode.shapeIndices,1); + g.indices = RC.Uint32Attribute(topNode.shapeIndices, 1); - if (node.abs_matrix) { - obj3d.absMatrix = new RC.Matrix4(); - obj3d.absMatrix.fromArray(node.matrix); - } else if (node.matrix) { - obj3d.matrix.fromArray(node.matrix); - obj3d.matrix.decompose(obj3d.position, obj3d.quaternion, obj3d.scale); - } + let mm = new RC.ZMultiMesh(g); + // nodes info + mm.nodeShapeIds = topNode.nodeShapeIds; + mm.nodeTrans = topNode.nodeTrans; + mm.nodeVisibility = topNode.nodeVisibility; - // add the mesh to the scene - three_prnt.add(obj3d); - obj3d.updateMatrixWorld(); + // shapes poly info + mm.shapeIndices = topNode.shapeIndices; // already in RC.Geomtery + mm.shapeIndicesOff = topNode.shapeIndicesOff; + mm.shapeIndicesSize = topNode.shapeIndicesSize; - three_prnt = obj3d; - } + // shape vertex info + mm.shapeVertices = topNode.shapeVertices; // aready in RC.Geometry + + // color + const floatBuffer = new Float32Array(rnr_data.vtxBuff); + const bytes = new Uint8Array(floatBuffer.buffer); + // console.log("color ", bytes); + mm.nodeColors = bytes; // aready in RC.Geometry + + // picking Ids: is this needed ??? + mm.nodeIds = topNode.nodeIds; - return three_prnt; - } // end clones create obj3d + mm.pickable = true; + let pick_children = false; + this.RcPickable(topNode, mm, pick_children); - return orc; + return mm; } //============================================================================== diff --git a/ui5/eve7/lib/EveScene.js b/ui5/eve7/lib/EveScene.js index e0ef39d79965f..e7aa6a34386be 100644 --- a/ui5/eve7/lib/EveScene.js +++ b/ui5/eve7/lib/EveScene.js @@ -56,13 +56,13 @@ sap.ui.define(['rootui5/eve7/lib/EveManager'], function(EveManager) { obj3d.geo_object = elem.fMasterId || elem.fElementId; obj3d.geo_name = elem.fName; // used for highlight - obj3d.matrixAutoUpdate = false; if (elem.render_data.matrix) { if (this.mgr.is_rcore) { obj3d.setMatrixFromArray(elem.render_data.matrix); } else { obj3d.matrix.fromArray(elem.render_data.matrix); obj3d.updateMatrixWorld(true); + obj3d.matrixAutoUpdate = false; } } diff --git a/ui5/eve7/lib/GlViewerRCore.js b/ui5/eve7/lib/GlViewerRCore.js index e9abf2ac505e3..7ee09758fd49d 100644 --- a/ui5/eve7/lib/GlViewerRCore.js +++ b/ui5/eve7/lib/GlViewerRCore.js @@ -99,7 +99,8 @@ sap.ui.define([ bootstrap() { RC.GLManager.sCheckFrameBuffer = false; - RC.Object3D.sDefaultPickable = false; + RC.Object3D.sDefaultQuaternionsAndAutoUpdate = false; + RC.Mesh.sDefaultPickable = false; RC.PickingShaderMaterial.DEFAULT_PICK_MODE = RC.PickingShaderMaterial.PICK_MODE.UINT; this.createRCoreRenderer(); @@ -460,14 +461,11 @@ sap.ui.define([ 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.centerMarker = s; // This will also call render(). this.resetRenderer(); @@ -543,6 +541,8 @@ sap.ui.define([ // console.log("resetRenderer 2D scene bbox ex ey", sbbox, ex, ey, ", camera_pos ", posC, ", look_at ", this.rot_center); } + this.centerMarker.visible = false; + this.controls.setFromBBox(sbbox); this.controls.update(); @@ -651,7 +651,8 @@ sap.ui.define([ color: this.fgCol, font: font_metrics, }); - text.position = ax.p; + text.matrix.setPosition(ax.p); + text.matrixChanged(); text.material.side = RC.FRONT_SIDE; ag.add(text); } @@ -674,7 +675,7 @@ sap.ui.define([ render() { - console.log("RENDER", this.scene, this.camera, this.canvas, this.renderer); + // console.log("RENDER", this.scene, this.camera, this.canvas, this.renderer); this.render_requested = false; if (this.render_requested_recalc_sbbox) { @@ -747,7 +748,7 @@ sap.ui.define([ // Note that rgt.render_end() releases all std textures. if (this.rqt.queue.used_fail_count == 0) { - // AMT: All render passess are drawn with the black bg + // AMT: All render passes are drawn with the black bg // except of the tone map render pass this.renderer.clearColor = '#' + this.bgCol.getHexString() + '00'; this.rqt.render_tone_map_to_screen(); @@ -1084,6 +1085,10 @@ sap.ui.define([ e.applyMatrix4(pthis.camera.testMtx); // console.log("picked word view coordinates ", e); + pthis.centerMarker.matrix.setPosition(e.x, e.y, e.z); + pthis.centerMarker.matrixChanged(); + pthis.centerMarker.visible = true; + pthis.controls.setCameraCenter(e.x, e.y, e.z); pthis.request_render(); } diff --git a/ui5/eve7/manifest.json b/ui5/eve7/manifest.json index b76ce8c161f57..4b095b152da1b 100644 --- a/ui5/eve7/manifest.json +++ b/ui5/eve7/manifest.json @@ -53,6 +53,10 @@ "name": "Table", "pattern": "table/:viewName:", "target": ["Table"] + }, { + "name": "GeoTable", + "pattern": "geotable/:viewName:", + "target": ["GeoTable"] }], "targets": { "Main": { @@ -74,6 +78,11 @@ "transition": "slide", "clearAggregation": false, "viewName": "EveTable" + }, + "GeoTable": { + "transition": "slide", + "clearAggregation": false, + "viewName": "GeoTable" } } } diff --git a/ui5/eve7/view/GeoTable.view.xml b/ui5/eve7/view/GeoTable.view.xml index 01c5466f1df96..bf070cadd175e 100644 --- a/ui5/eve7/view/GeoTable.view.xml +++ b/ui5/eve7/view/GeoTable.view.xml @@ -5,8 +5,7 @@ xmlns:mvc="sap.ui.core.mvc" xmlns:layout="sap.ui.layout" xmlns:m="sap.m" - xmlns:table="sap.ui.table" - xmlns:f="sap.ui.layout.form" + xmlns:t="sap.ui.table" height="100%"> @@ -16,7 +15,40 @@