Skip to content

Dynamic culling#1095

Merged
erikwijmans merged 5 commits intomasterfrom
dynamic-culling
Feb 23, 2021
Merged

Dynamic culling#1095
erikwijmans merged 5 commits intomasterfrom
dynamic-culling

Conversation

@erikwijmans
Copy link
Copy Markdown
Contributor

Motivation and Context

Culling for dynamic objects. This updates the local AABB to be in world coordinates if a scene node doesn't have a precomputed AABB. Uses caching and lazy computation to be efficient (@mosra I think I have done this correctly, but I would appreciate a double check).

How Has This Been Tested

Tests pass, in the viewer now you can see the number of culled objects increase as you add objects.

Types of changes

New feature (non-breaking change which adds functionality)

@facebook-github-bot facebook-github-bot added the CLA Signed Do not delete this pull request or issue due to inactivity. label Feb 16, 2021
Comment thread src/esp/scene/SceneNode.h

class SceneNode : public MagnumObject {
class SceneNode : public MagnumObject,
public Magnum::SceneGraph::AbstractFeature3D {
Copy link
Copy Markdown
Contributor

@bigbike bigbike Feb 17, 2021

Choose a reason for hiding this comment

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

My biggest concern comes from this inheritance. SceneNode is just a pure scene graph node, inherited from the MagnumObject, and a "feature" is an attachment on that node.
Logically, a class should not be a node and an attachment to that node at the same time. This is not a good design.

Can we do it using "composition method" instead of "inheritance method"? Namely you created a new feature inherited from AbstractFeature3D, and add a "feature pointer" to this new feature in the SceneNode class?

Copy link
Copy Markdown
Contributor Author

@erikwijmans erikwijmans Feb 17, 2021

Choose a reason for hiding this comment

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

This is the way it is recommended by the magnum docs and I believe it is the only way to do it: https://doc.magnum.graphics/magnum/scenegraph.html#scenegraph-features-caching

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Logically, a class should not be a node and an attachment to that node at the same time.

That's supported by design, and perfectly fine. (Unless your coding guidelines ban multiple inheritance.)

Could be also a member variable, but then everything becomes more verbose, and you'll need another derived class and...

else {
if (!worldCumulativeBB_)
worldCumulativeBB_ = {
geo::getTransformedBB(getCumulativeBB(), absoluteTransformation_)};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Glad to see geo::getTransformedBB becomes useful in this performance-critical project. I remembered I optimized this function so that it became 13x faster.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah! The existence of that function and it being very fast is what makes this work well :)

@bigbike
Copy link
Copy Markdown
Contributor

bigbike commented Feb 17, 2021

@mosra: would you take a pass? Thanks!

node.setFrustumPlaneIndex(*culledPlane);
}
// if it has value, it means the aabb is culled
return (culledPlane != Cr::Containers::NullOpt);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
return (culledPlane != Cr::Containers::NullOpt);
return !!culledPlane;

works too

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, but I do like the explicitness of this

Comment on lines +63 to +66
if (isDirty())
return absoluteTransformation().translation();
else
return absoluteTransformation_.translation();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this should instead be

Suggested change
if (isDirty())
return absoluteTransformation().translation();
else
return absoluteTransformation_.translation();
return setClean(), absoluteTransformation_.translation();

(or with less code golf, possibly). Basically you're going through the pain of calculating the absolute transformation but then you throw it away so next time absoluteTransformation() gets called, it will calculate it from scratch again, instead of reusing the cached value.

The docs suggest this also:

Before using the cached value explicitly request object cleaning by calling object()->setClean().

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The rationale here was that this method is marked as const (and makes sense to be const). I can cast around that tho

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ooh, right

(add a non-const overload that saves the work at least in 50% of cases? 😄)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's a good idea.

Copy link
Copy Markdown
Contributor

@aclegg3 aclegg3 left a comment

Choose a reason for hiding this comment

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

🎉

@erikwijmans erikwijmans merged commit cc77d89 into master Feb 23, 2021
@erikwijmans erikwijmans deleted the dynamic-culling branch February 23, 2021 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed Do not delete this pull request or issue due to inactivity.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants