Summary
The project
The project’s main goal was to create at least three new animation effects on LibreOffice Impress that are simulated using 2D physics engine Box2D. Which would use the 2D physics engine’s capabilities to create some exciting animations that bounce around interact with each other and hopefully look cool.
My work
First thing to do was bundling Box2D with the build system of LO.
After that, worked on a wrapper that was going to be the backbone of the project and abstract all Box2D related stuff. This wrapper didn’t take it’s final shape until the end of the project since it is the main place where the magic happened – throughout the project it always changed.
Building it from the start was useful though, since it gave me a solid vision on how would the animation engine interact with it (or what kind of information from LO would the wrapper need to function properly).
Later, I’ve connected up the animation engine creating a new animation node for physics animation by following the implementation of path motion animation. And worked on making them saveable through SMIL hierarchies on content.xml.
Up till this point all shapes in the slide were approximated by their bounding box in the simulations, which was not ideal. Therefore, I’ve worked on representing the shapes as closely as possible to their original shape. Got that to work by getting the shape’s bezier/polygon representation (simplifying it as much as i can without losing the resemblance of the original shape), triangulating it and adding the collection of triangles to a single physics body.
In the hope of spicing things up a little, added some options that can be used on xml hierarchies that make it possible to create more exciting physics based animation effects that specify the bounciness, density, and the starting velocity of the physics body.
To finish up, created a total of 4 animation effect presets that use the physics based animation effects.
Demonstration video
How does the current implementation function?
The Box2D wrapper lives in:
- slideshow/source/engine/box2dtools.hxx
- slideshow/source/engine/box2dtools.cxx
It manages the Box2D World and the Box2D Bodies. When a physics animation starts (if not initiated before by another physics animation) the Box2D World gets initiated and a physics body with an edge loop shaped fixture that represents the slide frame is created with it. This slide frame always has 100 meters width or height depending on which is actually greater in the current slide properties, and a scale factor is calculated depending on the slide size which is used in mapping the Box2D coordinates to LO coordinates and vice versa. Later, all the shapes in the current slide that are in the foreground (which are shapes that do not belong to the master slide and not a background shape) created as a static Box2D Body.
During this creation process if the shape is filled & closed it is created by triangulating the shape and adding the resulting triangles to the Box2D Body, this is necessary since a Box2D physics body can only have convex shaped fixtures.
If the shape isn’t a filled & closed one or is just an edge shape, it’s divided up into it’s edge segments and each edge segment is represented by a quadrilateral shaped fixture.
Here’s a visualization showing how a shape is represented in the Box2D world:
When a physics animation starts, it makes the corresponding physics body to it’s shape a dynamic one, and applies the density, bounciness, starting velocity parameters specified in the xml to it. On each update cycle physics animation steps through the simulation using box2DWorld::stepAmount
.
If there are other type of animation effects going in parallel with a physics animation, those animation effects queue up updates on what property they have manipulated (position, rotation etc.) and to which value. And then when a physics animation calls box2DWorld::stepAmount
, box2DWorld::processUpdateQueue
is called and these updates are processed in a way that produce convincing simulations. For instance if it is a change in position, instead of just setting the corresponding physics body’s position, a linear velocity is calculated which will make the body travel to the given position in the time box2DWorld::stepAmount
will step through and applied to the body.
When there are two physics animations going on in parallel, only one of them steps through the simulation. This is achieved using a simple lock mechanism. If the physics animation that was stepping the simulation ends, it unlocks and if there’s another one still going on it takes the lock.
Whats left to do or can be done?
- Physics animations do not take in account animation effects that manipulate size and skew of the shapes.
- Shapes that are self intersecting polygons/beziers are not handled properly.
- Bounciness, density options can be added to the animation side panel so that the user can have more control over the animation effects.
Conclusion
Overall, working on this project was really fun! I’m pretty proud with the outcome, and hoping it is some nice eye candy that the community and the users of LibreOffice will like :). If you’d like the check out and play around with the physics based animations you can build from master or grab a nightly build!
I’m really thankful for Google and LibreOffice for providing me with such a great opportunity which helped me grow quite a bit! Thanks to everyone in the LibreOffice community for giving me a helping hand :). And most importantly, greatly thankful to Thorsten Behrens which was my mentor throughout the GSoC period, he has literally guided me everyday on what to do, what not to do and how to do, on top of it answered each of my silly newbie questions. You were the greatest mentor I could’ve asked for!
Since working with the LibreOffice community was great and now that I’m kind of warmed up working on LibreOffice, my plan is to keep hacking on LibreOffice and especially Impress from now on!
Commits
All of the commits I’ve sent at the GSoC period can be found at:
https://gerrit.libreoffice.org/q/owner:q.sarperakdemir%2540gmail.com+after:2020-05-15+before:2020-09-01+-status:abandoned
They are also listed below:
- external: bundle box2d
- box2d: fix strict aliasing error and ignore -Wshadow
- adding XShapeToShapeMapSharedPtr getter to ShapeManager
- Add Shape mbIsForeground flag and getters and setters for it
- box2d tools: initial work for physics based animation effects
- add box2d to CppunitTest_slideshow
- make physics based animation effects part of the animation engine
- add version tag to ANIMATEPHYSICS
- fix box2dtools build error for non debug builds
- make physics based animation effects importable-exportable
- add support for complex shapes in physics animation effects
- box2dtools renaming some for clarity
- make physics animation effects always processed last
- make physics animations handle sequential animations correctly
- add bounciness velocity and density options to physics animations
- fix group shape crash for physics animations
- tdf#136097: make physics animation effects handle skips and rewinds
- tdf#136152: make physics animation effects handle animations with jumpy starts
- document physics animations and related code
- make physics animation imports forward compatible
- add missing initializers about physics animations to AnimationNode class
- add two physics based emphasis animation effects presets
- tdf#136276: fix physics animations faulty duplication
- add physics based exit animation effect preset Fall and fade out
- tdf#136301: fix parallel physics animations over-stepping during lock transfer