Re: box2d

Rene Engelhard <[email protected]>
Newsgroups gmane.linux.debian.devel.games
Organization Debian Project
Message-ID <[email protected]>
Hi,

missed the attachements...

Regards,

Rene

Am 10.08.26 um 16:59 schrieb Rene Engelhard:
> Hi,
> 
> Am 10.08.26 um 12:58 schrieb Alexandre Detiste:
>> Can we after this migrates start the transition to box2d 3.1.1
> Ask the release team?
>> Does this need to go through NEW or release managers ?
> 
> Probably if it changes SONAME (didn't check) and needs changes in a loads of packages. I assume the major API changes warrant one.
> 
> Though I didn't check which packages are affected. Unhelpfully that new version isn't available anywhere, so no tracker etc:
> 
> $ rmadison box2d
> box2d      | 2.3.1+ds-7    | oldoldstable    | source
> box2d      | 2.4.1-3       | oldstable       | source
> box2d      | 2.4.1-3       | stable          | source
> box2d      | 2.4.1-3       | testing         | source
> box2d      | 2.4.1-3       | unstable        | source
> box2d      | 2.4.1-3       | unstable-debug  | source
> box2d      | 2.4.1-4       | buildd-unstable | source
> box2d      | 2.4.1-4       | unstable        | source
> box2d      | 2.4.1-4       | unstable-debug  | source
> $
> 
> Anyways, libreoffice definitely would need the attached patches (+ resolving one fuzz..) to be uploaded...
> 
> 
> Regards,
> 
> 
> Rene
>
box2d-3.0.0.diff (text/x-patch, 32.1 KB)
commit 4b6a3b93525ffb5c29ef7388413575419db830b4
Author: Xisco Fauli <[email protected]>
Date:   Fri Apr 4 18:45:52 2025 +0200

    box2d: upgrade to 3.0.0
    
    Add android.patch to fix
    
    In file included from /home/tdf/jenkins/workspace/android_arm/workdir/UnpackedTarball/box2d/src/allocate.c:6:
    /home/tdf/jenkins/workspace/android_arm/workdir/UnpackedTarball/box2d/src/core.h:50:3: error: Unsupported CPU
       50 |         #error Unsupported CPU
          |          ^
    /home/tdf/jenkins/workspace/android_arm/workdir/UnpackedTarball/box2d/src/allocate.c:71:14: error: call to undeclared library function 'aligned_alloc' with type 'void *(unsigned int, unsigned int)'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
       71 |         void* ptr = aligned_alloc( B2_ALIGNMENT, size32 );
          |
    
    Downloaded from https://github.com/erincatto/box2d/archive/refs/tags/v3.0.0.tar.gz
    
    Change-Id: I8fa42a5e0317cf0cd7a62bbe9bcfe71c1405184d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183724
    Reviewed-by: Xisco Fauli <[email protected]>
    Tested-by: Jenkins

commit 304504b5232782253c9020a85229184f4e64ef7b
Author: Rene Engelhard <[email protected]>
Date:   Wed May 6 20:51:21 2026 +0200

    fix build with box2d 2.4 again
    
    after 4b6a3b93525ffb5c29ef7388413575419db830b4
    
    See https://gerrit.libreoffice.org/c/core/+/183724/comment/3cba4107_5e47fc16/
    
    Change-Id: I3f407f6a44526c2f6067bae03b2e2ea4c50a0c22
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/204890
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <[email protected]>

diff --git a/config_host/config_box2d.h.in b/config_host/config_box2d.h.in
index 431987866623..54eeeb7cacf0 100644
--- a/config_host/config_box2d.h.in
+++ b/config_host/config_box2d.h.in
@@ -1,6 +1,9 @@
 #ifndef CONFIG_BOX2D_H
 #define CONFIG_BOX2D_H
 
+#undef BOX2D_MAJOR
+#undef BOX2D_MINOR
+
 /* Box2D/Box2D.h is 2.3, 2.4 has box2d/box2d.h */
 #define BOX2D_HEADER <box2d/box2d.h>
 
diff --git a/configure.ac b/configure.ac
index da4353386091..7e6c62a20ee5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12191,21 +12191,26 @@ dnl ===================================================================
 dnl Check for system box2d
 dnl ===================================================================
 AC_MSG_CHECKING([which box2d to use])
+BOX2D_MAJOR=3
+BOX2D_MINOR=0
 if test "$with_system_box2d" = "yes"; then
     AC_MSG_RESULT([external])
     SYSTEM_BOX2D=TRUE
     AC_LANG_PUSH([C++])
-    AC_CHECK_HEADER(box2d/box2d.h, [BOX2D_H_FOUND='TRUE'],
-        [BOX2D_H_FOUND='FALSE'])
-    if test "$BOX2D_H_FOUND" = "TRUE"; then # 2.4.0+
-        _BOX2D_LIB=box2d
-        AC_DEFINE(BOX2D_HEADER,<box2d/box2d.h>)
-    else
-        # fail this. there's no other alternative to check when we are here.
-        AC_CHECK_HEADER([Box2D/Box2D.h], [],
-            [AC_MSG_ERROR(box2d headers not found.)])
-        _BOX2D_LIB=Box2D
-        AC_DEFINE(BOX2D_HEADER,<Box2D/Box2D.h>)
+    BOX2D_VERSION=`$PKG_CONFIG --modversion box2d 2>/dev/null`
+    BOX2D_MAJOR=`echo $BOX2D_VERSION | cut -d"." -f1`
+    BOX2D_MINOR=`echo $BOX2D_VERSION | cut -d"." -f2`
+    if test "$BOX2D_MAJOR" -eq "2"; then
+        if test "$BOX2D_MINOR" -eq "4"; then
+            _BOX2D_LIB=box2d
+            AC_DEFINE(BOX2D_HEADER,<box2d/box2d.h>)
+        else
+            # fail this. there's no other alternative to check when we are here.
+            AC_CHECK_HEADER([Box2D/Box2D.h], [],
+                [AC_MSG_ERROR(box2d headers not found.)])
+            _BOX2D_LIB=Box2D
+            AC_DEFINE(BOX2D_HEADER,<Box2D/Box2D.h>)
+        fi
     fi
     AC_CHECK_LIB([$_BOX2D_LIB], [main], [:],
         [ AC_MSG_ERROR(box2d library not found.) ], [])
@@ -12230,6 +12230,9 @@ AC_SUBST(SYSTEM_BOX2D)
 AC_SUBST(BOX2D_CFLAGS)
 AC_SUBST(BOX2D_LIBS)
 
+AC_DEFINE_UNQUOTED(BOX2D_MAJOR,$BOX2D_MAJOR)
+AC_DEFINE_UNQUOTED(BOX2D_MINOR,$BOX2D_MINOR)
+
 dnl ===================================================================
 dnl Checking for altlinuxhyph
 dnl ===================================================================
diff --git a/download.lst b/download.lst
index 0eb8d2f118c9..a02a934c2b1e 100644
--- a/download.lst
+++ b/download.lst
@@ -19,8 +19,8 @@ BOOST_TARBALL := boost_1_90_0.tar.xz
 # three static lines
 # so that git cherry-pick
 # will not run into conflicts
-BOX2D_SHA256SUM := d6b4650ff897ee1ead27cf77a5933ea197cbeef6705638dd181adc2e816b23c2
-BOX2D_TARBALL := box2d-2.4.1.tar.gz
+BOX2D_SHA256SUM := 64ad759006cd2377c99367f51fb36942b57f0e9ad690ed41548dd620e6f6c8b1
+BOX2D_TARBALL := box2d-3.0.0.tar.gz
 # three static lines
 # so that git cherry-pick
 # will not run into conflicts
diff --git a/external/box2d/StaticLibrary_box2d.mk b/external/box2d/StaticLibrary_box2d.mk
index ac16db04e176..e83bed2f375c 100644
--- a/external/box2d/StaticLibrary_box2d.mk
+++ b/external/box2d/StaticLibrary_box2d.mk
@@ -17,56 +17,52 @@ $(eval $(call gb_StaticLibrary_set_generated_cxx_suffix,box2d,cpp))
 
 $(eval $(call gb_StaticLibrary_set_include,box2d,\
     -I$(gb_UnpackedTarball_workdir)/box2d/include/\
-    -I$(gb_UnpackedTarball_workdir)/box2d/src/\
+    -I$(gb_UnpackedTarball_workdir)/box2d/extern/simde/\
     $$(INCLUDE)\
 ))
 
-$(eval $(call gb_StaticLibrary_add_generated_exception_objects,box2d,\
-	UnpackedTarball/box2d/src/common/b2_timer \
-	UnpackedTarball/box2d/src/common/b2_stack_allocator \
-	UnpackedTarball/box2d/src/common/b2_draw \
-	UnpackedTarball/box2d/src/common/b2_math \
-	UnpackedTarball/box2d/src/common/b2_block_allocator \
-	UnpackedTarball/box2d/src/common/b2_settings \
-	UnpackedTarball/box2d/src/dynamics/b2_body \
-	UnpackedTarball/box2d/src/dynamics/b2_polygon_circle_contact \
-	UnpackedTarball/box2d/src/dynamics/b2_circle_contact \
-	UnpackedTarball/box2d/src/dynamics/b2_contact_solver \
-	UnpackedTarball/box2d/src/dynamics/b2_polygon_contact \
-	UnpackedTarball/box2d/src/dynamics/b2_chain_polygon_contact \
-	UnpackedTarball/box2d/src/dynamics/b2_chain_circle_contact \
-	UnpackedTarball/box2d/src/dynamics/b2_contact \
-	UnpackedTarball/box2d/src/dynamics/b2_edge_polygon_contact \
-	UnpackedTarball/box2d/src/dynamics/b2_edge_circle_contact \
-	UnpackedTarball/box2d/src/dynamics/b2_wheel_joint \
-	UnpackedTarball/box2d/src/dynamics/b2_friction_joint \
-	UnpackedTarball/box2d/src/dynamics/b2_prismatic_joint \
-	UnpackedTarball/box2d/src/dynamics/b2_weld_joint \
-	UnpackedTarball/box2d/src/dynamics/b2_pulley_joint \
-	UnpackedTarball/box2d/src/dynamics/b2_mouse_joint \
-	UnpackedTarball/box2d/src/dynamics/b2_motor_joint \
-	UnpackedTarball/box2d/src/dynamics/b2_distance_joint \
-	UnpackedTarball/box2d/src/dynamics/b2_gear_joint \
-	UnpackedTarball/box2d/src/dynamics/b2_joint \
-	UnpackedTarball/box2d/src/dynamics/b2_revolute_joint \
-	UnpackedTarball/box2d/src/dynamics/b2_world_callbacks \
-	UnpackedTarball/box2d/src/dynamics/b2_fixture \
-	UnpackedTarball/box2d/src/dynamics/b2_contact_manager \
-	UnpackedTarball/box2d/src/dynamics/b2_island \
-	UnpackedTarball/box2d/src/dynamics/b2_world \
-	UnpackedTarball/box2d/src/rope/b2_rope \
-	UnpackedTarball/box2d/src/collision/b2_time_of_impact \
-	UnpackedTarball/box2d/src/collision/b2_collide_polygon \
-	UnpackedTarball/box2d/src/collision/b2_distance \
-	UnpackedTarball/box2d/src/collision/b2_collision \
-	UnpackedTarball/box2d/src/collision/b2_collide_edge \
-	UnpackedTarball/box2d/src/collision/b2_collide_circle \
-	UnpackedTarball/box2d/src/collision/b2_broad_phase \
-	UnpackedTarball/box2d/src/collision/b2_edge_shape \
-	UnpackedTarball/box2d/src/collision/b2_circle_shape \
-	UnpackedTarball/box2d/src/collision/b2_chain_shape \
-	UnpackedTarball/box2d/src/collision/b2_polygon_shape \
-	UnpackedTarball/box2d/src/collision/b2_dynamic_tree \
+ifeq ($(OS),WNT)
+$(eval $(call gb_StaticLibrary_add_cflags,box2d,\
+    /std:c17 /experimental:c11atomics \
+))
+endif
+
+$(eval $(call gb_StaticLibrary_add_generated_cobjects,box2d,\
+	UnpackedTarball/box2d/src/aabb \
+	UnpackedTarball/box2d/src/allocate \
+	UnpackedTarball/box2d/src/body \
+	UnpackedTarball/box2d/src/block_array \
+	UnpackedTarball/box2d/src/dynamic_tree \
+	UnpackedTarball/box2d/src/island \
+	UnpackedTarball/box2d/src/motor_joint \
+	UnpackedTarball/box2d/src/table \
+	UnpackedTarball/box2d/src/wheel_joint \
+	UnpackedTarball/box2d/src/broad_phase \
+	UnpackedTarball/box2d/src/core \
+	UnpackedTarball/box2d/src/geometry \
+	UnpackedTarball/box2d/src/joint \
+	UnpackedTarball/box2d/src/mouse_joint \
+	UnpackedTarball/box2d/src/shape \
+	UnpackedTarball/box2d/src/timer \
+	UnpackedTarball/box2d/src/world \
+	UnpackedTarball/box2d/src/array \
+	UnpackedTarball/box2d/src/constraint_graph \
+	UnpackedTarball/box2d/src/distance \
+	UnpackedTarball/box2d/src/hull \
+	UnpackedTarball/box2d/src/manifold \
+	UnpackedTarball/box2d/src/prismatic_joint \
+	UnpackedTarball/box2d/src/types \
+	UnpackedTarball/box2d/src/bitset \
+	UnpackedTarball/box2d/src/contact \
+	UnpackedTarball/box2d/src/contact_solver \
+	UnpackedTarball/box2d/src/distance_joint \
+	UnpackedTarball/box2d/src/id_pool \
+	UnpackedTarball/box2d/src/math_functions \
+	UnpackedTarball/box2d/src/revolute_joint \
+	UnpackedTarball/box2d/src/stack_allocator \
+	UnpackedTarball/box2d/src/solver \
+	UnpackedTarball/box2d/src/solver_set \
+	UnpackedTarball/box2d/src/weld_joint \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/external/box2d/UnpackedTarball_box2d.mk b/external/box2d/UnpackedTarball_box2d.mk
index 340a17511711..de54a396152a 100644
--- a/external/box2d/UnpackedTarball_box2d.mk
+++ b/external/box2d/UnpackedTarball_box2d.mk
@@ -11,4 +11,8 @@ $(eval $(call gb_UnpackedTarball_UnpackedTarball,box2d))
 
 $(eval $(call gb_UnpackedTarball_set_tarball,box2d,$(BOX2D_TARBALL)))
 
+$(eval $(call gb_UnpackedTarball_add_patches,box2d, \
+	external/box2d/android.patch \
+))
+
 # vim: set noet sw=4 ts=4:
diff --git a/external/box2d/android.patch b/external/box2d/android.patch
new file mode 100644
index 000000000000..b8eafcb2e01c
--- /dev/null
+++ b/external/box2d/android.patch
@@ -0,0 +1,41 @@
+--- box2d/src/core.h	2026-05-05 16:51:31.330228008 +0200
++++ box2d/src/core.h	2026-05-05 16:53:35.525696798 +0200
+@@ -40,14 +40,12 @@
+ #endif
+ 
+ // Define CPU
+-#if defined( __x86_64__ ) || defined( _M_X64 )
+-	#define B2_CPU_X64
+-#elif defined( __aarch64__ ) || defined( _M_ARM64 )
++#if defined( __aarch64__ ) || defined( _M_ARM64 )
+ 	#define B2_CPU_ARM
+ #elif defined( __EMSCRIPTEN__ )
+ 	#define B2_CPU_WASM
+ #else
+-	#error Unsupported CPU
++	#define B2_CPU_X64
+ #endif
+ 
+ // Define compiler
+--- box2d/src/allocate.c	2026-05-05 17:08:39.096202016 +0200
++++ box2d/src/allocate.c	2026-05-05 17:09:17.879976210 +0200
+@@ -66,9 +66,16 @@
+ 	}
+ 
+ #ifdef B2_PLATFORM_WINDOWS
+-	void* ptr = _aligned_malloc( size32, B2_ALIGNMENT );
++    void* ptr = _aligned_malloc( size32, B2_ALIGNMENT );
++#elif defined( B2_PLATFORM_ANDROID )
++    void* ptr = NULL;
++    if ( posix_memalign( &ptr, B2_ALIGNMENT, size32 ) != 0 )
++    {
++        // allocation failed, exit the application
++        exit( EXIT_FAILURE );
++    }
+ #else
+-	void* ptr = aligned_alloc( B2_ALIGNMENT, size32 );
++    void* ptr = aligned_alloc( B2_ALIGNMENT, size32 );
+ #endif
+ 
+ 	b2TracyCAlloc( ptr, size );
+
diff --git a/slideshow/source/engine/box2dtools.cxx b/slideshow/source/engine/box2dtools.cxx
index 1495aefc362a..7a2d1546fb3d 100644
--- a/slideshow/source/engine/box2dtools.cxx
+++ b/slideshow/source/engine/box2dtools.cxx
@@ -8,8 +8,6 @@
  */
 
 #include <box2dtools.hxx>
-#include <config_box2d.h>
-#include BOX2D_HEADER
 
 #include <shapemanager.hxx>
 #include <attributableshape.hxx>
@@ -82,12 +80,14 @@ b2Vec2 convertB2DPointToBox2DVec2(const basegfx::B2DPoint& aPoint, const double
 
 // expects rTriangleVector to have coordinates relative to the shape's bounding box center
 void addTriangleVectorToBody(const basegfx::triangulator::B2DTriangleVector& rTriangleVector,
+#if BOX2D_CHECK_VERSION(3, 0)
+                             b2BodyId* aBody, const double fScaleFactor)
+#else
                              b2Body* aBody, const double fScaleFactor)
+#endif
 {
     for (const basegfx::triangulator::B2DTriangle& aTriangle : rTriangleVector)
     {
-        b2FixtureDef aFixture;
-        b2PolygonShape aPolygonShape;
         b2Vec2 aTriangleVertices[3]
             = { convertB2DPointToBox2DVec2(aTriangle.getA(), fScaleFactor),
                 convertB2DPointToBox2DVec2(aTriangle.getB(), fScaleFactor),
@@ -100,19 +100,35 @@ void addTriangleVectorToBody(const basegfx::triangulator::B2DTriangleVector& rTr
 
         if (bValidPointDistance)
         {
-            // create a fixture that represents the triangle
+        // create a fixture that represents the triangle
+#if BOX2D_CHECK_VERSION(3, 0)
+            b2Hull aHull = b2ComputeHull(aTriangleVertices, 3);
+            b2ShapeDef aShapeDef = b2DefaultShapeDef();
+            aShapeDef.density = fDefaultStaticDensity;
+            aShapeDef.friction = fDefaultStaticFriction;
+            aShapeDef.restitution = fDefaultStaticBodyBounciness;
+            b2Polygon aPolygonShape = b2MakePolygon(&aHull, 0.0);
+            b2CreatePolygonShape(*aBody, &aShapeDef, &aPolygonShape);
+#else
+            b2FixtureDef aFixture;
+            b2PolygonShape aPolygonShape;
             aPolygonShape.Set(aTriangleVertices, 3);
             aFixture.shape = &aPolygonShape;
             aFixture.density = fDefaultStaticDensity;
             aFixture.friction = fDefaultStaticFriction;
             aFixture.restitution = fDefaultStaticBodyBounciness;
             aBody->CreateFixture(&aFixture);
+#endif
         }
     }
 }
 
 // expects rPolygon to have coordinates relative to it's center
+#if BOX2D_CHECK_VERSION(3, 0)
+void addEdgeShapeToBody(const basegfx::B2DPolygon& rPolygon, b2BodyId* aBody,
+#else
 void addEdgeShapeToBody(const basegfx::B2DPolygon& rPolygon, b2Body* aBody,
+#endif
                         const double fScaleFactor)
 {
     // make sure there's no bezier curves on the polygon
@@ -127,9 +143,6 @@ void addEdgeShapeToBody(const basegfx::B2DPolygon& rPolygon, b2Body* aBody,
 
     for (sal_uInt32 nIndex = 0; nIndex < aPolygon.count(); nIndex++)
     {
-        b2FixtureDef aFixture;
-        b2PolygonShape aPolygonShape;
-
         basegfx::B2DPoint aPointA;
         basegfx::B2DPoint aPointB;
         if (nIndex != 0)
@@ -153,10 +166,18 @@ void addEdgeShapeToBody(const basegfx::B2DPolygon& rPolygon, b2Body* aBody,
         // and make it a unit vector
         b2Vec2 aEdgeUnitVec(convertB2DPointToBox2DVec2(aPointB, fScaleFactor)
                             - convertB2DPointToBox2DVec2(aPointA, fScaleFactor));
+#if BOX2D_CHECK_VERSION(3, 0)
+        aEdgeUnitVec = b2Normalize(aEdgeUnitVec);
+#else
         aEdgeUnitVec.Normalize();
+#endif
 
         // create a unit vector that represents Normal of the edge
+#if BOX2D_CHECK_VERSION(3, 0)
+        b2Vec2 aEdgeNormal = { -aEdgeUnitVec.y, aEdgeUnitVec.x };
+#else
         b2Vec2 aEdgeNormal(-aEdgeUnitVec.y, aEdgeUnitVec.x);
+#endif
 
         // if there was an edge previously created it should just connect
         // using it's ending points so that there are no empty spots
@@ -182,13 +203,25 @@ void addEdgeShapeToBody(const basegfx::B2DPolygon& rPolygon, b2Body* aBody,
 
         if (bValidPointDistance)
         {
-            // create a quadrilateral shaped fixture to represent the edge
+        // create a quadrilateral shaped fixture to represent the edge
+#if BOX2D_CHECK_VERSION(3, 0)
+            b2Hull aHull = b2ComputeHull(aQuadrilateralVertices, 4);
+            b2ShapeDef aShapeDef = b2DefaultShapeDef();
+            aShapeDef.density = fDefaultStaticDensity;
+            aShapeDef.friction = fDefaultStaticFriction;
+            aShapeDef.restitution = fDefaultStaticBodyBounciness;
+            b2Polygon aPolygonShape = b2MakePolygon(&aHull, 0.0);
+            b2CreatePolygonShape(*aBody, &aShapeDef, &aPolygonShape);
+#else
+            b2FixtureDef aFixture;
+            b2PolygonShape aPolygonShape;
             aPolygonShape.Set(aQuadrilateralVertices, 4);
             aFixture.shape = &aPolygonShape;
             aFixture.density = fDefaultStaticDensity;
             aFixture.friction = fDefaultStaticFriction;
             aFixture.restitution = fDefaultStaticBodyBounciness;
             aBody->CreateFixture(&aFixture);
+#endif
 
             // prepare the quadrilateral edge for next connection
             aQuadrilateralVertices[0] = aQuadrilateralVertices[2];
@@ -197,7 +230,11 @@ void addEdgeShapeToBody(const basegfx::B2DPolygon& rPolygon, b2Body* aBody,
     }
 }
 
+#if BOX2D_CHECK_VERSION(3, 0)
+void addEdgeShapeToBody(const basegfx::B2DPolyPolygon& rPolyPolygon, b2BodyId* aBody,
+#else
 void addEdgeShapeToBody(const basegfx::B2DPolyPolygon& rPolyPolygon, b2Body* aBody,
+#endif
                         const double fScaleFactor)
 {
     for (const basegfx::B2DPolygon& rPolygon : rPolyPolygon)
@@ -208,7 +245,11 @@ void addEdgeShapeToBody(const basegfx::B2DPolyPolygon& rPolyPolygon, b2Body* aBo
 }
 
 box2DWorld::box2DWorld(const ::basegfx::B2DVector& rSlideSize)
+#if BOX2D_CHECK_VERSION(3, 0)
+    : mbWorldInitialized(false)
+#else
     : mpBox2DWorld()
+#endif
     , mfScaleFactor(calculateScaleFactor(rSlideSize))
     , mbShapesInitialized(false)
     , mbHasWorldStepper(false)
@@ -223,7 +264,16 @@ box2DWorld::~box2DWorld() = default;
 
 void box2DWorld::createStaticFrameAroundSlide(const ::basegfx::B2DVector& rSlideSize)
 {
+#if BOX2D_CHECK_VERSION(3, 0)
+    b2Vec2 gravity = { 0.0f, -30.0f };
+    b2WorldDef worldDef = b2DefaultWorldDef();
+    worldDef.gravity = gravity;
+
+    maBox2DWorldId = b2CreateWorld(&worldDef);
+    mbWorldInitialized = true;
+#else
     mpBox2DWorld = std::make_unique<b2World>(b2Vec2(0.0f, -30.0f));
+#endif
 
     float fWidth = static_cast<float>(rSlideSize.getX() * mfScaleFactor);
     float fHeight = static_cast<float>(rSlideSize.getY() * mfScaleFactor);
@@ -231,10 +281,26 @@ void box2DWorld::createStaticFrameAroundSlide(const ::basegfx::B2DVector& rSlide
     // static body for creating the frame around the slide
     b2BodyDef aBodyDef;
     aBodyDef.type = b2_staticBody;
+#if BOX2D_CHECK_VERSION(3, 0)
+    aBodyDef.position = { 0, 0 };
+#else
     aBodyDef.position.Set(0, 0);
+#endif
 
     // not going to be stored anywhere, will live
     // as long as the Box2DWorld does
+#if BOX2D_CHECK_VERSION(3, 0)
+    b2BodyId aBody = b2CreateBody(maBox2DWorldId, &aBodyDef);
+
+    // create an edge loop that represents slide frame
+    b2Vec2 aEdgePoints[4] = { { 0, 0 }, { 0, -fHeight }, { fWidth, -fHeight }, { fWidth, 0 } };
+
+    b2ChainDef aChainDef = b2DefaultChainDef();
+    aChainDef.points = aEdgePoints;
+    aChainDef.count = 4;
+    aChainDef.isLoop = true;
+    b2CreateChain(aBody, &aChainDef);
+#else
     b2Body* pStaticBody = mpBox2DWorld->CreateBody(&aBodyDef);
 
     // create an edge loop that represents slide frame
@@ -251,6 +317,7 @@ void box2DWorld::createStaticFrameAroundSlide(const ::basegfx::B2DVector& rSlide
     b2FixtureDef aFixtureDef;
     aFixtureDef.shape = &aEdgesChainShape;
     pStaticBody->CreateFixture(&aFixtureDef);
+#endif
 }
 
 void box2DWorld::setShapePosition(const css::uno::Reference<css::drawing::XShape>& xShape,
@@ -563,7 +630,11 @@ void box2DWorld::alertPhysicsAnimationStart(
     const ::basegfx::B2DVector& rSlideSize,
     const slideshow::internal::ShapeManagerSharedPtr& pShapeManager)
 {
+#if BOX2D_CHECK_VERSION(3, 0)
+    if (!mbWorldInitialized)
+#else
     if (!mpBox2DWorld)
+#endif
         createStaticFrameAroundSlide(rSlideSize);
 
     if (!mbShapesInitialized)
@@ -574,12 +645,18 @@ void box2DWorld::alertPhysicsAnimationStart(
 
 double box2DWorld::stepAmount(const double fPassedTime)
 {
+#if !BOX2D_CHECK_VERSION(3, 0)
     assert(mpBox2DWorld);
+#endif
 
     // attention fTimeStep should not vary.
     const float fTimeStep = 1.0f / 100.0f;
+#if BOX2D_CHECK_VERSION(3, 0)
+    const int nSubStepCount = 4;
+#else
     const int nVelocityIterations = 6;
     const int nPositionIterations = 2;
+#endif
 
     unsigned int nStepAmount = static_cast<unsigned int>(std::round(fPassedTime / fTimeStep));
     // find the actual time that will be stepped through so
@@ -593,7 +670,11 @@ double box2DWorld::stepAmount(const double fPassedTime)
     {
         for (unsigned int nStepCounter = 0; nStepCounter < nStepAmount; nStepCounter++)
         {
+#if BOX2D_CHECK_VERSION(3, 0)
+            b2World_Step(maBox2DWorldId, fTimeStep, nSubStepCount);
+#else
             mpBox2DWorld->Step(fTimeStep, nVelocityIterations, nPositionIterations);
+#endif
         }
     }
     else
@@ -608,7 +689,11 @@ double box2DWorld::stepAmount(const double fPassedTime)
 
 bool box2DWorld::isInitialized() const
 {
+#if BOX2D_CHECK_VERSION(3, 0)
+    if (mbWorldInitialized)
+#else
     if (mpBox2DWorld)
+#endif
         return true;
     else
         return false;
@@ -619,7 +704,9 @@ box2DWorld::makeShapeDynamic(const css::uno::Reference<css::drawing::XShape>& xS
                              const basegfx::B2DVector& rStartVelocity, const double fDensity,
                              const double fBounciness)
 {
+#if !BOX2D_CHECK_VERSION(3, 0)
     assert(mpBox2DWorld);
+#endif
     Box2DBodySharedPtr pBox2DBody = mpXShapeToBodyMap.find(xShape)->second;
     pBox2DBody->setDensityAndRestitution(fDensity, fBounciness);
     queueLinearVelocityUpdate(xShape, rStartVelocity, 1);
@@ -657,7 +744,22 @@ Box2DBodySharedPtr box2DWorld::createStaticBody(const slideshow::internal::Shape
               ->getTopmostAttributeLayer();
     if (pShapeAttributeLayer && pShapeAttributeLayer->isRotationAngleValid())
     {
-        // if the shape's rotation value was altered by another animation effect set it.
+    // if the shape's rotation value was altered by another animation effect set it.
+#if BOX2D_CHECK_VERSION(3, 0)
+        aBodyDef.rotation
+            = b2MakeRot(::basegfx::deg2rad(-pShapeAttributeLayer->getRotationAngle()));
+    }
+
+    auto pBody = std::shared_ptr<b2BodyId>(new b2BodyId(b2CreateBody(maBox2DWorldId, &aBodyDef)),
+                                           [](b2BodyId* pB2BodyId) {
+                                               if (pB2BodyId != nullptr)
+                                               {
+                                                   b2DestroyBody(*pB2BodyId);
+                                                   delete pB2BodyId;
+                                               }
+                                           });
+
+#else
         aBodyDef.angle = ::basegfx::deg2rad(-pShapeAttributeLayer->getRotationAngle());
     }
 
@@ -665,6 +767,7 @@ Box2DBodySharedPtr box2DWorld::createStaticBody(const slideshow::internal::Shape
     std::shared_ptr<b2Body> pBody(mpBox2DWorld->CreateBody(&aBodyDef), [](b2Body* pB2Body) {
         pB2Body->GetWorld()->DestroyBody(pB2Body);
     });
+#endif
 
     SdrObject* pSdrObject = SdrObject::getSdrObjectFromXShape(rShape->getXShape());
 
@@ -735,7 +838,11 @@ Box2DBodySharedPtr box2DWorld::createStaticBody(const slideshow::internal::Shape
 #pragma GCC diagnostic pop
 #endif
 
+#if BOX2D_CHECK_VERSION(3, 0)
+box2DBody::box2DBody(std::shared_ptr<b2BodyId> pBox2DBody, double fScaleFactor)
+#else
 box2DBody::box2DBody(std::shared_ptr<b2Body> pBox2DBody, double fScaleFactor)
+#endif
     : mpBox2DBody(std::move(pBox2DBody))
     , mfScaleFactor(fScaleFactor)
 {
@@ -743,7 +850,11 @@ box2DBody::box2DBody(std::shared_ptr<b2Body> pBox2DBody, double fScaleFactor)
 
 ::basegfx::B2DPoint box2DBody::getPosition() const
 {
+#if BOX2D_CHECK_VERSION(3, 0)
+    b2Vec2 aPosition = b2Body_GetPosition(*mpBox2DBody);
+#else
     b2Vec2 aPosition = mpBox2DBody->GetPosition();
+#endif
     double fX = static_cast<double>(aPosition.x) / mfScaleFactor;
     double fY = static_cast<double>(aPosition.y) / -mfScaleFactor;
     return ::basegfx::B2DPoint(fX, fY);
@@ -751,16 +862,26 @@ box2DBody::box2DBody(std::shared_ptr<b2Body> pBox2DBody, double fScaleFactor)
 
 void box2DBody::setPosition(const basegfx::B2DPoint& rPos)
 {
+#if BOX2D_CHECK_VERSION(3, 0)
+    b2Body_SetTransform(*mpBox2DBody, convertB2DPointToBox2DVec2(rPos, mfScaleFactor),
+                        b2Body_GetRotation(*mpBox2DBody));
+#else
     mpBox2DBody->SetTransform(convertB2DPointToBox2DVec2(rPos, mfScaleFactor),
                               mpBox2DBody->GetAngle());
+#endif
 }
 
 void box2DBody::setPositionByLinearVelocity(const basegfx::B2DPoint& rDesiredPos,
                                             const double fPassedTime)
 {
-    // kinematic bodies are not affected by other bodies, but unlike static ones can still have velocity
+// kinematic bodies are not affected by other bodies, but unlike static ones can still have velocity
+#if BOX2D_CHECK_VERSION(3, 0)
+    if (b2Body_GetType(*mpBox2DBody) != b2_kinematicBody)
+        b2Body_SetType(*mpBox2DBody, b2_kinematicBody);
+#else
     if (mpBox2DBody->GetType() != b2_kinematicBody)
         mpBox2DBody->SetType(b2_kinematicBody);
+#endif
 
     ::basegfx::B2DPoint aCurrentPos = getPosition();
     // calculate the velocity needed to reach the rDesiredPos in the given time frame
@@ -771,9 +892,14 @@ void box2DBody::setPositionByLinearVelocity(const basegfx::B2DPoint& rDesiredPos
 
 void box2DBody::setAngleByAngularVelocity(const double fDesiredAngle, const double fPassedTime)
 {
-    // kinematic bodies are not affected by other bodies, but unlike static ones can still have velocity
+// kinematic bodies are not affected by other bodies, but unlike static ones can still have velocity
+#if BOX2D_CHECK_VERSION(3, 0)
+    if (b2Body_GetType(*mpBox2DBody) != b2_kinematicBody)
+        b2Body_SetType(*mpBox2DBody, b2_kinematicBody);
+#else
     if (mpBox2DBody->GetType() != b2_kinematicBody)
         mpBox2DBody->SetType(b2_kinematicBody);
+#endif
 
     double fDeltaAngle = fDesiredAngle - getAngle();
 
@@ -790,17 +916,40 @@ void box2DBody::setLinearVelocity(const ::basegfx::B2DVector& rVelocity)
 {
     b2Vec2 aVelocity = { static_cast<float>(rVelocity.getX() * mfScaleFactor),
                          static_cast<float>(rVelocity.getY() * -mfScaleFactor) };
+#if BOX2D_CHECK_VERSION(3, 0)
+    b2Body_SetLinearVelocity(*mpBox2DBody, aVelocity);
+#else
     mpBox2DBody->SetLinearVelocity(aVelocity);
+#endif
 }
 
 void box2DBody::setAngularVelocity(const double fAngularVelocity)
 {
     float fBox2DAngularVelocity = static_cast<float>(basegfx::deg2rad(-fAngularVelocity));
+#if BOX2D_CHECK_VERSION(3, 0)
+    b2Body_SetAngularVelocity(*mpBox2DBody, fBox2DAngularVelocity);
+#else
     mpBox2DBody->SetAngularVelocity(fBox2DAngularVelocity);
+#endif
 }
 
 void box2DBody::setCollision(const bool bCanCollide)
 {
+#if BOX2D_CHECK_VERSION(3, 0)
+    int nShapeCount = b2Body_GetShapeCount(*mpBox2DBody);
+    std::vector<b2ShapeId> aShapeIds(nShapeCount);
+    b2Body_GetShapes(*mpBox2DBody, aShapeIds.data(), nShapeCount);
+
+    for (int i = 0; i < nShapeCount; ++i)
+    {
+        b2ShapeId aShapeId = aShapeIds[i];
+        b2Filter aFilter = b2Shape_GetFilter(aShapeId);
+        // 0xFFFF means collides with everything
+        // 0x0000 means collides with nothing
+        aFilter.maskBits = bCanCollide ? 0xFFFF : 0x0000;
+        b2Shape_SetFilter(aShapeId, aFilter);
+    }
+#else
     // collision have to be set for each fixture of the body individually
     for (b2Fixture* pFixture = mpBox2DBody->GetFixtureList(); pFixture;
          pFixture = pFixture->GetNext())
@@ -811,21 +960,45 @@ void box2DBody::setCollision(const bool bCanCollide)
         aFilter.maskBits = bCanCollide ? 0xFFFF : 0x0000;
         pFixture->SetFilterData(aFilter);
     }
+#endif
 }
 
 double box2DBody::getAngle() const
 {
+#if BOX2D_CHECK_VERSION(3, 0)
+    double fAngle = static_cast<double>(b2Rot_GetAngle(b2Body_GetRotation(*mpBox2DBody)));
+#else
     double fAngle = static_cast<double>(mpBox2DBody->GetAngle());
+#endif
     return ::basegfx::rad2deg(-fAngle);
 }
 
 void box2DBody::setAngle(const double fAngle)
 {
-    mpBox2DBody->SetTransform(mpBox2DBody->GetPosition(), ::basegfx::deg2rad(-fAngle));
+#if BOX2D_CHECK_VERSION(3, 0)
+    b2Body_SetTransform(*mpBox2DBody, b2Body_GetPosition(*mpBox2DBody),
+                        b2MakeRot(::basegfx::deg2rad(-fAngle)));
+#else
+    mpBox2DBody->SetTransform(*mpBox2DBody->GetPosition(), ::basegfx::deg2rad(-fAngle));
+#endif
 }
 
 void box2DBody::setDensityAndRestitution(const double fDensity, const double fRestitution)
 {
+#if BOX2D_CHECK_VERSION(3, 0)
+    int nShapeCount = b2Body_GetShapeCount(*mpBox2DBody);
+    std::vector<b2ShapeId> aShapeIds(nShapeCount);
+    b2Body_GetShapes(*mpBox2DBody, aShapeIds.data(), nShapeCount);
+
+    for (int i = 0; i < nShapeCount; ++i)
+    {
+        b2ShapeId aShapeId = aShapeIds[i];
+        b2Shape_SetDensity(aShapeId, static_cast<float>(fDensity));
+        b2Shape_SetRestitution(aShapeId, static_cast<float>(fRestitution));
+    }
+    // without resetting the massdata of the body, density change won't take effect
+    b2Body_ApplyMassFromShapes(*mpBox2DBody);
+#else
     // density and restitution have to be set for each fixture of the body individually
     for (b2Fixture* pFixture = mpBox2DBody->GetFixtureList(); pFixture;
          pFixture = pFixture->GetNext())
@@ -835,23 +1008,47 @@ void box2DBody::setDensityAndRestitution(const double fDensity, const double fRe
     }
     // without resetting the massdata of the body, density change won't take effect
     mpBox2DBody->ResetMassData();
+#endif
 }
 
 void box2DBody::setRestitution(const double fRestitution)
 {
+#if BOX2D_CHECK_VERSION(3, 0)
+    int nShapeCount = b2Body_GetShapeCount(*mpBox2DBody);
+    std::vector<b2ShapeId> aShapeIds(nShapeCount);
+    b2Body_GetShapes(*mpBox2DBody, aShapeIds.data(), nShapeCount);
+
+    for (int i = 0; i < nShapeCount; ++i)
+    {
+        b2ShapeId aShapeId = aShapeIds[i];
+        b2Shape_SetRestitution(aShapeId, static_cast<float>(fRestitution));
+    }
+#else
     for (b2Fixture* pFixture = mpBox2DBody->GetFixtureList(); pFixture;
          pFixture = pFixture->GetNext())
     {
         pFixture->SetRestitution(static_cast<float>(fRestitution));
     }
+#endif
 }
 
 void box2DBody::setType(box2DBodyType eType)
 {
+#if BOX2D_CHECK_VERSION(3, 0)
+    b2Body_SetType(*mpBox2DBody, getBox2DInternalBodyType(eType));
+#else
     mpBox2DBody->SetType(getBox2DInternalBodyType(eType));
+#endif
 }
 
-box2DBodyType box2DBody::getType() const { return getBox2DLOBodyType(mpBox2DBody->GetType()); }
+box2DBodyType box2DBody::getType() const
+{
+#if BOX2D_CHECK_VERSION(3, 0)
+    return getBox2DLOBodyType(b2Body_GetType(*mpBox2DBody));
+#else
+    return getBox2DLOBodyType(mpBox2DBody->GetType());
+#endif
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/slideshow/source/inc/box2dtools.hxx b/slideshow/source/inc/box2dtools.hxx
index f1b2b2ec47a0..c65b20f07810 100644
--- a/slideshow/source/inc/box2dtools.hxx
+++ b/slideshow/source/inc/box2dtools.hxx
@@ -9,14 +9,22 @@
 
 #pragma once
 
+#include <config_box2d.h>
+#define BOX2D_CHECK_VERSION(major, minor)                                                          \
+    (BOX2D_MAJOR > (major) || (BOX2D_MAJOR == (major) && BOX2D_MINOR >= (minor)))
+
+#include BOX2D_HEADER
+
 #include "shape.hxx"
 #include "shapeattributelayer.hxx"
 #include "attributemap.hxx"
 #include <unordered_map>
 #include <queue>
 
+#if !BOX2D_CHECK_VERSION(3, 0)
 class b2Body;
 class b2World;
+#endif
 
 namespace slideshow::internal
 {
@@ -76,8 +84,14 @@ struct Box2DDynamicUpdateInformation
 class box2DWorld
 {
 private:
+#if BOX2D_CHECK_VERSION(3, 0)
+    b2WorldId maBox2DWorldId;
+    bool mbWorldInitialized;
+#else
     /// Pointer to the real Box2D World that this class manages
     std::unique_ptr<b2World> mpBox2DWorld;
+#endif
+
     /// Scale factor for conversions between LO user space coordinates to Box2D World coordinates
     double mfScaleFactor;
     bool mbShapesInitialized;
@@ -332,12 +346,21 @@ class box2DBody
 {
 private:
     /// Pointer to the body that this class manages
+#if BOX2D_CHECK_VERSION(3, 0)
+    std::shared_ptr<b2BodyId> mpBox2DBody;
+#else
     std::shared_ptr<b2Body> mpBox2DBody;
+#endif
+
     /// Scale factor for conversions between LO user space coordinates to Box2D World coordinates
     double mfScaleFactor;
 
 public:
+#if BOX2D_CHECK_VERSION(3, 0)
+    box2DBody(std::shared_ptr<b2BodyId> pBox2DBody, double fScaleFactor);
+#else
     box2DBody(std::shared_ptr<b2Body> pBox2DBody, double fScaleFactor);
+#endif
 
     /// @return current position in LO user space coordinates
     ::basegfx::B2DPoint getPosition() const;
box2d-3.1.0.diff (text/x-patch, 6.5 KB)
commit aaf7a2286a2e01e9d6457549725e56b3cf4830eb
Author: Xisco Fauli <[email protected]>
Date:   Wed May 6 09:23:05 2026 +0200

    box2d: upgrade to 3.1.0
    
    Downloaded https://github.com/erincatto/box2d/archive/refs/tags/v3.1.0.tar.gz
    
    Change-Id: I21bf8d3e26cf2601607f586a3bc1010a32b78a06
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/204848
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <[email protected]>

diff --git a/configure.ac b/configure.ac
index c087d44865d2..c771de57418e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12194,7 +12194,7 @@ dnl Check for system box2d
 dnl ===================================================================
 AC_MSG_CHECKING([which box2d to use])
 BOX2D_MAJOR=3
-BOX2D_MINOR=0
+BOX2D_MINOR=1
 if test "$with_system_box2d" = "yes"; then
     AC_MSG_RESULT([external])
     SYSTEM_BOX2D=TRUE
diff --git a/download.lst b/download.lst
index 027402cfa182..b66b9ad8b537 100644
--- a/download.lst
+++ b/download.lst
@@ -19,8 +19,8 @@ BOOST_TARBALL := boost_1_90_0.tar.xz
 # three static lines
 # so that git cherry-pick
 # will not run into conflicts
-BOX2D_SHA256SUM := 64ad759006cd2377c99367f51fb36942b57f0e9ad690ed41548dd620e6f6c8b1
-BOX2D_TARBALL := box2d-3.0.0.tar.gz
+BOX2D_SHA256SUM := 7fac19801485efb31ee3745b2284d9d4601f9e8138a3383a7b0df6d788ea5785
+BOX2D_TARBALL := box2d-3.1.0.tar.gz
 # three static lines
 # so that git cherry-pick
 # will not run into conflicts
diff --git a/external/box2d/StaticLibrary_box2d.mk b/external/box2d/StaticLibrary_box2d.mk
index e83bed2f375c..50875b838476 100644
--- a/external/box2d/StaticLibrary_box2d.mk
+++ b/external/box2d/StaticLibrary_box2d.mk
@@ -29,9 +29,8 @@ endif
 
 $(eval $(call gb_StaticLibrary_add_generated_cobjects,box2d,\
 	UnpackedTarball/box2d/src/aabb \
-	UnpackedTarball/box2d/src/allocate \
+	UnpackedTarball/box2d/src/arena_allocator \
 	UnpackedTarball/box2d/src/body \
-	UnpackedTarball/box2d/src/block_array \
 	UnpackedTarball/box2d/src/dynamic_tree \
 	UnpackedTarball/box2d/src/island \
 	UnpackedTarball/box2d/src/motor_joint \
@@ -59,7 +58,7 @@ $(eval $(call gb_StaticLibrary_add_generated_cobjects,box2d,\
 	UnpackedTarball/box2d/src/id_pool \
 	UnpackedTarball/box2d/src/math_functions \
 	UnpackedTarball/box2d/src/revolute_joint \
-	UnpackedTarball/box2d/src/stack_allocator \
+	UnpackedTarball/box2d/src/sensor \
 	UnpackedTarball/box2d/src/solver \
 	UnpackedTarball/box2d/src/solver_set \
 	UnpackedTarball/box2d/src/weld_joint \
diff --git a/external/box2d/UnpackedTarball_box2d.mk b/external/box2d/UnpackedTarball_box2d.mk
index de54a396152a..340a17511711 100644
--- a/external/box2d/UnpackedTarball_box2d.mk
+++ b/external/box2d/UnpackedTarball_box2d.mk
@@ -11,8 +11,4 @@ $(eval $(call gb_UnpackedTarball_UnpackedTarball,box2d))
 
 $(eval $(call gb_UnpackedTarball_set_tarball,box2d,$(BOX2D_TARBALL)))
 
-$(eval $(call gb_UnpackedTarball_add_patches,box2d, \
-	external/box2d/android.patch \
-))
-
 # vim: set noet sw=4 ts=4:
diff --git a/external/box2d/android.patch b/external/box2d/android.patch
deleted file mode 100644
index b8eafcb2e01c..000000000000
--- a/external/box2d/android.patch
+++ /dev/null
@@ -1,41 +0,0 @@
---- box2d/src/core.h	2026-05-05 16:51:31.330228008 +0200
-+++ box2d/src/core.h	2026-05-05 16:53:35.525696798 +0200
-@@ -40,14 +40,12 @@
- #endif
- 
- // Define CPU
--#if defined( __x86_64__ ) || defined( _M_X64 )
--	#define B2_CPU_X64
--#elif defined( __aarch64__ ) || defined( _M_ARM64 )
-+#if defined( __aarch64__ ) || defined( _M_ARM64 )
- 	#define B2_CPU_ARM
- #elif defined( __EMSCRIPTEN__ )
- 	#define B2_CPU_WASM
- #else
--	#error Unsupported CPU
-+	#define B2_CPU_X64
- #endif
- 
- // Define compiler
---- box2d/src/allocate.c	2026-05-05 17:08:39.096202016 +0200
-+++ box2d/src/allocate.c	2026-05-05 17:09:17.879976210 +0200
-@@ -66,9 +66,16 @@
- 	}
- 
- #ifdef B2_PLATFORM_WINDOWS
--	void* ptr = _aligned_malloc( size32, B2_ALIGNMENT );
-+    void* ptr = _aligned_malloc( size32, B2_ALIGNMENT );
-+#elif defined( B2_PLATFORM_ANDROID )
-+    void* ptr = NULL;
-+    if ( posix_memalign( &ptr, B2_ALIGNMENT, size32 ) != 0 )
-+    {
-+        // allocation failed, exit the application
-+        exit( EXIT_FAILURE );
-+    }
- #else
--	void* ptr = aligned_alloc( B2_ALIGNMENT, size32 );
-+    void* ptr = aligned_alloc( B2_ALIGNMENT, size32 );
- #endif
- 
- 	b2TracyCAlloc( ptr, size );
-
diff --git a/slideshow/source/engine/box2dtools.cxx b/slideshow/source/engine/box2dtools.cxx
index 7a2d1546fb3d..25a131c04926 100644
--- a/slideshow/source/engine/box2dtools.cxx
+++ b/slideshow/source/engine/box2dtools.cxx
@@ -105,8 +105,13 @@ void addTriangleVectorToBody(const basegfx::triangulator::B2DTriangleVector& rTr
             b2Hull aHull = b2ComputeHull(aTriangleVertices, 3);
             b2ShapeDef aShapeDef = b2DefaultShapeDef();
             aShapeDef.density = fDefaultStaticDensity;
+#if BOX2D_CHECK_VERSION(3, 1)
+            aShapeDef.material.friction = fDefaultStaticFriction;
+            aShapeDef.material.restitution = fDefaultStaticBodyBounciness;
+#else
             aShapeDef.friction = fDefaultStaticFriction;
             aShapeDef.restitution = fDefaultStaticBodyBounciness;
+#endif
             b2Polygon aPolygonShape = b2MakePolygon(&aHull, 0.0);
             b2CreatePolygonShape(*aBody, &aShapeDef, &aPolygonShape);
 #else
@@ -208,8 +213,13 @@ void addEdgeShapeToBody(const basegfx::B2DPolygon& rPolygon, b2Body* aBody,
             b2Hull aHull = b2ComputeHull(aQuadrilateralVertices, 4);
             b2ShapeDef aShapeDef = b2DefaultShapeDef();
             aShapeDef.density = fDefaultStaticDensity;
+#if BOX2D_CHECK_VERSION(3, 1)
+            aShapeDef.material.friction = fDefaultStaticFriction;
+            aShapeDef.material.restitution = fDefaultStaticBodyBounciness;
+#else
             aShapeDef.friction = fDefaultStaticFriction;
             aShapeDef.restitution = fDefaultStaticBodyBounciness;
+#endif
             b2Polygon aPolygonShape = b2MakePolygon(&aHull, 0.0);
             b2CreatePolygonShape(*aBody, &aShapeDef, &aPolygonShape);
 #else
@@ -993,7 +1003,11 @@ void box2DBody::setDensityAndRestitution(const double fDensity, const double fRe
     for (int i = 0; i < nShapeCount; ++i)
     {
         b2ShapeId aShapeId = aShapeIds[i];
+#if BOX2D_CHECK_VERSION(3, 1)
+        b2Shape_SetDensity(aShapeId, static_cast<float>(fDensity), false);
+#else
         b2Shape_SetDensity(aShapeId, static_cast<float>(fDensity));
+#endif
         b2Shape_SetRestitution(aShapeId, static_cast<float>(fRestitution));
     }
     // without resetting the massdata of the body, density change won't take effect
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.