Skip to content

PhysicsCollisionEvent getIndex0 and getIndex1 with CompoundCollisionShape #45

Description

@hazidh

I built a robot collision scenario and created a GImpactShape for each geom of the robot, then combined these Gimpactshapes into a CompoundCollisionShape. But when I use getIndex0 and getIndex1 in PhysicsCollisionEvent, the comment is If shape is a CompoundCollisionShape, the index identifies a child shape, but the result will say more than the length of the array.
'
public class HelloGeomQuery extends SimpleApplication {

private BulletAppState bulletAppState;
private Spatial robotKinematic1;
private Spatial robotKinematic2;
boolean init;
boolean startGeomQuery;
private RigidBodyControl floor_phy;
private PhysicsCollisionListener collisionListener;
ArrayList<Boolean> overlapStateList;
ArrayList<Float> timeList;
private RigidBodyControl bodyControl1;
private RigidBodyControl bodyControl2;
private ChildCollisionShape[] childCollisionShapes1;
private ChildCollisionShape[] childCollisionShapes;


public static void main(String[] args) {

    //配置参数
    AppSettings setting = new AppSettings(true);
    setting.setResolution(1580, 960);  // 设置窗口大小
    setting.setAudioRenderer(null);

    HelloGeomQuery app = new HelloGeomQuery();
    app.setSettings(setting);
    app.setShowSettings(false);
    app.start();

}

@Override
public void simpleInitApp() {


    cam.setLocation(new Vector3f(-2.1795945f, 5.9709883f, 19.46696f));
    cam.setRotation(new Quaternion(0.0045973924f, 0.9947644f, -0.087805875f, 0.052084833f));

    flyCam.setDragToRotate(true);
    flyCam.setMoveSpeed(2);

    bulletAppState = new BulletAppState();
    bulletAppState.setDebugEnabled(true);
    stateManager.attach(bulletAppState);

    initInputs();
    initFloor();

    bulletAppState.getPhysicsSpace().addCollisionListener(new PhysicsCollisionListener() {
        @Override
        public void collision(PhysicsCollisionEvent event) {
            init = false;

            int index0 = event.getIndex0();
            int index1 = event.getIndex1();

            CollisionShape shape = childCollisionShapes[index0].getShape();
            CollisionShape shape1 = childCollisionShapes[index1].getShape();


        }
    });


    init = false;
    startGeomQuery = false;

    timeList = new ArrayList<>();
    overlapStateList = new ArrayList<>();


    /*
    光源参数与添加节点
     */
    //创建光源
    DirectionalLight sun = new DirectionalLight();
    sun.setDirection(new Vector3f(-1, -2, -3));
    //环境光
    AmbientLight ambient = new AmbientLight();
    //调整光照亮度
    ColorRGBA lightColor = new ColorRGBA();
    sun.setColor(lightColor.mult(0.6f));
    ambient.setColor(lightColor.mult(0.4f));
    rootNode.addLight(sun);
    rootNode.addLight(ambient);

}

public void initFloor() {

    Box floor = new Box(10f, 0.15f, 5f);
    Material floor_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    Geometry floor_geo = new Geometry("Floor", floor);
    floor_geo.setMaterial(floor_mat);
    floor_geo.setLocalTranslation(0, -0.1f, 0);

    floor_phy = new RigidBodyControl(0.0f);
    floor_geo.addControl(floor_phy);
    bulletAppState.getPhysicsSpace().add(floor_phy);

    this.rootNode.attachChild(floor_geo);
}

private void initInputs() {
    inputManager.addMapping("robot1",
            new KeyTrigger(KeyInput.KEY_1));
    inputManager.addMapping("robot2",
            new KeyTrigger(KeyInput.KEY_2));
    inputManager.addMapping("startGeomQueryKey",
            new KeyTrigger(KeyInput.KEY_3));
    inputManager.addMapping("saveFile",
            new KeyTrigger(KeyInput.KEY_4));
    inputManager.addListener(actionListener, "robot1");
    inputManager.addListener(actionListener, "robot2");
    inputManager.addListener(actionListener, "startGeomQueryKey");
    inputManager.addListener(actionListener, "saveFile");

}

final private ActionListener actionListener = new ActionListener() {

    @Override
    public void onAction(String name, boolean keyPressed, float tpf) {
        if (name.equals("robot1") && !keyPressed) {
            robotKinematic1 = createRobotList(new Vector3f(0f, 0.5f, 0f), new Vector3f(0, 0, 0),
                    true);
            bodyControl1 = robotKinematic1.getControl(RigidBodyControl.class);
            CompoundCollisionShape collisionShape = (CompoundCollisionShape) bodyControl1.getCollisionShape();
            childCollisionShapes = collisionShape.listChildren();

        } else if (name.equals("robot2") && !keyPressed) {
            robotKinematic2 = createRobotList(new Vector3f(5, 1.2f, 0.5f), new Vector3f(90, -90, -90),
                    true);
            bodyControl2 = robotKinematic2.getControl(RigidBodyControl.class);
            CompoundCollisionShape collisionShape1 = (CompoundCollisionShape) bodyControl2.getCollisionShape();
            childCollisionShapes1 = collisionShape1.listChildren();

            init = true;
        } else if (name.equals("startGeomQueryKey") && !keyPressed) {
            startGeomQuery = true;
        } else if (name.equals("saveFile") && !keyPressed) {
            startGeomQuery = false;
            saveFile("F:\\11-物理引擎\\Physx\\BulletTime.csv");
        }
    }
};

private Spatial createRobot(Vector3f translation, Vector3f rotation, boolean isKinematic) {

    Spatial robotSpatial = assetManager.loadModel("Models/Oto/robot.j3o");

    robotSpatial.setLocalTranslation(translation.x, translation.y, translation.z);
    robotSpatial.rotate((float) Math.toRadians(rotation.x), (float) Math.toRadians(rotation.y),
            (float) Math.toRadians(rotation.z));

    CollisionShape mergedMeshShape = CollisionShapeFactory.createGImpactShape(robotSpatial);

    //不依靠shape,自行判断
    RigidBodyControl robotControl = new RigidBodyControl(mergedMeshShape);
    if (isKinematic) {
        robotControl.setKinematic(true);
    }
    robotSpatial.addControl(robotControl);
    bulletAppState.getPhysicsSpace().add(robotControl);

    this.rootNode.attachChild(robotSpatial);
    return robotSpatial;

}

private Spatial createRobotList(Vector3f translation, Vector3f rotation, boolean isKinematic) {

    Spatial robotSpatial = assetManager.loadModel("Models/Oto/robot.j3o");


    ArrayList<Geometry> geomList = new ArrayList<>();
    traverseGeometry((Node) robotSpatial, geomList);

    CompoundCollisionShape shape = new CompoundCollisionShape(geomList.size());

    for (Geometry geom : geomList) {

        CollisionShape mergedMeshShape = CollisionShapeFactory.createGImpactShape(geom);

        geom.setLocalTranslation(geom.getWorldTranslation());
        geom.setLocalRotation(geom.getWorldRotation());
        geom.setLocalScale(geom.getWorldScale());

        shape.addChildShape(mergedMeshShape, geom.getWorldTransform());

    }
    robotSpatial.setLocalTranslation(translation.x, translation.y, translation.z);
    robotSpatial.rotate((float) Math.toRadians(rotation.x), (float) Math.toRadians(rotation.y),
            (float) Math.toRadians(rotation.z));

    RigidBodyControl robotControl = new RigidBodyControl(shape);
    if (isKinematic) {
        robotControl.setKinematic(true);
    }
    robotSpatial.addControl(robotControl);
    bulletAppState.getPhysicsSpace().add(robotControl);
    this.rootNode.attachChild(robotSpatial);
    return robotSpatial;

}


private ArrayList<Geometry> traverseGeometry(Node node, ArrayList<Geometry> geomList) {

    // 遍历当前节点下的所有子节点
    for (int i = 0; i < node.getQuantity(); i++) {
        com.jme3.scene.Spatial spatial = node.getChild(i);

        if (spatial instanceof Geometry) {
            Geometry geometry = (Geometry) spatial;

            // 复制几何体以保留变换
            Geometry geometryCopy = geometry.clone();

            // 应用父节点的全局变换到子节点上
            geometryCopy.setLocalTranslation(geometry.getWorldTranslation());
            geometryCopy.setLocalRotation(geometry.getWorldRotation());
            geometryCopy.setLocalScale(geometry.getWorldScale());

            geomList.add(geometryCopy);
        } else if (spatial instanceof Node) {
            // 如果是 Node 类型,则递归遍历其子节点
            traverseGeometry((Node) spatial, geomList); // 递归遍历时传递当前父节点
        }
    }
    return geomList;
}


private Spatial createRobotMesh(Vector3f translation, Vector3f rotation, boolean isKinematic) {

    Spatial robotSpatial = assetManager.loadModel("Models/Oto/robot.j3o");

    robotSpatial.setLocalTranslation(translation.x, translation.y, translation.z);
    robotSpatial.rotate((float) Math.toRadians(rotation.x), (float) Math.toRadians(rotation.y),
            (float) Math.toRadians(rotation.z));

    CollisionShape meshShape = CollisionShapeFactory.createMeshShape(robotSpatial);

    //不依靠shape,自行判断
    RigidBodyControl robotControl = new RigidBodyControl(meshShape, 0);
    if (isKinematic) {
        robotControl.setKinematic(true);
    }
    robotSpatial.addControl(robotControl);
    bulletAppState.getPhysicsSpace().add(robotControl);

    this.rootNode.attachChild(robotSpatial);


    return robotSpatial;
}


private Spatial createRobotSensor(Vector3f translation, Vector3f rotation) {


    Spatial robotSpatial = assetManager.loadModel("Models/Oto/robot.j3o");

    robotSpatial.setLocalTranslation(translation.x, translation.y, translation.z);
    robotSpatial.rotate((float) Math.toRadians(rotation.x), (float) Math.toRadians(rotation.y),
            (float) Math.toRadians(rotation.z));

    CollisionShape meshShape = CollisionShapeFactory.createMeshShape(robotSpatial);

    //不依靠shape,自行判断
    GhostControl robotControl = new GhostControl(meshShape);
    robotSpatial.addControl(robotControl);
    bulletAppState.getPhysicsSpace().add(robotControl);

    this.rootNode.attachChild(robotSpatial);

    return robotSpatial;
}


@Override
public void simpleUpdate(float tpf) {

    if (init) {
        RigidBodyControl bodyControl2 = robotKinematic2.getControl(RigidBodyControl.class);
        bodyControl2.setAngularVelocity(new Vector3f(1f, 0, 0));
        robotKinematic2.setLocalTranslation(robotKinematic2.getLocalTranslation().add(new Vector3f(-tpf, 0, 0)));
    }



}

private void saveFile(String filePath) {

    BufferedWriter writer = null;

    try {

        // 初始化
        writer = new BufferedWriter(new FileWriter(filePath, true));

        String overlapStateText = "重叠状态";
        String timeText = "时间(s)";

        // 写入标题
        writeContentToCell(writer, overlapStateText, ",");
        writeContentToCell(writer, timeText, ",");
        String dataTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH.mm.ss"));
        writeContentToCell(writer, dataTime, ",");

        //换行
        writer.newLine();

        for (int i = 0; i < Math.min(overlapStateList.size(), timeList.size()); i++) {

            writeContentToCell(writer, String.valueOf(overlapStateList.get(i)).replaceAll("\\s", ""),
                    ",");
            writeContentToCell(writer, String.valueOf(timeList.get(i)), ",");

            writer.newLine();
        }

        System.out.println("saveFileSucceed");

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (writer != null) {
                writer.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

private static void writeContentToCell(BufferedWriter writer, String content, String separator) throws IOException {
    // 写入内容进去csv
    writer.write(content);
    writer.write(separator);
}

}
`
image
robot.zip

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions