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);
}
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 {
}

`
robot.zip