fabmax / physx-jni

Java JNI bindings for Nvidia PhysX
MIT License
89 stars 9 forks source link

PxMeshOverlapUtil #33

Closed LNDF closed 2 years ago

LNDF commented 2 years ago

I am using the PxController to create a character controller. When the player is moved (PxController::move method is called), the following error occurs. /usr/lib/jvm/java-15-openjdk/bin/java: symbol lookup error: /tmp/de.fabmax.physx-jni/0.4.15/libPhysXJniBindings_64.so: undefined symbol: _ZN5physx17PxMeshOverlapUtilC1Ev

I started researching and I found that the class PxMeshOverlapUtil is also missing. Is this a missing feature? Is there a workarrownd?

Thanks

EDIT: I realicen that doesnt happen con windows. Maybe there is a linking error con linux when building the linux native libs.

fabmax commented 2 years ago

PxMeshOverlapUtil is not mapped to Java but that should not mean that it is not included in the native library if any internal native code uses it.

Do you have some short example code I can use to reproduce this?

LNDF commented 2 years ago

Hello. The following code will crash on linux but will work just fine on windows. Cannot test on mac os.

package test.test;

import org.joml.Vector3f;
import org.lwjgl.system.MemoryStack;

import physx.PxTopLevelFunctions;
import physx.character.PxCapsuleControllerDesc;
import physx.character.PxController;
import physx.character.PxControllerFilters;
import physx.character.PxControllerManager;
import physx.common.PxBoundedData;
import physx.common.PxDefaultErrorCallback;
import physx.common.PxFoundation;
import physx.common.PxIDENTITYEnum;
import physx.common.PxQuat;
import physx.common.PxTolerancesScale;
import physx.common.PxTransform;
import physx.common.PxVec3;
import physx.cooking.PxCooking;
import physx.cooking.PxCookingParams;
import physx.cooking.PxTriangleMeshDesc;
import physx.extensions.PxDefaultAllocator;
import physx.geomutils.PxMeshScale;
import physx.geomutils.PxTriangleMesh;
import physx.geomutils.PxTriangleMeshGeometry;
import physx.physics.PxFilterData;
import physx.physics.PxMaterial;
import physx.physics.PxPairFlagEnum;
import physx.physics.PxPhysics;
import physx.physics.PxRigidDynamic;
import physx.physics.PxScene;
import physx.physics.PxSceneDesc;
import physx.physics.PxShape;
import physx.support.Vector_PxU32;
import physx.support.Vector_PxVec3;

public class Test {

public static final int PX_PHYSX_VERSION = PxTopLevelFunctions.getPHYSICS_VERSION();

    private static PxControllerFilters filters;

    private static PxDefaultAllocator defaultAllocator;
    private static PxDefaultErrorCallback defaultErrorCallback;
    private static PxFoundation foundation;
    private static PxPhysics physics;
    private static PxFilterData filterData;
    private static PxCookingParams cookingParams;
    private static PxCooking cooking;
    private static PxTolerancesScale toleranceScale;

    private static final int[] planeIndices = {
            2, 1, 0,
            2, 3, 1
    };

    private static final float[] planePositions = {
             0.5f,  0.5f, 0.0f,
             0.5f, -0.5f, 0.0f,
            -0.5f,  0.5f, 0.0f,
            -0.5f, -0.5f, 0.0f
    };

    //start physx
    public static void start() {
        defaultAllocator = new PxDefaultAllocator();
        defaultErrorCallback = new PxDefaultErrorCallback();
        foundation = PxTopLevelFunctions.CreateFoundation(PX_PHYSX_VERSION, defaultAllocator, defaultErrorCallback);
        toleranceScale = new PxTolerancesScale();
        physics = PxTopLevelFunctions.CreatePhysics(PX_PHYSX_VERSION, foundation, toleranceScale);
        filterData = new PxFilterData(0, 0, 0, 0);
        filterData.setWord0(1);
        filterData.setWord1(0xffffffff);
        filterData.setWord2(
                PxPairFlagEnum.eNOTIFY_TOUCH_FOUND      |
                PxPairFlagEnum.eNOTIFY_TOUCH_LOST       |
                PxPairFlagEnum.eNOTIFY_TOUCH_PERSISTS   |
                PxPairFlagEnum.eNOTIFY_CONTACT_POINTS);
        filterData.setWord3(0);
        cookingParams = new PxCookingParams(toleranceScale);
        cooking = PxTopLevelFunctions.CreateCooking(PX_PHYSX_VERSION, foundation, cookingParams);
        filters = new PxControllerFilters();
    }

    //stop physx
    public static void stop() {
        filters.destroy();
        cooking.release();
        cookingParams.destroy();
        filterData.destroy();
        physics.release();
        toleranceScale.destroy();
        foundation.release();
        defaultAllocator.destroy();
        defaultErrorCallback.destroy();
    }

