1/**
2 * Copyright (c) 2006-2023 LOVE Development Team
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 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20
21#include "Shape.h"
22
23// Module
24#include "Body.h"
25#include "World.h"
26#include "Physics.h"
27
28// STD
29#include <bitset>
30
31namespace love
32{
33namespace physics
34{
35namespace box2d
36{
37
38Shape::Shape()
39 : shape(nullptr)
40 , own(false)
41{
42}
43
44Shape::Shape(b2Shape *shape, bool own)
45 : shape(shape)
46 , own(own)
47{
48}
49
50Shape::~Shape()
51{
52 if (shape && own)
53 delete shape;
54 shape = nullptr;
55}
56
57Shape::Type Shape::getType() const
58{
59 switch (shape->GetType())
60 {
61 case b2Shape::e_circle:
62 return SHAPE_CIRCLE;
63 case b2Shape::e_polygon:
64 return SHAPE_POLYGON;
65 case b2Shape::e_edge:
66 return SHAPE_EDGE;
67 case b2Shape::e_chain:
68 return SHAPE_CHAIN;
69 default:
70 return SHAPE_INVALID;
71 }
72}
73
74float Shape::getRadius() const
75{
76 return Physics::scaleUp(shape->m_radius);
77}
78
79int Shape::getChildCount() const
80{
81 return shape->GetChildCount();
82}
83
84bool Shape::testPoint(float x, float y, float r, float px, float py) const
85{
86 b2Vec2 point(px, py);
87 b2Transform transform(Physics::scaleDown(b2Vec2(x, y)), b2Rot(r));
88 return shape->TestPoint(transform, Physics::scaleDown(point));
89}
90
91int Shape::rayCast(lua_State *L) const
92{
93 float p1x = Physics::scaleDown((float)luaL_checknumber(L, 1));
94 float p1y = Physics::scaleDown((float)luaL_checknumber(L, 2));
95 float p2x = Physics::scaleDown((float)luaL_checknumber(L, 3));
96 float p2y = Physics::scaleDown((float)luaL_checknumber(L, 4));
97 float maxFraction = (float)luaL_checknumber(L, 5);
98 float x = Physics::scaleDown((float)luaL_checknumber(L, 6));
99 float y = Physics::scaleDown((float)luaL_checknumber(L, 7));
100 float r = (float)luaL_checknumber(L, 8);
101 int childIndex = (int) luaL_optinteger(L, 9, 1) - 1; // Convert from 1-based index
102 b2RayCastInput input;
103 input.p1.Set(p1x, p1y);
104 input.p2.Set(p2x, p2y);
105 input.maxFraction = maxFraction;
106 b2Transform transform(b2Vec2(x, y), b2Rot(r));
107 b2RayCastOutput output;
108 if (!shape->RayCast(&output, input, transform, childIndex))
109 return 0; // No hit.
110 lua_pushnumber(L, output.normal.x);
111 lua_pushnumber(L, output.normal.y);
112 lua_pushnumber(L, output.fraction);
113 return 3;
114}
115
116int Shape::computeAABB(lua_State *L) const
117{
118 float x = Physics::scaleDown((float)luaL_checknumber(L, 1));
119 float y = Physics::scaleDown((float)luaL_checknumber(L, 2));
120 float r = (float)luaL_checknumber(L, 3);
121 int childIndex = (int) luaL_optinteger(L, 4, 1) - 1; // Convert from 1-based index
122 b2Transform transform(b2Vec2(x, y), b2Rot(r));
123 b2AABB box;
124 shape->ComputeAABB(&box, transform, childIndex);
125 box = Physics::scaleUp(box);
126 lua_pushnumber(L, box.lowerBound.x);
127 lua_pushnumber(L, box.lowerBound.y);
128 lua_pushnumber(L, box.upperBound.x);
129 lua_pushnumber(L, box.upperBound.y);
130 return 4;
131}
132
133int Shape::computeMass(lua_State *L) const
134{
135 float density = (float)luaL_checknumber(L, 1);
136 b2MassData data;
137 shape->ComputeMass(&data, density);
138 b2Vec2 center = Physics::scaleUp(data.center);
139 lua_pushnumber(L, center.x);
140 lua_pushnumber(L, center.y);
141 lua_pushnumber(L, data.mass);
142 lua_pushnumber(L, Physics::scaleUp(Physics::scaleUp(data.I)));
143 return 4;
144}
145
146} // box2d
147} // physics
148} // love
149