Collision Detection in a Tile Based Platformer - java

I have a set of methods in my platformer in progress to detect and resolve collisions between entities and the tilemap, but they are doing a bad job of it.
The bottom method is the one being called, like this:
player.velocity = player.velocity.add(getFinalCollisionVector());
where player.velocity is a Vec2D.
private List<Rectangle2D> getCollidingTiles(){
List<Rectangle2D> collidingTiles = new ArrayList<Rectangle2D>();
for(int x = (int) (this.getX()/Tile.SIZE); x <= (int) (this.getX()/Tile.SIZE) + this.getRect2D().getWidth()/Tile.SIZE; x++){
for(int y = (int) (this.getX()/Tile.SIZE); y <= (int) (this.getX()/Tile.SIZE) + this.getRect2D().getHeight()/Tile.SIZE; y++){
if(map.getTileAt(x, y).getAttribute(Attribute.SOLID))
if(map.getCollisionBoxAt(x,y).isColliding(this.collisionBox))
collidingTiles.add(new Rectangle2D.Double(x, y, Tile.SIZE, Tile.SIZE));
}
}
return collidingTiles;
}
private List<Vec2D> getAllTileCollisionVectors(){
List<Rectangle2D> collidingTiles = getCollidingTiles();
List<Vec2D> collisionVectors = new ArrayList<Vec2D>();
for(Rectangle2D rec : collidingTiles){
collisionVectors.add(getCorrectionVector(rec));
}
return collisionVectors;
}
private Vec2D getCorrectionVector(Rectangle2D target)
{
Vec2D ret = new Vec2D();
double x1 = (this.getX() + this.getSize().x) - target.getX();
double x2 = this.getX() - (target.getX() + target.getWidth());
double y1 = (this.getY() + this.getSize().y) - target.getY();
double y2 = this.getY() - (target.getY() + target.getHeight());
// calculate displacement along X-axis
if (x1 < x2)
{
ret.x = x1;
}
else if (x1 > x2)
{
ret.x = x2;
}
// calculate displacement along Y-axis
if (y1 < y2)
{
ret.y = y1;
}
else if (y1 > y2)
{
ret.y = y2;
}
return ret;
}
protected Vec2D getFinalCollisionVector(){
List<Vec2D> collisionVectors = getAllTileCollisionVectors();
if(collisionVectors.size() < 1)
return new Vec2D(0,0);
Vec2D finalVector = new Vec2D();
for(Vec2D vec : collisionVectors){
finalVector = finalVector.add(vec);
}
return finalVector;
}
What am I doing wrong in my code? This is the behavior that the player shows, where he falls (due to gravity) to that point, and then he freezes.

OP here:
Since there are no other answers, I've posted my own.
I've abandonded the old implementation,started from the ground up, and it works now. This is the new implementation:
public Corners getCornersAreSolid(double x, double y) {
int leftTile = (int)(x / Tile.SIZE);
int rightTile = (int)((x + moveData.collisionBox.getWidth()) / Tile.SIZE);
int topTile = (int)(y / Tile.SIZE);
int bottomTile = (int)((y + moveData.collisionBox.getHeight()) / Tile.SIZE);
boolean topLeft = hasAttribute(map, Attribute.SOLID, topTile, leftTile);
boolean topRight = hasAttribute(map, Attribute.SOLID, topTile, rightTile);
boolean bottomLeft = hasAttribute(map, Attribute.SOLID, bottomTile, leftTile);
boolean bottomRight = hasAttribute(map, Attribute.SOLID, bottomTile, rightTile);
Corners solidCorners = new Corners();
solidCorners.topLeft = topLeft;
solidCorners.topRight = topRight;
solidCorners.bottomRight = bottomRight;
solidCorners.bottomLeft = bottomLeft;
return solidCorners;
}
private boolean hasAttribute(GameMap map, Attribute attribute, int tileY, int tileX) {
boolean result = false;
if (tileX >= 0 && tileX < map.getWidthInTiles() && tileY >= 0 && tileY < map.getHeightInTiles()) {
result = map.getTileAt(tileX, tileY).getAttribute(attribute);
}
return result;
}
public Vec2D getNextPosition() {
int currCol = (int) (getX() / Tile.SIZE);
int currRow = (int) (getY() / Tile.SIZE);
double destX = getX() + moveData.velocity.x;
double destY = getY() + moveData.velocity.y;
double tempX = getX();
double tempY = getY();
Corners solidCorners = getCornersAreSolid(getX(), destY);
boolean topLeft = solidCorners.topLeft;
boolean topRight = solidCorners.topRight;
boolean bottomLeft = solidCorners.bottomLeft;
boolean bottomRight = solidCorners.bottomRight;
this.framesSinceLastCollision += 1;
if(moveData.velocity.y < 0) {
if(topLeft || topRight) {
moveData.velocity.y = 0;
tempY = currRow * Tile.SIZE;
this.framesSinceLastCollision = 0;
}
else {
tempY += moveData.velocity.y;
}
}
else if(moveData.velocity.y > 0) {
if(bottomLeft || bottomRight) {
moveData.velocity.y = 0;
tempY = (currRow + 1) * Tile.SIZE - moveData.collisionBox.getHeight() % Tile.SIZE - 1 ;
this.framesSinceLastCollision = 0;
}
else {
tempY += moveData.velocity.y;
}
}
solidCorners = getCornersAreSolid(destX, getY());
topLeft = solidCorners.topLeft;
topRight = solidCorners.topRight;
bottomLeft = solidCorners.bottomLeft;
bottomRight = solidCorners.bottomRight;
if(moveData.velocity.x < 0) {
if(topLeft || bottomLeft) {
moveData.velocity.x = 0;
tempX = currCol * Tile.SIZE;
this.framesSinceLastCollision = 0;
}
else {
tempX += moveData.velocity.x;
}
}
if(moveData.velocity.x > 0) {
if(topRight || bottomRight) {
moveData.velocity.x = 0;
tempX = (currCol + 1) * Tile.SIZE - moveData.collisionBox.getWidth() % Tile.SIZE -1 ;
this.framesSinceLastCollision = 0;
}
else {
tempX += moveData.velocity.x;
}
}
return new Vec2D(tempX, tempY);
}
private static class Corners{
public boolean topLeft, topRight;
public boolean bottomLeft, bottomRight;
public Corners(){
topLeft = false;
topRight = false;
bottomLeft = false;
bottomRight = false;
}
}

Related

circle collision practice, advice?

can anyone tell me what i'm doing wrong? i'm trying to get the circles to bounce off each other but they don't seem to be working.i keep making changes to fix the issue but that only makes more issues, whilst the main issue isn't resolved. have i used the wrong math's algorithm to check for collisions? or is it right and i have just made an error i cant seem to find? any help would be appreciated.
public float[][] CreateDots() {
if (first == true) {
for (int i = 0; i < dotNumber; i++) {
do{
dotX = r.nextInt(300);
dotY = r.nextInt(300);
dotWidth = r.nextFloat() * 50;
dotRadius = dotWidth / 2;
dotMass = r.nextFloat() / 10;
dotCentreX = dotX + dotRadius;
dotCentreY = dotY + dotRadius;
dotVelocityX = r.nextFloat();
dotVelocityY = r.nextFloat();
dots[i][0] = dotX;
dots[i][1] = dotY;
dots[i][2] = dotVelocityX;
dots[i][3] = dotVelocityY;
dots[i][4] = dotRadius;
dots[i][5] = dotCentreX;
dots[i][6] = dotCentreY;
dots[i][7] = dotMass;
dots[i][8] = dotWidth;
}while(collision == true);
}
first = false;
} else {
for (int i = 0; i < dotNumber; i++) {
dots[i][0] = dots[i][0] + dots[i][2];
dots[i][1] = dots[i][1] + dots[i][3];
if (dots[i][0] + dots[i][8] >= wallX) {
dots[i][2] = -dots[i][2];
}
if (dots[i][1] + dots[i][8] >= wallY) {
dots[i][3] = -dots[i][3];
}
if (dots[i][0] < 0) {
dots[i][2] = -dots[i][2];
}
if (dots[i][1] < 0) {
dots[i][3] = -dots[i][3];
}
}
}
repaint();
return dots;
}
public void bounce() {
collisionDot = false;
for (int i = 0; i < dotNumber; i++) {
for (int a = i + 1; a < dotNumber; a++) {
// difference between the x and y velocity of two dots
float xVelDiff = dots[i][2] - dots[a][2];
float yVelDiff = dots[i][3] - dots[a][3];
//difference between the centre x and y of two dots
float xDist = dots[i][5] - dots[a][5];
float yDist = dots[i][6] - dots[a][6];
System.out.println(xVelDiff + " * " + xDist + " + " + yVelDiff + " * " + yDist + " = "+ (xVelDiff * xDist + yVelDiff * yDist));
//not quite sure yet
if (xVelDiff * xDist + yVelDiff * yDist <= 0) {
angleCollision = (float) -Math.atan2(dots[a][0] - dots[i][0], dots[a][1] - dots[i][1]);
float mass = (dots[i][7] + dots[a][7]);
float mass2 = (dots[i][7] - dots[a][7]);
// x and y velocity and angle of collision for the two dots
float[] u1 = rotate(dots[i][2], dots[i][3], (float) angleCollision);
float[] u2 = rotate(dots[a][2], dots[a][3], (float) angleCollision);
//Velocity of dot 1
float[] v1 = new float[2];
v1[0] = u1[0] * mass2 / mass + u2[0] * 2 * dots[a][7] / (mass);
v1[1] = u1[1];
// velocity of dot 2
float[] v2 = new float[2];
v2[0] = u2[0] * mass2 / mass + u1[0] * 2 * dots[a][7] / (mass);
v2[1] = u2[1];
// final velocity of two colliding dots is:
float[] vFinal1 = rotate(v1[0], v1[1], (float) -angleCollision);;
float[] vFinal2 = rotate(v2[0], v2[1], (float) -angleCollision);;
if (a != i && !(dots[a][0] == 0 && dots[a][1] == 0)) {
// if the x and y distance between the two dots centres is less than their radii combined then the dots have collided
boolean thisCollision = Math.pow(xDist, 2) + Math.pow(yDist, 2) <= Math.pow((dots[a][4] + dots[i][4]), 2);
//if the dots collided, create new final velocity's from the angle of collision and the x and y velocitys at collision
if (thisCollision) {
collisionDot = true;
dots[i][2] = vFinal1[0];
dots[i][3] = vFinal1[1];
dots[a][2] = vFinal2[0];
dots[a][3] = vFinal2[1];
return;
}
}
}
}
}
}
public float[] rotate(float velocityX, float velocityY, float angle) {
float x1 = (float) (velocityX * Math.cos(angle) - velocityY * Math.sin(angle));
float y1 = (float) (velocityX * Math.sin(angle) - velocityY * Math.cos(angle));
float vel[] = new float[2];
vel[0] = x1;
vel[1] = y1;
return vel;
}

How change shape and size of custom drawn shader in glsurface view by getting coordinates from view class

In my application i'm having a custom graph like view firstly beneath the overlaying graph view there is a custom cameraview which extends glsurfaceview here inside camera view class i'm applying live blur filter to camera of device without any problems but however i want to change the shape and size of blur as per the coordinate of my overlay grap view here i'm attaching screenshots of my application:
Below Is the screenshot of what i'm trying to achieve:
Below Is Screenshot of What i'm actaully getting:
Here's my overlaying view class:
public class OverlayView2 extends View {
MainActivity f2396a;
double f2397b;
double f2398c;
double f2399d;
double f2400e;
double f2401f;
int f2402g = 1;
C0905a[] f2403h = {new C0905a(), new C0905a(), new C0905a(), new C0905a(), new C0905a()};
Paint f2404i = new Paint();
double f2405j = 1.0d;
double f2406k;
double f2407l;
double f2408m;
class C0905a {
double f2409a;
double f2410b;
int f2411c = -1;
double f2412d;
double f2413e;
C0905a() {
}
}
public OverlayView2(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
mo3504a();
if (!isInEditMode() && (context instanceof MainActivity)) {
this.f2396a = (MainActivity) context;
}
}
public static float m4357a(Context context, float f) {
return TypedValue.applyDimension(1, f, context.getResources().getDisplayMetrics());
}
public void mo3504a() {
this.f2397b = 0.0d;
this.f2398c = 0.0d;
this.f2399d = 0.0d;
this.f2400e = 0.4d;
this.f2401f = 0.25d;
invalidate();
}
public void mo3505a(double d, double d2, double d3, double d4, Canvas canvas) {
double width = (double) ((getWidth() + getHeight()) * 2);
canvas.drawLine((float) (d - (d3 * width)), (float) (d2 - (d4 * width)), (float) ((d3 * width) + d), (float) ((width * d4) + d2), this.f2404i);
}
public void mo3506a(double d, double d2, Canvas canvas) {
canvas.drawOval(new RectF((float) (0.0d - d), (float) (0.0d - d2), (float) (0.0d + d), (float) (0.0d + d2)), this.f2404i);
}
/* access modifiers changed from: 0000 */
/* renamed from: b */
public void mo3507b() {
double scale = getScale();
double width = (((double) getWidth()) * 0.5d) + (this.f2397b * scale);
double height = (((double) getHeight()) * 0.5d) + (this.f2398c * scale);
double cos = Math.cos(Math.toRadians(this.f2399d)) * this.f2400e * scale;
double sin = Math.sin(Math.toRadians(this.f2399d)) * this.f2400e * scale;
double d = (-Math.sin(Math.toRadians(this.f2399d))) * this.f2401f * scale;
double cos2 = Math.cos(Math.toRadians(this.f2399d)) * this.f2401f * scale;
this.f2403h[0].f2409a = width;
this.f2403h[0].f2410b = height;
this.f2403h[1].f2409a = width - cos;
this.f2403h[1].f2410b = height - sin;
this.f2403h[2].f2409a = cos + width;
this.f2403h[2].f2410b = sin + height;
this.f2403h[3].f2409a = width - d;
this.f2403h[3].f2410b = height - cos2;
this.f2403h[4].f2409a = width + d;
this.f2403h[4].f2410b = height + cos2;
Matrix matrix = new Matrix();
matrix.postScale((float) (this.f2400e * scale), (float) (this.f2401f * scale));
matrix.postRotate((float) this.f2399d);
matrix.postTranslate(((float) getWidth()) * 0.5f, ((float) getHeight()) * 0.5f);
matrix.postTranslate((float) (this.f2397b * scale), (float) (scale * this.f2398c));
matrix.postScale(1.0f / ((float) getWidth()), -1.0f / ((float) getHeight()));
matrix.postTranslate(0.0f, 1.0f);
matrix.invert(matrix);
if (this.f2396a != null && this.f2396a.cameraView != null) {
/* matrix.getValues(this.f2396a.cameraView.f2132f);*/
}
}
public void mo3508c() {
double d;
double scale = getScale();
C0905a aVar = this.f2403h[0];
if (aVar.f2411c >= 0) {
this.f2397b = (aVar.f2409a - (((double) getWidth()) * 0.5d)) / scale;
this.f2398c = (aVar.f2410b - (((double) getHeight()) * 0.5d)) / scale;
}
double d2 = 0.0d;
int i = 0;
double d3 = 0.0d;
double d4 = 0.0d;
int i2 = 0;
int i3 = 0;
for (int i4 = 1; i4 < this.f2403h.length; i4++) {
C0905a aVar2 = this.f2403h[i4];
if (aVar2.f2411c >= 0) {
if (i4 == 1) {
d2 += Math.toDegrees(Math.atan2(-(aVar2.f2410b - this.f2403h[0].f2410b), -(aVar2.f2409a - this.f2403h[0].f2409a)));
i++;
}
if (i4 == 2) {
d2 += Math.toDegrees(Math.atan2(aVar2.f2410b - this.f2403h[0].f2410b, aVar2.f2409a - this.f2403h[0].f2409a));
i++;
}
if (this.f2402g != 1) {
if (i4 == 3) {
d2 += Math.toDegrees(Math.atan2(aVar2.f2409a - this.f2403h[0].f2409a, -(aVar2.f2410b - this.f2403h[0].f2410b)));
i++;
}
if (i4 == 4) {
d2 += Math.toDegrees(Math.atan2(-(aVar2.f2409a - this.f2403h[0].f2409a), aVar2.f2410b - this.f2403h[0].f2410b));
i++;
}
}
double d5 = (this.f2403h[0].f2409a - aVar2.f2409a) / scale;
double d6 = (this.f2403h[0].f2410b - aVar2.f2410b) / scale;
if (i4 == 1 || i4 == 2) {
double cos = (Math.cos(Math.toRadians(this.f2399d)) * d5) + (Math.sin(Math.toRadians(this.f2399d)) * d6);
if (i4 == 2) {
cos = -cos;
}
d = Math.max(0.0d, cos) + d3;
i2++;
} else {
d = d3;
}
if (i4 == 3 || i4 == 4) {
double cos2 = ((-Math.sin(Math.toRadians(this.f2399d))) * d5) + (d6 * Math.cos(Math.toRadians(this.f2399d)));
if (i4 == 4) {
cos2 = -cos2;
}
d4 += Math.max(0.0d, cos2);
i3++;
d3 = d;
} else {
d3 = d;
}
}
}
if (i > 0) {
this.f2399d = d2 / ((double) i);
}
if (i2 > 0) {
this.f2400e = d3 / ((double) i2);
}
if (i3 > 0) {
this.f2401f = d4 / ((double) i3);
}
if (this.f2397b < -0.8d) {
this.f2397b = -0.8d;
}
if (this.f2398c < -0.8d) {
this.f2398c = -0.8d;
}
if (this.f2397b > 0.8d) {
this.f2397b = 0.8d;
}
if (this.f2398c > 0.8d) {
this.f2398c = 0.8d;
}
if (this.f2400e < 0.05d) {
this.f2400e = 0.05d;
}
if (this.f2401f < 0.05d) {
this.f2401f = 0.05d;
}
if (this.f2400e > 1.0d) {
this.f2400e = 1.0d;
}
if (this.f2401f > 1.0d) {
this.f2401f = 1.0d;
}
}
public double getHandleRadius() {
return (double) m4357a(getContext(), 16.0f);
}
public double getScale() {
return (double) (((float) (getWidth() + getHeight())) * 0.5f);
}
public void onDraw(Canvas canvas) {
if (this.f2402g != 0) {
this.f2404i.setColor(-1140850689);
this.f2404i.setStrokeWidth(m4357a(getContext(), 1.5f));
this.f2404i.setStyle(Style.STROKE);
this.f2404i.setAntiAlias(true);
canvas.save();
double scale = getScale();
canvas.translate(((float) getWidth()) * 0.5f, ((float) getHeight()) * 0.5f);
canvas.translate((float) (this.f2397b * scale), (float) (this.f2398c * scale));
canvas.rotate((float) this.f2399d);
mo3505a(0.0d, 0.0d, 1.0d, 0.0d, canvas);
if (this.f2402g == 1) {
mo3505a(0.0d, (this.f2401f * scale) + 0.0d, 1.0d, 0.0d, canvas);
mo3505a(0.0d, 0.0d - (this.f2401f * scale), 1.0d, 0.0d, canvas);
}
mo3505a(0.0d, 0.0d, 0.0d, 1.0d, canvas);
if (this.f2402g == 2) {
mo3506a(this.f2400e * scale, this.f2401f * scale, canvas);
}
canvas.restore();
mo3507b();
double handleRadius = getHandleRadius();
for (int i = 0; i < this.f2403h.length; i++) {
canvas.drawCircle((float) this.f2403h[i].f2409a, (float) this.f2403h[i].f2410b, (float) (this.f2403h[i].f2411c >= 0 ? 1.25d * handleRadius : handleRadius), this.f2404i);
}
}
}
public boolean onTouchEvent(MotionEvent motionEvent) {
boolean z;
C0905a[] aVarArr;
C0905a[] aVarArr2;
if (this.f2402g == 0) {
for (C0905a aVar : this.f2403h) {
aVar.f2411c = -1;
}
return super.onTouchEvent(motionEvent);
}
boolean z2 = false;
int actionMasked = motionEvent.getActionMasked();
if (actionMasked == 0 || actionMasked == 5) {
z2 = true;
double d = Double.MAX_VALUE;
C0905a aVar2 = null;
int actionIndex = motionEvent.getActionIndex();
int pointerId = motionEvent.getPointerId(actionIndex);
double x = (double) motionEvent.getX(actionIndex);
double y = (double) motionEvent.getY(actionIndex);
double handleRadius = getHandleRadius() * 2.5d;
double d2 = handleRadius * handleRadius;
C0905a[] aVarArr3 = this.f2403h;
int length = aVarArr3.length;
int i = 0;
while (i < length) {
C0905a aVar3 = aVarArr3[i];
double d3 = aVar3.f2409a - x;
double d4 = aVar3.f2410b - y;
double d5 = (d3 * d3) + (d4 * d4);
if (d5 >= d2 || d5 >= d) {
aVar3 = aVar2;
d5 = d;
}
i++;
d = d5;
aVar2 = aVar3;
}
if (aVar2 != null) {
aVar2.f2411c = pointerId;
aVar2.f2412d = x - aVar2.f2409a;
aVar2.f2413e = y - aVar2.f2410b;
}
}
if (actionMasked == 5) {
for (C0905a aVar4 : this.f2403h) {
aVar4.f2411c = -1;
}
}
if ((actionMasked == 2 || actionMasked == 5) && motionEvent.getPointerCount() == 2) {
double x2 = (double) (motionEvent.getX(0) - motionEvent.getX(1));
double y2 = (double) (motionEvent.getY(0) - motionEvent.getY(1));
double sqrt = Math.sqrt((x2 * x2) + (y2 * y2));
double degrees = Math.toDegrees(Math.atan2((double) (motionEvent.getY(0) - motionEvent.getY(1)), (double) (motionEvent.getX(0) - motionEvent.getX(1))));
if (actionMasked == 2) {
double d6 = sqrt / this.f2405j;
this.f2400e *= d6;
this.f2401f = d6 * this.f2401f;
this.f2399d += degrees - this.f2408m;
}
this.f2405j = sqrt;
this.f2408m = degrees;
}
if (actionMasked == 2 || actionMasked == 5 || actionMasked == 0 || actionMasked == 1 || actionMasked == 6) {
double d7 = 0.0d;
double d8 = 0.0d;
int i2 = 0;
for (int i3 = 0; i3 < motionEvent.getPointerCount(); i3++) {
if (actionMasked != 6 || i3 != motionEvent.getActionIndex()) {
d7 += (double) motionEvent.getX(i3);
d8 += (double) motionEvent.getY(i3);
i2++;
}
}
if (i2 > 0) {
double d9 = d7 / ((double) i2);
double d10 = d8 / ((double) i2);
if (actionMasked == 2) {
boolean z3 = true;
for (C0905a aVar5 : this.f2403h) {
if (aVar5.f2411c >= 0) {
z3 = false;
}
}
if (z3) {
double scale = 1.0d / getScale();
this.f2397b += (d9 - this.f2406k) * scale;
this.f2398c = (scale * (d10 - this.f2407l)) + this.f2398c;
}
}
this.f2406k = d9;
this.f2407l = d10;
}
}
if (actionMasked == 2) {
z = true;
int pointerCount = motionEvent.getPointerCount();
for (int i4 = 0; i4 < pointerCount; i4++) {
int pointerId2 = motionEvent.getPointerId(i4);
double x3 = (double) motionEvent.getX(i4);
double y3 = (double) motionEvent.getY(i4);
for (C0905a aVar6 : this.f2403h) {
if (aVar6.f2411c == pointerId2) {
aVar6.f2409a = x3 - aVar6.f2412d;
aVar6.f2410b = y3 - aVar6.f2413e;
}
}
}
} else {
z = z2;
}
if (actionMasked == 1 || actionMasked == 6) {
z = true;
int pointerId3 = motionEvent.getPointerId(motionEvent.getActionIndex());
for (C0905a aVar7 : this.f2403h) {
if (aVar7.f2411c == pointerId3) {
aVar7.f2411c = -1;
}
}
}
if (actionMasked == 3) {
z = true;
for (C0905a aVar8 : this.f2403h) {
aVar8.f2411c = -1;
}
}
if (z) {
mo3508c();
invalidate();
if (this.f2396a != null) {
this.f2396a.cameraView.requestRender();
}
}
return super.onTouchEvent(motionEvent) || z;
}
}
Here's my cameraview class:
public class CameraView extends GLSurfaceView implements Renderer {
public static long maxsize = 1280;
final String TAG = "CameraView";
public Bitmap bitmap = null;
public Bitmap bitmap0 = null;
int bitmaptexture = -1;
boolean bresize = true;
public float f0c;
public static Camera camera;
SurfaceTexture cameraSurface;
int cameraTexture;
boolean created = false;
boolean doloadbitmap = false;
public boolean isFrontFacing;
Framebuffer fa;
Framebuffer fb;
/* renamed from: h */
int f1h;
public static int ak;
OnPhotoListener photoListener;
Quad quad = new Quad();
public float f2r;
public float f3s;
Shader shblur;
Shader shconv;
Shader shcopy;
Shader shfina;
Shader shflip;
int f4w;
public float f5y;
public interface OnPhotoListener {
void onPhoto(Bitmap bitmap);
}
public void takePhoto(OnPhotoListener l) {
this.photoListener = l;
requestRender();
}
static Bitmap takeScreenshot(int x, int y, int w, int h) {
int[] b = new int[((y + h) * w)];
int[] bt = new int[(w * h)];
IntBuffer ib = IntBuffer.wrap(b);
ib.position(0);
GLES20.glReadPixels(x, 0, w, y + h, 6408, 5121, ib);
int i = 0;
int k = 0;
while (i < h) {
for (int j = 0; j < w; j++) {
int pix = b[(i * w) + j];
bt[(((h - k) - 1) * w) + j] = ((-16711936 & pix) | ((pix << 16) & 16711680)) | ((pix >> 16) & MotionEventCompat.ACTION_MASK);
}
i++;
k++;
}
return Bitmap.createBitmap(bt, w, h, Config.ARGB_8888);
}
public CameraView(Context context, AttributeSet attrs) {
super(context, attrs);
setEGLContextClientVersion(2);
setRenderer(this);
setRenderMode(0);
requestRender();
}
void m7x(Framebuffer src, Framebuffer dst, float dx, float dy) {
dst.bind(this.f4w, this.f1h);
this.shblur.use();
this.shblur.tex("s", src.tex());
this.shblur.set("o", (double) dx, (double) dy);
this.shblur.set("y", (double) this.f5y);
this.shblur.set("z", (double) this.f3s);
this.quad.draw();
}
void m6x() {
float radius = this.f2r;
float rx = ((radius / 8.0f) / ((float) this.f4w)) * ((float) this.f1h);
float ry = radius / 8.0f;
m7x(this.fa, this.fb, rx / 8.0f, 0.0f);
m7x(this.fb, this.fa, rx / 1.0f, 0.0f);
m7x(this.fa, this.fb, 0.0f, ry / 8.0f);
m7x(this.fb, this.fa, 0.0f, ry / 1.0f);
m7x(this.fa, this.fb, rx / 8.0f, 0.0f);
m7x(this.fb, this.fa, rx / 1.0f, 0.0f);
m7x(this.fa, this.fb, 0.0f, ry / 8.0f);
m7x(this.fb, this.fa, 0.0f, ry / 1.0f);
}
public void onDrawFrame(GL10 _gl) {
GLES20.glClear(16384);
GLES20.glDisable(2929);
GLES20.glDisable(2884);
GLES20.glDisable(3042);
GLES20.glEnableVertexAttribArray(0);
Bitmap b = this.bitmap;
if (b != null) {
this.f4w = b.getWidth();
this.f1h = b.getHeight();
if (this.doloadbitmap) {
loadbitmap();
this.doloadbitmap = false;
}
this.fa.bind(this.f4w, this.f1h);
this.shflip.use();
this.shflip.tex("s", this.bitmaptexture);
this.quad.draw();
} else if (this.camera != null && this.cameraSurface != null) {
Size cameraSize = null;
try {
this.camera.setPreviewTexture(this.cameraSurface);
this.cameraSurface.updateTexImage();
cameraSize = this.camera.getParameters().getPreviewSize();
} catch (Exception e) {
e.printStackTrace();
}
if (this.camera != null && cameraSize != null && this.cameraSurface != null) {
this.f4w = cameraSize.width;
this.f1h = cameraSize.height;
this.fa.bind(this.f4w, this.f1h);
this.shconv.use();
this.shconv.tex("s", this.cameraTexture, 0, 36197);
this.quad.draw();
} else {
return;
}
} else {
return;
}
m6x();
this.fb.bind(this.fa.f7w, this.fa.f6h);
this.shfina.use();
this.shfina.tex("s", this.fa.tex());
this.shfina.set("c", (double) this.f0c);
this.quad.draw();
OnPhotoListener l = this.photoListener;
this.photoListener = null;
if (l != null) {
Bitmap bmp = takeScreenshot(0, 0, this.f4w, this.f1h);
l.onPhoto(bmp);
bmp.recycle();
requestRender();
}
Framebuffer.reset(getWidth(), getHeight());
GLES20.glClear(16384);
if ((((double) this.f4w) * 1.0d) / ((double) this.f1h) > (((double) getWidth()) * 1.0d) / ((double) getHeight())) {
int h2 = (getWidth() * this.f1h) / this.f4w;
GLES20.glViewport(0, (getHeight() - h2) / 2, getWidth(), h2);
} else {
int w2 = (getHeight() * this.f4w) / this.f1h;
GLES20.glViewport((getWidth() - w2) / 2, 0, w2, getHeight());
}
this.shcopy.use();
this.shcopy.tex("s", this.fb.tex());
this.quad.draw();
}
public void onSurfaceChanged(GL10 _gl, int width, int height) {
}
int genTexture() {
int[] tt = new int[1];
GLES20.glGenTextures(1, tt, 0);
return tt[0];
}
public void onSurfaceCreated(GL10 _gl, EGLConfig config) {
this.fa = new Framebuffer();
this.fb = new Framebuffer();
this.shconv = new Shader(getContext(), R.raw.flip, R.raw.conv);
this.shflip = new Shader(getContext(), R.raw.flip, R.raw.copy);
this.shblur = new Shader(getContext(), R.raw.btex, R.raw.blur);
this.shfina = new Shader(getContext(), R.raw.quad, R.raw.fina);
this.shcopy = new Shader(getContext(), R.raw.quad, R.raw.copy);
this.cameraTexture = genTexture();
this.cameraSurface = new SurfaceTexture(this.cameraTexture);
this.bitmaptexture = genTexture();
this.created = true;
this.doloadbitmap = true;
}
public void createCamera(int mReqCameraId) {
Log.i(TAG, "createCamera");
requestRender();
if (this.camera == null) {
try {
if (mReqCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
isFrontFacing = false;
} else {
isFrontFacing = true;
}
this.camera = Camera.open(mReqCameraId);
/*if(Share.back_camera){
this.camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
}else{
this.camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
}*/
Parameters params = this.camera.getParameters();
params.setRecordingHint(true);
if (params.getSupportedFocusModes().contains("continuous-picture")) {
params.setFocusMode("continuous-picture");
}
Size best = null;
for (Size s : params.getSupportedPreviewSizes()) {
if (best == null || s.width * s.height < best.width * best.height) {
best = s;
}
}
if (best != null) {
Log.i("Size", best.width + " " + best.height);
params.setPreviewSize(best.width, best.height);
}
this.camera.setParameters(params);
this.camera.startPreview();
setRenderMode(1);
} catch (final Throwable ex) {
((Activity) getContext()).runOnUiThread(new Runnable() {
class C01341 implements OnClickListener {
C01341() {
}
public void onClick(DialogInterface arg0, int arg1) {
CameraView.this.createCamera(0);
}
#Override
public void onClick(View v) {
}
}
/* renamed from: camera.tiltshift.CameraView$1$2 */
class C01352 implements OnClickListener {
C01352() {
}
public void onClick(DialogInterface arg0, int arg1) {
throw new RuntimeException(ex);
}
#Override
public void onClick(View v) {
}
}
public void run() {
}
});
}
}
}
void destroyCamera() {
Log.i("CameraView", "destroyCamera");
if (this.camera != null) {
this.camera.stopPreview();
this.camera.release();
}
this.camera = null;
setRenderMode(0);
requestRender();
}
public void setBitmap(Bitmap b) {
this.bitmap0 = b;
if (b != null && this.bresize && (((long) b.getWidth()) > maxsize || ((long) b.getHeight()) > maxsize)) {
long mx = (long) Math.max(b.getWidth(), b.getHeight());
b = createScaledBitmap2(b, (int) ((((long) b.getWidth()) * maxsize) / mx), (int) ((((long) b.getHeight()) * maxsize) / mx), true);
}
this.bitmap = b;
this.doloadbitmap = true;
requestRender();
}
static Bitmap createScaledBitmap2(Bitmap src, int dstWidth, int dstHeight, boolean filter) {
Log.i("createScaledBitmap2", dstWidth + " " + dstHeight);
Matrix m = new Matrix();
m.setScale(((float) dstWidth) / ((float) src.getWidth()), ((float) dstHeight) / ((float) src.getHeight()));
Bitmap result = Bitmap.createBitmap(dstWidth, dstHeight, Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setFilterBitmap(filter);
canvas.drawBitmap(src, m, paint);
return result;
}
void loadbitmap() {
Bitmap b = this.bitmap;
if (b != null && this.created) {
GLES20.glBindTexture(3553, this.bitmaptexture);
GLES20.glTexParameteri(3553, 10241, 9728);
GLES20.glTexParameteri(3553, 10240, 9728);
GLES20.glTexParameteri(3553, 10242, 33071);
GLES20.glTexParameteri(3553, 10243, 33071);
GLUtils.texImage2D(3553, 0, b, 0);
this.doloadbitmap = false;
}
}
}

elastic collision of balls

i am having a bug which i can't figure out.I tried many times,the collision detection and calculating new velocities seems fine ,but some balls seem to stuck with each other i don't why.Can you please help me out.
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.util.Random;
import javax.swing.JFrame;
public class ElasticCollision extends Canvas implements Runnable {
private static final int WIDTH = 300;
private static final int HEIGHT = WIDTH / 16 * 9;
private static final int SCALE = 3;
private static final String TITLE = "Elastic collision";
private boolean running = false;
private JFrame frame;
private Thread thread;
private Random random = new Random();
private Color color;
private int a, b, c;
private Ball[] ball;
private int x = 0, y = 0;
private int radius = 0;
private int speedX = 0, speedY = 0;
private int noOfBalls = 25;
private double newVelX1 = 0, newVelY1 = 0;
private double newVelX2 = 0, newVelY2 = 0;
private double angle1 = 0, angle2 = 0, angle3 = 0;
private int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
public ElasticCollision() {
Dimension size = new Dimension(WIDTH * SCALE, HEIGHT * SCALE);
setPreferredSize(size);
frame = new JFrame();
ball = new Ball[noOfBalls];
}
public void start() {
for (int i = 0; i < noOfBalls; i++) {
x = random.nextInt(getWidth());
y = random.nextInt(getHeight());
radius = 25 + random.nextInt(25);
speedX = 1 + random.nextInt(2);
speedY = 1 + random.nextInt(2);
ball[i] = new Ball(x, y, radius, speedX, speedY);
}
running = true;
thread = new Thread(this);
thread.start();
}
public void stop() {
running = false;
}
public void run() {
long lastTime = System.nanoTime();
double unprocessed = 0;
double nsPerTick = 1000000000.0 / 60;
int frames = 0;
int ticks = 0;
long lastTimer = System.currentTimeMillis();
while (running) {
long now = System.nanoTime();
unprocessed += (now - lastTime) / nsPerTick;
lastTime = now;
while (unprocessed >= 1) {
ticks++;
update();
unprocessed -= 1;
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < noOfBalls; i++) {
for (int j = i + 1; j < noOfBalls; j++) {
if (ball[i].inCollision != true
|| ball[j].inCollision != true)
checkCollision(ball[i], ball[j]);
}
}
frames++;
render();
if (System.currentTimeMillis() - lastTimer > 1000) {
lastTimer += 1000;
frame.setTitle(TITLE + " | " + ticks + " ticks, " + frames
+ " fps");
frames = 0;
ticks = 0;
}
}
stop();
}
public void update() {
for (int i = 0; i < noOfBalls; i++) {
ball[i].x += ball[i].speedX;
ball[i].y += ball[i].speedY;
if (ball[i].x >= getWidth() - ball[i].radius && ball[i].speedX > 0)
ball[i].speedX = -ball[i].speedX;
if (ball[i].x <= ball[i].radius && ball[i].speedX < 0)
ball[i].speedX = -ball[i].speedX;
if (ball[i].y >= getHeight() - ball[i].radius && ball[i].speedY > 0)
ball[i].speedY = -ball[i].speedY;
if (ball[i].y <= ball[i].radius && ball[i].speedY < 0)
ball[i].speedY = -ball[i].speedY;
}
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.yellow);
g.fillRect(0, 0, getWidth(), getHeight());
for (int i = 0; i < noOfBalls; i++)
ball[i].paint(g);
g.dispose();
bs.show();
}
public void checkCollision(Ball ball1, Ball ball2) {
double distance;
if (ball1.x + ball1.radius + ball2.radius > ball2.x
&& ball1.x < ball1.x + ball1.radius + ball2.radius
&& ball1.y + ball1.radius + ball2.radius > ball2.y
&& ball1.y < ball2.y + ball1.radius + ball2.radius) {
distance = Math.sqrt(((ball1.x - ball2.x) * (ball1.x - ball2.x))
+ ((ball1.y - ball2.y) * (ball1.y - ball2.y)));
if ((int) distance < ball1.radius + ball2.radius) {
ball1.collision = true;
ball2.collision = true;
ball1.inCollision = true;
ball2.inCollision = true;
ball1.collisionX = ((ball1.x * ball2.radius) + (ball2.x * ball1.radius))
/ (ball1.radius + ball2.radius) + ball1.radius;
ball1.collisionY = ((ball1.y * ball2.radius) + (ball2.y * ball1.radius))
/ (ball1.radius + ball2.radius) + ball1.radius;
ball2.collisionX = ((ball1.x * ball2.radius) + (ball2.x * ball1.radius))
/ (ball1.radius + ball2.radius) + ball2.radius;
ball2.collisionY =
((ball1.y * ball2.radius) + (ball2.y * ball1.radius))
/ (ball1.radius + ball2.radius) + ball2.radius;
/*
* x1 = (ball1.x - getWidth()) / 2; y1 = (ball2.y - getHeight())
* / 2; angle1 = Math.toDegrees(Math.atan2(y1, x1));
*
* x2 = (ball1.x - getWidth()) / 2; y2 = (ball2.y - getHeight())
* / 2; angle2 = Math.toDegrees(Math.atan2(y2, x2));
*/
double colision_angle = Math.toDegrees(Math.atan2(
(ball2.y - ball1.y), (ball2.x - ball1.x)));
double speed1 = Math.sqrt(ball1.speedX * ball1.speedX
+ ball1.speedY * ball1.speedY);
double speed2 = Math.sqrt(ball2.speedX * ball2.speedX
+ ball2.speedY * ball2.speedY);
double direction1 = Math.atan2(ball1.speedY, ball1.speedX);
double direction2 = Math.atan2(ball2.speedY, ball2.speedX);
double vx_1 = speed1 * Math.cos(direction1 - colision_angle);
double vy_1 = speed1 * Math.sin(direction1 - colision_angle);
double vx_2 = speed2 * Math.cos(direction2 - colision_angle);
double vy_2 = speed2 * Math.sin(direction2 - colision_angle);
double final_vx_1 = ((ball1.radius - ball2.radius) * vx_1 + (ball2.radius + ball2.radius)
* vx_2)
/ (ball1.radius + ball2.radius);
double final_vx_2 = ((ball1.radius + ball1.radius) * vx_1 + (ball2.radius - ball1.radius)
* vx_2)
/ (ball1.radius + ball2.radius);
double final_vy_1 = vy_1;
double final_vy_2 = vy_2;
newVelX1 = (int) (Math.cos(colision_angle) * final_vx_1 + Math
.cos(colision_angle + Math.PI / 2) * final_vy_1);
newVelY1 = (int) (Math.sin(colision_angle) * final_vx_1 + Math
.sin(colision_angle + Math.PI / 2) * final_vy_1);
newVelX2 = (int) (Math.cos(colision_angle) * final_vx_2 + Math
.cos(colision_angle + Math.PI / 2) * final_vy_2);
newVelY2 = (int) (Math.sin(colision_angle) * final_vx_2 + Math
.sin(colision_angle + Math.PI / 2) * final_vy_2);
ball1.speedX = (int) newVelX1;
ball1.speedY = (int) newVelY1;
ball2.speedX = (int) newVelX2;
ball2.speedY = (int) newVelY2;
ball1.x = ball1.x + (int) newVelX1;
ball1.y = ball1.y + (int) newVelY1;
ball2.x = ball2.x + (int) newVelX2;
ball2.y = ball2.y + (int) newVelY2;
}
}
}
public static void main(String[] args) {
ElasticCollision balls = new ElasticCollision();
balls.frame.setResizable(false);
balls.frame.add(balls);
balls.frame.pack();
balls.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
balls.frame.setVisible(true);
balls.start();
}
}
class Ball {
protected int x = 0, y = 0;
protected int radius;
protected int speedX = 0, speedY = 0;
protected boolean collision = false;
protected int collisionX = 0, collisionY = 0;
protected boolean inCollision = false;
public Ball(int x, int y, int radius, int speedX, int speedY) {
this.x = x + radius;
this.y = y + radius;
this.radius = radius;
this.speedX = speedX;
this.speedY = speedY;
}
public void paint(Graphics g) {
if (!collision) {
g.setColor(Color.red);
g.fillOval(x - radius, y - radius, radius * 2, radius * 2);
} else {
g.setColor(Color.green);
g.fillOval(x - radius, y - radius, radius * 2, radius * 2);
g.setColor(Color.blue);
g.fillOval(collisionX - radius, collisionY - radius, 20, 20);
g.setColor(Color.black);
g.drawOval(collisionX - radius, collisionY - radius, 20, 20);
collision = false;
inCollision = false;
}
g.setColor(Color.black);
g.drawOval(x - radius, y - radius, radius * 2, radius * 2);
}
}
My guess is that your logic doesn't let the balls move apart once the collision is detected. Only change the direction of movement once and not every instant the balls are close to one another.

