1 /**
  2  * The Render Engine
  3  * ConvexHull
  4  *
  5  * @fileoverview A collision shape which represents a convex hull.
  6  *
  7  * @author: Brett Fattori (brettf@renderengine.com)
  8  *
  9  * @author: $Author: bfattori $
 10  * @version: $Revision: 1555 $
 11  *
 12  * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com)
 13  *
 14  * Permission is hereby granted, free of charge, to any person obtaining a copy
 15  * of this software and associated documentation files (the "Software"), to deal
 16  * in the Software without restriction, including without limitation the rights
 17  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 18  * copies of the Software, and to permit persons to whom the Software is
 19  * furnished to do so, subject to the following conditions:
 20  *
 21  * The above copyright notice and this permission notice shall be included in
 22  * all copies or substantial portions of the Software.
 23  *
 24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 27  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 28  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 29  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 30  * THE SOFTWARE.
 31  *
 32  */
 33 
 34 // The class this file defines and its required classes
 35 R.Engine.define({
 36     "class":"R.collision.ConvexHull",
 37     "requires":[
 38         "R.engine.PooledObject",
 39         "R.math.Rectangle2D",
 40         "R.math.Point2D",
 41         "R.math.Vector2D",
 42         "R.math.Math2D"
 43     ]
 44 });
 45 
 46 /**
 47  * @class A convex hull with which to perform collision testing.  A convex hull
 48  *        is a simplification of the points which either comprise an object, or
 49  *        the points around an object.  There are two simplified hull types which
 50  *        can also be used: {@link R.collision.OBBHull} and {@link R.collision.CircleHull}
 51  *
 52  * @param points {Array} An array of {@link R.math.Point2D} which make up the shape to
 53  *       create the hull from.
 54  * @param [lod] {Number} The level of detail for the hull.  Larger numbers make for a more
 55  *       complex hull.  Points will not be created if the number of points availble is
 56  *       less than the LOD.  Default: 4
 57  *
 58  * @extends R.engine.PooledObject
 59  * @constructor
 60  * @description Create a polygonal convex hull which has, at most, <tt>lod</tt> vertexes.
 61  */
 62 R.collision.ConvexHull = function () {
 63     "use strict";
 64     return R.engine.PooledObject.extend(/** @scope R.collision.ConvexHull.prototype */{
 65 
 66         oCenter:null,
 67         oVerts:null,
 68         uVerts:null,
 69         center:null,
 70         vertexes:null,
 71         hostObj:null,
 72 
 73         radius:-1,
 74 
 75         /** @private */
 76         constructor:function (points, lod) {
 77             this.base("ConvexHull");
 78             lod = lod || 4;
 79 
 80             // Calculate the center and radius based on the given points
 81             var cX = 0, cY = 0;
 82             var x1 = R.lang.Math2.MAX_INT, x2 = -R.lang.Math2.MAX_INT;
 83             var y1 = x1, y2 = x2;
 84             for (var p = 0; p < points.length; p++) {
 85                 cX += points[p].x;
 86                 cY += points[p].y;
 87             }
 88             this.center = R.math.Point2D.create(cX / points.length, cY / points.length);
 89             this.oCenter = R.math.Point2D.create(this.center);
 90 
 91             // Back through the points again to find the point farthest from the center
 92             // to create our smallest radius which encloses our shape
 93             var dist = -1;
 94             var rVec = R.math.Vector2D.create(0, 0);
 95             var d = R.math.Vector2D.create(0, 0);
 96             for (p = 0; p < points.length; p++) {
 97                 d.set(points[p]);
 98                 d.sub(this.center);
 99                 if (d.len() > dist) {
100                     dist = d.len();
101                     rVec.set(d);
102                 }
103             }
104             d.destroy();
105             this.radius = rVec.len();
106             rVec.destroy();
107 
108             // Create the simplified hull
109             this.vertexes = R.math.Math2D.convexHull(points, lod);
110             this.oVerts = [];
111             this.uVerts = [];
112             for (p in this.vertexes) {
113                 this.oVerts.push(R.math.Vector2D.create(this.vertexes[p]));
114                 this.uVerts.push(R.math.Vector2D.create(this.vertexes[p]).sub(this.center));
115             }
116         },
117 
118         /**
119          * Destroy the object
120          */
121         destroy:function () {
122             // Destroy the center
123             this.oCenter.destroy();
124             this.center.destroy();
125 
126             // Destroy the verts
127             for (var v in this.vertexes) {
128                 this.vertexes[v].destroy();
129                 this.oVerts[v].destroy();
130                 this.uVerts[v].destroy();
131             }
132 
133             this.base();
134         },
135 
136         /**
137          * Return the object to the pool
138          */
139         release:function () {
140             this.base();
141 
142             // Free the matrices
143             this.txfm = null;
144 
145             // Free the verts and center
146             this.hostObj = null;
147             this.center = null;
148             this.oCenter = null;
149             this.vertexes = null;
150             this.oVerts = null;
151             this.uVerts = null;
152         },
153 
154         /**
155          * Deprecated in favor of {@link #setGameObject}
156          * @deprecated
157          */
158         setHostObject:function (obj) {
159             this.setGameObject(obj);
160         },
161 
162         /**
163          * Set the object which is using this collision hull.
164          *
165          * @param hostObj {R.objects.Object2D} The object which is using the hull
166          */
167         setGameObject:function (gameObject) {
168             this.hostObj = gameObject;
169         },
170 
171         /**
172          * Deprecated in favor of {@link #getGameObject}.
173          * @deprecated
174          */
175         getHostObject:function () {
176             return this.getGameObject();
177         },
178 
179         /**
180          * Get the object which is using this collision hull.
181          * @return {R.objects.Object2D}
182          */
183         getGameObject:function () {
184             return this.hostObj;
185         },
186 
187         /**
188          * Get the point at the center of the convex hull
189          * @return {R.math.Point2D}
190          */
191         getCenter:function () {
192             var txfm = this.hostObj.getTransformationMatrix();
193 
194             // Transform the center of the hull
195             this.center.set(this.oCenter);
196             this.center.transform(txfm);
197             return this.center;
198         },
199 
200         /**
201          * Get the radius (distance to farthest point in shape, from center)
202          * @return {Number}
203          */
204         getRadius:function () {
205             return this.radius;
206         },
207 
208         /**
209          * Get the array of vertexes in the convex hull
210          * @return {Array} of {@link R.math.Point2D}
211          */
212         getVertexes:function () {
213             var txfm = this.hostObj.getTransformationMatrix();
214 
215             // Transform the vertexes
216             for (var p = 0; p < this.vertexes.length; p++) {
217                 this.vertexes[p].set(this.oVerts[p]);
218                 this.vertexes[p].transform(txfm);
219             }
220             return this.vertexes;
221         },
222 
223         /**
224          * Get the array of untransformed vertexes in the convex hull
225          * @return {Array} of {@link R.math.Point2D}
226          */
227         getUntransformedVertexes:function () {
228             return this.uVerts;
229         },
230 
231         /**
232          * Return the type of convex hull this represents.
233          * @return {Number} {@link #CONVEX_NGON}
234          */
235         getType:function () {
236             return R.collision.ConvexHull.CONVEX_NGON;
237         }
238 
239     }, /** @scope R.collision.ConvexHull.prototype */{
240 
241         /**
242          * Get the class name of this object
243          * @return {String} "R.collision.ConvexHull"
244          */
245         getClassName:function () {
246             return "R.collision.ConvexHull";
247         },
248 
249         /**
250          * An N-gon convex hull shape (3 or more vertexes)
251          * @type {Number}
252          */
253         CONVEX_NGON:1,
254 
255         /**
256          * A circular convex hull shape (center and radius)
257          * @type {Number}
258          */
259         CONVEX_CIRCLE:2
260     });
261 
262 };