I'm working on a Minecraft like game engine and recently I've been trying to add good collision response which I have kind of. The collision response is perfect when I try and go through the right side or front side of this cube.
I'm doing a dot product between my player's velocity vector and the normals for each side of the cube (ex: new Vector3f(0.0f,1.0f,0.0f) //Up
) and seeing which normal gives the dot product which is the greatest and then I multiply my velocity vector by that normal vector in order to create this cool sliding effect.
This sliding effect only works for the right and front sides of the cube and the rest of the sides have a weird effect which is not sliding at all. Anyway if anyone can help with this it would be very much appreciated :). This is my method for detecting collision which works efficiently. Then there's the method for detecting which way the player should slide which is called velocityDirection. Update: Whenever I try and touch ANY side of the cube (I am printing out the variable BestMatch from the velocityDirection class which is one of the normals from the array of normals) it returns a value of Vector3f(0,1,0) and when I try and move and go through the right side like a ghost it returns Vector3f(-1,0,0) and for the front side it returns Vector3f(0,0,-1), and remember the right and front sides both have perfect collision.
Collision Detection Method:
public static boolean IsCollision(AABB player, AABB block)
{
boolean x = player.getMaxX() > block.getMinX() && player.getMinX() < block.getMaxX();
boolean y = player.getMaxY() > block.getMinY() && player.getMinY() < block.getMaxY();
boolean z = player.getMaxZ() > block.getMinZ() && player.getMinZ() < block.getMaxZ();
return (x && y && z);
}
Sliding Response Method :
public static Vector3f velocityDirection(Vector3f velocityDirection){
Vector3f normalsArray[] = new Vector3f[]{
new Vector3f(0.0f,1.0f,0.0f), // Up
new Vector3f(1.0f,0.0f,0.0f),//Right
new Vector3f(0.0f,-1.0f,0.0f), // Down
new Vector3f(-1.0f,0.0f,0.0f), //Left
new Vector3f(0.0f,0.0f,1.0f), //Front
new Vector3f(0.0f,0.0f,-1.0f) //Back
};
Vector3f BestMatch = new Vector3f();
Vector3f TrueVelocity = new Vector3f();
float max = 0;
for(int i = 0 ; i < normalsArray.length ; i++){
float dot = Vector3f.dot(velocityDirection, normalsArray[i]);
if(dot > max){
max = dot;
BestMatch = normalsArray[i];
}
}
TrueVelocity = new Vector3f(velocityDirection.x * BestMatch.x, velocityDirection.y * BestMatch.y, velocityDirection.z * BestMatch.z );
return TrueVelocity;
}
Camera Class:
public class Camera {
private static Vector3f position = new Vector3f(0,0,0);
public static float pitch = 20 ;
public static float rx, ry, rz;
public static float velocityX;
public static float velocityY;
public static float velocityZ;
public static float yaw;
public static float roll;
private final static float RUN_SPEED = 20;
private final static float TURN_SPEED = 150;
private static float JUMP_POWER = 10;
private static float currentSpeed = 0;
public static float currentTurnSpeed = 0;
public static boolean isMovingX = false;
public static boolean isMovingY = false;
public float angleAroundPlayer = 0;
private static final Vector4f Forward = new Vector4f(0,0,-1,0);
private static final Vector4f Backward = new Vector4f(0,0,1,0);
public static boolean isColliding = false;
public static void moveCamera(AABB player,AABB box){
calculatePitch();
if(Keyboard.isKeyDown(Keyboard.KEY_W)){
isMovingX = true;
currentSpeed = -RUN_SPEED;
}
else if(Keyboard.isKeyDown(Keyboard.KEY_S)){
currentSpeed = RUN_SPEED;
isMovingX = true;
}
else{
isMovingX = false;
currentSpeed = 0;
}
if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
currentTurnSpeed = -TURN_SPEED;
} else if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
currentTurnSpeed = TURN_SPEED;
} else {
currentTurnSpeed = 0;
}
if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)){
isMovingY = true;
velocityY = -JUMP_POWER * DisplayManager.getFrameTimeSeconds();
}
else if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
isMovingY = true;
velocityY = JUMP_POWER * DisplayManager.getFrameTimeSeconds();
}
else{
isMovingY = false;
velocityY = 0;
}
yaw -= currentTurnSpeed * DisplayManager.getFrameTimeSeconds();
Matrix4f rotation = calculateCameraRotationMatrix();
Vector3f TrueForward = new Vector3f(Matrix4f.transform(rotation,Forward , null));
Vector3f TrueBackward = new Vector3f(Matrix4f.transform(rotation,Backward , null));
Vector3f CameraPos = Camera.getPosition();
float distance = currentSpeed * DisplayManager.getFrameTimeSeconds();
velocityX = (float) (distance * Math.sin(Math.toRadians(getRy())));
velocityZ = (float) (distance * Math.cos(Math.toRadians(getRy())));
increasePosition(velocityX,velocityY,velocityZ);
System.out.println(new Vector3f(velocityX, velocityY, velocityZ));
if(isColliding){
Vector3f velocityDirection = VectorMath.velocityDirection(new Vector3f(velocityX, velocityY, velocityZ));
increasePosition(velocityDirection.x , velocityDirection.y, velocityDirection.z );
}
increaseRotation(0, currentTurnSpeed * DisplayManager.getFrameTimeSeconds(), 0);
yaw %= 360;
}
private static Matrix4f calculateCameraRotationMatrix() {
Matrix4f rotation = new Matrix4f();
rotation.rotate((float) Math.toRadians(getPitch()), new Vector3f(1, 0, 0));
rotation.rotate((float) Math.toRadians(getYaw()), new Vector3f(0, 1, 0));
return rotation;
}
public static void increasePosition(float dx, float dy, float dz){
position.x += dx;
position.y += dy;
position.z += dz;
}
public static void increaseRotation(float dx, float dy, float dz){
rx += dx;
ry += dy;
rz += dz;
}
private static void calculatePitch() {
float pitchChange = Mouse.getDY() * 0.63f;
pitch -= pitchChange;
if (pitch < -40) {
pitch = -40;
} else if (pitch > 90) {
pitch = 90;
}
}
public static Vector3f getPosition() {
return position;
}
public static void setPosition(Vector3f position) {
Camera.position = position;
}
public static float getPitch() {
return pitch;
}
public static float getRx() {
return rx;
}
public static float getRy() {
return ry;
}
public static float getRz() {
return rz;
}
public static float getYaw() {
return yaw;
}
public static float getRoll() {
return roll;
}