java graphics gouraud shading

I want to fill triangles with gouraud shading
I calculated normals for each vertex and used the following code but it dosn't work correctly
I interpolated colors against y using these formulas
Ir = Ir2 - (Ir2 - Ir1)* (v2.y -y)/dy;
Ig = Ig2 - (Ig2 - Ig1)* (v2.y -y)/dy;
Ib = Ib2 - (Ib2 - Ib1)* (v2.y -y)/dy;
and against x direction using
rr = r2- (r2-r1)*(Xs2-j)/dxs;
in method drawCurrentTriangle(Graphics2D g) how can i calculate color from interpolated vertex normal.(there is no lights in the scene (only triangle color))
public boolean convert(Triangle triangle) {
ensureCapacity();
clearCurrentScan();
triangle.getVlist()[0].r = triangle.normals[0].x;
triangle.getVlist()[0].g = triangle.normals[0].y;
triangle.getVlist()[0].b = triangle.normals[0].z;
triangle.getVlist()[1].r = triangle.normals[1].x;
triangle.getVlist()[1].g = triangle.normals[1].y;
triangle.getVlist()[1].b = triangle.normals[1].z;
triangle.getVlist()[2].r = triangle.normals[2].x;
triangle.getVlist()[2].g = triangle.normals[2].y;
triangle.getVlist()[2].b = triangle.normals[2].z;
for (int i = 0; i < 3; i++) {
Vector3d v1 = triangle.getVlist()[i];
Vector3d v2;
if (i == 2) {
v2 = triangle.getVlist()[0];
} else {
v2 = triangle.getVlist()[i + 1];
}
// ensure v1.y < v2.y
if (v1.y > v2.y) {
Vector3d temp = v1;
v1 = v2;
v2 = temp;
}
double dy = v2.y - v1.y;
Ir1 = v1.r;
Ig1 = v1.g;
Ib1 = v1.b;
Ir2 = v2.r;
Ig2 = v2.g;
Ib2 = v2.b;
// ignore horizontal lines
if (dy == 0) {
continue;
}
int startY = Math.max(FastMath.ceil(v1.y), minY);
int endY = Math.min(FastMath.ceil(v2.y) - 1, maxY);
top = Math.min(top, startY);
bottom = Math.max(bottom, endY);
double dx = v2.x - v1.x;
double Ir;
double Ig;
double Ib;
double Ic;
double Ia;
double Yc;
// special case: vertical line
if (dx == 0) {
int x = FastMath.ceil(v1.x);
// ensure x within view bounds
x = Math.min(maxX + 1, Math.max(x, minX));
for (int y = startY; y <= endY; y++) {
Ir = Ir2 - (Ir2 - Ir1)* (v2.y -y)/dy;
Ig = Ig2 - (Ig2 - Ig1)* (v2.y -y)/dy;
Ib = Ib2 - (Ib2 - Ib1)* (v2.y -y)/dy;
scans[y].setBoundary(x, Ir, Ig, Ib);
}
} else {
// scan-convert this edge (line equation)
double gradient = dx / dy;
// (slower version)
for (int y = startY; y <= endY; y++) {
int x = FastMath.ceil(v1.x + (y - v1.y) * gradient);
// ensure x within view bounds
x = Math.min(maxX + 1, Math.max(x, minX));
Ir = Ir2 - (Ir2 - Ir1)* (v2.y -y)/dy;
Ig = Ig2 - (Ig2 - Ig1)* (v2.y -y)/dy;
Ib = Ib2 - (Ib2 - Ib1)* (v2.y -y)/dy;
scans[y].setBoundary(x, Ir, Ig, Ib);
}
// check if visible (any valid scans)
for (int i = top; i <= bottom; i++) {
if (scans[i].isValid()) {
return true;
}
}
return false;
}
}
}
protected void drawCurrentTriangle(Graphics2D g) {
int y = scanConverter.getTopBoundary();
double Xs1 = 0;
double Xs2 = 0;
double dxs = 0;
double r1 = 0;
double g1 = 0;
double b1 = 0;
double r2 = 0;
double g2 = 0;
double b2 = 0;
double rr = 0;
double gg = 0;
double bb = 0;
while (y <= scanConverter.getBottomBoundary()) {
GouraudTriangleScanConverter.Scan scan = scanConverter.getScan(y);
if (scan.isValid()) {
r1 = scan.rL;
g1 = scan.gL;
b1 = scan.bL;
r2 = scan.rR;
g2 = scan.gR;
b2 = scan.bR;
Xs1 = scan.left;
Xs2 = scan.right;
dxs = Xs2-Xs1;
for (int j = scan.left; j < scan.right; j++) {
rr = r2- (r2-r1)*(Xs2-j)/dxs;
gg = g2- (g2-g1)*(Xs2-j)/dxs;
bb = b2- (b2-b1)*(Xs2-j)/dxs;
if(rr > 255) rr = 255;
if(gg > 255) gg = 255;
if(bb > 255) bb = 255;
g.setColor(new Color((int)rr, (int)gg, (int)bb));
g.drawLine(j,y,j,y);
}
//g.drawLine(scan.right,y,scan.right,y);
}
y++;
}
}
public static class Scan {
public int left;
public int right;
public double rL = -1;
public double gL = -1;
public double bL = -1;
public double rR = -1;
public double gR = -1;
public double bR = -1;
/**
* Sets the left and right boundary for this scan if
* the x value is outside the current boundary.
*/
public void setBoundary(int x, double r, double g, double b) {
if (x > max)
max = x;
if (x < left) {
left = x;
rL = r;
gL = g;
bL = b;
}
if (x - 1 > right) {
right = x - 1;
rR = r;
gR = g;
bR = b;
}
}
/**
* Determines if this scan is valid (if left <= right).
*/
public boolean isValid() {
return (left <= right);
}
}
how can i apply colors to mesh.when i in
fix colors(no lighting)

