Mirror Body built with vertexes in box2d and libgdx - java

How can I mirror the fixture of a body in one axis(x or y), because when I want to mirror it only in one, an assertion error occurs, but when i mirror it in the two axis, no problem occur.
public Vector2[][] getPolygons(String bodyName, float scaleX, float scaleY)
{
Vector2[][] vectors = null;
Element fixture;
Element semiPolygon;
float auxX, auxY;
this.element = reader.parse(xml);
fixture = this.element.getChildByName(bodyName);
vectors = new Vector2[fixture.getChildCount()][];
for(int child = 0; child < fixture.getChildCount(); child++)
{
semiPolygon = fixture.getChild(child);
vectors[child] = new Vector2[semiPolygon.getChildCount()];
for(int part = 0; part < semiPolygon.getChildCount(); part++)
{
auxX = semiPolygon.getChild(part).getFloatAttribute("x")*-scaleX;
auxY = semiPolygon.getChild(part).getFloatAttribute("y")*-scaleY;
vectors[child][part] = World.toGameCoordinates(auxX, auxY);
}
}
return vectors;
}

Polygon vertices must be specified in counter clockwise order. Each time the shape is mirrored the winding order is reversed, so with only one mirror the order will be backwards, then if you mirror it again it will be ok, as you have discovered. So if you only mirror over one axis, you'll need to reverse the order of the vertices.

Related

How should I be implementing a view clipping plane in a 3D Engine?

