package com.gebauz.bauzoid.math.collision;
import com.badlogic.gdx.Gdx;
import com.gebauz.bauzoid.graphics.Graphics;
import com.gebauz.bauzoid.graphics.sprite.SpriteTransform;
import com.gebauz.bauzoid.math.Line2;
import com.gebauz.bauzoid.math.Vector2;
import com.gebauz.bauzoid.math.collision.Shape;
/** Interface for shape element. */
public abstract class BaseShapeElement
{
// Constants========================================================================================
// Embedded Types===================================================================================
// Fields===========================================================================================
private Shape mOwner =
null;
protected Vector2
[] mProjectionAxes =
null;
protected Vector2
[] mPoints =
null;
protected Vector2
[] mUntransformedPoints =
null;
protected Line2
[] mLines =
null;
protected Line2
[] mUntransformedLines =
null;
protected Line2
[] mSweepLines =
null;
// Methods==========================================================================================
public BaseShapeElement
(Shape shape
)
{
mOwner = shape
;
}
/** Copy shape with new owner. */
public abstract BaseShapeElement copy
(Shape newOwner
);
/** Calculate intersection with a group of shape elements. */
/*public CollisionResult collide(Shape shape)
{
return collide(shape, null);
}*/
/** Calculate intersection with a group of shape elements along movement vector.
* Returns true if a collision occurs.
* resultPenetration contains the minimal penetration vector.
* resultContactPoint contains the contact point.
*/
public boolean collide
(Shape shape, Vector2 move, Vector2 resultPenetration, Vector2 resultContactPoint
)
{
//CollisionResult result = new CollisionResult();
boolean isColliding =
false;
// move
float tempX = getOwner
().
transform.
x;
float tempY = getOwner
().
transform.
y;
if (move
!=
null)
{
getOwner
().
transform.
x += move.
x;
getOwner
().
transform.
y += move.
y;
}
Vector2 contactPoint =
new Vector2
();
int numContactPoints =
0;
for (int i =
0; i
< shape.
getShapeElementCount(); i++
)
{
//Line2[] poly1 = getSweepLineSegments(move);
Line2
[] poly1 = getLineSegments
();
Vector2
[] axes1 = getProjectionAxes
();
Line2
[] poly2 = shape.
getShapeElement(i
).
getLineSegments();
Vector2
[] axes2 = shape.
getShapeElement(i
).
getProjectionAxes();
// do magic
CollisionUtil.
PenetrationResult penetrationResult = CollisionUtil.
calculatePenetration(poly1, poly2, axes1, axes2
);
if (penetrationResult.
penetrationVector !=
null)
{
isColliding =
true;
resultPenetration.
addVector(penetrationResult.
penetrationVector);
// apply correction
getOwner
().
transform.
x += penetrationResult.
penetrationVector.
x;
getOwner
().
transform.
y += penetrationResult.
penetrationVector.
y;
numContactPoints =
1;
contactPoint.
set(penetrationResult.
contactPoint);
}
}
if (isColliding
)
{
// get contact point
contactPoint.
x /= numContactPoints
;
contactPoint.
y /= numContactPoints
;
resultContactPoint.
set(contactPoint
);
}
// restore original position (result penetration vector is going to be applied outside)
getOwner
().
transform.
x = tempX
;
getOwner
().
transform.
y = tempY
;
return isColliding
;
}
/** Collide with a ray.
* Only returns a contact point, no penetration vector.
*/
public boolean collideRayCast
(Line2 ray, Vector2 resultContactPoint
)
{
Line2 lines
[] = getUntransformedLineSegments
();
float minimumDistanceSqr =
Float.
MAX_VALUE;
Vector2 contact =
null;
//Gdx.app.log("BLA", "---");
for (int i =
0; i
< lines.
length; i++
)
{
Vector2 p = ray.
getSegmentIntersection(lines
[i
]);
if (p ==
null)
continue;
Vector2 posToContact =
new Vector2
(p.
x - ray.
ax, p.
y - ray.
ay);
float distanceSqr = posToContact.
squaredLength();
if (distanceSqr
< minimumDistanceSqr
)
{
//Gdx.app.log("BLA", i + ": " + p.x + ", " + p.y);
minimumDistanceSqr = distanceSqr
;
contact = p
;
}
}
if (contact
!=
null)
{
resultContactPoint.
set(contact
);
return true;
}
return false;
}
/** Render debug output. */
public abstract void renderDebug
(Graphics graphics, SpriteTransform t
);
/** Get a list of untransformed points that make up the polygon. */
public abstract Vector2
[] getUntransformedPoints
();
/** Get a list of transformed (with the parent shape's SpriteTransform) points that make up the polygon. */
public abstract Vector2
[] getPoints
();
/** Get a list of untransformed line segments that make up the polygon. */
public abstract Line2
[] getUntransformedLineSegments
();
/** Get a list of transformed (with the parent shape's SpriteTransform) line segments that make up the polygon. */
public abstract Line2
[] getLineSegments
();
/** Get a list of transformed line segments including the swept shape. */
public abstract Line2
[] getSweepLineSegments
(Vector2 move
);
/** Get all vectors for all distinct projection axes for separating axis theorem. */
public abstract Vector2
[] getProjectionAxes
();
// Getters/Setters==================================================================================
public final void setOwner
(Shape shape
)
{
mOwner = shape
;
}
public final Shape getOwner
()
{
return mOwner
;
}
public final SpriteTransform getTransform
()
{
return mOwner.
transform;
}
public final Vector2 getCenter
()
{
Vector2 result =
new Vector2
();
Vector2
[] points = getPoints
();
for (int i =
0; i
< points.
length; i++
)
{
result.
addVector(points
[i
]);
}
result.
x /= points.
length;
result.
y /= points.
length;
return result
;
}
}