Last active
December 3, 2023 20:47
-
-
Save capdevon/5ddb980c8ff68eee79e4172303d6acf1 to your computer and use it in GitHub Desktop.
Testing Minie 7.7.1-SNAPSHOT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mygame.physics; | |
import java.util.Arrays; | |
import com.jme3.bullet.PhysicsSpace; | |
import com.jme3.bullet.collision.ContactListener; | |
import com.jme3.bullet.collision.PhysicsCollisionObject; | |
/** | |
* | |
* @author capdevon | |
*/ | |
public class MyContactListener implements ContactListener { | |
// PhysicsSpace whose notifications are being managed. | |
private final PhysicsSpace space; | |
public MyContactListener(PhysicsSpace space) { | |
this.space = space; | |
} | |
@Override | |
public void onContactEnded(long manifoldId) { | |
System.out.printf("%s onContactEnded: %d%n", toHexString(this), manifoldId); | |
System.out.println(Arrays.toString(space.listManifoldIds())); | |
} | |
@Override | |
public void onContactProcessed(PhysicsCollisionObject pcoA, PhysicsCollisionObject pcoB, long manifoldPointId) { | |
System.out.printf("%s onContactProcessed: %d%n", toHexString(this), manifoldPointId); | |
} | |
@Override | |
public void onContactStarted(long manifoldId) { | |
System.out.printf("%s onContactStarted: %d%n", toHexString(this), manifoldId); | |
System.out.println(Arrays.toString(space.listManifoldIds())); | |
} | |
private String toHexString(Object obj) { | |
if (obj != null) { | |
return obj.getClass().getSimpleName() + '@' + Integer.toHexString(obj.hashCode()); | |
} | |
return null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mygame.physics; | |
import java.util.ArrayDeque; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.Deque; | |
import java.util.List; | |
import com.jme3.bullet.ContactManager; | |
import com.jme3.bullet.PhysicsSpace; | |
import com.jme3.bullet.collision.ContactListener; | |
import com.jme3.bullet.collision.PersistentManifolds; | |
import com.jme3.bullet.collision.PhysicsCollisionEvent; | |
import com.jme3.bullet.collision.PhysicsCollisionListener; | |
import com.jme3.bullet.collision.PhysicsCollisionObject; | |
/** | |
* | |
* @author capdevon | |
*/ | |
public class MyContactManager implements ContactManager { | |
public boolean doEnded = true; | |
public boolean doProcessed = true; | |
public boolean doStarted = true; | |
private final Deque<PhysicsCollisionEvent> ongoingEvents = new ArrayDeque<>(99); | |
private final Deque<PhysicsCollisionEvent> startedEvents = new ArrayDeque<>(99); | |
private final Collection<PhysicsCollisionListener> ongoingListeners = new ArrayList<>(4); | |
private final Collection<PhysicsCollisionListener> startedListeners = new ArrayList<>(4); | |
private final List<ContactListener> immediateListeners = new ArrayList<>(4); | |
// PhysicsSpace whose notifications are being managed. | |
private final PhysicsSpace space; | |
public MyContactManager(PhysicsSpace space) { | |
this.space = space; | |
} | |
@Override | |
public void onContactEnded(long manifoldId) { | |
for (ContactListener listener : immediateListeners) { | |
listener.onContactEnded(manifoldId); | |
} | |
} | |
@Override | |
public void onContactProcessed(PhysicsCollisionObject pcoA, PhysicsCollisionObject pcoB, long pointId) { | |
for (ContactListener listener : immediateListeners) { | |
listener.onContactProcessed(pcoA, pcoB, pointId); | |
} | |
if (!ongoingListeners.isEmpty()) { | |
PhysicsCollisionEvent event = new PhysicsCollisionEvent(pcoA, pcoB, pointId); | |
// Queue the event to be handled later by distributeEvents(). | |
ongoingEvents.add(event); | |
} | |
} | |
@Override | |
public void onContactStarted(long manifoldId) { | |
for (ContactListener listener : immediateListeners) { | |
listener.onContactStarted(manifoldId); | |
} | |
if (!startedListeners.isEmpty()) { | |
int numPoints = PersistentManifolds.countPoints(manifoldId); | |
if (numPoints > 0) { | |
long bodyAId = PersistentManifolds.getBodyAId(manifoldId); | |
PhysicsCollisionObject pcoA = PhysicsCollisionObject.findInstance(bodyAId); | |
long bodyBId = PersistentManifolds.getBodyBId(manifoldId); | |
PhysicsCollisionObject pcoB = PhysicsCollisionObject.findInstance(bodyBId); | |
for (int i = 0; i < numPoints; ++i) { | |
long pointId = PersistentManifolds.getPointId(manifoldId, i); | |
PhysicsCollisionEvent event = new PhysicsCollisionEvent(pcoA, pcoB, pointId); | |
// Queue the event to be handled later by distributeEvents(). | |
startedEvents.add(event); | |
} | |
} | |
} | |
} | |
/** | |
* Distribute queued collision events to registered listeners. | |
*/ | |
@Override | |
public void distributeEvents() { | |
while (!startedEvents.isEmpty()) { | |
PhysicsCollisionEvent event = startedEvents.pop(); | |
for (PhysicsCollisionListener listener : startedListeners) { | |
listener.collision(event); | |
} | |
} | |
while (!ongoingEvents.isEmpty()) { | |
PhysicsCollisionEvent event = ongoingEvents.pop(); | |
for (PhysicsCollisionListener listener : ongoingListeners) { | |
listener.collision(event); | |
} | |
} | |
} | |
@Override | |
public void update(float timeInterval, int maxSteps) { | |
space.update(timeInterval, maxSteps, doEnded, doProcessed, doStarted); | |
} | |
@Override | |
public void addCollisionListener(PhysicsCollisionListener listener) { | |
startedListeners.add(listener); | |
} | |
@Override | |
public void addOngoingCollisionListener(PhysicsCollisionListener listener) { | |
ongoingListeners.add(listener); | |
} | |
@Override | |
public void addContactListener(ContactListener listener, boolean doEnded, boolean doProcessed, boolean doStarted) { | |
// ignore flags | |
immediateListeners.add(listener); | |
} | |
@Override | |
public void removeCollisionListener(PhysicsCollisionListener listener) { | |
startedListeners.remove(listener); | |
} | |
@Override | |
public void removeOngoingCollisionListener(PhysicsCollisionListener listener) { | |
ongoingListeners.remove(listener); | |
} | |
@Override | |
public void removeContactListener(ContactListener listener) { | |
immediateListeners.remove(listener); | |
} | |
@Override | |
public int countCollisionListeners() { | |
return ongoingListeners.size() + startedListeners.size(); | |
} | |
public void clearContactListeners() { | |
immediateListeners.clear(); | |
} | |
public void clearCollisionListeners() { | |
startedListeners.clear(); | |
} | |
public void clearOngoingCollisionListeners() { | |
ongoingListeners.clear(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mygame; | |
import com.jme3.app.SimpleApplication; | |
import com.jme3.bullet.BulletAppState; | |
import com.jme3.bullet.PhysicsSpace; | |
import com.jme3.bullet.collision.PhysicsCollisionObject; | |
import com.jme3.bullet.collision.shapes.CollisionShape; | |
import com.jme3.bullet.control.GhostControl; | |
import com.jme3.bullet.control.RigidBodyControl; | |
import com.jme3.bullet.objects.PhysicsBody; | |
import com.jme3.bullet.util.CollisionShapeFactory; | |
import com.jme3.font.BitmapText; | |
import com.jme3.input.KeyInput; | |
import com.jme3.input.controls.ActionListener; | |
import com.jme3.input.controls.KeyTrigger; | |
import com.jme3.input.controls.Trigger; | |
import com.jme3.material.Material; | |
import com.jme3.math.ColorRGBA; | |
import com.jme3.math.Vector3f; | |
import com.jme3.renderer.RenderManager; | |
import com.jme3.renderer.ViewPort; | |
import com.jme3.scene.Geometry; | |
import com.jme3.scene.Spatial; | |
import com.jme3.scene.control.AbstractControl; | |
import com.jme3.scene.shape.Box; | |
import com.jme3.scene.shape.Sphere; | |
import com.jme3.system.AppSettings; | |
import com.jme3.util.mikktspace.MikktspaceTangentGenerator; | |
import mygame.physics.MyContactListener; | |
import mygame.physics.MyContactManager; | |
/** | |
* | |
* @author capdevon | |
*/ | |
public class Test_Main2 extends SimpleApplication implements ActionListener { | |
/** | |
* | |
* @param args | |
*/ | |
public static void main(String[] args) { | |
Test_Main2 app = new Test_Main2(); | |
AppSettings settings = new AppSettings(true); | |
settings.setResolution(1280, 720); | |
app.setSettings(settings); | |
app.setShowSettings(false); | |
app.setPauseOnLostFocus(false); | |
app.start(); | |
} | |
private BulletAppState physics; | |
private RigidBodyControl ball; | |
private BitmapText hud; | |
@Override | |
public void simpleInitApp() { | |
// viewPort.setBackgroundColor(new ColorRGBA(0.5f, 0.6f, 0.7f, 1.0f)); | |
hud = makeTextUI(20, 10); | |
configCamera(); | |
initPhysics(); | |
createFloor(); | |
createSphere(); | |
createCube(); | |
setupKeys(); | |
} | |
private void configCamera() { | |
float aspect = (float) cam.getWidth() / cam.getHeight(); | |
cam.setFrustumPerspective(45, aspect, 0.01f, 1000f); | |
flyCam.setDragToRotate(true); | |
flyCam.setMoveSpeed(25f); | |
cam.setLocation(new Vector3f(32, 32, 32)); | |
cam.lookAt(new Vector3f(0, 2, 0), Vector3f.UNIT_Y); | |
} | |
private void initPhysics() { | |
physics = new BulletAppState(); | |
stateManager.attach(physics); | |
physics.setDebugEnabled(true); | |
PhysicsSpace pSpace = physics.getPhysicsSpace(); | |
// MyContactManager manager = new MyContactManager(pSpace); | |
// manager.doProcessed = false; | |
// pSpace.setContactManager(manager); | |
// pSpace.addContactListener(new MyContactListener(pSpace)); | |
pSpace.addContactListener(new MyContactListener(pSpace), false, false, true); | |
pSpace.addContactListener(new MyContactListener(pSpace), true, false, false); | |
} | |
private BitmapText makeTextUI(float xPos, float yPos) { | |
BitmapText bmp = new BitmapText(guiFont); | |
bmp.setColor(ColorRGBA.Red); | |
bmp.setSize(guiFont.getCharSet().getRenderedSize()); | |
bmp.setLocalTranslation(xPos, settings.getHeight() - yPos, 0); | |
guiNode.attachChild(bmp); | |
return bmp; | |
} | |
private void createFloor() { | |
float boxSize = 140f; | |
Box box = new Box(boxSize, 0.5f, boxSize); | |
Geometry geo = new Geometry("Floor", box); | |
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | |
mat.setColor("Color", ColorRGBA.Green); | |
geo.setMaterial(mat); | |
rootNode.attachChild(geo); | |
addStaticRigidBody(geo); | |
} | |
private void createCube() { | |
Box box = new Box(4, 4, 4); | |
Geometry geo = new Geometry("Box", box); | |
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | |
mat.setColor("Color", ColorRGBA.Red); | |
mat.getAdditionalRenderState().setWireframe(true); | |
geo.setMaterial(mat); | |
rootNode.attachChild(geo); | |
GhostControl ghost = addGhostControl(geo); | |
geo.addControl(new AbstractControl() { | |
@Override | |
protected void controlUpdate(float tpf) { | |
for (PhysicsCollisionObject pco : ghost.getOverlappingObjects()) { | |
System.out.println("ghostOverlapping: " + pco.getUserObject()); | |
} | |
} | |
@Override | |
protected void controlRender(RenderManager rm, ViewPort vp) { | |
} | |
}); | |
geo.setLocalTranslation(new Vector3f(0, 20, 0)); | |
//ghost.setPhysicsLocation(new Vector3f(0, 20, 0)); | |
} | |
private void createSphere() { | |
Sphere sphere = new Sphere(32, 32, 4); | |
sphere.setTextureMode(Sphere.TextureMode.Projected); | |
Geometry geo = new Geometry("Ball", sphere); | |
MikktspaceTangentGenerator.generate(geo); | |
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | |
mat.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg")); | |
geo.setMaterial(mat); | |
geo.setLocalTranslation(new Vector3f(0, 5, 0)); | |
rootNode.attachChild(geo); | |
ball = addDynamicRigidBody(geo, 1f); | |
} | |
private GhostControl addGhostControl(Spatial sp) { | |
CollisionShape shape = CollisionShapeFactory.createBoxShape(sp); | |
GhostControl ghost = new GhostControl(shape); | |
sp.addControl(ghost); | |
physics.getPhysicsSpace().add(ghost); | |
return ghost; | |
} | |
private RigidBodyControl addStaticRigidBody(Spatial sp) { | |
CollisionShape shape = CollisionShapeFactory.createMeshShape(sp); | |
RigidBodyControl rb = new RigidBodyControl(shape, PhysicsBody.massForStatic); | |
sp.addControl(rb); | |
physics.getPhysicsSpace().add(rb); | |
return rb; | |
} | |
private RigidBodyControl addDynamicRigidBody(Spatial sp, float mass) { | |
CollisionShape shape = CollisionShapeFactory.createDynamicMeshShape(sp); | |
RigidBodyControl rb = new RigidBodyControl(shape, mass); | |
sp.addControl(rb); | |
physics.getPhysicsSpace().add(rb); | |
return rb; | |
} | |
@Override | |
public void simpleUpdate(float tpf) { | |
int m = physics.getPhysicsSpace().countManifolds(); | |
hud.setText("countManifolds: " + m); | |
} | |
private void setupKeys() { | |
addMapping("JUMP", new KeyTrigger(KeyInput.KEY_SPACE)); | |
} | |
public void addMapping(String bindingName, Trigger... triggers) { | |
inputManager.addMapping(bindingName, triggers); | |
inputManager.addListener(this, bindingName); | |
} | |
@Override | |
public void onAction(String name, boolean isPressed, float tpf) { | |
if (name.equals("JUMP") && isPressed) { | |
ball.applyCentralImpulse(Vector3f.UNIT_Y.mult(10)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment