En el siguiente código, he puesto un ejemplo de algo que quiero hacer. Tengo la cámara y quiero que deje de moverse cada vez que golpea una de las cajas, ¿cómo hago esto?
public class Main extends ApplicationAdapter {
private final ModelBuilder builder = new ModelBuilder();
private final Environment environment = new Environment();
private ModelBatch modelBatch;
private PerspectiveCamera camera;
private Model model;
private ArrayList<ModelInstance> instance = new ArrayList<ModelInstance>();
private FirstPersonCameraController controller;
private BoundingBox[] boxBounds = new BoundingBox[1000];
private BoundingBox cameraBox = new BoundingBox();
private Vector3 cameraSpeed = new Vector3();
private Vector3 oldCameraPos = new Vector3();
private Vector3 newCameraPos = new Vector3();
@Override
public void create() {
modelBatch = new ModelBatch();
//build the camera
camera = new PerspectiveCamera(67, graphics.getWidth(), graphics.getHeight());
camera.position.set(0f, 10f, 0f);
camera.lookAt(0, 10, 0);
camera.near = 1f;
camera.far = 1000f;
camera.update();
//build all the boxes
for (int i = 0; i < 1000; i++) {
model = builder.createBox(
(float) Math.random() * 50,
(float) Math.random() * 50,
(float) Math.random() * 50,
new Material(ColorAttribute.createDiffuse(
(float) random(),
(float) random(),
(float) random(), 1)
), Position | Normal);
instance.add(new ModelInstance(model));
instance.get(i).transform.setToTranslation(
(float) random() * 1000 - 500,
(float) random() * 1000,
(float) random() * 1000 - 500);
boxBounds[i] = new BoundingBox();
boxBounds[i] = model.calculateBoundingBox(boxBounds[i]);
}
//build the ground
model = builder.createBox(700f, 1f, 700f, new Material(ColorAttribute.createDiffuse(Color.GREEN)), Position | Normal);
ModelInstance ground = new ModelInstance(model);
instance.add(ground);
//build the center
model = builder.createBox(5f, 5f, 5f, new Material(ColorAttribute.createDiffuse(Color.RED)), Position | Normal);
ModelInstance center = new ModelInstance(model);
instance.add(center);
//code the lights here
DirectionalLight light = new DirectionalLight().set(255, 255, 255,
(float) random(),
(float) random(),
(float) random());
//set up the enviroment
environment.set(new ColorAttribute(AmbientLight, 255f, 255f, 255f, 1f));
environment.add(light);
//set up the camera controller
controller = new FirstPersonCameraController(camera);
controller.setDegreesPerPixel(0.25f);
controller.setVelocity(20);
input.setInputProcessor(controller);
}
@Override
public void render() {
//set up OpenGL
gl.glViewport(0, 0, graphics.getWidth(), graphics.getHeight());
gl.glEnable(GL_BLEND);
gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gl.glClearColor(0, 0, 0, 0);
//render the modelInstances
modelBatch.begin(camera);
modelBatch.render(instance, environment);
modelBatch.end();
controller.update();
if (input.isKeyPressed(Input.Keys.R)) {
camera.lookAt(0, 0, 0);
}
cameraSpeed = newCameraPos.sub(oldCameraPos);
cameraBox = new BoundingBox(new Vector3(camera.position.x,
camera.position.y,
camera.position.z),
new Vector3(camera.position.x + 10,
camera.position.y + 10,
camera.position.z + 10));
for (int i = 0; i < 1000; i++) {
if (cameraBox.contains(boxBounds[i])) {
camera.position.x = camera.position.x - cameraSpeed.x;
camera.position.y = camera.position.y - cameraSpeed.y;
camera.position.z = camera.position.z - cameraSpeed.z;
}
}
System.out.println(cameraSpeed.x + " " + cameraSpeed.y + " " + cameraSpeed.z);
}
@Override
public void dispose() {
modelBatch.dispose();
model.dispose();
}
}
Resultado:
java
collision-detection
3d
libgdx
SirMathhman
fuente
fuente
Respuestas:
Los motores de física que he escrito funcionan en tres pasos.
Cada cuadro:
El motor de física recorre los objetos y actualiza sus nuevas posiciones según
posición + = velocidad * deltaTime;
El motor de física resuelve todas las colisiones.
Primero, sugiero que en lugar de dejar que su FirstPersonCameraController establezca la posición de la cámara, haga que la cámara sea un objeto físico haciendo que FirstPersonCameraController controle la velocidad de la cámara, no la posición, y luego deje que el motor físico actualice la posición de la cámara.
Escribir un motor de física puede sonar aterrador, pero en realidad es solo un método que mueve todos los objetos de una escena y luego se asegura de que los objetos sólidos no se superpongan.
Por último, dependiendo de sus necesidades, hay dos enfoques que he utilizado para resolver las colisiones.
Después de que su motor de física haya movido todos los objetos. Luego recorra los objetos para ver cuáles se superponen. Si alguno se superpone, entonces han chocado. Debe decidir cómo se resolverá esta colisión, pero generalmente esto significa que mueve uno o ambos objetos hacia atrás hasta que ya no se superponen.
El mayor inconveniente de este enfoque se llama el problema de bala a través del papel. Si su cámara se mueve lo suficientemente rápido como para atravesar un cubo entero en un cuadro, cuando compruebe las colisiones, no registrará que los dos objetos colisionaron. Hay maneras de superar esto, como asegurarse de que ningún objeto vaya horriblemente rápido y arreglar su paso temporal
He tenido un éxito variado con este método. Básicamente, la idea es que puede combinar la fase de detección de movimiento y colisión para determinar que dados los vectores de velocidad de dos objetos, a qué hora colisionarán si lo hacen. Profundizar en cómo lograr esto está fuera del alcance de esta respuesta ya larga, pero aquí hay un buen artículo
Este método resuelve la viñeta a través de un problema en papel, pero es más difícil de entender / implementar y más costoso desde el punto de vista computacional.
Puede haber más métodos disponibles que pueden beneficiarlo al buscar en Internet la detección de colisiones.
fuente