Skip to content

[eve7] Bounding boxes from the server; the element tree as a RenderCore object tree - #23776

Merged
linev merged 7 commits into
root-project:masterfrom
osschar:bh-bbox
Oct 21, 2026
Merged

linev merged 7 commits into
root-project:masterfrom
osschar:bh-bbox

Conversation

@osschar

@osschar osschar commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

This Pull request:

The server sends a bounding box for every element that draws, and the client
builds the element tree as a tree of RenderCore objects: matrices compose down
the tree, bounding spheres combine up it, and the renderer culls whole
subtrees. Projections use the matrices of a model's ancestors, as the 3D view
does. One commit per topic.

Changes or fixes:

  • RenderCore 2.3 ([rcore] Cull subtrees by bounding sphere, Group.self, bounds fixes; RenderCore 2.3 UL-FRI-LGM/RenderCore#30, tag 2.3): subtree bounding spheres and culling, Group.self and
    visibleChildren, correct bounds of 2D vertices. Its copy of
    REveCameraControls is removed; ROOT has its own.
  • Bounding boxes are computed on the server and streamed with the render data.
    REveElement holds the box; TAttBBox is gone from REve.
  • Projections use the matrices of the model's ancestors. Depth and name
    changes reach the client.
  • The client builds the element tree from RenderCore objects; fRnrSelf and
    fRnrChildren map onto them. Matrices travel as JSON, base64 of doubles,
    and no longer in the render data. Near and far follow moving elements.
  • Motion survives full updates, and new clients and viewers get the running
    motions. Messages carry the server time, which the client's clock uses.
  • New tutorial orbits.C; trans_update.C moves four boxes round a square.
  • REveBoxSet: axis-aligned boxes by centre and half size, with corner adders,
    and clearer names. The old names are kept as aliases.

Notes for review:

  • A matrix change, of a model or now of its ancestor, does not reproject by
    itself; ProjectChildren() or an import does, as before.
  • REveBoxSet: boxes that do not set a size are drawn half as large as before.
    The default size is now a unit box (SetDefWidth() takes the full size).
  • On kCBCoreJson, the client calls refresh(el) of a drawing that has one,
    otherwise rebuilds it. No maker defines refresh() yet.

Checklist:

  • tested changes locally: eve7 gtests; event_demo.C, projection_axes.C,
    trans_update.C, orbits.C, boxset.C, boxset_cones.C, boing.C in a browser
  • updated the docs (if necessary): class docs of the changed classes

Developed with AI assistance: Claude Code (Anthropic). The commits carry
the corresponding Assisted-by: trailer.

- Culls a subtree by a bounding sphere around an object and everything below
  it, which the element tree of renderer objects needs.
- Group.self holds a group's own drawing, and Group.visibleChildren hides the
  other children.
- Computes the bounds of 2D-vertex geometry correctly and drops cached
  bounds on new vertices.
- Draws the outline only of selected objects that were drawn in that pass.
- No longer contains REveCameraControls; ROOT has its own in
  ui5/eve7/lib since 609e7d2.

Assisted-by: Claude:Opus 5.5
The client needs a box for every drawing to bound and cull it. Seven classes
had one, through TAttBBox, in three layouts; the rest had none.

- REveElement holds the box and its state, with ComputeBBox() and
  AssertBBox(). Removed TAttBBox from seven classes, and the unused TAtt3D
  from REveCaloViz and REveDigitSet.
- WriteCoreJson() writes the box with the render data, as "bbox", or
  "bbox_not_in_world" for screen-space elements. kCBObjProps invalidates it.
- Removed the boxes in render-data normals and own JSON; the client reads
  el.bbox.
- BBoxInit() starts from +-infinity; a box that no point reached is
  kBBoxNone. Added BBoxCheckBox(centre, half sizes), and
  REveVectorT::SetMin(), SetMax().
- Fixed the boxes of REveGeoShape and REveBoxSet. The box of
  REveProjectionManager is the union of the projected ones.
- Renamed kCBTransBBox, StampTransBBox() to kCBTrans, StampTrans().
- Added gtests.

Assisted-by: Claude:Opus 5.5
… changes

Projections used only the model's own matrix, while the 3D view composes
those of its ancestors. Depth and name changes did not reach the client.

- Added REveProjectionManager::GetModelTrans(), the model's matrix chain in
  the manager's frame, and used it in all projected classes.
- REveGeoShape's buffer stays in the shape's frame; REveJetConeProjected
  projects the apex.
- Import warns when the receiver's frame differs from the manager's.
- SetDepthCommon() stamps kCBObjProps.
- Renamed kCBColorSelection to kCBCoreJson. Name and title changes stamp it;
  EveScene then calls refresh(el) of the drawing or rebuilds it.
- Added REveElement::ComposeSceneTrans(), the matrices of an element and its
  mothers up to its scene, and AuntChanged(), which an aunt calls on its
  nieces. The projection manager uses both; REveProjectionAxis follows it
  through AuntChanged() after every import and reprojection.
- Added gtests.

Assisted-by: Claude:Opus 5.5
Drawings were placed flat in the scene, so an element's matrix did not reach
its children and nothing could bound or cull a subtree.

- Each element has a node that carries its matrix: its drawing when it has
  no children, else a group whose self is the drawing and whose other
  children are the children's nodes.
- fRnrSelf hides the drawing, fRnrChildren the group's other children. On
  three.js a kids object under the group does the latter.
- A leaf that gets a child is wrapped in a group, which takes its matrix and
  motion.
- The server streams every matrix as JSON, a base64 string of its 16
  doubles; REveRenderData no longer carries it (removed SetMatrix(),
  "trans_size"). It sends no old drawing for an emptied element.
- The client places elements by their nodes' matrices. A full update sets
  the matrix, identity when there is none; moves and motion set the node; a
  rebuild without new state keeps it.
- The client copies render data out of the message buffer, so the buffer
  is freed.
- The scene box is the union of the server boxes, and near and far follow
  moving elements. The orthographic camera also fits the width.
- Frustum-culled instanced hits and box sets.
- sceneElementChange() reads the message's change bits. With the element's
  stale bits, a visibility change rebuilt the drawing, on master too.
- Removed the null checks of EveScene.glctrl.
- Added a gtest.

Assisted-by: Claude:Opus 5.5
A moving element lost its motion on a full update, and a new client or a new
viewer showed no motion until the next transformation change. The client's
clock came from motion start times, which are old for a new client.

- Wrote the motion next to the matrix in a full write, which holds the whole
  transformation. Added kCBFullRebuild as an alias of kCBObjProps.
- InitMainTrans() and DestroyMainTrans() stamp kCBTrans; InitMainTrans() also
  clears the motion.
- Added server_time to scene and Motion messages, as the last field with a
  fixed width. REveUtil::AppendServerTime() adds it after the dump and
  StampServerTime() sets it in place just before each send, so streaming time
  does not count. The full stream carries it in a trailer entry, which the
  client takes off.
- Moved the server clock from Motion to EveManager, which feeds it from
  server_time.
- Kept the trajectory on the element's node through rebuilds. A full update
  and a new node register it from the element's motion, or drop it.
- Renamed the message key mot to motion.

Assisted-by: Claude:Opus 5.5
- orbits.C: bodies orbiting in the frames of their parents, three levels of
  six by default, 258 bodies; spins set with REveTrans::SetMotion() and
  refreshed every 2 s. Shapes as in gl/glViewerLOD.C.
- trans_update.C: a still box in the centre and four boxes going round a
  square about it, each moved by SetTransMatrix() every 200 ms.

Assisted-by: Claude:Opus 5.5
…dders, clearer names

The REveBoxSet API was inconsistent and hard to understand: the docs and the
drawing disagreed on where an axis-aligned box is, and the names did not say
which convention a call uses. This commit sanitizes the API, keeping the old
enum kBT_FreeBox and the two box registration functions AddFreeBox() and
AddBox(verts) as aliases.

- Stored kBT_Instanced and kBT_InstancedScaled instances as centre and half
  size, which is what the client draws.
- AddInstance(), AddInstanceScaled(): take centre and half size.
- Added AddInstanceCorner(), AddInstanceScaledCorner(): take lower corner and
  full size, as TEveBoxSet::AddBox().
- Removed the two axis-aligned AddBox() overloads.
- Applied the default size to kBT_Instanced only. SetDefWidth() & co. set the
  full size; added SetDefHalfWidth() & co. for the half size. Default is 1,
  a unit box; boxes that do not set a size draw half as large as before.
- Renamed EShape_e to EInstanceShape_e (kIS_*), SetShape() to
  SetInstanceShape().
- Renamed kBT_FreeBox to kBT_Vertices, BFreeBox_t to Vertices_t, AddFreeBox()
  to AddVertices().
- Added the box-type check to AddCone() and AddEllipticCone(); adder errors
  name the function and the expected box type.
- ComputeBBox() adds the box of each instance; it widened the box of the
  positions by the largest instance.
- Aligned the digit structs; removed a stale TODO.
- Added a gtest for the corner adders and the default-size setters.

Assisted-by: Claude:Opus 5.5
@linev linev self-assigned this Oct 21, 2026

@linev linev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huge PR!

I see changes in basic tutorials - are they intended?
Like renaming kBT_FreeBox -> kBT_Vertices and AddBox -> AddVertices
Seems to be old constant and old method are still there.
But this is cosmetic.

Lets wait until all tests are passed.

@github-actions

Copy link
Copy Markdown

Test Results

    24 files      24 suites   4d 1h 7m 3s ⏱️
 3 892 tests  3 892 ✅ 0 💤 0 ❌
83 326 runs  83 326 ✅ 0 💤 0 ❌

Results for commit 2dffca1.

@linev
linev merged commit 4e2be8c into root-project:master Oct 21, 2026
31 of 32 checks passed
@osschar

osschar commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Thank you Sergey!

Yes, it was huge -- but it was also one of the bothersome TEve half-legacies. Bounding boxes and the object 3D hierarchy was never properly done in REve -- now it is! :)

I'm trying to work towards closing up issues from the notes I have accumulated over the years -- so we can finally consider moving REve out of Experimental. That's why I'm also cleaning up the API and making it clearer (while keeping some old names for backward compatibility, mostly in Fireworks).

With this I'm done for 6.42. I will keep testing it, making sure with Alja that things work in Fireworks, too.

@osschar
osschar deleted the bh-bbox branch October 22, 2026 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants