NokiMo
neosvr
neosvr

patreon


BEPUv2 upgrade complete - improved performance, step up logic, proto-rigidbodies

Hello everyone and welcome to another of our weekly updates!

Last  week we have released one of the biggest updates to Neos yet, upgrading  the physics engine from BEPUv1 to BEPUv2, with a greatly improved  performance and re-engineered how the integration works with Neos and  has been one of the top requested changes both by GitHub and Patreon  voting.

Combined this has greatly improved performance in many  situations (particularly collider heavy worlds and items), improved  physics behavior (e.g. when really small or going really fast) and fixed  number of longstanding issues, such us users getting dropped out of  fast moving vehicles or colliders lagging a frame behind.

There's  a number of improvements as well, for example we implemented proper  step up logic for character controller - no longer will you get stuck on  small bumps in the environment - now you can walk up 2 meter tall  stairs steps if you really want to!

Character controller can now  also use any shape and update in realtime. With this it now respects  your actual height in-game, so you can duck and walk under obstacles!  Another addition lets you modify the interaction with specific colliders  (or even spot on a collider using a texture), making surface sticky,  slippery, bouncy and more!

And perhaps the most fun, you can now  unlock rotation on character controller. As somewhat unintended side  effect, this lets you create simple "proto-rigidbodies", that many of  you have already been having fun with.

While we don't want to  stop anyone from messing around with those (they are very fun after  all!), please give the post below a read to understand their limitations  and what is planned for the full rigidbody support that's coming at  later point as separate major update, so you don't run into any nasty  surprises!

You can read a lot more about the changes and  improvements below and check out the detailed change log - we don't  think that any build in the past ever had one this big!

In big  part it's also thanks to our QC Team and Danger Testers, who helped  catch dozens of issues and content breakages before the update went  public, ensuring mostly smooth release.

There's a lot more  exciting stuff to come in the future with the upgrade done, such as full  rigidbody physics, culling systems for optimizations, value control  volumes and more!

BEPUphysics v2 upgrade complete!

Last week we completed one of the biggest upgrades of Neos’ codebase to date - switching the physics engine from BEPUv1 to BEPUv2 and completely re-engineering how Neos integrates with a physics engine to power its interactions.

Despite  the name, BEPUv1 and BEPUv2 are completely different physics engines,  with BEPUv2 being written completely from scratch for greatly improved  performance and flexibility of integration. Both are open-source  projects by Ross Nordby.



Inside  of Neos the physics engine is used to power the majority of  interactions - whenever you point at something with a laser, grab an  object, use a tool to interact with in-world items or move around the  environment, the physics engine is used to figure out which objects in  the 3D space are hit.

Because it’s the underlying layer for the  majority of the core interactions with the environment, the integration  with BEPUv1 has been one of the oldest parts of Neos’ codebase and it  was showing its age in a number of issues that have accumulated over the  years, both with glitchy behaviors and performance.

With the  upgrade, we took the opportunity to completely scrap all the Neos code  that integrates the physics engine as well and write a completely new  one, with the latest conventions and good practices of Neos’ codebase.

In  combination with BEPUv2 being a major upgrade in terms of performance  and allowing better flexibility in integration thanks to its low level  interface, Neos now has greatly improved performance in many areas,  fixed numerous bugs and implemented a number of new features that have  been requested for a while, with much more to come in the future! Let’s  dive into them!

Improved world performance

Thanks  to BEPUv2’s performance oriented design and our re-engineered  integration, performance issues in a number of areas have been fixed,  particularly with very collider heavy worlds.

The improvement  will depend greatly on a world or session, depending on what particular  bottleneck is. Certain worlds have seen great improvement in  performance. For example Dark City 2 went from 70 FPS to around 120 FPS  on the same system in the same spot. Large Minecraft import worlds have  seen huge benefits thanks to their heavy use for triggers, some of the  biggest ones going from 20 FPS to smooth 110 FPS and being limited by  the amount of rendered geometry instead.

https://youtu.be/7DUJ6Krljzo

Many of these improvements are to improve handling of the colliders,  ensuring that changes and moved colliders don’t cause unnecessary  calculations (such as waking up colliders that aren’t interested in the  updates) and certain parts of the update process run asynchronously from  the rest of the updates.

Other worlds have seen smaller  performance boosts, while other very negligible ones, due to being  bottlenecked by other parts of the system, such as heavy LogiX use. This  was expected, since with any complex system any part can become  bottlenecked and our goal is to continually optimize all of them, with  each optimization improving the general performance.