This project is written entirely from scratch in Java. I've just been bored ever since Covid started, so I wanted something that would take up my time, and teach me something cool. I've been stuck on this problem for about a week now though. When I try to use my near plane clipping method it skews the new vertices to the opposite side of the screen, but sometimes times it works just fine.
Failure Screenshot
Success Screenshot
So my thought is maybe that since it works sometimes, I'm just not doing the clipping at the correct time in the pipeline?
I start by face culling and lighting,
Then I apply a Camera View Transformation to the Vertices,
Then I clip on the near plane
Finally I apply the projection matrix and Clip any remaining off screen Triangles
Code:
This calculates the intersection points. Sorry if it's messy or to long I'm not very experienced in coding, my major is physics, not CS.
public Vertex vectorIntersectPlane(Vector3d planePos, Vector3d planeNorm, Vector3d lineStart, Vector3d lineEnd){
float planeDot = planeNorm.dotProduct(planePos);
float startDot = lineStart.dotProduct(planeNorm);
float endDot = lineEnd.dotProduct(planeNorm);
float midPoint = (planeDot - startDot) / (endDot - startDot);
Vector3d lineStartEnd = lineEnd.sub(lineStart);
Vector3d lineToIntersect = lineStartEnd.scale(midPoint);
return new Vertex(lineStart.add(lineToIntersect));
}
public float distanceFromPlane(Vector3d planePos, Vector3d planeNorm, Vector3d vert){
float x = planeNorm.getX() * vert.getX();
float y = planeNorm.getY() * vert.getY();
float z = planeNorm.getZ() * vert.getZ();
return (x + y + z - (planeNorm.dotProduct(planePos)));
}
//When a triangle gets clipped it has 4 possible outcomes
// 1 it doesn't actually need clipping and gets returned
// 2 it gets clipped into 1 new triangle, for testing these are red
// 3 it gets clipped into 2 new triangles, for testing 1 is green, and 1 is blue
// 4 it is outside the view planes and shouldn't be rendered
public void clipTriangles(){
Vector3d planePos = new Vector3d(0, 0, ProjectionMatrix.fNear, 1f);
Vector3d planeNorm = Z_AXIS.clone();
final int length = triangles.size();
for(int i = 0; i < length; i++) {
Triangle t = triangles.get(i);
if(!t.isDraw())
continue;
Vector3d[] insidePoint = new Vector3d[3];
int insidePointCount = 0;
Vector3d[] outsidePoint = new Vector3d[3];
int outsidePointCount = 0;
float d0 = distanceFromPlane(planePos, planeNorm, t.getVerticesVectors()[0]);
float d1 = distanceFromPlane(planePos, planeNorm, t.getVerticesVectors()[1]);
float d2 = distanceFromPlane(planePos, planeNorm, t.getVerticesVectors()[2]);
//Storing distances from plane and counting inside outside points
{
if (d0 >= 0){
insidePoint[insidePointCount] = t.getVerticesVectors()[0];
insidePointCount++;
}else{
outsidePoint[outsidePointCount] = t.getVerticesVectors()[0];
outsidePointCount++;
}
if (d1 >= 0){
insidePoint[insidePointCount] = t.getVerticesVectors()[1];
insidePointCount++;
}else{
outsidePoint[outsidePointCount] = t.getVerticesVectors()[1];
outsidePointCount++;
}
if (d2 >= 0){
insidePoint[insidePointCount] = t.getVerticesVectors()[2];
insidePointCount++;
}else{
outsidePoint[outsidePointCount] = t.getVerticesVectors()[2];
}
}
//Triangle has 1 point still inside view, remove original triangle add new clipped triangle
if (insidePointCount == 1) {
t.dontDraw();
Vertex newVert1 = vectorIntersectPlane(planePos, planeNorm, insidePoint[0], outsidePoint[0]);
Vertex newVert2 = vectorIntersectPlane(planePos, planeNorm, insidePoint[0], outsidePoint[1]);
vertices.add(newVert1);
vertices.add(newVert2);
//Triangles are stored with vertex references instead of the actual vertex object.
Triangle temp = new Triangle(t.getVertKeys()[0], vertices.size() - 2, vertices.size() - 1, vertices);
temp.setColor(1,0,0, t.getBrightness(), t.getAlpha());
triangles.add(temp);
continue;
}
//Triangle has two points inside remove original add two new clipped triangles
if (insidePointCount == 2) {
t.dontDraw();
Vertex newVert1 = vectorIntersectPlane(planePos, planeNorm, insidePoint[0], outsidePoint[0]);
Vertex newVert2 = vectorIntersectPlane(planePos, planeNorm, insidePoint[1], outsidePoint[0]);
vertices.add(newVert1);
vertices.add(newVert2);
Triangle temp = new Triangle(t.getVertKeys()[0], t.getVertKeys()[1], vertices.size() - 1, vertices);
temp.setColor(0, 1, 0, t.getBrightness(), t.getAlpha());
triangles.add(temp);
temp = new Triangle(t.getVertKeys()[0], t.getVertKeys()[1], vertices.size() - 2, vertices);
temp.setColor(0, 0, 1, t.getBrightness(), t.getAlpha());
triangles.add(temp);
continue;
}
}
}
I figured out the problem, The new clipped triangles were not being given the correct vertex references. they were just being given the first vertex of the triangle irregardless of if that was inside the view or not.

Java - How to check if a lat/lng coords are inside a polygon

I want to check if a given point on a map (with its latitude and longitude) is inside a certain polygon. I have the vertex coords (in lat/long) of the polygon.
I thought of creating a Polygon and check if point is inside, but it gives me that the point is always outside... Maybe the polygon does not work with georeferential coords?
Double[] xCoords = {40.842226, 40.829498, 40.833394, 40.84768, 40.858716}
Double[] yCoords = {14.211753, 14.229262, 14.26617, 14.278701, 14.27715}
Double[] myPoint = {40.86141, 14.279932};
Path2D myPolygon = new Path2D.Double();
myPolygon.moveTo(xCoords[0], yCoords[0]); //first point
for(int i = 1; i < xCoords.length; i ++) {
myPolygon.lineTo(xCoords[i], yCoords[i]); //draw lines
}
myPolygon.closePath(); //draw last line
if(myPolygon.contains(myPoint{0}, myPoint{1})) {
//it's inside;
}
This is how it looks like in google maps
It always return false... but the point it's inside the polygon...
That point can't possibly be contained in that polygon, no matter what shape the polygon has.
Your right-most coordinate is at 40.858716 while the point has an x value of 40.86141, this means that the point lies on the right of your polygon. Same for y, max y coordinate in the polygon is 14.278701 while the point is at 14.279932. This means that the point is outside.
Also, you're inverting the coordinates, the coordinates of our beloved city are 40.8518° N, 14.2681° E, this means that 40 is the y and 14 the x.
Path2D will do just fine. My observation just tells you that the point is not in the polygon but checking the extremes is not a general solution for verifying that a point is inside a polygon.
public class CoordinatesDTO {
private Long id;
private double latitude;
private double longnitude;
}
public static boolean isLocationInsideTheFencing(CoordinatesDTO location, List<CoordinatesDTO> fencingCoordinates) { //this is important method for Checking the point exist inside the fence or not.
boolean blnIsinside = false;
List<CoordinatesDTO> lstCoordinatesDTO = fencingCoordinates;
Path2D myPolygon = new Path2D.Double();
myPolygon.moveTo(lstCoordinatesDTO.get(0).getLatitude(), lstCoordinatesDTO.get(0).getLongnitude()); // first
// point
for (int i = 1; i < lstCoordinatesDTO.size(); i++) {
myPolygon.lineTo(lstCoordinatesDTO.get(i).getLatitude(), lstCoordinatesDTO.get(i).getLongnitude()); // draw
// lines
}
myPolygon.closePath(); // draw last line
// myPolygon.contains(p);
Point2D P2D2 = new Point2D.Double();
P2D2.setLocation(location.getLatitude(), location.getLongnitude());
if (myPolygon.contains(P2D2)) {
blnIsinside = true;
} else {
blnIsinside = false;
}
return blnIsinside;
}

Catmull Rom Spline implementation (LibGDX)

I want to generate a random spline across my screen.
Here is what I have so far:
public class CurvedPath {
Random rn;
CatmullRomSpline<Vector2> curve;
float[] xPts;
float[] yPts;
Vector2[] points;
public CurvedPath(){
points = new Vector2[10];
rn = new Random();
curve = new CatmullRomSpline<Vector2>(points,false);
for(int i = 0 ; i < 10; i++){
xPts[i] = rn.nextFloat()*SampleGame.WIDTH;
yPts[i] = SampleGame.HEIGHT*i/10;
}
}
}
I'm pretty confused on the documentation that has been provided on how to use the CatmullRomSpline object ( https://github.com/libgdx/libgdx/wiki/Path-interface-&-Splines )
Basically what I am trying to do here is generate 10 random points equally distributed across the height of my screen, and randomly placed along the width of the screen to create a randomized curved path.
So within the constructor's for loop you can see that I generate the x and y values of each control point for the spline.
How can I give input these points into the spline object and render it on the screen?
-thanks
update
Let me reword my question to be a little more specific..
I have my control points represented by xPts and yPts. Now I want to get the points that fall along the spline, how do I do this using these two vectors? The constructor for a CatmullRomSpline takes a Vector2, not two float[] 's
what you did. Fill with points:
curve = new CatmullRomSpline<Vector2>(points,false);
To get a point on the curve:
Vector2 point = new Vector2();
curve.valueAt(point, 0.5f);
valueAt() Parameter explanation:
1 (point) the point you are looking for is stored in the Vector2 object.
float between 0 and 1, 0 is the first point, 1 the last one. 0.5f is middle. This float represents the hole distance from first to last point.
Getting and render 100 points can look like this:
Vector2 point = new Vector2();
for (int i = 0; i <= 100; i++) {
curve.valueAt(point, i * 0.01f);
// draw using point.x and point.y
}
answer to you edited question:
for(int i = 0 ; i < 10; i++){
points[i].x = rn.nextFloat()*SampleGame.WIDTH;
points[i].y = SampleGame.HEIGHT*i/10;
}
curve = new CatmullRomSpline<Vector2>(points,false);
The process is also detailed here: https://github.com/libgdx/libgdx/wiki/Path-interface-&-Splines
/*members*/
int k = 100; //increase k for more fidelity to the spline
Vector2[] points = new Vector2[k];
/*init()*/
CatmullRomSpline<Vector2> myCatmull = new CatmullRomSpline<Vector2>(dataSet, true);
for(int i = 0; i < k; ++i)
{
points[i] = new Vector2();
myCatmull.valueAt(points[i], ((float)i)/((float)k-1));
}

