1 | /* |
2 | * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org |
3 | * |
4 | * This software is provided 'as-is', without any express or implied |
5 | * warranty. In no event will the authors be held liable for any damages |
6 | * arising from the use of this software. |
7 | * Permission is granted to anyone to use this software for any purpose, |
8 | * including commercial applications, and to alter it and redistribute it |
9 | * freely, subject to the following restrictions: |
10 | * 1. The origin of this software must not be misrepresented; you must not |
11 | * claim that you wrote the original software. If you use this software |
12 | * in a product, an acknowledgment in the product documentation would be |
13 | * appreciated but is not required. |
14 | * 2. Altered source versions must be plainly marked as such, and must not be |
15 | * misrepresented as being the original software. |
16 | * 3. This notice may not be removed or altered from any source distribution. |
17 | */ |
18 | |
19 | #include <Box2D/Collision/Shapes/b2EdgeShape.h> |
20 | #include <new> |
21 | |
22 | void b2EdgeShape::Set(const b2Vec2& v1, const b2Vec2& v2) |
23 | { |
24 | m_vertex1 = v1; |
25 | m_vertex2 = v2; |
26 | m_hasVertex0 = false; |
27 | m_hasVertex3 = false; |
28 | } |
29 | |
30 | b2Shape* b2EdgeShape::Clone(b2BlockAllocator* allocator) const |
31 | { |
32 | void* mem = allocator->Allocate(sizeof(b2EdgeShape)); |
33 | b2EdgeShape* clone = new (mem) b2EdgeShape; |
34 | *clone = *this; |
35 | return clone; |
36 | } |
37 | |
38 | int32 b2EdgeShape::GetChildCount() const |
39 | { |
40 | return 1; |
41 | } |
42 | |
43 | bool b2EdgeShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const |
44 | { |
45 | B2_NOT_USED(xf); |
46 | B2_NOT_USED(p); |
47 | return false; |
48 | } |
49 | |
50 | // p = p1 + t * d |
51 | // v = v1 + s * e |
52 | // p1 + t * d = v1 + s * e |
53 | // s * e - t * d = p1 - v1 |
54 | bool b2EdgeShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, |
55 | const b2Transform& xf, int32 childIndex) const |
56 | { |
57 | B2_NOT_USED(childIndex); |
58 | |
59 | // Put the ray into the edge's frame of reference. |
60 | b2Vec2 p1 = b2MulT(xf.q, input.p1 - xf.p); |
61 | b2Vec2 p2 = b2MulT(xf.q, input.p2 - xf.p); |
62 | b2Vec2 d = p2 - p1; |
63 | |
64 | b2Vec2 v1 = m_vertex1; |
65 | b2Vec2 v2 = m_vertex2; |
66 | b2Vec2 e = v2 - v1; |
67 | b2Vec2 normal(e.y, -e.x); |
68 | normal.Normalize(); |
69 | |
70 | // q = p1 + t * d |
71 | // dot(normal, q - v1) = 0 |
72 | // dot(normal, p1 - v1) + t * dot(normal, d) = 0 |
73 | float32 numerator = b2Dot(normal, v1 - p1); |
74 | float32 denominator = b2Dot(normal, d); |
75 | |
76 | if (denominator == 0.0f) |
77 | { |
78 | return false; |
79 | } |
80 | |
81 | float32 t = numerator / denominator; |
82 | if (t < 0.0f || input.maxFraction < t) |
83 | { |
84 | return false; |
85 | } |
86 | |
87 | b2Vec2 q = p1 + t * d; |
88 | |
89 | // q = v1 + s * r |
90 | // s = dot(q - v1, r) / dot(r, r) |
91 | b2Vec2 r = v2 - v1; |
92 | float32 rr = b2Dot(r, r); |
93 | if (rr == 0.0f) |
94 | { |
95 | return false; |
96 | } |
97 | |
98 | float32 s = b2Dot(q - v1, r) / rr; |
99 | if (s < 0.0f || 1.0f < s) |
100 | { |
101 | return false; |
102 | } |
103 | |
104 | output->fraction = t; |
105 | if (numerator > 0.0f) |
106 | { |
107 | output->normal = -b2Mul(xf.q, normal); |
108 | } |
109 | else |
110 | { |
111 | output->normal = b2Mul(xf.q, normal); |
112 | } |
113 | return true; |
114 | } |
115 | |
116 | void b2EdgeShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const |
117 | { |
118 | B2_NOT_USED(childIndex); |
119 | |
120 | b2Vec2 v1 = b2Mul(xf, m_vertex1); |
121 | b2Vec2 v2 = b2Mul(xf, m_vertex2); |
122 | |
123 | b2Vec2 lower = b2Min(v1, v2); |
124 | b2Vec2 upper = b2Max(v1, v2); |
125 | |
126 | b2Vec2 r(m_radius, m_radius); |
127 | aabb->lowerBound = lower - r; |
128 | aabb->upperBound = upper + r; |
129 | } |
130 | |
131 | void b2EdgeShape::ComputeMass(b2MassData* massData, float32 density) const |
132 | { |
133 | B2_NOT_USED(density); |
134 | |
135 | massData->mass = 0.0f; |
136 | massData->center = 0.5f * (m_vertex1 + m_vertex2); |
137 | massData->I = 0.0f; |
138 | } |
139 | |