https://youtu.be/ablQ4-zqiQ0

Smoother loading

The  loading process should be now smoother as well. We fixed a number of  issues causing extremely heavy CPU and memory usage which could lock up  some systems, due to computing mesh metadata and colliders.

With  BEPUv1 the acceleration structures required for mesh colliders and  convex hulls were always computed on the fly as you loaded into the  world, resulting in more stutters. With BEPUv2 integration the system  now utilizes our asset variant system instead, computing the data only  once and then loading it from the cache or the cloud.

Thanks to  this the loading process should now be smoother and cause less load on  the system. In our testing, computing a mesh collider for a dense mesh  would take around 680 ms, while decompressing and loading a precomputed  one took around 40 ms.

More efficient Raycast and Sweep queries

Thanks  for BEPUv2’s low level design, we could optimize the common queries  against the physics representation of the world - raycasts and convex  sweeps, used to find which objects are hit in the world - e.g. when you  use a tool, click on something with your laser or shoot a weapon.

If  the query is interested in only one closest hit, it now uses a  specialized path that adjusts the tested ray distance based on the found  hits and avoids building a list of all hits to sort out later, reducing  some memory usage. Both the LogiX RaycastOne and internal uses (e.g.  particle system collisions) have been replaced with this variant.

More efficient dynamic bone chain collision queries

Part  of our reason to upgrade to BEPUv2 was to also utilize some of its  efficient data structures for our own features and various culling  systems. One of the first such optimizations has been reworking the way  dynamic bone chains look for potential colliders in the environment.

Previously  each chain would scan all users by itself individually. With an  increasing number of users (and dynamic bone chains) in the world, this  would scale poorly and cost more and more CPU performance.

With  the reworked system the initial intersections are now efficiently  distributed using BEPUv2’s Tree structure, which should provide much  better scaling and give us framework for more culling optimizations in  the future.

https://youtu.be/R-7MfNqsA4Y

Character Step Up logic

One  of the longstanding issues in Neos reported by many users was the  character controller getting stuck on small obstacles, requiring the  heavy use of ramps when building worlds. We have previously deferred  this issue to the BEPUv2 upgrade and with it now done, the issue has  been resolved!

Thanks to the low level integration, we have  implemented a proper step up logic, which will automatically walk up  vertical obstacles, such as stairs, bumps and even tall vertical walls  if the step height is configured so.

This should provide a lot  more flexibility for creators to build the environments and make it  easier for users to walk around any map, without getting stuck on small  bumps and pieces of geometry. Setting up ramps might still be  preferable, as it will provide a smoother movement, but is no longer  necessary.

https://youtu.be/FTCW_5O-SUs

Character Controller now respects your current height and can be any shape

Another  of the long requested features has been the ability for character  controller to respect your current height - for example when you crouch,  the shape representing you in the world gets smaller, allowing you to  walk under obstacles.

With the upgrade and the logic of the  character controller reworked, this is now fully supported! Rather than  always being a fixed capsule shape, the collider has now been decoupled  from Character Controller and is presented by a separate component on  the same Slot.

https://youtu.be/6uiYs45uXeE

As a result, you can use any convex shape - box, cylinder, sphere, even  convex hull! The shape can also be updated as any other too. For  Character Controller specifically there’s a new  SingleShapeCharacterControllerManager component, which automatically  adjusts the height of the collider based on the current position of your  head.

This means in VR you can now duck and walk under  obstacles! Desktop mode has a bit of extra behavior as well on top,  which will prevent the character from standing up after crouching if  there’s something above them.

https://youtu.be/GNW59n3M8sQ

We are looking into doing more in the future as well. With planned  compound collider support, it should be possible to split the character  body into multiple shapes instead of a single one and provide even more  precise collisions with the environment when leaning over or laying down  in full-body.

Character Controller surface modifiers

To  give you even more flexibility when building worlds, we introduced a  new type of component - character controller modifiers! These allow you  to modify the behavior of a particular collider for character collisions  - dynamically changing the traction parameters, speed, jump height and  more.

With this you can easily create surfaces that are sticky  (like the purple goo from DOOM Eternal), slippery (like ice that makes  you slide), ladders that you can climb vertically by walking into them  and much more!

It’s also possible to utilize a texture to control  the parameters, allowing you to vary the parameters depending on where  the player is colliding. This can be very useful for terrains. We can’t  wait to see what kinds of maps and cool things you’ll build with this  new mechanism!

https://youtu.be/aMcHxTBKcFU

