/** * Copyright 2013 The Loon Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package loon.physics; import loon.geom.Vector2f; import loon.utils.CollectionUtils; import loon.utils.MathUtils; public class PConcavePolygonShape extends PShape { PConvexPolygonShape[] convexes; Vector2f[] localVers; int numConvexes; int numVertices; PPolygonizer poly; PFigure fig; PTriangulator tri; Vector2f[] vers; public PConcavePolygonShape(float[] xvers, float[] yvers, float density) { fig = new PFigure(); tri = new PTriangulator(); poly = new PPolygonizer(); numVertices = xvers.length; localVers = new Vector2f[numVertices]; vers = new Vector2f[numVertices]; _dens = density; for (int i = 0; i < numVertices; i++) { localVers[i] = new Vector2f(xvers[i], yvers[i]); vers[i] = new Vector2f(xvers[i], yvers[i]); } fig.figure(localVers, numVertices); numVertices = fig.numVertices; localVers = new Vector2f[numVertices]; vers = new Vector2f[numVertices]; for (int i = 0; i < numVertices; i++) { localVers[i] = new Vector2f(fig.done[i].x, fig.done[i].y); vers[i] = new Vector2f(fig.done[i].x, fig.done[i].y); } tri.triangulate(fig.done, fig.numVertices); poly.polygonize(tri.triangles, tri.numTriangles); convexes = new PConvexPolygonShape[1024]; for (int i = 0; i < poly.numPolygons; i++) { convexes[i] = new PConvexPolygonShape(poly.polygons[i].xs, poly.polygons[i].ys, _dens); } numConvexes = poly.numPolygons; calcMassData(); _type = PShapeType.CONCAVE_SHAPE; } void calcAABB() { for (int i = 0; i < numConvexes; i++) { PConvexPolygonShape c = convexes[i]; c.calcAABB(); c._sapAABB.update(); if (i == 0) { _aabb.set(c._aabb.minX, c._aabb.minY, c._aabb.maxX, c._aabb.maxY); } else { _aabb.set(MathUtils.min(_aabb.minX, c._aabb.minX), MathUtils.min(_aabb.minY, c._aabb.minY), MathUtils.max(_aabb.maxX, c._aabb.maxX), MathUtils.max(_aabb.maxY, c._aabb.maxY)); } } } private void calcMassData() { correctCenterOfGravity(); mm = ii = 0.0F; for (int j = 0; j < numConvexes; j++) { mm += convexes[j].mm * convexes[j]._dens; ii += convexes[j].ii * convexes[j]._dens; ii += (convexes[j]._localPos.x * convexes[j]._localPos.x + convexes[j]._localPos.y * convexes[j]._localPos.y) * convexes[j].mm * convexes[j]._dens; } } private void correctCenterOfGravity() { float cy; float cx = cy = 0.0F; float total = 0.0F; for (int j = 0; j < numConvexes; j++) { total += convexes[j].mm * convexes[j]._dens; cx += convexes[j]._localPos.x * convexes[j].mm * convexes[j]._dens; cy += convexes[j]._localPos.y * convexes[j].mm * convexes[j]._dens; } if (numConvexes > 0) { total = 1.0F / total; cx *= total; cy *= total; } _localPos.x += cx; _localPos.y += cy; for (int i = 0; i < numVertices; i++) { localVers[i].x -= cx; localVers[i].y -= cy; } for (int j = 0; j < numConvexes; j++) { convexes[j]._localPos.x -= cx; convexes[j]._localPos.y -= cy; } } public PConvexPolygonShape[] getConvexes() { return CollectionUtils.copyOf(convexes, numConvexes); } public Vector2f[] getVertices() { Vector2f[] vertices = new Vector2f[numVertices]; System.arraycopy(vers, 0, vertices, 0, numVertices); return vertices; } void update() { float twoPI = MathUtils.TWO_PI; for (int i = 0; i < numConvexes; i++) { PConvexPolygonShape c = convexes[i]; c._pos.set(c._localPos.x, c._localPos.y); _mAng.mulEqual(c._pos); c._pos.addSelf(_pos); c._localAng = (c._localAng + twoPI) % twoPI; c._ang = _ang + c._localAng; c._mAng.setRotate(c._ang); c.update(); } for (int i = 0; i < numVertices; i++) { vers[i].set(localVers[i].x, localVers[i].y); _mAng.mulEqual(vers[i]); vers[i].addSelf(_pos); } } }