Point inside Oriented Bounding Box?

I have an OBB2D class based on SAT.
This is my point in OBB method:
public boolean pointInside(float x, float y)
{
float newy = (float) (Math.sin(angle) * (y - center.y) + Math.cos(angle) *
(x - center.x));
float newx = (float) (Math.cos(angle) * (x - center.x) - Math.sin(angle) *
(y - center.y));
return (newy > center.y - (getHeight() / 2)) &&
(newy < center.y + (getHeight() / 2))
&& (newx > center.x - (getWidth() / 2)) &&
(newx < center.x + (getWidth() / 2));
}
public boolean pointInside(Vector2D v)
{
return pointInside(v.x,v.y);
}
Here is the rest of the class; the parts that pertain:
public class OBB2D
{
private Vector2D projVec = new Vector2D();
private static Vector2D projAVec = new Vector2D();
private static Vector2D projBVec = new Vector2D();
private static Vector2D tempNormal = new Vector2D();
private Vector2D deltaVec = new Vector2D();
private ArrayList<Vector2D> collisionPoints = new ArrayList<Vector2D>();
// Corners of the box, where 0 is the lower left.
private Vector2D corner[] = new Vector2D[4];
private Vector2D center = new Vector2D();
private Vector2D extents = new Vector2D();
private RectF boundingRect = new RectF();
private float angle;
//Two edges of the box extended away from corner[0].
private Vector2D axis[] = new Vector2D[2];
private double origin[] = new double[2];
public OBB2D(float centerx, float centery, float w, float h, float angle)
{
for(int i = 0; i < corner.length; ++i)
{
corner[i] = new Vector2D();
}
for(int i = 0; i < axis.length; ++i)
{
axis[i] = new Vector2D();
}
set(centerx,centery,w,h,angle);
}
public OBB2D(float left, float top, float width, float height)
{
for(int i = 0; i < corner.length; ++i)
{
corner[i] = new Vector2D();
}
for(int i = 0; i < axis.length; ++i)
{
axis[i] = new Vector2D();
}
set(left + (width / 2), top + (height / 2),width,height,0.0f);
}
public void set(float centerx,float centery,float w, float h,float angle)
{
float vxx = (float)Math.cos(angle);
float vxy = (float)Math.sin(angle);
float vyx = (float)-Math.sin(angle);
float vyy = (float)Math.cos(angle);
vxx *= w / 2;
vxy *= (w / 2);
vyx *= (h / 2);
vyy *= (h / 2);
corner[0].x = centerx - vxx - vyx;
corner[0].y = centery - vxy - vyy;
corner[1].x = centerx + vxx - vyx;
corner[1].y = centery + vxy - vyy;
corner[2].x = centerx + vxx + vyx;
corner[2].y = centery + vxy + vyy;
corner[3].x = centerx - vxx + vyx;
corner[3].y = centery - vxy + vyy;
this.center.x = centerx;
this.center.y = centery;
this.angle = angle;
computeAxes();
extents.x = w / 2;
extents.y = h / 2;
computeBoundingRect();
}
//Updates the axes after the corners move. Assumes the
//corners actually form a rectangle.
private void computeAxes()
{
axis[0].x = corner[1].x - corner[0].x;
axis[0].y = corner[1].y - corner[0].y;
axis[1].x = corner[3].x - corner[0].x;
axis[1].y = corner[3].y - corner[0].y;
// Make the length of each axis 1/edge length so we know any
// dot product must be less than 1 to fall within the edge.
for (int a = 0; a < axis.length; ++a)
{
float l = axis[a].length();
float ll = l * l;
axis[a].x = axis[a].x / ll;
axis[a].y = axis[a].y / ll;
origin[a] = corner[0].dot(axis[a]);
}
}
public void computeBoundingRect()
{
boundingRect.left = JMath.min(JMath.min(corner[0].x, corner[3].x), JMath.min(corner[1].x, corner[2].x));
boundingRect.top = JMath.min(JMath.min(corner[0].y, corner[1].y),JMath.min(corner[2].y, corner[3].y));
boundingRect.right = JMath.max(JMath.max(corner[1].x, corner[2].x), JMath.max(corner[0].x, corner[3].x));
boundingRect.bottom = JMath.max(JMath.max(corner[2].y, corner[3].y),JMath.max(corner[0].y, corner[1].y));
}
public void set(RectF rect)
{
set(rect.centerX(),rect.centerY(),rect.width(),rect.height(),0.0f);
}
// Returns true if other overlaps one dimension of this.
private boolean overlaps1Way(OBB2D other)
{
for (int a = 0; a < axis.length; ++a) {
double t = other.corner[0].dot(axis[a]);
// Find the extent of box 2 on axis a
double tMin = t;
double tMax = t;
for (int c = 1; c < corner.length; ++c) {
t = other.corner[c].dot(axis[a]);
if (t < tMin) {
tMin = t;
} else if (t > tMax) {
tMax = t;
}
}
// We have to subtract off the origin
// See if [tMin, tMax] intersects [0, 1]
if ((tMin > 1 + origin[a]) || (tMax < origin[a])) {
// There was no intersection along this dimension;
// the boxes cannot possibly overlap.
return false;
}
}
// There was no dimension along which there is no intersection.
// Therefore the boxes overlap.
return true;
}
public void moveTo(float centerx, float centery)
{
float cx,cy;
cx = center.x;
cy = center.y;
deltaVec.x = centerx - cx;
deltaVec.y = centery - cy;
for (int c = 0; c < 4; ++c)
{
corner[c].x += deltaVec.x;
corner[c].y += deltaVec.y;
}
boundingRect.left += deltaVec.x;
boundingRect.top += deltaVec.y;
boundingRect.right += deltaVec.x;
boundingRect.bottom += deltaVec.y;
this.center.x = centerx;
this.center.y = centery;
computeAxes();
}
// Returns true if the intersection of the boxes is non-empty.
public boolean overlaps(OBB2D other)
{
if(right() < other.left())
{
return false;
}
if(bottom() < other.top())
{
return false;
}
if(left() > other.right())
{
return false;
}
if(top() > other.bottom())
{
return false;
}
if(other.getAngle() == 0.0f && getAngle() == 0.0f)
{
return true;
}
return overlaps1Way(other) && other.overlaps1Way(this);
}
public Vector2D getCenter()
{
return center;
}
public float getWidth()
{
return extents.x * 2;
}
public float getHeight()
{
return extents.y * 2;
}
public void setAngle(float angle)
{
set(center.x,center.y,getWidth(),getHeight(),angle);
}
public float getAngle()
{
return angle;
}
public void setSize(float w,float h)
{
set(center.x,center.y,w,h,angle);
}
public float left()
{
return boundingRect.left;
}
public float right()
{
return boundingRect.right;
}
public float bottom()
{
return boundingRect.bottom;
}
public float top()
{
return boundingRect.top;
}
public RectF getBoundingRect()
{
return boundingRect;
}
public boolean overlaps(float left, float top, float right, float bottom)
{
if(right() < left)
{
return false;
}
if(bottom() < top)
{
return false;
}
if(left() > right)
{
return false;
}
if(top() > bottom)
{
return false;
}
return true;
}
public static float distance(float ax, float ay,float bx, float by)
{
if (ax < bx)
return bx - ay;
else
return ax - by;
}
public Vector2D project(float ax, float ay)
{
projVec.x = Float.MAX_VALUE;
projVec.y = Float.MIN_VALUE;
for (int i = 0; i < corner.length; ++i)
{
float dot = Vector2D.dot(corner[i].x,corner[i].y,ax,ay);
projVec.x = JMath.min(dot, projVec.x);
projVec.y = JMath.max(dot, projVec.y);
}
return projVec;
}
public Vector2D getCorner(int c)
{
return corner[c];
}
public int getNumCorners()
{
return corner.length;
}
public boolean pointInside(float x, float y)
{
float newy = (float) (Math.sin(angle) * (y - center.y) + Math.cos(angle) *
(x - center.x));
float newx = (float) (Math.cos(angle) * (x - center.x) - Math.sin(angle) *
(y - center.y));
return (newy > center.y - (getHeight() / 2)) &&
(newy < center.y + (getHeight() / 2))
&& (newx > center.x - (getWidth() / 2)) &&
(newx < center.x + (getWidth() / 2));
}
public boolean pointInside(Vector2D v)
{
return pointInside(v.x,v.y);
}
public ArrayList<Vector2D> getCollsionPoints(OBB2D b)
{
collisionPoints.clear();
for(int i = 0; i < corner.length; ++i)
{
if(b.pointInside(corner[i]))
{
collisionPoints.add(corner[i]);
}
}
for(int i = 0; i < b.corner.length; ++i)
{
if(pointInside(b.corner[i]))
{
collisionPoints.add(b.corner[i]);
}
}
return collisionPoints;
}
};
What could be wrong? When I getCollisionPoints for 2 OBBs I know are penetrating, it returns no points.
Thanks
I also tried:
public boolean pointInside(float x, float y)
{
float xx = (x - center.x);
float yy = (y - center.y);
float newx = (float) (xx * Math.cos(angle) - yy * Math.sin(angle));
float newy = (float) (xx * Math.sin(angle) + yy * Math.cos(angle));
return (newy > center.y - (getHeight() / 2)) &&
(newy < center.y + (getHeight() / 2))
&& (newx > center.x - (getWidth() / 2)) &&
(newx < center.x + (getWidth() / 2));
}
With no luck.
I didn't read all of your class, but I'm assuming angle is the angle by which you would need to rotate your rectangle clockwise in order to make it axis-aligned.
I believe that both sin(angle) * (y-center.y) and cos(angle) * (x-center.x) are equal to the distance between your center point and the point you're testing. So newy will always equal twice that distance, and newx will always equal 0.
This is how I prefer to rotate a point about another point: get the angle and distance between the two points, then apply the rotation to the angle, then calculate the new position from the angle and distance. In pseudocode:
//takes a point and rotates it `theta` angles
//counterclockwise around the given center point
function rotateAboutPoint(x,y, centerX, centerY, theta){
radius = sqrt((centerX-x)**2 + (centerY-y)**2) //`**` is the exponentiation operator
currentAngle = atan2(y-centerY, x-centerX) //prefer `atan2` over ordinary `atan` if you can get it
newAngle = currentAngle + theta
newX = centerX + radius*cos(newAngle)
newY = centerY + radius*sin(newAngle)
return (newX, newY)
}
function pointInside(x,y){
//point must be rotated clockwise, so we provide a negative angle
newX, newY = rotateAboutPoint(x,y,center.x, center.y, -angle)
return (
newY > center.y - (getHeight() / 2) &&
newY < center.y + (getHeight() / 2) &&
newX > center.x - (getHeight() / 2) &&
newX < center.x + (getHeight() / 2) &&
)
}

Categories

Resources