/* * Copyright (c) 2006-2007 Erin Catto http: * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked, and must not be * misrepresented the original software. * 3. This notice may not be removed or altered from any source distribution. */ // Shapes are created automatically when a body is created. // Client code does not normally interact with shapes. var b2Shape = Class.create(); b2Shape.prototype = { TestPoint: function(p){return false}, GetUserData: function(){return this.m_userData;}, GetType: function(){ return this.m_type; }, // Get the parent body of this shape. GetBody: function(){ return this.m_body; }, GetPosition: function(){ return this.m_position; }, GetRotationMatrix: function(){ return this.m_R; }, // Remove and then add proxy from the broad-phase. // This is used to refresh the collision filters. ResetProxy: function(broadPhase){}, // Get the next shape in the parent body's shape list. GetNext: function(){ return this.m_next; }, //--------------- Internals Below ------------------- initialize: function(def, body){ // initialize instance variables for references this.m_R = new b2Mat22(); this.m_position = new b2Vec2(); // this.m_userData = def.userData; this.m_friction = def.friction; this.m_restitution = def.restitution; this.m_body = body; this.m_proxyId = b2Pair.b2_nullProxy; this.m_maxRadius = 0.0; this.m_categoryBits = def.categoryBits; this.m_maskBits = def.maskBits; this.m_groupIndex = def.groupIndex; }, // Internal use only. Do not call. //b2Shape::~b2Shape() //{ // this.m_body->m_world->m_broadPhase->this.DestroyProxy(this.m_proxyId); //} DestroyProxy: function() { if (this.m_proxyId != b2Pair.b2_nullProxy) { this.m_body.m_world.m_broadPhase.DestroyProxy(this.m_proxyId); this.m_proxyId = b2Pair.b2_nullProxy; } }, // Internal use only. Do not call. Synchronize: function(position1, R1, position2, R2){}, QuickSync: function(position, R){}, Support: function(dX, dY, out){}, GetMaxRadius: function(){ return this.m_maxRadius; }, m_next: null, m_R: new b2Mat22(), m_position: new b2Vec2(), m_type: 0, m_userData: null, m_body: null, m_friction: null, m_restitution: null, m_maxRadius: null, m_proxyId: 0, m_categoryBits: 0, m_maskBits: 0, m_groupIndex: 0 // b2ShapeType }; b2Shape.Create = function(def, body, center){ switch (def.type) { case b2Shape.e_circleShape: { //void* mem = body->m_world->m_blockAllocator.Allocate(sizeof(b2CircleShape)); return new b2CircleShape(def, body, center); } case b2Shape.e_boxShape: case b2Shape.e_polyShape: { //void* mem = body->m_world->m_blockAllocator.Allocate(sizeof(b2PolyShape)); return new b2PolyShape(def, body, center); } } //b2Settings.b2Assert(false); return null; }; b2Shape.Destroy = function(shape) { /*b2BlockAllocator& allocator = shape->m_body->m_world->m_blockAllocator; switch (shape.m_type) { case b2Shape.e_circleShape: shape->~b2Shape(); allocator.Free(shape, sizeof(b2CircleShape)); break; case b2Shape.e_polyShape: shape->~b2Shape(); allocator.Free(shape, sizeof(b2PolyShape)); break; default: b2Assert(false); } shape = NULL;*/ // FROM DESTRUCTOR if (shape.m_proxyId != b2Pair.b2_nullProxy) shape.m_body.m_world.m_broadPhase.DestroyProxy(shape.m_proxyId); }; b2Shape.e_unknownShape = -1; b2Shape.e_circleShape = 0; b2Shape.e_boxShape = 1; b2Shape.e_polyShape = 2; b2Shape.e_meshShape = 3; b2Shape.e_shapeTypeCount = 4; b2Shape.PolyMass = function(massData, vs, count, rho) { //b2Settings.b2Assert(count >= 3); //var center = new b2Vec2(0.0, 0.0); var center = new b2Vec2(); center.SetZero(); var area = 0.0; var I = 0.0; // pRef is the reference point for forming triangles. // It's location doesn't change the result (except for rounding error). var pRef = new b2Vec2(0.0, 0.0); var inv3 = 1.0 / 3.0; for (var i = 0; i < count; ++i) { // Triangle vertices. var p1 = pRef; var p2 = vs[i]; var p3 = i + 1 < count ? vs[i+1] : vs[0]; var e1 = b2Math.SubtractVV(p2, p1); var e2 = b2Math.SubtractVV(p3, p1); var D = b2Math.b2CrossVV(e1, e2); var triangleArea = 0.5 * D; area += triangleArea; // Area weighted centroid // center += triangleArea * inv3 * (p1 + p2 + p3); var tVec = new b2Vec2(); tVec.SetV(p1); tVec.Add(p2); tVec.Add(p3); tVec.Multiply(inv3*triangleArea); center.Add(tVec); var px = p1.x; var py = p1.y; var ex1 = e1.x; var ey1 = e1.y; var ex2 = e2.x; var ey2 = e2.y; var intx2 = inv3 * (0.25 * (ex1*ex1 + ex2*ex1 + ex2*ex2) + (px*ex1 + px*ex2)) + 0.5*px*px; var inty2 = inv3 * (0.25 * (ey1*ey1 + ey2*ey1 + ey2*ey2) + (py*ey1 + py*ey2)) + 0.5*py*py; I += D * (intx2 + inty2); } // Total mass massData.mass = rho * area; // Center of mass //b2Settings.b2Assert(area > Number.MIN_VALUE); center.Multiply( 1.0 / area ); massData.center = center; // Inertia tensor relative to the center. I = rho * (I - area * b2Math.b2Dot(center, center)); massData.I = I; }; b2Shape.PolyCentroid = function(vs, count, out) { //b2Settings.b2Assert(count >= 3); //b2Vec2 c; c.Set(0.0f, 0.0f); var cX = 0.0; var cY = 0.0; //float32 area = 0.0f; var area = 0.0; // pRef is the reference point for forming triangles. // It's location doesn't change the result (except for rounding error). //b2Vec2 pRef(0.0f, 0.0f); var pRefX = 0.0; var pRefY = 0.0; /* // This code would put the reference point inside the polygon. for (var i = 0; i < count; ++i) { //pRef += vs[i]; pRef.x += vs[i].x; pRef.y += vs[i].y; } pRef.x *= 1.0 / count; pRef.y *= 1.0 / count; */ //const float32 inv3 = 1.0f / 3.0f; var inv3 = 1.0 / 3.0; for (var i = 0; i < count; ++i) { // Triangle vertices. //b2Vec2 p1 = pRef; var p1X = pRefX; var p1Y = pRefY; //b2Vec2 p2 = vs[i]; var p2X = vs[i].x; var p2Y = vs[i].y; //b2Vec2 p3 = i + 1 < count ? vs[i+1] : vs[0]; var p3X = i + 1 < count ? vs[i+1].x : vs[0].x; var p3Y = i + 1 < count ? vs[i+1].y : vs[0].y; //b2Vec2 e1 = p2 - p1; var e1X = p2X - p1X; var e1Y = p2Y - p1Y; //b2Vec2 e2 = p3 - p1; var e2X = p3X - p1X; var e2Y = p3Y - p1Y; //float32 D = b2Cross(e1, e2); var D = (e1X * e2Y - e1Y * e2X); //float32 triangleArea = 0.5f * D; var triangleArea = 0.5 * D; area += triangleArea; // Area weighted centroid //c += triangleArea * inv3 * (p1 + p2 + p3); cX += triangleArea * inv3 * (p1X + p2X + p3X); cY += triangleArea * inv3 * (p1Y + p2Y + p3Y); } // Centroid //b2Settings.b2Assert(area > Number.MIN_VALUE); cX *= 1.0 / area; cY *= 1.0 / area; // Replace return with 'out' vector //return c; out.Set(cX, cY); };