/** * 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; public class PConvexPolygonShape extends PShape { Vector2f[] localNors; Vector2f[] localVers; Vector2f[] nors; int numVertices; Vector2f[] vers; public PConvexPolygonShape(float xvers[], float yvers[], float density) { float xs[] = xvers; float ys[] = yvers; numVertices = xs.length; _dens = density; localVers = new Vector2f[numVertices]; nors = new Vector2f[numVertices]; float fakeCenterY; float fakeCenterX = fakeCenterY = 0.0F; for (int i = 0; i < numVertices; i++) { fakeCenterX += xs[i]; fakeCenterY += ys[i]; } fakeCenterX /= numVertices; fakeCenterY /= numVertices; for (int i = 0; i < numVertices; i++) { localVers[i] = new Vector2f(xs[i] - fakeCenterX, ys[i] - fakeCenterY); nors[i] = new Vector2f(); } vers = new Vector2f[numVertices]; for (int j = 0; j < localVers.length; j++) { mm += localVers[j].cross(localVers[(j + 1) % numVertices]) * 0.5F; } float cy; float cx = cy = 0.0F; float invThree = 0.3333333F; for (int j = 0; j < localVers.length; j++) { Vector2f ver = localVers[j]; Vector2f nextVer = localVers[(j + 1) % numVertices]; float triArea = ver.cross(nextVer) * 0.5F; cx += triArea * (ver.x + nextVer.x) * invThree; cy += triArea * (ver.y + nextVer.y) * invThree; } float invM = 1.0F / mm; cx *= invM; cy *= invM; cx += fakeCenterX; cy += fakeCenterY; for (int i = 0; i < numVertices; i++) { localVers[i].x += fakeCenterX; localVers[i].y += fakeCenterY; } _localPos.set(cx, cy); for (int i = 0; i < numVertices; i++) { vers[i] = new Vector2f(localVers[i].x, localVers[i].y); } for (int i = 0; i < numVertices; i++) { localVers[i].subLocal(_localPos); } float invSix = 0.1666667F; for (int j = 0; j < localVers.length; j++) { Vector2f ver = localVers[j]; Vector2f nextVer = localVers[(j + 1) % numVertices]; float triArea = ver.cross(nextVer) * 0.5F; this.ii += triArea * invSix * (ver.x * ver.x + ver.y * ver.y + ver.x * nextVer.x + ver.y * nextVer.y + nextVer.x * nextVer.x + nextVer.y * nextVer.y); } localNors = new Vector2f[numVertices]; for (int i = 0; i < numVertices; i++) { Vector2f ver = localVers[i]; Vector2f nextVer = localVers[(i + 1) % localVers.length]; localNors[i] = new Vector2f(nextVer.y - ver.y, -nextVer.x + ver.x); localNors[i].normalize(); } _type = PShapeType.CONVEX_SHAPE; setDensity(_dens); calcAABB(); } void calcAABB() { float miny; float maxx; float maxy; float minx = miny = maxx = maxy = 0.0F; for (int i = 0; i < numVertices; i++) { Vector2f vertex = vers[i]; if (i == 0) { minx = vertex.x; miny = vertex.y; maxx = vertex.x; maxy = vertex.y; } else { minx = minx <= vertex.x ? minx : vertex.x; miny = miny <= vertex.y ? miny : vertex.y; maxx = maxx >= vertex.x ? maxx : vertex.x; maxy = maxy >= vertex.y ? maxy : vertex.y; } } _aabb.set(minx, miny, maxx, maxy); } public Vector2f[] getVertices() { Vector2f[] vertices = new Vector2f[numVertices]; System.arraycopy(vers, 0, vertices, 0, numVertices); return vertices; } void 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); nors[i].set(localNors[i].x, localNors[i].y); _mAng.mulEqual(nors[i]); } } }