SOLEVELOFDETAIL(3iv)

πŸ’… SoLevelOfDetail β€” level-of-detail switching group node πŸ’…

Hiii bestie, welcome to the SoLevelOfDetail(3IV) page, aka the node that decides which version of your lil object gets to show up depending on how big it looks on screen. She's giving main character energy and she's here to explain herself. πŸŽ€


πŸ¦‹ INHERITS FROM

SoBase > SoFieldContainer > SoNode > SoGroup > SoLevelOfDetail

So yeah, she's a whole descendant chain β€” everything in that line is her ancestry, and she carries all their baggage (and their methods, which is honestly a slay). ✨


🌸 SYNOPSIS

#include <Inventor/nodes/SoLevelOfDetail.h>

Fields from class SoLevelOfDetail:

  • SoMFFloat screenArea

Methods from class SoLevelOfDetail:

  • SoLevelOfDetail()
  • static SoType getClassTypeId()

Methods from class SoGroup:

  • void addChild(SoNode *child)
  • void insertChild(SoNode *child, int newChildIndex)
  • SoNode * getChild(int index) const
  • int findChild(const SoNode *child) const
  • int getNumChildren() const
  • void removeChild(int index)
  • void removeChild(SoNode *child)
  • void removeAllChildren()
  • void replaceChild(int index, SoNode *newChild)
  • void replaceChild(SoNode *oldChild, SoNode *newChild)

Methods from class SoNode:

  • void setOverride(SbBool state)
  • SbBool isOverride() const
  • SoNode * copy(SbBool copyConnections = FALSE) const
  • virtual SbBool affectsState() const
  • static SoNode * getByName(const SbName &name)
  • static int getByName(const SbName &name, SoNodeList &list)

Methods from class SoFieldContainer:

  • void setToDefaults()
  • SbBool hasDefaultValues() const
  • SbBool fieldsAreEqual(const SoFieldContainer *fc) const
  • void copyFieldValues(const SoFieldContainer *fc, SbBool copyConnections = FALSE)
  • SbBool set(const char *fieldDataString)
  • void get(SbString &fieldDataString)
  • virtual int getFields(SoFieldList &resultList) const
  • virtual SoField * getField(const SbName &fieldName) const
  • SbBool getFieldName(const SoField *field, SbName &fieldName) const
  • SbBool isNotifyEnabled() const
  • SbBool enableNotify(SbBool flag)

Methods from class SoBase:

  • void ref()
  • void unref() const
  • void unrefNoDelete() const
  • void touch()
  • virtual SoType getTypeId() const
  • SbBool isOfType(SoType type) const
  • virtual void setName(const SbName &name)
  • virtual SbName getName() const

✨ DESCRIPTION ✨

Okay so picture this: the children of this node are all the same object or objects, just at varying levels of detail, listed from highest detail to lowest. 🫢 And the thing that picks the winner is β€” drumroll β€” the size of the objects when projected into the viewport. That's literally the whole vibe check. Whichever version matches that size gets traversed (i.e., which child gets traversed).

So how is that size computed? It's the area of the screen rectangle enclosing the projection of the 3D bounding box that encloses all of the children. When rendering, this size gets compared against the values sitting in the screenArea field, and the rules are:

  • If the size is greater than the first value, child 0 is traversed. πŸ‘‘
  • If it's smaller than the first, but greater than the second, child 1 is traversed.
  • And so on, and so on, forever and ever. πŸ’«
  • If there are fewer children than are required by this rule, the last child is traversed. (No crash, no drama, she just serves you what she's got.)
  • The screenArea field contains just 0 by default, so the first child is always traversed out of the box. Periodt.

Now β€” the size calculation takes the current complexity into account, and this part matters, so listen up:

  • If the complexity is 0 or is of type BOUNDING_BOX, the last child is always traversed.
  • If the complexity is less than .5, the computed size is scaled down appropriately to use (possibly) a less detailed representation.
  • If the complexity is greater than .5, the size is scaled up.
  • At complexity 1, the first child is always used.
πŸ’€ Also note, bestie: the SoLOD node is similar to SoLevelOfDetail, except the switching between levels in the SoLOD node is based on distance from the camera, which is faster than using screen area. Two different girls, two different strategies. Pick your fighter. πŸ”₯

🌈 FIELDS 🌈

  • SoMFFloat screenArea β€” Areas to use for comparison. That's it, that's the field. She's simple but she runs the whole show. πŸ’…

🧚 METHODS 🧚

  • SoLevelOfDetail() β€” Creates a level-of-detail node with default settings. Fresh out the box, defaults on, ready to go. ✨
  • static SoType getClassTypeId() β€” Returns type identifier for this class. Iykyk, you need this for all the type-checking nonsense. πŸŽ€

πŸ¦„ ACTION BEHAVIOR

SoGLRenderAction, SoRayPickAction, SoCallbackAction

  • Only the child with the appropriate level of detail is traversed. She's not doing extra work, she's efficient, she's iconic. πŸ’…

SoGetBoundingBoxAction

  • The box that encloses all children is computed. (This is the box that is needed to compute the projected size.) Like, all of them, even the low-detail ones. Because math. 😭

others

  • All implemented as for SoGroup. No surprises, no chaos, just group behavior. 🌸

πŸ’– FILE FORMAT/DEFAULTS πŸ’–

LevelOfDetail {
   screenArea  0
}

Look at her. One field. Zero. Beautiful. πŸŽ€


πŸ‘‘ SEE ALSO πŸ‘‘

SoLOD, SoComplexity, SoSwitch, SoGroup


And that's the whole page, bestie! 🫢 This was SoLevelOfDetail(3IV)() β€” the footer's got the manual name and that empty date slot sitting there unfilled, so if anyone asks, that's the version stamp and we're not gonna pretend otherwise. Go forth and let the screen area decide which child gets to shine. πŸ’–βœ¨πŸ¦‹