Cogs.Core
ConstraintSystem.cpp
1#include "ConstraintSystem.h"
2
3#include "Systems/Core/TransformSystem.h"
4
5#include "ExtensionRegistry.h"
6
7#include "Services/Services.h"
8
9#include "PhysicsManager.h"
10#include "RigidBodySystem.h"
11
12#include "Foundation/ComponentModel/Entity.h"
13
14namespace
15{
16 using namespace Cogs::Core;
17
18 template<typename ComponentType, typename SystemType>
19 void removeConstraint(Context * context, SystemType * system, ComponentType * component)
20 {
21 auto manager = context->services->getService<PhysicsManager>();
22
23 auto & data = system->getData(component);
24
25 if (data.constraint) {
26 manager->removeConstraint(data.constraint.get());
27 }
28 }
29
30 void updateConstraintData(Context * context, ConstraintComponent * component, ConstraintData & data, bool updateTransform = true)
31 {
32 auto rigidBodySystem = ExtensionRegistry::getExtensionSystem<RigidBodySystem>(context);
33
34 auto rigidA = component->getComponent<RigidBodyComponent>();
35 auto rigidB = component->target->getComponent<RigidBodyComponent>();
36
37 if (!rigidA || !rigidB) return;
38
39 auto & dataA = rigidBodySystem->getData(rigidA);
40 auto & dataB = rigidBodySystem->getData(rigidB);
41
42 data.rigidBody = dataA.rigidBody.get();
43 data.targetRigidBody = dataB.rigidBody.get();
44
45 if (dataA.rigidBody && dataB.rigidBody) {
46 dataA.rigidBody->setActivationState(DISABLE_DEACTIVATION);
47 dataB.rigidBody->setActivationState(DISABLE_DEACTIVATION);
48
49 if (updateTransform) {
50 auto transformComponentA = component->getComponent<TransformComponent>();
51 auto transformComponentB = component->target->getComponent<TransformComponent>();
52
53 context->transformSystem->updateLocalToWorldTransform(*transformComponentA, true);
54 data.transform = context->transformSystem->getLocalToWorld(transformComponentA);
55
56 context->transformSystem->updateLocalToWorldTransform(*transformComponentB, true);
57 data.targetTransform = context->transformSystem->getLocalToWorld(transformComponentB);
58 }
59 }
60 }
61}
62
64{
65 auto manager = context->services->getService<PhysicsManager>();
66
67 for (auto & component : pool) {
68 auto & data = getData(&component);
69
70 if (!data.constraint || component.hasChanged()) {
71 updateConstraintData(context, &component, data);
72
73 if (!data.rigidBody || !data.targetRigidBody) continue;
74
75 auto positionA = glm::vec4(data.transform[3]);
76 auto positionB = glm::vec4(data.targetTransform[3]);
77
78 btTransform tA = btTransform(btQuaternion(0, 0, 0));
79 btTransform tB = btTransform(btQuaternion(0, 0, 0), toBullet(positionA - positionB));
80 auto constraint = data.createConstraint<btFixedConstraint>(*data.rigidBody, *data.targetRigidBody, tA, tB);
81
82 manager->addConstraint(constraint);
83 }
84 }
85}
86
88{
89 removeConstraint(context, this, component.resolveComponent<FixedConstraintComponent>());
90
92}
93
95{
96 auto manager = context->services->getService<PhysicsManager>();
97
98 for (auto & component : pool) {
99 auto & data = getData(&component);
100
101 if (!data.constraint || component.hasChanged()) {
102 updateConstraintData(context, &component, data);
103
104 if (!data.rigidBody || !data.targetRigidBody) continue;
105
106 auto constraint = data.createConstraint<btHingeConstraint>(
107 *data.rigidBody,
108 *data.targetRigidBody,
109 toBullet(component.anchor),
110 toBullet(component.targetAnchor),
111 toBullet(component.axis),
112 toBullet(component.targetAxis),
113 true);
114
115 manager->addConstraint(constraint);
116 }
117 }
118}
119
121{
122 removeConstraint(context, this, component.resolveComponent<HingeConstraintComponent>());
123
125}
126
128{
129 auto manager = context->services->getService<PhysicsManager>();
130
131 for (auto & component : pool) {
132 auto & data = getData(&component);
133
134 if (!data.constraint || component.hasChanged()) {
135 updateConstraintData(context, &component, data);
136
137 if (!data.rigidBody || !data.targetRigidBody) continue;
138
139 auto positionA = glm::vec3(data.transform[3]);
140 auto positionB = glm::vec3(data.targetTransform[3]);
141
142 btTransform tA = btTransform(btQuaternion(0, 0, 0));
143 btTransform tB = btTransform(btQuaternion(0, 0, 0), toBullet((positionA + component.anchor) - (positionB + component.targetAnchor)));
144
145 auto constraint = data.createConstraint<btGeneric6DofSpring2Constraint>(*data.rigidBody, *data.targetRigidBody, tA, tB);
146
147 for (int i = 0; i < 6; ++i) {
148 constraint->enableSpring(i, true);
149 constraint->setLimit(i, -10, 10);
150 constraint->setStiffness(i, component.stiffness);
151 constraint->setDamping(i, component.damping);
152 constraint->setEquilibriumPoint(i, 0);
153 }
154
155 manager->addConstraint(constraint);
156 }
157 }
158}
159
161{
162 removeConstraint(context, this, component.resolveComponent<SpringConstraintComponent>());
163
165}
166
168{
169 auto manager = context->services->getService<PhysicsManager>();
170
171 for (auto & component : pool) {
172 auto & data = getData(&component);
173
174 if (!data.constraint || component.hasChanged()) {
175 updateConstraintData(context, &component, data);
176
177 if (!data.rigidBody || !data.targetRigidBody) continue;
178
179 auto positionA = glm::vec3(data.transform[3]);
180 auto positionB = glm::vec3(data.targetTransform[3]);
181
182 btTransform tA = btTransform(btQuaternion(0, 0, 0));
183 btTransform tB = btTransform(btQuaternion(0, 0, 0), toBullet((positionA + component.anchor) - (positionB + component.targetAnchor)));
184
185 auto constraint = data.createConstraint<btGeneric6DofSpring2Constraint>(*data.rigidBody, *data.targetRigidBody, tA, tB);
186
187 manager->addConstraint(constraint);
188 }
189 }
190}
191
193{
194 removeConstraint(context, this, component.resolveComponent<GenericConstraintComponent>());
195
197}
ComponentType * getComponent() const
Definition: Component.h:159
Context * context
Pointer to the Context instance the system lives in.
virtual void destroyComponent(ComponentHandle)
Destroy the component held by the given handle.
void update()
Updates the system state to that of the current frame.
ComponentPool< ComponentType > pool
Pool of components managed by the system.
EntityPtr target
Target entity. Constraint is created between owner of this component and target.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
std::unique_ptr< class Services > services
Services.
Definition: Context.h:174
void destroyComponent(ComponentHandle component) final
Destroy the component held by the given handle.
void destroyComponent(ComponentHandle component) final
Destroy the component held by the given handle.
void destroyComponent(ComponentHandle component) final
Destroy the component held by the given handle.
void destroyComponent(ComponentHandle component) final
Destroy the component held by the given handle.
Defines a 4x4 transformation matrix for the entity and a global offset for root entities.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
Handle to a Component instance.
Definition: Component.h:67
ComponentType * resolveComponent() const
Definition: Component.h:90