Use an ArrayList to display multiple vector Objects Java

I'm creating a Ray Tracer in java and I just need to print out each of the three Spheres that I have made.
I created 3 sphere objects and stored them in an arraylist in my main which I am now passing to my camera so that I can create an image.
To do this I need to figure out:
If the intersection point isn't null, get the distance between the ray's origin and the intersection point.
If this is the first sphere in inner loop, set a variable to this distance – if not see if this distance is less than the previously measured distance – if so save this distance to compare to other spheres and set the index of the closest sphere to the index of the sphere being evaluated (the counter used in the inner loop going through the spheres).
Outside of this inner loop write the pixel back to the buffered image – but when calling
localReflectionModel use the sphere that is closest (using the index of the closest sphere you saved in the inner loop).
Code:
for(int x = 0; x < filmResolutionX; x++) {
for(int y =0; y < filmResolutionY; y++) {
for (int z = 0; z < s.size(); z++) {
double planeX = -0.5+ x / (double) filmResolutionX;
double planeY = 0.5 - y / (double) filmResolutionY;
double planeZ = 1;
Coord3D planes = new Coord3D(planeX, planeY, planeZ);
Coord3D Origin = new Coord3D(0,0,0);
Ray plane = new Ray(Origin, planes);
Coord3D iPoint = plane.intersectionPoint(s.get(z));
Color colorSphere = new Color(0xD72448);
if (iPoint != null){
double distance = plane.getOrigin().distanceBetween(iPoint);
}
if (z == 0) {
double distanceCheck1 = plane.getOrigin().distanceBetween(iPoint);
} else if (z != 0) {
}
if (iPoint == null) {
newImage.setRGB(x, y, 0);
} else {
colorSphere = s.get(z).localReflectionModel(iPoint, l, plane);
int rgb = colorSphere.getRGB();
newImage.setRGB(x, y, rgb);
}
}
}
}
return newImage;
}
}
I am having problems trying to compare the distances from the previous spheres. When I try to reference the variables distance or distance check 1 I get an error saying that distance cannot be resolved to a variable
It looks like you're having difficulties with scope.
If you declare variables inside a block, like you do in the case of if (something) { double x = ...; }, the variables are visible only inside the declared block.
If you later want to access these variables, you have to change the scope so that they are visible in the block you want to use them in. Of course you could just declare them at the global level, but the art lies in finding the smallest effective scope.

How to avoid overlapping polygon

