add SweptSphereWorldCollisionChecker implementation
This commit is contained in:
parent
0bc881aafd
commit
890becd05b
|
@ -0,0 +1,93 @@
|
||||||
|
package com.blarg.gdx.tilemap3d;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.math.Matrix4;
|
||||||
|
import com.badlogic.gdx.math.Vector3;
|
||||||
|
import com.badlogic.gdx.math.collision.BoundingBox;
|
||||||
|
import com.blarg.gdx.Bitfield;
|
||||||
|
import com.blarg.gdx.math.SweptSphere;
|
||||||
|
import com.blarg.gdx.math.SweptSphereCollisionTester;
|
||||||
|
import com.blarg.gdx.math.SweptSphereWorldCollisionChecker;
|
||||||
|
import com.blarg.gdx.tilemap3d.tilemesh.TileMesh;
|
||||||
|
|
||||||
|
public class TileMapSweptSphereCollisionChecker implements SweptSphereWorldCollisionChecker {
|
||||||
|
static final TileCoord min = new TileCoord();
|
||||||
|
static final TileCoord max = new TileCoord();
|
||||||
|
static final Vector3 tileWorldPosition = new Vector3();
|
||||||
|
static final Vector3 a = new Vector3();
|
||||||
|
static final Vector3 b = new Vector3();
|
||||||
|
static final Vector3 c = new Vector3();
|
||||||
|
|
||||||
|
TileMap tileMap;
|
||||||
|
|
||||||
|
public TileMapSweptSphereCollisionChecker(TileMap tileMap) {
|
||||||
|
if (tileMap == null)
|
||||||
|
throw new IllegalArgumentException("tileMap can not be null.");
|
||||||
|
|
||||||
|
this.tileMap = tileMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkForCollisions(SweptSphere sphere, BoundingBox possibleCollisionArea) {
|
||||||
|
min.set(0, 0, 0);
|
||||||
|
max.set(0, 0, 0);
|
||||||
|
|
||||||
|
float lastCollisionDistance = Float.MAX_VALUE;
|
||||||
|
|
||||||
|
// TODO: I don't think we even need to check if the area overlaps ... ?
|
||||||
|
// (it probably always will, right?)
|
||||||
|
boolean overlapping = tileMap.getOverlappedTiles(possibleCollisionArea, min, max);
|
||||||
|
if (overlapping) {
|
||||||
|
for (int y = min.y; y <= max.y; ++y) {
|
||||||
|
for (int z = min.z; z < max.z; ++z) {
|
||||||
|
for (int x = min.x; x < max.x; ++x) {
|
||||||
|
Tile tile = tileMap.get(x, y, z);
|
||||||
|
|
||||||
|
// only check solid tiles
|
||||||
|
if (Bitfield.isSet(Tile.FLAG_COLLIDEABLE, tile.flags)) {
|
||||||
|
// check each triangle in this tile's mesh
|
||||||
|
TileMesh mesh = tileMap.tileMeshes.get(tile);
|
||||||
|
Vector3[] vertices = mesh.getCollisionVertices();
|
||||||
|
|
||||||
|
// world position of this tile, will be used to move each
|
||||||
|
// mesh triangle into world space
|
||||||
|
tileWorldPosition.set(x, y, z);
|
||||||
|
|
||||||
|
// also add the global TileMesh offset so the mesh is within
|
||||||
|
// 0,0,0 to 1,1,1 and not -0.5,-0.5,-0.5 to 0.5,0.5,0.5
|
||||||
|
tileWorldPosition.add(TileMesh.OFFSET);
|
||||||
|
|
||||||
|
Matrix4 transform = Tile.getTransformationFor(tile);
|
||||||
|
|
||||||
|
for (int i = 0; i < vertices.length; i += 3) {
|
||||||
|
// get the vertices making up this triangle
|
||||||
|
a.set(vertices[i]);
|
||||||
|
b.set(vertices[i + 1]);
|
||||||
|
c.set(vertices[i + 2]);
|
||||||
|
|
||||||
|
if (transform != null) {
|
||||||
|
a.mul(transform);
|
||||||
|
b.mul(transform);
|
||||||
|
c.mul(transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
// move these vertices into world space
|
||||||
|
a.add(tileWorldPosition);
|
||||||
|
b.add(tileWorldPosition);
|
||||||
|
c.add(tileWorldPosition);
|
||||||
|
|
||||||
|
// test against it. we don't actually care about the
|
||||||
|
// return value, but just want the CollisionPacket
|
||||||
|
// to be updated. at the end of all these tests, it
|
||||||
|
// will contain info for the closest intersection
|
||||||
|
// found
|
||||||
|
boolean collided = SweptSphereCollisionTester.test(sphere, a, b, c);
|
||||||
|
if (collided && sphere.nearestCollisionDistance < lastCollisionDistance)
|
||||||
|
lastCollisionDistance = sphere.nearestCollisionDistance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue