W poniższym kodzie umieściłem przykład czegoś, co chcę zrobić. Mam aparat i chcę, aby przestał się poruszać, gdy trafi w jedno z pudeł, jak to zrobić?
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();
}
}
Wynik:
java
collision-detection
3d
libgdx
SirMathhman
źródło
źródło
Odpowiedzi:
Silniki fizyki, które napisałem, działają w trzech krokach
Każda ramka:
Silnik fizyki zapętla obiekty i aktualizuje ich nowe pozycje na podstawie
pozycja + = prędkość * deltaTime;
Silnik fizyki rozwiązuje wszystkie kolizje
Po pierwsze, sugeruję, aby zamiast pozwalać Twojemu FirstPersonCameraControllerowi ustawić pozycję kamery, uczynić kamerę obiektem fizycznym, pozwalając FirstPersonCameraControllerowi kontrolować prędkość kamery, a nie pozycję, a następnie pozwolić silnikowi fizyki aktualizować pozycję kamery.
Pisanie silnika fizyki może brzmieć przerażająco, ale tak naprawdę jest to tylko metoda, która porusza wszystkie obiekty w scenie, a następnie upewnia się, że obiekty stałe nie nakładają się.
Wreszcie, w zależności od potrzeb, istnieją dwa podejścia, których użyłem do rozwiązania kolizji.
Po tym, jak silnik fizyki poruszy każdy obiekt. Następnie przejdź przez obiekty, aby zobaczyć, które się nakładają. Jeśli jakieś się pokrywają, to się zderzyły. Musisz zdecydować, w jaki sposób ta kolizja zostanie rozwiązana, ale zwykle oznacza to, że przesuwasz jeden lub oba obiekty do tyłu, aż przestaną się nakładać.
Największą wadą tego podejścia jest problem polegający na pocisku przez papier. Jeśli kamera porusza się wystarczająco szybko, aby przejść przez cały sześcian w jednej ramce, to podczas sprawdzania kolizji nie zarejestrujesz kolizji dwóch obiektów. Istnieją sposoby na przezwyciężenie tego, na przykład upewnienie się, że żaden przedmiot nie idzie okropnie szybko i ustalenie czasu
Dzięki tej metodzie miałem różne sukcesy. Zasadniczo chodzi o to, że można połączyć fazę wykrywania ruchu i kolizji, aby ustalić, że biorąc pod uwagę wektory prędkości dwóch obiektów, o której godzinie się zderzą, jeśli w ogóle się zderzą. Zagłębianie się w to, jak to osiągnąć, jest poza zasięgiem tej i tak już długiej odpowiedzi, ale oto dobry artykuł
Ta metoda rozwiązuje problem polegający na problemie z papierem, ale trudniej jest go zrozumieć / wdrożyć, a także jest bardziej kosztowny obliczeniowo.
Może być więcej metod, które mogą przynieść ci korzyść, przeszukując Internet w celu wykrycia kolizji.
źródło