diff --git a/graf3d/eve7/inc/ROOT/REveGeomData.hxx b/graf3d/eve7/inc/ROOT/REveGeomData.hxx index f25bbf797ac078f62d9e82b715158386ad2d9823..f5b7d1309cd87e2b4a0152b4b21e60da38c7c7d1 100644 --- a/graf3d/eve7/inc/ROOT/REveGeomData.hxx +++ b/graf3d/eve7/inc/ROOT/REveGeomData.hxx @@ -111,10 +111,11 @@ public: class REveGeomDrawing { public: int numnodes{0}; ///< total number of nodes in description - std::vector<REveGeomNode*> nodes; ///< all used nodes to display visible items and not known for client - std::vector<REveGeomVisible> visibles; ///< all visible items std::string drawopt; ///< draw options for TGeoPainter + int nsegm{0}; ///< number of segments for cylindrical shapes int binlen{0}; ///< extra binary data for that drawing + std::vector<REveGeomNode*> nodes; ///< all used nodes to display visible items and not known for client + std::vector<REveGeomVisible> visibles; ///< all visible items }; @@ -176,8 +177,9 @@ class REveGeomDescription { int fFacesLimit{0}; ///<! maximal number of faces to be selected for drawing int fNodesLimit{0}; ///<! maximal number of nodes to be selected for drawing bool fPreferredOffline{false}; ///<! indicates that full description should be provided to client + bool fBuildShapes{true}; ///<! if TGeoShape build already on server (default) or send as is to client - int fJsonComp{103}; ///<! default JSON compression - all class info can be removed + int fJsonComp{0}; ///<! default JSON compression void PackMatrix(std::vector<float> &arr, TGeoMatrix *matr); @@ -262,13 +264,25 @@ public: void SelectNode(TGeoNode *); + /** Set number of segments for cylindrical shapes, if 0 - default value will be used */ void SetNSegments(int n = 0) { fNSegments = n; } + /** Return of segments for cylindrical shapes, if 0 - default value will be used */ int GetNSegments() const { return fNSegments; } - void SetJsonComp(int comp = 103) { fJsonComp = comp; } + /** Set JSON compression level for data transfer */ + void SetJsonComp(int comp = 0) { fJsonComp = comp; } + /** Returns JSON compression level for data transfer */ int GetJsonComp() const { return fJsonComp; } + /** Set draw options as string for JSROOT TGeoPainter */ void SetDrawOptions(const std::string &opt = "") { fDrawOptions = opt; } + /** Returns draw options, used for JSROOT TGeoPainter */ + std::string GetDrawOptions() const { return fDrawOptions; } + + /** Instruct to build binary 3D model already on the server (true) or send TGeoShape as is to client, which can build model itself */ + void SetBuildShapes(bool on = true) { fBuildShapes = on; } + /** Retuns true if binary 3D model build already by C++ server (default) */ + bool IsBuildShapes() const { return fBuildShapes; } std::unique_ptr<REveGeomNodeInfo> MakeNodeInfo(const std::string &path); }; diff --git a/graf3d/eve7/src/REveGeomData.cxx b/graf3d/eve7/src/REveGeomData.cxx index 07949c979e54b1dde01441c3ac8bfe139b36bc86..c7840e562ba26a7f5496dad8632769513da55a86 100644 --- a/graf3d/eve7/src/REveGeomData.cxx +++ b/graf3d/eve7/src/REveGeomData.cxx @@ -576,9 +576,7 @@ std::string ROOT::Experimental::REveGeomDescription::ProcessBrowserRequest(const for (auto &item : fDesc) vect[cnt++]= &item; - res = "DESCR:"; - - res.append(TBufferJSON::ToJSON(&vect,GetJsonComp()).Data()); + res = "DESCR:"s + TBufferJSON::ToJSON(&vect,GetJsonComp()).Data(); // example how iterator can be used RGeomBrowserIter iter(*this); @@ -619,8 +617,7 @@ std::string ROOT::Experimental::REveGeomDescription::ProcessBrowserRequest(const for (auto &n : temp_nodes) reply.nodes.emplace_back(&n); - res = "BREPL:"; - res.append(TBufferJSON::ToJSON(&reply, GetJsonComp()).Data()); + res = "BREPL:"s + TBufferJSON::ToJSON(&reply, GetJsonComp()).Data(); } return res; @@ -650,12 +647,10 @@ ROOT::Experimental::REveGeomDescription::MakeShapeDescr(TGeoShape *shape, bool a { auto &elem = FindShapeDescr(shape); - if (!elem.fRenderData) { + if (elem.nfaces == 0) { TGeoCompositeShape *comp = dynamic_cast<TGeoCompositeShape *>(shape); - bool create_binaries = true; - - if (create_binaries) { + if (IsBuildShapes() || (comp != nullptr)) { auto poly = std::make_unique<REveGeoPolyShape>(); @@ -684,7 +679,7 @@ ROOT::Experimental::REveGeomDescription::MakeShapeDescr(TGeoShape *shape, bool a ri.rnr_func.clear(); ri.rnr_offset = 0; ri.vert_size = ri.norm_size = ri.index_size = 0; - } else if (ri.rnr_offset < 0) { + } else if (rd && (ri.rnr_offset < 0)) { ri.shape = nullptr; ri.rnr_offset = fRndrOffest; fRndrOffest += rd->GetBinarySize(); @@ -820,6 +815,7 @@ bool ROOT::Experimental::REveGeomDescription::CollectVisibles() REveGeomDrawing drawing; ResetRndrInfos(); + bool has_shape = false; ScanNodes(true, [&, this](REveGeomNode &node, std::vector<int> &stack, bool) { if (node.sortid < fDrawIdCut) { @@ -834,6 +830,7 @@ bool ROOT::Experimental::REveGeomDescription::CollectVisibles() auto &sd = MakeShapeDescr(volume->GetShape(), true); item.ri = sd.rndr_info(); + if (item.ri->shape) has_shape = true; } return true; }); @@ -843,10 +840,12 @@ bool ROOT::Experimental::REveGeomDescription::CollectVisibles() // create binary data with all produced shapes BuildRndrBinary(fDrawBinary); - drawing.drawopt = fDrawOptions; + drawing.drawopt = GetDrawOptions(); + drawing.nsegm = GetNSegments(); drawing.binlen = fDrawBinary.size(); - fDrawJson = "GDRAW:"s + TBufferJSON::ToJSON(&drawing, GetJsonComp()).Data(); + int compcut = has_shape ? 100 : 1000; + fDrawJson = "GDRAW:"s + TBufferJSON::ToJSON(&drawing, GetJsonComp() % compcut).Data(); return true; } @@ -977,6 +976,7 @@ int ROOT::Experimental::REveGeomDescription::SearchVisibles(const std::string &f ResetRndrInfos(); REveGeomDrawing drawing; + bool has_shape = true; ScanNodes(false, [&, this](REveGeomNode &node, std::vector<int> &stack, bool is_vis) { // select only nodes which should match @@ -1029,16 +1029,19 @@ int ROOT::Experimental::REveGeomDescription::SearchVisibles(const std::string &f auto &sd = MakeShapeDescr(volume->GetShape(), true); item.ri = sd.rndr_info(); + if (item.ri->shape) has_shape = true; return true; }); - hjson = "FESCR:"s + TBufferJSON::ToJSON(&found_desc, GetJsonComp()).Data(); + int compcut = has_shape ? 100 : 1000; + hjson = "FESCR:"s + TBufferJSON::ToJSON(&found_desc, GetJsonComp() % compcut).Data(); CollectNodes(drawing); BuildRndrBinary(binary); - drawing.drawopt = fDrawOptions; + drawing.drawopt = GetDrawOptions(); + drawing.nsegm = GetNSegments(); drawing.binlen = binary.size(); json = "FDRAW:"s + TBufferJSON::ToJSON(&drawing, GetJsonComp()).Data(); @@ -1188,9 +1191,7 @@ std::string ROOT::Experimental::REveGeomDescription::ProduceModifyReply(int node if (fNodes[id++]->GetVolume() == vol) nodes.emplace_back(&desc); - std::string res = "MODIF:"; - res.append(TBufferJSON::ToJSON(&nodes, GetJsonComp()).Data()); - return res; + return "MODIF:"s + TBufferJSON::ToJSON(&nodes, GetJsonComp()).Data(); } @@ -1237,20 +1238,26 @@ bool ROOT::Experimental::REveGeomDescription::ProduceDrawingFor(int nodeid, std: ResetRndrInfos(); + bool has_shape = false; + auto &sd = MakeShapeDescr(vol->GetShape(), true); // assign shape data - for (auto &item : drawing.visibles) + for (auto &item : drawing.visibles) { item.ri = sd.rndr_info(); + if (item.ri->shape) has_shape = true; + } CollectNodes(drawing); BuildRndrBinary(binary); - drawing.drawopt = fDrawOptions; + drawing.drawopt = GetDrawOptions(); + drawing.nsegm = GetNSegments(); drawing.binlen = binary.size(); - json.append(TBufferJSON::ToJSON(&drawing, GetJsonComp()).Data()); + int compcut = has_shape ? 100 : 1000; + json.append(TBufferJSON::ToJSON(&drawing, GetJsonComp() % compcut).Data()); return true; } @@ -1326,12 +1333,9 @@ std::unique_ptr<ROOT::Experimental::REveGeomNodeInfo> ROOT::Experimental::REveGe res->ri = &shape_descr.fRenderInfo; // temporary pointer, can be used preserved for short time - printf("OFFSET %d\n", fRndrOffest); - BuildRndrBinary(res->rndr_binary); printf("BINARY SIZE %u\n", (unsigned) res->rndr_binary.size()); - } } diff --git a/graf3d/eve7/src/REveGeomViewer.cxx b/graf3d/eve7/src/REveGeomViewer.cxx index 3f809667ee540efcfa046049a2ee068f8a9ee8f0..daff1c7dccabe66550f111af383ef33541001fc6 100644 --- a/graf3d/eve7/src/REveGeomViewer.cxx +++ b/graf3d/eve7/src/REveGeomViewer.cxx @@ -40,8 +40,8 @@ ROOT::Experimental::REveGeomViewer::REveGeomViewer(TGeoManager *mgr) if (mgr) SetGeometry(mgr); fDesc.SetPreferredOffline(gEnv->GetValue("WebGui.PreferredOffline",0) != 0); - auto comp = gEnv->GetValue("WebGui.JsonComp", -1); - if (comp >= 0) fDesc.SetJsonComp(comp); + fDesc.SetJsonComp(gEnv->GetValue("WebGui.JsonComp", TBufferJSON::kSkipTypeInfo + TBufferJSON::kNoSpaces)); + fDesc.SetBuildShapes(gEnv->GetValue("WebGui.GeomBuildShapes", 1) > 0); } ////////////////////////////////////////////////////////////////////////////////////////////// @@ -138,7 +138,8 @@ void ROOT::Experimental::REveGeomViewer::SendGeometry(unsigned connid) fWebWindow->Send(connid, json); - fWebWindow->SendBinary(connid, binary.data(), binary.size()); + if (binary.size() > 0) + fWebWindow->SendBinary(connid, binary.data(), binary.size()); } diff --git a/ui5/eve7/controller/GeomViewer.controller.js b/ui5/eve7/controller/GeomViewer.controller.js index e1e4bd47e7498ce40357ce01320d79df7542fe86..76610d2f52090f7a081c6f89ad6ae70bccd1a83e 100644 --- a/ui5/eve7/controller/GeomViewer.controller.js +++ b/ui5/eve7/controller/GeomViewer.controller.js @@ -301,7 +301,7 @@ sap.ui.define(['sap/ui/core/Component', * Draw message is vector of REveGeomVisible objects, including info where shape is in raw data */ extractRawShapes: function(draw_msg) { - var nodes = null; + var nodes = null, old_gradpersegm = 0; // array for descriptors for each node // if array too large (>1M), use JS object while only ~1K nodes are expected to be used @@ -324,6 +324,11 @@ sap.ui.define(['sap/ui/core/Component', this.geo_clones.name_prefix = this.geo_clones.GetNodeName(0); } + if (draw_msg.nsegm) { + old_gradpersegm = JSROOT.GEO.GradPerSegm; + JSROOT.GEO.GradPerSegm = 360 / Math.max(draw_msg.nsegm,6); + } + for (var cnt = 0; cnt < draw_msg.visibles.length; ++cnt) { var item = draw_msg.visibles[cnt], rd = item.ri; @@ -339,6 +344,9 @@ sap.ui.define(['sap/ui/core/Component', this.createServerShape(rd, draw_msg.raw, draw_msg.offset); } + if (old_gradpersegm) + JSROOT.GEO.GradPerSegm = old_gradpersegm; + return true; },