    public static PxScene createScene(Vector3f gravity) {
        try (MemoryStack mem = MemoryStack.stackPush()) {
            PxSceneDesc desc = PxSceneDesc.createAt(mem, MemoryStack::nmalloc, physics.getTolerancesScale());
            desc.setGravity(PxVec3.createAt(mem, MemoryStack::nmalloc, gravity.x, gravity.y, gravity.z));
            desc.setCpuDispatcher(PxTopLevelFunctions.DefaultCpuDispatcherCreate(4));
            desc.setFilterShader(PxTopLevelFunctions.DefaultFilterShader());
            return physics.createScene(desc);
        }
    }

    public static PxShape createPhysXMesh(int[] indices, float[] positions, PxMaterial material) {
        try (MemoryStack mem = MemoryStack.stackPush()) {
            Vector_PxVec3 vPoints = new Vector_PxVec3();
            Vector_PxU32 vIndices = new Vector_PxU32();
            PxVec3 tmpVec = PxVec3.createAt(mem, MemoryStack::nmalloc);
            for (int i = 0; i < positions.length; i += 3) {
                tmpVec.setX(positions[i]);
                tmpVec.setY(positions[i + 1]);
                tmpVec.setZ(positions[i + 2]);
                vPoints.push_back(tmpVec);
            }
            for (int i = 0; i < indices.length; i++) {
                vIndices.push_back(indices[i]);
            }
            PxBoundedData boundedPoints = PxBoundedData.createAt(mem, MemoryStack::nmalloc);
            boundedPoints.setCount(vPoints.size());
            boundedPoints.setStride(PxVec3.SIZEOF);
            boundedPoints.setData(vPoints.data());
            PxBoundedData boundedIndices = PxBoundedData.createAt(mem, MemoryStack::nmalloc);
            boundedIndices.setCount(vIndices.size() / 3);
            boundedIndices.setStride(4 * 3);
            boundedIndices.setData(vIndices.data());
            PxTriangleMeshDesc meshDesc = PxTriangleMeshDesc.createAt(mem, MemoryStack::nmalloc);
            meshDesc.setPoints(boundedPoints);
            meshDesc.setTriangles(boundedIndices);
            PxTriangleMesh triangleMesh = cooking.createTriangleMesh(meshDesc, physics.getPhysicsInsertionCallback());
            vPoints.destroy();
            vIndices.destroy();
            PxMeshScale pxScale = PxMeshScale.createAt(mem, MemoryStack::nmalloc, PxVec3.createAt(mem, MemoryStack::nmalloc, 1, 1, 1), PxQuat.createAt(mem, MemoryStack::nmalloc, PxIDENTITYEnum.PxIdentity));
            PxTriangleMeshGeometry meshGeom = PxTriangleMeshGeometry.createAt(mem, MemoryStack::nmalloc, triangleMesh, pxScale);
            PxShape mesh = physics.createShape(meshGeom, material);
            mesh.setSimulationFilterData(filterData);
            return mesh;
        }
    }

    public static void main(String[] args) {
        start();
        PxScene scene = createScene(new Vector3f(0, -9.81f, 0));
        PxMaterial material = physics.createMaterial(0.5f, 0.5f, 0.5f);
        PxShape mesh = createPhysXMesh(planeIndices, planePositions, material);
        PxControllerManager controllerManager = PxTopLevelFunctions.CreateControllerManager(scene);
        PxController controller;
        PxRigidDynamic rigid;
        try (MemoryStack mem = MemoryStack.stackPush()) {
            rigid = physics.createRigidDynamic(PxTransform.createAt(mem, MemoryStack::nmalloc, PxIDENTITYEnum.PxIdentity));
            rigid.attachShape(mesh);
            scene.addActor(rigid);
            PxCapsuleControllerDesc desc = PxCapsuleControllerDesc.createAt(mem, MemoryStack::nmalloc);
            desc.setMaterial(material);
            desc.setHeight(1);
            desc.setRadius(0.5f);
            controller = controllerManager.createController(desc);
            controller.move(PxVec3.createAt(mem, MemoryStack::nmalloc, 1, 1, 1), 0, 1f / 60f, filters);
        }
        scene.simulate(1f / 60f);
        scene.fetchResults(true);
        controllerManager.release();
        rigid.detachShape(mesh);
        mesh.release();
        rigid.release();
        material.release();
        scene.release();
        stop();
    }

}
fabmax commented 2 years ago

Should be fixed now (with version 0.4.16). It's a bit weird though: I had to include bindings to PxMeshOverlapUtil and then it worked, however the linker shouldn't remove functions used by internal code, so it should not matter if PxMeshOverlapUtil is publicly available or not...

Anyway I tested the new version on Linux and it seems to work there.