Fixed collisions being a frame behind and getting dropped out of vehicles

With  previous integration users ran into a number of problems, particularly  when building fast moving vehicles. Oftentimes users would end up  randomly dropping out of the vehicle if it’s moving fast enough and  interacting with any colliders within it would be difficult as well, as  they would be lagging a frame behind from the visual.

https://youtu.be/xEABzn_ed-M

Thanks to the whole integration being re-engineered, we put a lot more  care into how the new one is designed to avoid those problems  altogether, by paying more attention about the order of operations and  ensuring that the physics representation is updated at the right time.

This  was done by splitting movement events between general and physics,  allowing the colliders to update their poses before interactions happen,  without causing issues with other components that must update late.

Along  with a whole number of smaller design changes, those issues are now  completely gone! Vehicles and other behavior should now be reliable and  easier to enjoy!

Improved interactions at small scales

One  of the big changes in BEPUv2’s design is it’s auto-tuning mechanism.  The previous version had a number of manual settings to make it behave  well for particular use-case and scale. As a result if you scaled  yourself down in Neos (or large), interactions with the environment  would feel “off” and glitchy.

BEPUv2’s design however tries to  avoid those manual settings whenever possible and instead the  calculations are tuned automatically. As a result of the upgrade,  interactions while being scaled significantly down in Neos now feel the  same as at regular scale, giving users more flexibility on interacting  with the environment!

Mesh Colliders can now be single sided

Previously  all mesh colliders in Neos would be dual-sided - you would collide and  hit the mesh from whichever side you’d come in. In a large number of  cases, this was actually undesirable - you could easily get stuck in the  geometry or halfway through a terrain due to colliding with both sides  of it.

With the new integration, we have now exposed this as a  configurable option, allowing you to set collisions to only happen from  the front side of the mesh - the one that you see with a single  sided-material.

On top of that we have also added heuristic that  automatically converts any character colliders into Front sided only,  unless some conditions are met - there’s a dual-sided material on the  same slot or any negative scaling.

This technically changes  behavior of existing content, but from our testing phase this seems  generally beneficial in improving the behaviors of those worlds and  improving performance, with the heuristics preventing the upgrade in  cases where it would cause issues. If you find any more, let us know  though and we can tweak them some more!

Static Trigger types

We  have added some new collider types to the mix as well! In addition to  Trigger and HapticTrigger, there are now static variants as well -  StaticTrigger and HapticStaticTrigger. These are functionally the same,  but assuming they don’t move relative to the world, will skip some of  the overhead that non-static variants have.

If you’re building  new content, it’s recommended to use those types whenever you know that  it won’t move which can give you a bit of extra performance (especially  if there’s a lot of them). If they are moving however, use the regular  ones.

You’ll probably notice that there’s also “Auto” variants of  these. Any existing content is automatically switched to those, so it  can gain benefits of their optimizations. If any movement is detected  over several frames, they will automatically be switched to the  non-static version.

Main physics and Haptic colliders are now separated

Previously  a single physics simulation was used to handle all the different types  of colliders - both for environment collisions and triggers, as well as  haptic volumes, triggering any haptic interactions in the environment.

Because  those two types of interactions never interact with each other, the new  integration now splits them up into two completely separate  simulations. Not only does this avoid a bunch of cross testing of  colliders that will never interact, but allows us to update them fully  in parallel, for a bit of additional performance!

Mesh density heuristics - no more lag when laser tries to stick to dense mesh

Another  of the small, but hopefully impactful performance improvements is  handling of dense mesh colliders. Lasers in Neos have a “sticking”  logic, which tries to stick the laser point to the last object when it  goes past the edge.

https://youtu.be/yxwZjOg9VEM

Generally this works pretty well, unless the object is using a dense  mesh collider. The sticking tests can be very expensive against those  colliders, which would cause your framerate to randomly drop as you  interact with the environment.

Neos now computes average triangle  sizes and areas as part of the mesh metadata, which now allows us to  estimate average density of the mesh relative to the scale it’s being  tested at. If we detect that the test would be likely too expensive, we  simply skip the expensive tests and just stick to the last known point.

This  should help improve the general user experience with unoptimized  content and avoid another case of accidental stutters that can be  uncomfortable to users.

Double buffered procedural mesh collider updates

When  using mesh colliders with procedural meshes, Neos would previously try  to update the acceleration data in-place. In some cases this would  result in glitchy behaviors, where certain colliders would seem to  flicker in and out of existence or produce random ghost collisions, due  to being in the middle of an update. You could particularly notice this  with LogiX in some cases.

