sensor.cpp
Go to the documentation of this file.
1 // MIT License
2 
3 // Copyright (c) 2019 Erin Catto
4 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 
23 #include "test.h"
24 #include "imgui/imgui.h"
25 
26 // This shows how to use sensor shapes. Sensors don't have collision, but report overlap events.
27 class Sensors : public Test
28 {
29 public:
30 
31  enum
32  {
33  e_count = 7
34  };
35 
37  {
38  {
39  b2BodyDef bd;
40  b2Body* ground = m_world->CreateBody(&bd);
41 
42  {
43  b2EdgeShape shape;
44  shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
45  ground->CreateFixture(&shape, 0.0f);
46  }
47 
48 #if 0
49  {
50  b2FixtureDef sd;
51  sd.SetAsBox(10.0f, 2.0f, b2Vec2(0.0f, 20.0f), 0.0f);
52  sd.isSensor = true;
53  m_sensor = ground->CreateFixture(&sd);
54  }
55 #else
56  {
57  b2CircleShape shape;
58  shape.m_radius = 5.0f;
59  shape.m_p.Set(0.0f, 10.0f);
60 
61  b2FixtureDef fd;
62  fd.shape = &shape;
63  fd.isSensor = true;
64  m_sensor = ground->CreateFixture(&fd);
65  }
66 #endif
67  }
68 
69  {
70  b2CircleShape shape;
71  shape.m_radius = 1.0f;
72 
73  for (int32 i = 0; i < e_count; ++i)
74  {
75  b2BodyDef bd;
76  bd.type = b2_dynamicBody;
77  bd.position.Set(-10.0f + 3.0f * i, 20.0f);
78  bd.userData.pointer = i;
79 
80  m_touching[i] = false;
81  m_bodies[i] = m_world->CreateBody(&bd);
82 
83  m_bodies[i]->CreateFixture(&shape, 1.0f);
84  }
85  }
86 
87  m_force = 100.0f;
88  }
89 
90  // Implement contact listener.
91  void BeginContact(b2Contact* contact) override
92  {
93  b2Fixture* fixtureA = contact->GetFixtureA();
94  b2Fixture* fixtureB = contact->GetFixtureB();
95 
96  if (fixtureA == m_sensor)
97  {
98  uintptr_t index = fixtureB->GetBody()->GetUserData().pointer;
99  if (index < e_count)
100  {
101  m_touching[index] = true;
102  }
103  }
104 
105  if (fixtureB == m_sensor)
106  {
107  uintptr_t index = fixtureA->GetBody()->GetUserData().pointer;
108  if (index < e_count)
109  {
110  m_touching[index] = true;
111  }
112  }
113  }
114 
115  // Implement contact listener.
116  void EndContact(b2Contact* contact) override
117  {
118  b2Fixture* fixtureA = contact->GetFixtureA();
119  b2Fixture* fixtureB = contact->GetFixtureB();
120 
121  if (fixtureA == m_sensor)
122  {
123  uintptr_t index = fixtureB->GetBody()->GetUserData().pointer;
124  if (index < e_count)
125  {
126  m_touching[index] = false;
127  }
128  }
129 
130  if (fixtureB == m_sensor)
131  {
132  uintptr_t index = fixtureA->GetBody()->GetUserData().pointer;
133  if (index < e_count)
134  {
135  m_touching[index] = false;
136  }
137  }
138  }
139 
140  void UpdateUI() override
141  {
142  ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f));
143  ImGui::SetNextWindowSize(ImVec2(200.0f, 60.0f));
144  ImGui::Begin("Sensor Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
145 
146  ImGui::SliderFloat("Force", &m_force, 0.0f, 2000.0f, "%.0f");
147 
148  ImGui::End();
149  }
150 
151  void Step(Settings& settings) override
152  {
153  Test::Step(settings);
154 
155  // Traverse the contact results. Apply a force on shapes
156  // that overlap the sensor.
157  for (int32 i = 0; i < e_count; ++i)
158  {
159  if (m_touching[i] == false)
160  {
161  continue;
162  }
163 
164  b2Body* body = m_bodies[i];
165  b2Body* ground = m_sensor->GetBody();
166 
168  b2Vec2 center = ground->GetWorldPoint(circle->m_p);
169 
170  b2Vec2 position = body->GetPosition();
171 
172  b2Vec2 d = center - position;
173  if (d.LengthSquared() < FLT_EPSILON * FLT_EPSILON)
174  {
175  continue;
176  }
177 
178  d.Normalize();
179  b2Vec2 F = m_force * d;
180  body->ApplyForce(F, position, false);
181  }
182  }
183 
184  static Test* Create()
185  {
186  return new Sensors;
187  }
188 
191  float m_force;
193 };
194 
195 static int testIndex = RegisterTest("Collision", "Sensors", Sensors::Create);
const b2Shape * shape
Definition: b2_fixture.h:76
d
IMGUI_API void SetNextWindowSize(const ImVec2 &size, ImGuiCond cond=0)
Definition: imgui.cpp:6054
b2Fixture * CreateFixture(const b2FixtureDef *def)
Definition: b2_body.cpp:165
uintptr_t pointer
For legacy compatibility.
Definition: b2_settings.h:66
f
Sensors()
Definition: sensor.cpp:36
Definition: imgui.h:164
b2Fixture * GetFixtureB()
Get fixture B in this contact.
Definition: b2_contact.h:306
void ApplyForce(const b2Vec2 &force, const b2Vec2 &point, bool wake)
Definition: b2_body.h:739
Definition: test.h:80
void EndContact(b2Contact *contact) override
Called when two fixtures cease to touch.
Definition: sensor.cpp:116
float m_force
Definition: sensor.cpp:191
const b2Vec2 & GetPosition() const
Definition: b2_body.h:484
b2BodyUserData & GetUserData()
Get the user data pointer that was provided in the body definition.
Definition: b2_body.h:734
A solid circle shape.
A 2D column vector.
Definition: b2_math.h:41
signed int int32
Definition: b2_types.h:28
b2Vec2 m_p
Position.
void SetTwoSided(const b2Vec2 &v1, const b2Vec2 &v2)
Set this as an isolated edge. Collision is two-sided.
IMGUI_API bool Begin(const char *name, bool *p_open=NULL, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:4736
b2BodyType type
Definition: b2_body.h:74
A rigid body. These are created via b2World::CreateBody.
Definition: b2_body.h:128
float m_radius
Definition: b2_shape.h:102
float LengthSquared() const
Definition: b2_math.h:96
void Set(float x_, float y_)
Set this vector to some specified coordinates.
Definition: b2_math.h:53
static Test * Create()
Definition: sensor.cpp:184
bool m_touching[e_count]
Definition: sensor.cpp:192
IMGUI_API void End()
Definition: imgui.cpp:5371
void Step(Settings &settings) override
Definition: sensor.cpp:151
b2BodyUserData userData
Use this to store application specific body data.
Definition: b2_body.h:121
b2World * m_world
Definition: test.h:128
bool isSensor
Definition: b2_fixture.h:96
void UpdateUI() override
Definition: sensor.cpp:140
b2Fixture * GetFixtureA()
Get fixture A in this contact.
Definition: b2_contact.h:296
IMGUI_API void SetNextWindowPos(const ImVec2 &pos, ImGuiCond cond=0, const ImVec2 &pivot=ImVec2(0, 0))
Definition: imgui.cpp:6045
b2Vec2 position
Definition: b2_body.h:78
IMGUI_API bool SliderFloat(const char *label, float *v, float v_min, float v_max, const char *format="%.3f", float power=1.0f)
void BeginContact(b2Contact *contact) override
Called when two fixtures begin to touch.
Definition: sensor.cpp:91
float Normalize()
Convert this vector into a unit vector. Returns the length.
Definition: b2_math.h:102
b2Vec2 GetWorldPoint(const b2Vec2 &localPoint) const
Definition: b2_body.h:561
int RegisterTest(const char *category, const char *name, TestCreateFcn *fcn)
Definition: test.cpp:458
b2Body * m_bodies[e_count]
Definition: sensor.cpp:190
static int testIndex
Definition: sensor.cpp:195
b2Fixture * m_sensor
Definition: sensor.cpp:189
virtual void Step(Settings &settings)
Definition: test.cpp:278
b2Shape * GetShape()
Definition: b2_fixture.h:258
b2Body * CreateBody(const b2BodyDef *def)
Definition: b2_world.cpp:115
b2Body * GetBody()
Definition: b2_fixture.h:283


mvsim
Author(s):
autogenerated on Tue Jul 4 2023 03:08:21