1 /********************************************************************************
2 * ReactPhysics3D physics library, http://www.reactphysics3d.com                 *
3 * Copyright (c) 2010-2020 Daniel Chappuis                                       *
4 *********************************************************************************
5 *                                                                               *
6 * This software is provided 'as-is', without any express or implied warranty.   *
7 * In no event will the authors be held liable for any damages arising from the  *
8 * use of this software.                                                         *
9 *                                                                               *
10 * Permission is granted to anyone to use this software for any purpose,         *
11 * including commercial applications, and to alter it and redistribute it        *
12 * freely, subject to the following restrictions:                                *
13 *                                                                               *
14 * 1. The origin of this software must not be misrepresented; you must not claim *
15 *    that you wrote the original software. If you use this software in a        *
16 *    product, an acknowledgment in the product documentation would be           *
17 *    appreciated but is not required.                                           *
18 *                                                                               *
19 * 2. Altered source versions must be plainly marked as such, and must not be    *
20 *    misrepresented as being the original software.                             *
21 *                                                                               *
22 * 3. This notice may not be removed or altered from any source distribution.    *
23 *                                                                               *
24 ********************************************************************************/
25 
26 // Libraries
27 #include <reactphysics3d/components/BallAndSocketJointComponents.h>
28 #include <reactphysics3d/engine/EntityManager.h>
29 #include <reactphysics3d/mathematics/Matrix3x3.h>
30 #include <cassert>
31 
32 // We want to use the ReactPhysics3D namespace
33 using namespace reactphysics3d;
34 
35 // Constructor
BallAndSocketJointComponents(MemoryAllocator & allocator)36 BallAndSocketJointComponents::BallAndSocketJointComponents(MemoryAllocator& allocator)
37                     :Components(allocator, sizeof(Entity) + sizeof(BallAndSocketJoint*) + sizeof(Vector3) +
38                                 sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) +
39                                 sizeof(Matrix3x3) + sizeof(Matrix3x3) + sizeof(Vector3) +
40                                 sizeof(Matrix3x3) + sizeof(Vector3)) {
41 
42     // Allocate memory for the components data
43     allocate(INIT_NB_ALLOCATED_COMPONENTS);
44 }
45 
46 // Allocate memory for a given number of components
allocate(uint32 nbComponentsToAllocate)47 void BallAndSocketJointComponents::allocate(uint32 nbComponentsToAllocate) {
48 
49     assert(nbComponentsToAllocate > mNbAllocatedComponents);
50 
51     // Size for the data of a single component (in bytes)
52     const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
53 
54     // Allocate memory
55     void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
56     assert(newBuffer != nullptr);
57 
58     // New pointers to components data
59     Entity* newJointEntities = static_cast<Entity*>(newBuffer);
60     BallAndSocketJoint** newJoints = reinterpret_cast<BallAndSocketJoint**>(newJointEntities + nbComponentsToAllocate);
61     Vector3* newLocalAnchorPointBody1 = reinterpret_cast<Vector3*>(newJoints + nbComponentsToAllocate);
62     Vector3* newLocalAnchorPointBody2 = reinterpret_cast<Vector3*>(newLocalAnchorPointBody1 + nbComponentsToAllocate);
63     Vector3* newR1World = reinterpret_cast<Vector3*>(newLocalAnchorPointBody2 + nbComponentsToAllocate);
64     Vector3* newR2World = reinterpret_cast<Vector3*>(newR1World + nbComponentsToAllocate);
65     Matrix3x3* newI1 = reinterpret_cast<Matrix3x3*>(newR2World + nbComponentsToAllocate);
66     Matrix3x3* newI2 = reinterpret_cast<Matrix3x3*>(newI1 + nbComponentsToAllocate);
67     Vector3* newBiasVector = reinterpret_cast<Vector3*>(newI2 + nbComponentsToAllocate);
68     Matrix3x3* newInverseMassMatrix = reinterpret_cast<Matrix3x3*>(newBiasVector + nbComponentsToAllocate);
69     Vector3* newImpulse = reinterpret_cast<Vector3*>(newInverseMassMatrix + nbComponentsToAllocate);
70 
71     // If there was already components before
72     if (mNbComponents > 0) {
73 
74         // Copy component data from the previous buffer to the new one
75         memcpy(newJointEntities, mJointEntities, mNbComponents * sizeof(Entity));
76         memcpy(newJoints, mJoints, mNbComponents * sizeof(BallAndSocketJoint*));
77         memcpy(newLocalAnchorPointBody1, mLocalAnchorPointBody1, mNbComponents * sizeof(Vector3));
78         memcpy(newLocalAnchorPointBody2, mLocalAnchorPointBody2, mNbComponents * sizeof(Vector3));
79         memcpy(newR1World, mR1World, mNbComponents * sizeof(Vector3));
80         memcpy(newR2World, mR2World, mNbComponents * sizeof(Vector3));
81         memcpy(newI1, mI1, mNbComponents * sizeof(Matrix3x3));
82         memcpy(newI2, mI2, mNbComponents * sizeof(Matrix3x3));
83         memcpy(newBiasVector, mBiasVector, mNbComponents * sizeof(Vector3));
84         memcpy(newInverseMassMatrix, mInverseMassMatrix, mNbComponents * sizeof(Matrix3x3));
85         memcpy(newImpulse, mImpulse, mNbComponents * sizeof(Vector3));
86 
87         // Deallocate previous memory
88         mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * mComponentDataSize);
89     }
90 
91     mBuffer = newBuffer;
92     mJointEntities = newJointEntities;
93     mJoints = newJoints;
94     mNbAllocatedComponents = nbComponentsToAllocate;
95     mLocalAnchorPointBody1 = newLocalAnchorPointBody1;
96     mLocalAnchorPointBody2 = newLocalAnchorPointBody2;
97     mR1World = newR1World;
98     mR2World = newR2World;
99     mI1 = newI1;
100     mI2 = newI2;
101     mBiasVector = newBiasVector;
102     mInverseMassMatrix = newInverseMassMatrix;
103     mImpulse = newImpulse;
104 }
105 
106 // Add a component
addComponent(Entity jointEntity,bool isSleeping,const BallAndSocketJointComponent & component)107 void BallAndSocketJointComponents::addComponent(Entity jointEntity, bool isSleeping, const BallAndSocketJointComponent& component) {
108 
109     // Prepare to add new component (allocate memory if necessary and compute insertion index)
110     uint32 index = prepareAddComponent(isSleeping);
111 
112     // Insert the new component data
113     new (mJointEntities + index) Entity(jointEntity);
114     mJoints[index] = nullptr;
115     new (mLocalAnchorPointBody1 + index) Vector3(0, 0, 0);
116     new (mLocalAnchorPointBody2 + index) Vector3(0, 0, 0);
117     new (mR1World + index) Vector3(0, 0, 0);
118     new (mR2World + index) Vector3(0, 0, 0);
119     new (mI1 + index) Matrix3x3();
120     new (mI2 + index) Matrix3x3();
121     new (mBiasVector + index) Vector3(0, 0, 0);
122     new (mInverseMassMatrix + index) Matrix3x3();
123     new (mImpulse + index) Vector3(0, 0, 0);
124 
125     // Map the entity with the new component lookup index
126     mMapEntityToComponentIndex.add(Pair<Entity, uint32>(jointEntity, index));
127 
128     mNbComponents++;
129 
130     assert(mDisabledStartIndex <= mNbComponents);
131     assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
132 }
133 
134 // Move a component from a source to a destination index in the components array
135 // The destination location must contain a constructed object
moveComponentToIndex(uint32 srcIndex,uint32 destIndex)136 void BallAndSocketJointComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) {
137 
138     const Entity entity = mJointEntities[srcIndex];
139 
140     // Copy the data of the source component to the destination location
141     new (mJointEntities + destIndex) Entity(mJointEntities[srcIndex]);
142     mJoints[destIndex] = mJoints[srcIndex];
143     new (mLocalAnchorPointBody1 + destIndex) Vector3(mLocalAnchorPointBody1[srcIndex]);
144     new (mLocalAnchorPointBody2 + destIndex) Vector3(mLocalAnchorPointBody2[srcIndex]);
145     new (mR1World + destIndex) Vector3(mR1World[srcIndex]);
146     new (mR2World + destIndex) Vector3(mR2World[srcIndex]);
147     new (mI1 + destIndex) Matrix3x3(mI1[srcIndex]);
148     new (mI2 + destIndex) Matrix3x3(mI2[srcIndex]);
149     new (mBiasVector + destIndex) Vector3(mBiasVector[srcIndex]);
150     new (mInverseMassMatrix + destIndex) Matrix3x3(mInverseMassMatrix[srcIndex]);
151     new (mImpulse + destIndex) Vector3(mImpulse[srcIndex]);
152 
153     // Destroy the source component
154     destroyComponent(srcIndex);
155 
156     assert(!mMapEntityToComponentIndex.containsKey(entity));
157 
158     // Update the entity to component index mapping
159     mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, destIndex));
160 
161     assert(mMapEntityToComponentIndex[mJointEntities[destIndex]] == destIndex);
162 }
163 
164 // Swap two components in the array
swapComponents(uint32 index1,uint32 index2)165 void BallAndSocketJointComponents::swapComponents(uint32 index1, uint32 index2) {
166 
167     // Copy component 1 data
168     Entity jointEntity1(mJointEntities[index1]);
169     BallAndSocketJoint* joint1 = mJoints[index1];
170     Vector3 localAnchorPointBody1(mLocalAnchorPointBody1[index1]);
171     Vector3 localAnchorPointBody2(mLocalAnchorPointBody2[index1]);
172     Vector3 r1World1(mR1World[index1]);
173     Vector3 r2World1(mR2World[index1]);
174     Matrix3x3 i11(mI1[index1]);
175     Matrix3x3 i21(mI2[index1]);
176     Vector3 biasVector1(mBiasVector[index1]);
177     Matrix3x3 inverseMassMatrix1(mInverseMassMatrix[index1]);
178     Vector3 impulse1(mImpulse[index1]);
179 
180     // Destroy component 1
181     destroyComponent(index1);
182 
183     moveComponentToIndex(index2, index1);
184 
185     // Reconstruct component 1 at component 2 location
186     new (mJointEntities + index2) Entity(jointEntity1);
187     mJoints[index2] = joint1;
188     new (mLocalAnchorPointBody1 + index2) Vector3(localAnchorPointBody1);
189     new (mLocalAnchorPointBody2 + index2) Vector3(localAnchorPointBody2);
190     new (mR1World + index2) Vector3(r1World1);
191     new (mR2World + index2) Vector3(r2World1);
192     new (mI1 + index2) Matrix3x3(i11);
193     new (mI2 + index2) Matrix3x3(i21);
194     new (mBiasVector + index2) Vector3(biasVector1);
195     new (mInverseMassMatrix + index2) Matrix3x3(inverseMassMatrix1);
196     new (mImpulse + index2) Vector3(impulse1);
197 
198     // Update the entity to component index mapping
199     mMapEntityToComponentIndex.add(Pair<Entity, uint32>(jointEntity1, index2));
200 
201     assert(mMapEntityToComponentIndex[mJointEntities[index1]] == index1);
202     assert(mMapEntityToComponentIndex[mJointEntities[index2]] == index2);
203     assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
204 }
205 
206 // Destroy a component at a given index
destroyComponent(uint32 index)207 void BallAndSocketJointComponents::destroyComponent(uint32 index) {
208 
209     Components::destroyComponent(index);
210 
211     assert(mMapEntityToComponentIndex[mJointEntities[index]] == index);
212 
213     mMapEntityToComponentIndex.remove(mJointEntities[index]);
214 
215     mJointEntities[index].~Entity();
216     mJoints[index] = nullptr;
217     mLocalAnchorPointBody1[index].~Vector3();
218     mLocalAnchorPointBody2[index].~Vector3();
219     mR1World[index].~Vector3();
220     mR2World[index].~Vector3();
221     mI1[index].~Matrix3x3();
222     mI2[index].~Matrix3x3();
223     mBiasVector[index].~Vector3();
224     mInverseMassMatrix[index].~Matrix3x3();
225     mImpulse[index].~Vector3();
226 }
227