I created a program to draw many polygons automatically everytimes user presses a button. The points of the polygon are generated automatically using the random function. The problem is that, since the points of the polygon were randomly generated, some of the polygon are overlap with other polygon. How can I avoid this, so that every polygon shown without being overlapped?
.....
List<Polygon> triangles = new LinkedList<Polygon>();
Random generator = new Random();
public void paintComponent(Graphics g) {
for(int i = 0; i < 10; i++) {
double xWidth = generator.nextDouble() * 40.0 + 10.0;
double yHeight = generator.nextDouble() * 40.0 + 10.0;
xCoord[0] = generator.nextInt(MAX_WIDTH);
yCoord[0] = generator.nextInt(MAX_HEIGHT);
xCoord[1] = (int) (xCoord[0] - xWidth);
xCoord[2] = (int) (xCoord[1] + (xWidth/2));
yCoord[1] = yCoord[0];
yCoord[2] = (int) (yCoord[1] - yHeight);
triangles.add( new Polygon(xCoord,yCoord, 3));
}
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(1));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.00f));
g2.setPaint(Color.black);//set the polygon line
for (Polygon triangle : triangles) g2.drawPolygon(triangle);
Polygon[] triArray = triangles.toArray(new Polygon[triangles.size()]);
for (Polygon p:triArray) triangles.remove (p);
}
Check out the game programming wiki on Polygon Collision:
http://gpwiki.org/index.php/Polygon_Collision
You could break your canvas into 10 regions and constrain your polygons each to their own region. To do this, you could use your i value and a %100 (or other suitable magnitude) of your randomly generated value and apply them to your x coordinates and y coordinates as applicable. The result would be a grid of similarly constrained(no larger than the grid cell), but randomly shaped, Polygons.
EDIT:
Taking another look and fooling around a bit, I took the general concept as I described above and made a stab at an implementation:
public void paintComponent(Graphics g) {
int[] xCoord = new int[3];
int[] yCoord = new int[3];
int colCnt = 5;
int rowCnt = 2;
int maxCellWidth = getWidth() / colCnt;
int maxCellHeight = getHeight() / rowCnt;
for (int i = 0; i < (colCnt * rowCnt); i++) {
int xMultiple = i % colCnt;
int yMultiple = i / colCnt;
for (int j = 0; j < 3; j++) {
xCoord[j] = generator.nextInt(maxCellWidth)
+ (maxCellWidth * xMultiple);
yCoord[j] = generator.nextInt(maxCellHeight)
+ (maxCellHeight * yMultiple);
}
triangles.add(new Polygon(xCoord, yCoord, 3));
}
//... the rest of your method
}
As you can see, all of the Polygons have all points randomly generated, as opposed to your method of generating the first point and then making the rest relative to the first. There is a sense of randomness that is lost, however, as the Polygons are laid out in a grid-like pattern.
Create Area objects from your new polygon as well as for all existing polygons.
Subtract the new polygon's area from the existing ones. If the subtract changed the area, the polygons overlap.
Area newArea = new Area(newPolygon);
Area existingArea = new Area(existingPolygon);
Area existingAreaSub = new Area(existingPolygon); existingAreaSub.subtract(newArea);
boolean intersects = existingAreaSub.equals(existingArea);
You could implement a method Polycon.containsPoint( x, y ) and repeat your random generation until this method returns false for all drawn Polygons.
I have achieved this in Android Using Kotlin (See github project) by using JTS see here
Step-1:
Add JTS library to your project
implementation group: 'org.locationtech.jts', name: 'jts-core', version: '1.15.0'
Step-2:
Create JTS polygon objects for both polygon
// create polygons One
var polygoneOneArray: ArrayList<Coordinate> = ArrayList()
for (points in polygonOnePointsList) {
polygoneOneArray.add(Coordinate(points.latitude(), points.longitude()))
}
val polygonOne: org.locationtech.jts.geom.Polygon = GeometryFactory().createPolygon(
polygoneOneArray.toTypedArray()
)
// create polygons Two
var polygoneTwoArray: ArrayList<Coordinate> = ArrayList()
for (points in polygoneTwoPointsList) {
polygoneTwoArray.add(Coordinate(points.latitude(), points.longitude()))
}
val polygonTwo: org.locationtech.jts.geom.Polygon = GeometryFactory().createPolygon(
polygoneTwo.toTypedArray()
)
Step-3:
Get Common Area of both Polygon
val intersection: org.locationtech.jts.geom.Geometry = polygonOne.intersection(polygonTwo)
Step-4:
Remove common Area from polygonTwo
val difference: org.locationtech.jts.geom.Geometry = polygonTwo.difference(intersection)
Step-5:
Merge Both polygonOne and update polygonTwo
val union: org.locationtech.jts.geom.Geometry = mergePolygonList.get(0).polygons.union(difference)
Step-5:
Now pick points from Geometry and draw a final merged Polygon
val array: ArrayList<Coordinate> = union.coordinates.toList() as ArrayList<Coordinate>
val pointList: ArrayList<Point> = ArrayList()
for (item in array) {
pointList.add(Point.fromLngLat(item.y, item.x))
}
var list: ArrayList<List<Point>> = ArrayList<List<Point>>()
list.add(pointList)
style.addSource(
GeoJsonSource(
"source-id${timeStamp}",
Feature.fromGeometry(Polygon.fromLngLats(list))
)
)

Categories