To improve this behavior and prevent  potential race conditions, the new mechanism is now double buffered,  simply computing a new acceleration structure in the background, while  the existing one is in use and then swapping them over.

This mechanism also improves the memory management, avoiding lots of new allocations on frequently changing mesh colliders.

While  this improves the behavior, generally it’s recommended to use simpler  colliders instead, especially for anything that changes over time, as it  will provide better performance.

Numerous other performance improvements and fixes

Apart  from these notable changes, the upgrade process had many more bug fixes  and small performance improvements that should overall help improve the  user experience for both end users and creators.

If you’d like to see a more complete list of the changes, check out the release notes here, which go into a bit more detail.

https://store.steampowered.com/news/app/740250/view/2944778418489689559

Proto-rigidbody physics - what are they?

Perhaps  one of the most exciting and somewhat unintended features of the BEPUv2  upgrade is the ability to get simple rigidbody simulation, thanks to  the combination of being able to use any shape with CharacterController  and new ability to unlock its rotation.

With this, you can get  objects that behave like rigidbodies, which can be very fun to interact  and play with, but which also come with some important limitations that  everyone needs to understand first.

Importantly, those are NOT  what the actual planned rigidbody support entails - it is a separate  body of work that will come at a later point after this upgrade and will  be designed to handle the rigidbody simulation efficiently (both on  system resources and network) and give you full control.

Why character controllers aren't suitable for rigidbody simulations

Now  if you understand these limitations, feel free to have fun with them in  the meanwhile, before the full support actually comes. Neos is all  about tinkering, toying around and messing with things and it will give  you a bit of a taste of what will come.

Here are some videos of our users playing with them!

https://youtu.be/Oz7t3L7xH1s

https://youtu.be/Oz8q7_GUDV4

https://youtu.be/FsBAhxJKe-4

What will full rigidbody support offer?

The  full rigidbody support covered by this issue is a significant chunk of  work that will come after the BEPUv2 upgrade completes. It will focus on  following:

Make sure to also check  the roadmap for physics support, we'll expand it with individual tasks  once work begins on this (we're still finishing BEPUv2 upgrade at the  moment, so it won't happen before then): https://github.com/Neos-Metaverse/NeosPublic/projects/19

Big thanks to everyone who helped with the upgrade!

The  upgrade has been a relatively long and tedious process, as we had to  remove a significant chunk of Neos’ codebase and completely redesign and  rework it on a new system, while making sure that existing interactions  and content doesn’t break.

--- ---

BEPUv2  integration merge request, right before public release, along with all  reports by QC team and public testing (click to view full image)

Before  releasing the upgrade to the public, we ran closed testing first with  our new QC team in order to find out the most egregious bugs and issues,  followed by public testing with our Danger Tester group afterwards, to  get much broader coverage of issues and problems.

Thanks to  everyone’s efforts, we found dozens of bugs, content breakages, crashes,  performance issues and other issues during the testing phase and  addressed them before the public release, leading to a relatively smooth  release. Of course if you find any more bugs and regressions, feel free  to report them on GitHub, we'll still be fixing what we can even  post-release!

Here’s a huge thanks to Shifty and her QC team for helping out catch all the early bugs, as well as Danger Tester's who participated in the public testing: Shadow  Panther, Beaned, ohzee, Zyzyl, Alex from Alaska, Snooper, Pat cat,  LucasRo7, Turk, Enverex, MattyK, Cyro, Modern, 1amNick, Hayden,  Toxic_Cookie | NTC CEO, Elizabeth Dayax, Epsilion, epicEaston197,  DrFrank, TheBasementNerd (she/her), Alex rainbowdashie, Sloppy McFloppy ,  Ian Corvid, Kulza, Tatsu Kimiero, Sylva, Gawdl3y and everyone who  tested without reports!

Another huge thanks also goes to Ross Nordby, the developer of BEPUphysics 2,  for his detailed explanations and responses that helped with the  integration process and quick bug fixes of issues we found in the  physics engine itself!

And last but not least, there’s a huge  thanks to everyone in the community and our Patreon supporters, who have  enabled us to work on this large project. BEPUv2 upgrade has been one  of the top requested changes, both on GitHub and Patreon and with it now  complete Neos has made an important leap forward, with many great  things to come in the future on top of this foundation.

There are exciting times ahead! See you next week!


Comments

As seen, you work quite progressively thanks to all your close-knit team! Glad to all the improvements you've made

NakedSunFlower


Related Creators